diff options
author | Yaroslav <contact@yaroslavps.com> | 2019-09-05 19:35:38 +0300 |
---|---|---|
committer | Yaroslav <contact@yaroslavps.com> | 2019-09-05 19:35:38 +0300 |
commit | 212dcd0bf753f08c0127a26a71b673c734b45c02 (patch) | |
tree | 4a43e43c7c9b9ccfcaef4088ba9e5f52154994b5 /.vim/autoload | |
download | vimrice-212dcd0bf753f08c0127a26a71b673c734b45c02.tar.gz vimrice-212dcd0bf753f08c0127a26a71b673c734b45c02.zip |
init commit, extracted vim config from i3rice
Diffstat (limited to '.vim/autoload')
193 files changed, 19578 insertions, 0 deletions
diff --git a/.vim/autoload/airline.vim b/.vim/autoload/airline.vim new file mode 100644 index 0000000..eacdc7c --- /dev/null +++ b/.vim/autoload/airline.vim @@ -0,0 +1,267 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let g:airline_statusline_funcrefs = get(g:, 'airline_statusline_funcrefs', []) + +let s:sections = ['a','b','c','gutter','x','y','z', 'error', 'warning'] +let s:inactive_funcrefs = [] +let s:contexts = {} +let s:core_funcrefs = [ + \ function('airline#extensions#apply'), + \ function('airline#extensions#default#apply') ] + + +function! airline#add_statusline_func(name) + call airline#add_statusline_funcref(function(a:name)) +endfunction + +function! airline#add_statusline_funcref(function) + if index(g:airline_statusline_funcrefs, a:function) >= 0 + call airline#util#warning(printf('The airline statusline funcref "%s" has already been added.', string(a:function))) + return + endif + call add(g:airline_statusline_funcrefs, a:function) +endfunction + +function! airline#remove_statusline_func(name) + let i = index(g:airline_statusline_funcrefs, function(a:name)) + if i > -1 + call remove(g:airline_statusline_funcrefs, i) + endif +endfunction + +function! airline#add_inactive_statusline_func(name) + call add(s:inactive_funcrefs, function(a:name)) +endfunction + +function! airline#load_theme() + let g:airline_theme = get(g:, 'airline_theme', 'dark') + if exists('*airline#themes#{g:airline_theme}#refresh') + call airline#themes#{g:airline_theme}#refresh() + endif + + let palette = g:airline#themes#{g:airline_theme}#palette + call airline#themes#patch(palette) + + if exists('g:airline_theme_patch_func') + let Fn = function(g:airline_theme_patch_func) + call Fn(palette) + endif + + call airline#highlighter#load_theme() + call airline#extensions#load_theme() + call airline#update_statusline() +endfunction + +" Load an airline theme +function! airline#switch_theme(name, ...) + let silent = get(a:000, '0', 0) + " get all available themes + let themes = airline#util#themes('') + let err = 0 + try + if index(themes, a:name) == -1 + " Theme not available + if !silent + call airline#util#warning(printf('The specified theme "%s" cannot be found.', a:name)) + endif + throw "not-found" + let err = 1 + else + exe "ru autoload/airline/themes/". a:name. ".vim" + let g:airline_theme = a:name + endif + catch /^Vim/ + " catch only Vim errors, not "not-found" + call airline#util#warning(printf('There is an error in theme "%s".', a:name)) + if &vbs + call airline#util#warning(v:exception) + endif + let err = 1 + endtry + + if err + if exists('g:airline_theme') + return + else + let g:airline_theme = 'dark' + endif + endif + + unlet! w:airline_lastmode + call airline#load_theme() + + call airline#util#doautocmd('AirlineAfterTheme') + + " this is required to prevent clobbering the startup info message, i don't know why... + call airline#check_mode(winnr()) +endfunction + +" Try to load the right theme for the current colorscheme +function! airline#switch_matching_theme() + if exists('g:colors_name') + let existing = g:airline_theme + let theme = tr(tolower(g:colors_name), '-', '_') + try + call airline#switch_theme(theme, 1) + return 1 + catch + for map in items(g:airline_theme_map) + if match(g:colors_name, map[0]) > -1 + try + call airline#switch_theme(map[1], 1) + catch + call airline#switch_theme(existing) + endtry + return 1 + endif + endfor + endtry + endif + return 0 +endfunction + +" Update the statusline +function! airline#update_statusline() + if airline#util#getwinvar(winnr(), 'airline_disabled', 0) + return + endif + let range = filter(range(1, winnr('$')), 'v:val != winnr()') + " create inactive statusline + call airline#update_statusline_inactive(range) + + unlet! w:airline_render_left w:airline_render_right + exe 'unlet! ' 'w:airline_section_'. join(s:sections, ' w:airline_section_') + + " Now create the active statusline + let w:airline_active = 1 + let context = { 'winnr': winnr(), 'active': 1, 'bufnr': winbufnr(winnr()) } + call s:invoke_funcrefs(context, g:airline_statusline_funcrefs) +endfunction + +" Function to be called to make all statuslines inactive +" Triggered on FocusLost autocommand +function! airline#update_statusline_focuslost() + if get(g:, 'airline_focuslost_inactive', 0) + let bufnr=bufnr('%') + call airline#highlighter#highlight_modified_inactive(bufnr) + call airline#highlighter#highlight(['inactive'], bufnr) + call airline#update_statusline_inactive(range(1, winnr('$'))) + endif +endfunction + +" Function to draw inactive statuslines for inactive windows +function! airline#update_statusline_inactive(range) + if airline#util#getwinvar(winnr(), 'airline_disabled', 0) + return + endif + for nr in a:range + if airline#util#getwinvar(nr, 'airline_disabled', 0) + continue + endif + call setwinvar(nr, 'airline_active', 0) + let context = { 'winnr': nr, 'active': 0, 'bufnr': winbufnr(nr) } + if get(g:, 'airline_inactive_alt_sep', 0) + call extend(context, { + \ 'left_sep': g:airline_left_alt_sep, + \ 'right_sep': g:airline_right_alt_sep }, 'keep') + endif + call s:invoke_funcrefs(context, s:inactive_funcrefs) + endfor +endfunction + +" Gather output from all funcrefs which will later be returned by the +" airline#statusline() function +function! s:invoke_funcrefs(context, funcrefs) + let builder = airline#builder#new(a:context) + let err = airline#util#exec_funcrefs(a:funcrefs + s:core_funcrefs, builder, a:context) + if err == 1 + let a:context.line = builder.build() + let s:contexts[a:context.winnr] = a:context + call setwinvar(a:context.winnr, '&statusline', '%!airline#statusline('.a:context.winnr.')') + endif +endfunction + +" Main statusline function per window +" will be set to the statusline option +function! airline#statusline(winnr) + if has_key(s:contexts, a:winnr) + return '%{airline#check_mode('.a:winnr.')}'.s:contexts[a:winnr].line + endif + + " in rare circumstances this happens...see #276 + return '' +endfunction + +" Check if mode as changed +function! airline#check_mode(winnr) + if !has_key(s:contexts, a:winnr) + return '' + endif + let context = s:contexts[a:winnr] + + if get(w:, 'airline_active', 1) + let l:m = mode(1) + if l:m ==# "i" + let l:mode = ['insert'] + elseif l:m[0] ==# "i" + let l:mode = ['insert'] + elseif l:m ==# "Rv" + let l:mode =['replace'] + elseif l:m[0] ==# "R" + let l:mode = ['replace'] + elseif l:m[0] =~# '\v(v|V||s|S|)' + let l:mode = ['visual'] + elseif l:m ==# "t" + let l:mode = ['terminal'] + elseif l:m[0] ==# "c" + let l:mode = ['commandline'] + elseif l:m ==# "no" " does not work, most likely, Vim does not refresh the statusline in OP mode + let l:mode = ['normal'] + elseif l:m[0:1] ==# 'ni' + let l:mode = ['normal'] + let l:m = 'ni' + else + let l:mode = ['normal'] + endif + if index(['Rv', 'no', 'ni', 'ix', 'ic'], l:m) == -1 + let l:m = l:m[0] + endif + let w:airline_current_mode = get(g:airline_mode_map, l:m, l:m) + else + let l:mode = ['inactive'] + let w:airline_current_mode = get(g:airline_mode_map, '__') + endif + + if g:airline_detect_modified && &modified + call add(l:mode, 'modified') + endif + + if g:airline_detect_paste && &paste + call add(l:mode, 'paste') + endif + + if g:airline_detect_crypt && exists("+key") && !empty(&key) + call add(l:mode, 'crypt') + endif + + if g:airline_detect_spell && &spell + call add(l:mode, 'spell') + endif + + if &readonly || ! &modifiable + call add(l:mode, 'readonly') + endif + + let mode_string = join(l:mode) + if get(w:, 'airline_lastmode', '') != mode_string + call airline#highlighter#highlight_modified_inactive(context.bufnr) + call airline#highlighter#highlight(l:mode, context.bufnr) + call airline#util#doautocmd('AirlineModeChanged') + let w:airline_lastmode = mode_string + endif + + return '' +endfunction diff --git a/.vim/autoload/airline/async.vim b/.vim/autoload/airline/async.vim new file mode 100644 index 0000000..93bbfe7 --- /dev/null +++ b/.vim/autoload/airline/async.vim @@ -0,0 +1,259 @@ +" MIT License. Copyright (c) 2013-2018 C.Brabandt et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:untracked_jobs = {} +let s:mq_jobs = {} +let s:po_jobs = {} + +" Generic functions handling on exit event of the various async functions +function! s:untracked_output(dict, buf) + if a:buf =~? ('^'. a:dict.cfg['untracked_mark']) + let a:dict.cfg.untracked[a:dict.file] = get(g:, 'airline#extensions#branch#notexists', g:airline_symbols.notexists) + else + let a:dict.cfg.untracked[a:dict.file] = '' + endif +endfunction + +" also called from branch extension (for non-async vims) +function! airline#async#mq_output(buf, file) + let buf=a:buf + if !empty(a:buf) + if a:buf =~# 'no patches applied' || + \ a:buf =~# "unknown command 'qtop'" || + \ a:buf =~# "abort" + let buf = '' + elseif exists("b:mq") && b:mq isnot# buf + " make sure, statusline is updated + unlet! b:airline_head + endif + let b:mq = buf + endif + if has_key(s:mq_jobs, a:file) + call remove(s:mq_jobs, a:file) + endif +endfunction + +function! s:po_output(buf, file) + if !empty(a:buf) + let b:airline_po_stats = printf("%s", a:buf) + else + let b:airline_po_stats = '' + endif + if has_key(s:po_jobs, a:file) + call remove(s:po_jobs, a:file) + endif +endfunction + +function! s:valid_dir(dir) + if empty(a:dir) || !isdirectory(a:dir) + return getcwd() + endif + return a:dir +endfunction + +if v:version >= 800 && has("job") + " Vim 8.0 with Job feature + " TODO: Check if we need the cwd option for the job_start() functions + " (only works starting with Vim 8.0.0902) + + function! s:on_stdout(channel, msg) dict abort + let self.buf .= a:msg + endfunction + + function! s:on_exit_mq(channel) dict abort + call airline#async#mq_output(self.buf, self.file) + endfunction + + function! s:on_exit_untracked(channel) dict abort + call s:untracked_output(self, self.buf) + if has_key(s:untracked_jobs, self.file) + call remove(s:untracked_jobs, self.file) + endif + endfunction + + function! s:on_exit_po(channel) dict abort + call s:po_output(self.buf, self.file) + call airline#extensions#po#shorten() + endfunction + + function! airline#async#get_mq_async(cmd, file) + if g:airline#init#is_windows && &shell =~ 'cmd' + let cmd = a:cmd + else + let cmd = ['sh', '-c', a:cmd] + endif + + let options = {'cmd': a:cmd, 'buf': '', 'file': a:file} + if has_key(s:mq_jobs, a:file) + if job_status(get(s:mq_jobs, a:file)) == 'run' + return + elseif has_key(s:mq_jobs, a:file) + call remove(s:mq_jobs, a:file) + endif + endif + let id = job_start(cmd, { + \ 'err_io': 'out', + \ 'out_cb': function('s:on_stdout', options), + \ 'close_cb': function('s:on_exit_mq', options)}) + let s:mq_jobs[a:file] = id + endfunction + + function! airline#async#get_msgfmt_stat(cmd, file) + if g:airline#init#is_windows || !executable('msgfmt') + " no msgfmt on windows? + return + else + let cmd = ['sh', '-c', a:cmd. shellescape(a:file)] + endif + + let options = {'buf': '', 'file': a:file} + if has_key(s:po_jobs, a:file) + if job_status(get(s:po_jobs, a:file)) == 'run' + return + elseif has_key(s:po_jobs, a:file) + call remove(s:po_jobs, a:file) + endif + endif + let id = job_start(cmd, { + \ 'err_io': 'out', + \ 'out_cb': function('s:on_stdout', options), + \ 'close_cb': function('s:on_exit_po', options)}) + let s:po_jobs[a:file] = id + endfunction + + function! airline#async#vim_vcs_untracked(config, file) + if g:airline#init#is_windows && &shell =~ 'cmd' + let cmd = a:config['cmd'] . shellescape(a:file) + else + let cmd = ['sh', '-c', a:config['cmd'] . shellescape(a:file)] + endif + + let options = {'cfg': a:config, 'buf': '', 'file': a:file} + if has_key(s:untracked_jobs, a:file) + if job_status(get(s:untracked_jobs, a:file)) == 'run' + return + elseif has_key(s:untracked_jobs, a:file) + call remove(s:untracked_jobs, a:file) + endif + endif + let id = job_start(cmd, { + \ 'err_io': 'out', + \ 'out_cb': function('s:on_stdout', options), + \ 'close_cb': function('s:on_exit_untracked', options)}) + let s:untracked_jobs[a:file] = id + endfunction + +elseif has("nvim") + " NVim specific functions + + function! s:nvim_output_handler(job_id, data, event) dict + if a:event == 'stdout' || a:event == 'stderr' + let self.buf .= join(a:data) + endif + endfunction + + function! s:nvim_untracked_job_handler(job_id, data, event) dict + if a:event == 'exit' + call s:untracked_output(self, self.buf) + if has_key(s:untracked_jobs, self.file) + call remove(s:untracked_jobs, self.file) + endif + endif + endfunction + + function! s:nvim_mq_job_handler(job_id, data, event) dict + if a:event == 'exit' + call airline#async#mq_output(self.buf, self.file) + endif + endfunction + + function! s:nvim_po_job_handler(job_id, data, event) dict + if a:event == 'exit' + call s:po_output(self.buf, self.file) + call airline#extensions#po#shorten() + endif + endfunction + + function! airline#async#nvim_get_mq_async(cmd, file) + let config = { + \ 'buf': '', + \ 'file': a:file, + \ 'cwd': s:valid_dir(fnamemodify(a:file, ':p:h')), + \ 'on_stdout': function('s:nvim_output_handler'), + \ 'on_stderr': function('s:nvim_output_handler'), + \ 'on_exit': function('s:nvim_mq_job_handler') + \ } + if g:airline#init#is_windows && &shell =~ 'cmd' + let cmd = a:cmd + else + let cmd = ['sh', '-c', a:cmd] + endif + + if has_key(s:mq_jobs, a:file) + call remove(s:mq_jobs, a:file) + endif + let id = jobstart(cmd, config) + let s:mq_jobs[a:file] = id + endfunction + + function! airline#async#nvim_get_msgfmt_stat(cmd, file) + let config = { + \ 'buf': '', + \ 'file': a:file, + \ 'cwd': s:valid_dir(fnamemodify(a:file, ':p:h')), + \ 'on_stdout': function('s:nvim_output_handler'), + \ 'on_stderr': function('s:nvim_output_handler'), + \ 'on_exit': function('s:nvim_po_job_handler') + \ } + if g:airline#init#is_windows && &shell =~ 'cmd' + " no msgfmt on windows? + return + else + let cmd = ['sh', '-c', a:cmd. shellescape(a:file)] + endif + + if has_key(s:po_jobs, a:file) + call remove(s:po_jobs, a:file) + endif + let id = jobstart(cmd, config) + let s:po_jobs[a:file] = id + endfunction + +endif + +" Should work in either Vim pre 8 or Nvim +function! airline#async#nvim_vcs_untracked(cfg, file, vcs) + let cmd = a:cfg.cmd . shellescape(a:file) + let id = -1 + let config = { + \ 'buf': '', + \ 'vcs': a:vcs, + \ 'cfg': a:cfg, + \ 'file': a:file, + \ 'cwd': s:valid_dir(fnamemodify(a:file, ':p:h')) + \ } + if has("nvim") + call extend(config, { + \ 'on_stdout': function('s:nvim_output_handler'), + \ 'on_exit': function('s:nvim_untracked_job_handler')}) + if has_key(s:untracked_jobs, config.file) + " still running + return + endif + try + let id = jobstart(cmd, config) + catch + " catch-all, jobstart() failed, fall back to system() + let id=-1 + endtry + let s:untracked_jobs[a:file] = id + endif + " vim without job feature or nvim jobstart failed + if id < 1 + let output=system(cmd) + call s:untracked_output(config, output) + call airline#extensions#branch#update_untracked_config(a:file, a:vcs) + endif +endfunction diff --git a/.vim/autoload/airline/builder.vim b/.vim/autoload/airline/builder.vim new file mode 100644 index 0000000..b0352e3 --- /dev/null +++ b/.vim/autoload/airline/builder.vim @@ -0,0 +1,244 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:prototype = {} + +function! s:prototype.split(...) dict + call add(self._sections, ['|', a:0 ? a:1 : '%=']) +endfunction + +function! s:prototype.add_section_spaced(group, contents) dict + let spc = empty(a:contents) ? '' : g:airline_symbols.space + call self.add_section(a:group, spc.a:contents.spc) +endfunction + +function! s:prototype.add_section(group, contents) dict + call add(self._sections, [a:group, a:contents]) +endfunction + +function! s:prototype.add_raw(text) dict + call add(self._sections, ['', a:text]) +endfunction + +function! s:prototype.insert_section(group, contents, position) dict + call insert(self._sections, [a:group, a:contents], a:position) +endfunction + +function! s:prototype.insert_raw(text, position) dict + call insert(self._sections, ['', a:text], a:position) +endfunction + +function! s:prototype.get_position() dict + return len(self._sections) +endfunction + +function! airline#builder#get_prev_group(sections, i) + let x = a:i - 1 + while x >= 0 + let group = a:sections[x][0] + if group != '' && group != '|' + return group + endif + let x = x - 1 + endwhile + return '' +endfunction + +function! airline#builder#get_next_group(sections, i) + let x = a:i + 1 + let l = len(a:sections) + while x < l + let group = a:sections[x][0] + if group != '' && group != '|' + return group + endif + let x = x + 1 + endwhile + return '' +endfunction + +function! s:prototype.build() dict + let side = 1 + let line = '' + let i = 0 + let length = len(self._sections) + let split = 0 + let is_empty = 0 + let prev_group = '' + + while i < length + let section = self._sections[i] + let group = section[0] + let contents = section[1] + let pgroup = prev_group + let prev_group = airline#builder#get_prev_group(self._sections, i) + if group ==# 'airline_c' && &buftype ==# 'terminal' && self._context.active + let group = 'airline_term' + elseif group ==# 'airline_c' && !self._context.active && has_key(self._context, 'bufnr') + let group = 'airline_c'. self._context.bufnr + elseif prev_group ==# 'airline_c' && !self._context.active && has_key(self._context, 'bufnr') + let prev_group = 'airline_c'. self._context.bufnr + endif + if is_empty + let prev_group = pgroup + endif + let is_empty = s:section_is_empty(self, contents) + + if is_empty + " need to fix highlighting groups, since we + " have skipped a section, we actually need + " the previous previous group and so the + " seperator goes from the previous previous group + " to the current group + let pgroup = group + endif + + if group == '' + let line .= contents + elseif group == '|' + let side = 0 + let line .= contents + let split = 1 + else + if prev_group == '' + let line .= '%#'.group.'#' + elseif split + if !is_empty + let line .= s:get_transitioned_seperator(self, prev_group, group, side) + endif + let split = 0 + else + if !is_empty + let line .= s:get_seperator(self, prev_group, group, side) + endif + endif + let line .= is_empty ? '' : s:get_accented_line(self, group, contents) + endif + + let i = i + 1 + endwhile + + if !self._context.active + "let line = substitute(line, '%#airline_c#', '%#airline_c'.self._context.bufnr.'#', '') + let line = substitute(line, '%#.\{-}\ze#', '\0_inactive', 'g') + endif + return line +endfunction + +function! airline#builder#should_change_group(group1, group2) + if a:group1 == a:group2 + return 0 + endif + let color1 = airline#highlighter#get_highlight(a:group1) + let color2 = airline#highlighter#get_highlight(a:group2) + if g:airline_gui_mode ==# 'gui' + return color1[1] != color2[1] || color1[0] != color2[0] + else + return color1[3] != color2[3] || color1[2] != color2[2] + endif +endfunction + +function! s:get_transitioned_seperator(self, prev_group, group, side) + let line = '' + if get(a:self._context, 'tabline', 0) && get(g:, 'airline#extensions#tabline#alt_sep', 0) && a:group ==# 'airline_tabsel' && a:side + call airline#highlighter#add_separator(a:prev_group, a:group, 0) + let line .= '%#'.a:prev_group.'_to_'.a:group.'#' + let line .= a:self._context.right_sep.'%#'.a:group.'#' + else + call airline#highlighter#add_separator(a:prev_group, a:group, a:side) + let line .= '%#'.a:prev_group.'_to_'.a:group.'#' + let line .= a:side ? a:self._context.left_sep : a:self._context.right_sep + let line .= '%#'.a:group.'#' + endif + return line +endfunction + +function! s:get_seperator(self, prev_group, group, side) + if airline#builder#should_change_group(a:prev_group, a:group) + return s:get_transitioned_seperator(a:self, a:prev_group, a:group, a:side) + else + return a:side ? a:self._context.left_alt_sep : a:self._context.right_alt_sep + endif +endfunction + +function! s:get_accented_line(self, group, contents) + if a:self._context.active + " active window + let contents = [] + let content_parts = split(a:contents, '__accent') + for cpart in content_parts + let accent = matchstr(cpart, '_\zs[^#]*\ze') + call add(contents, cpart) + endfor + let line = join(contents, a:group) + let line = substitute(line, '__restore__', a:group, 'g') + else + " inactive window + let line = substitute(a:contents, '%#__accent[^#]*#', '', 'g') + let line = substitute(line, '%#__restore__#', '', 'g') + endif + return line +endfunction + +function! s:section_is_empty(self, content) + let start=1 + + " do not check for inactive windows or the tabline + if a:self._context.active == 0 + return 0 + elseif get(a:self._context, 'tabline', 0) + return 0 + endif + + " only check, if airline#skip_empty_sections == 1 + if get(g:, 'airline_skip_empty_sections', 0) == 0 + return 0 + endif + + " only check, if airline#skip_empty_sections == 1 + if get(w:, 'airline_skip_empty_sections', -1) == 0 + return 0 + endif + " assume accents sections to be never empty + " (avoides, that on startup the mode message becomes empty) + if match(a:content, '%#__accent_[^#]*#.*__restore__#') > -1 + return 0 + endif + if empty(a:content) + return 1 + endif + let list=matchlist(a:content, '%{\zs.\{-}\ze}', 1, start) + if empty(list) + return 0 " no function in statusline text + endif + while len(list) > 0 + let expr = list[0] + try + " catch all exceptions, just in case + if !empty(eval(expr)) + return 0 + endif + catch + return 0 + endtry + let start += 1 + let list=matchlist(a:content, '%{\zs.\{-}\ze}', 1, start) + endw + return 1 +endfunction + +function! airline#builder#new(context) + let builder = copy(s:prototype) + let builder._context = a:context + let builder._sections = [] + + call extend(builder._context, { + \ 'left_sep': g:airline_left_sep, + \ 'left_alt_sep': g:airline_left_alt_sep, + \ 'right_sep': g:airline_right_sep, + \ 'right_alt_sep': g:airline_right_alt_sep, + \ }, 'keep') + return builder +endfunction diff --git a/.vim/autoload/airline/debug.vim b/.vim/autoload/airline/debug.vim new file mode 100644 index 0000000..afa42af --- /dev/null +++ b/.vim/autoload/airline/debug.vim @@ -0,0 +1,51 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#debug#profile1() + profile start airline-profile-switch.log + profile func * + profile file * + split + for i in range(1, 1000) + wincmd w + redrawstatus + endfor + profile pause + noautocmd qall! +endfunction + +function! airline#debug#profile2() + profile start airline-profile-cursor.log + profile func * + profile file * + edit blank + call setline(1, 'all your base are belong to us') + call setline(2, 'all your base are belong to us') + let positions = [[1,2], [2,2], [1,2], [1,1]] + for i in range(1, 1000) + for pos in positions + call cursor(pos[0], pos[1]) + redrawstatus + endfor + endfor + profile pause + noautocmd qall! +endfunction + +function! airline#debug#profile3() + profile start airline-profile-mode.log + profile func * + profile file * + + for i in range(1000) + startinsert + redrawstatus + stopinsert + redrawstatus + endfor + + profile pause + noautocmd qall! +endfunction diff --git a/.vim/autoload/airline/extensions.vim b/.vim/autoload/airline/extensions.vim new file mode 100644 index 0000000..726e983 --- /dev/null +++ b/.vim/autoload/airline/extensions.vim @@ -0,0 +1,389 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:loaded_ext = [] +let s:ext = {} +let s:ext._theme_funcrefs = [] + +function! s:ext.add_statusline_func(name) dict + call airline#add_statusline_func(a:name) +endfunction +function! s:ext.add_statusline_funcref(function) dict + call airline#add_statusline_funcref(a:function) +endfunction +function! s:ext.add_inactive_statusline_func(name) dict + call airline#add_inactive_statusline_func(a:name) +endfunction +function! s:ext.add_theme_func(name) dict + call add(self._theme_funcrefs, function(a:name)) +endfunction + +let s:script_path = tolower(resolve(expand('<sfile>:p:h'))) + +let s:filetype_overrides = { + \ 'nerdtree': [ get(g:, 'NERDTreeStatusline', 'NERD'), '' ], + \ 'gundo': [ 'Gundo', '' ], + \ 'vimfiler': [ 'vimfiler', '%{vimfiler#get_status_string()}' ], + \ 'minibufexpl': [ 'MiniBufExplorer', '' ], + \ 'startify': [ 'startify', '' ], + \ 'vim-plug': [ 'Plugins', '' ], + \ } + +let s:filetype_regex_overrides = {} + +function! s:check_defined_section(name) + if !exists('w:airline_section_{a:name}') + let w:airline_section_{a:name} = g:airline_section_{a:name} + endif +endfunction + +function! airline#extensions#append_to_section(name, value) + call <sid>check_defined_section(a:name) + let w:airline_section_{a:name} .= a:value +endfunction + +function! airline#extensions#prepend_to_section(name, value) + call <sid>check_defined_section(a:name) + let w:airline_section_{a:name} = a:value . w:airline_section_{a:name} +endfunction + +function! airline#extensions#apply_left_override(section1, section2) + let w:airline_section_a = a:section1 + let w:airline_section_b = a:section2 + let w:airline_section_c = airline#section#create(['readonly']) + let w:airline_render_left = 1 + let w:airline_render_right = 0 +endfunction + +function! airline#extensions#apply(...) + + if s:is_excluded_window() + return -1 + endif + + if &buftype == 'help' + call airline#extensions#apply_left_override('Help', '%f') + let w:airline_section_x = '' + let w:airline_section_y = '' + let w:airline_render_right = 1 + endif + + if &buftype == 'terminal' + let w:airline_section_x = '' + let w:airline_section_y = '' + endif + + if &previewwindow + let w:airline_section_a = 'Preview' + let w:airline_section_b = '' + let w:airline_section_c = bufname(winbufnr(winnr())) + endif + + if has_key(s:filetype_overrides, &ft) + let args = s:filetype_overrides[&ft] + call airline#extensions#apply_left_override(args[0], args[1]) + endif + + for item in items(s:filetype_regex_overrides) + if match(&ft, item[0]) >= 0 + call airline#extensions#apply_left_override(item[1][0], item[1][1]) + endif + endfor +endfunction + +function! s:is_excluded_window() + for matchft in g:airline_exclude_filetypes + if matchft ==# &ft + return 1 + endif + endfor + + for matchw in g:airline_exclude_filenames + if matchstr(expand('%'), matchw) ==# matchw + return 1 + endif + endfor + + if g:airline_exclude_preview && &previewwindow + return 1 + endif + + return 0 +endfunction + +function! airline#extensions#load_theme() + call airline#util#exec_funcrefs(s:ext._theme_funcrefs, g:airline#themes#{g:airline_theme}#palette) +endfunction + +function! airline#extensions#load() + let s:loaded_ext = [] + + if exists('g:airline_extensions') + for ext in g:airline_extensions + try + call airline#extensions#{ext}#init(s:ext) + catch /^Vim\%((\a\+)\)\=:E117/ " E117, function does not exist + call airline#util#warning("Extension '".ext."' not installed, ignoring!") + endtry + endfor + return + endif + + call airline#extensions#quickfix#init(s:ext) + call add(s:loaded_ext, 'quickfix') + + if get(g:, 'loaded_unite', 0) + call airline#extensions#unite#init(s:ext) + call add(s:loaded_ext, 'unite') + endif + + if get(g:, 'loaded_denite', 0) + call airline#extensions#denite#init(s:ext) + call add(s:loaded_ext, 'denite') + endif + + if exists(':NetrwSettings') + call airline#extensions#netrw#init(s:ext) + call add(s:loaded_ext, 'netrw') + endif + + if has("terminal") || has('nvim') + call airline#extensions#term#init(s:ext) + call add(s:loaded_ext, 'term') + endif + + if get(g:, 'airline#extensions#ycm#enabled', 0) + call airline#extensions#ycm#init(s:ext) + call add(s:loaded_ext, 'ycm') + endif + + if get(g:, 'loaded_vimfiler', 0) + let g:vimfiler_force_overwrite_statusline = 0 + endif + + if get(g:, 'loaded_ctrlp', 0) + call airline#extensions#ctrlp#init(s:ext) + call add(s:loaded_ext, 'ctrlp') + endif + + if get(g:, 'loaded_localsearch', 0) + call airline#extensions#localsearch#init(s:ext) + call add(s:loaded_ext, 'localsearch') + endif + + if get(g:, 'CtrlSpaceLoaded', 0) + call airline#extensions#ctrlspace#init(s:ext) + call add(s:loaded_ext, 'ctrlspace') + endif + + if get(g:, 'command_t_loaded', 0) + call airline#extensions#commandt#init(s:ext) + call add(s:loaded_ext, 'commandt') + endif + + if exists(':UndotreeToggle') + call airline#extensions#undotree#init(s:ext) + call add(s:loaded_ext, 'undotree') + endif + + if get(g:, 'airline#extensions#hunks#enabled', 1) + \ && (exists('g:loaded_signify') || exists('g:loaded_gitgutter') || exists('g:loaded_changes') || exists('g:loaded_quickfixsigns')) + call airline#extensions#hunks#init(s:ext) + call add(s:loaded_ext, 'hunks') + endif + + if get(g:, 'airline#extensions#vimagit#enabled', 1) + \ && (exists('g:loaded_magit')) + call airline#extensions#vimagit#init(s:ext) + call add(s:loaded_ext, 'vimagit') + endif + + if get(g:, 'airline#extensions#tagbar#enabled', 1) + \ && exists(':TagbarToggle') + call airline#extensions#tagbar#init(s:ext) + call add(s:loaded_ext, 'tagbar') + endif + + if get(g:, 'airline#extensions#csv#enabled', 1) + \ && (get(g:, 'loaded_csv', 0) || exists(':Table')) + call airline#extensions#csv#init(s:ext) + call add(s:loaded_ext, 'csv') + endif + + if exists(':VimShell') + let s:filetype_overrides['vimshell'] = ['vimshell','%{vimshell#get_status_string()}'] + let s:filetype_regex_overrides['^int-'] = ['vimshell','%{substitute(&ft, "int-", "", "")}'] + endif + + if exists(':Defx') + let s:filetype_overrides['defx'] = ['defx', '%{b:defx.paths[0]}'] + endif + + if get(g:, 'airline#extensions#branch#enabled', 1) && ( + \ airline#util#has_fugitive() || + \ airline#util#has_lawrencium() || + \ airline#util#has_vcscommand() || + \ airline#util#has_custom_scm()) + call airline#extensions#branch#init(s:ext) + call add(s:loaded_ext, 'branch') + endif + + if get(g:, 'airline#extensions#bufferline#enabled', 1) + \ && exists('*bufferline#get_status_string') + call airline#extensions#bufferline#init(s:ext) + call add(s:loaded_ext, 'bufferline') + endif + + if get(g:, 'airline#extensions#fugitiveline#enabled', 1) + \ && airline#util#has_fugitive() + \ && index(s:loaded_ext, 'bufferline') == -1 + call airline#extensions#fugitiveline#init(s:ext) + call add(s:loaded_ext, 'fugitiveline') + endif + + if (get(g:, 'airline#extensions#virtualenv#enabled', 1) && (exists(':VirtualEnvList') || isdirectory($VIRTUAL_ENV))) + call airline#extensions#virtualenv#init(s:ext) + call add(s:loaded_ext, 'virtualenv') + endif + + if (get(g:, 'airline#extensions#eclim#enabled', 1) && exists(':ProjectCreate')) + call airline#extensions#eclim#init(s:ext) + call add(s:loaded_ext, 'eclim') + endif + + if get(g:, 'airline#extensions#syntastic#enabled', 1) + \ && exists(':SyntasticCheck') + call airline#extensions#syntastic#init(s:ext) + call add(s:loaded_ext, 'syntastic') + endif + + if (get(g:, 'airline#extensions#ale#enabled', 1) && exists(':ALELint')) + call airline#extensions#ale#init(s:ext) + call add(s:loaded_ext, 'ale') + endif + + if (get(g:, 'airline#extensions#languageclient#enabled', 1) && exists(':LanguageClientStart')) + call airline#extensions#languageclient#init(s:ext) + call add(s:loaded_ext, 'languageclient') + endif + + if get(g:, 'airline#extensions#whitespace#enabled', 1) + call airline#extensions#whitespace#init(s:ext) + call add(s:loaded_ext, 'whitespace') + endif + + if (get(g:, 'airline#extensions#neomake#enabled', 1) && exists(':Neomake')) + call airline#extensions#neomake#init(s:ext) + call add(s:loaded_ext, 'neomake') + endif + + if get(g:, 'airline#extensions#po#enabled', 1) && executable('msgfmt') + call airline#extensions#po#init(s:ext) + call add(s:loaded_ext, 'po') + endif + + if get(g:, 'airline#extensions#wordcount#enabled', 1) + call airline#extensions#wordcount#init(s:ext) + call add(s:loaded_ext, 'wordcount') + endif + + if get(g:, 'airline#extensions#tabline#enabled', 0) + call airline#extensions#tabline#init(s:ext) + call add(s:loaded_ext, 'tabline') + endif + + if get(g:, 'airline#extensions#tmuxline#enabled', 1) && exists(':Tmuxline') + call airline#extensions#tmuxline#init(s:ext) + call add(s:loaded_ext, 'tmuxline') + endif + + if get(g:, 'airline#extensions#promptline#enabled', 1) && exists(':PromptlineSnapshot') && len(get(g:, 'airline#extensions#promptline#snapshot_file', '')) + call airline#extensions#promptline#init(s:ext) + call add(s:loaded_ext, 'promptline') + endif + + if get(g:, 'airline#extensions#nrrwrgn#enabled', 1) && exists(':NR') == 2 + call airline#extensions#nrrwrgn#init(s:ext) + call add(s:loaded_ext, 'nrrwrgn') + endif + + if get(g:, 'airline#extensions#unicode#enabled', 1) && exists(':UnicodeTable') == 2 + call airline#extensions#unicode#init(s:ext) + call add(s:loaded_ext, 'unicode') + endif + + if (get(g:, 'airline#extensions#capslock#enabled', 1) && exists('*CapsLockStatusline')) + call airline#extensions#capslock#init(s:ext) + call add(s:loaded_ext, 'capslock') + endif + + if (get(g:, 'airline#extensions#gutentags#enabled', 1) && get(g:, 'loaded_gutentags', 0)) + call airline#extensions#gutentags#init(s:ext) + call add(s:loaded_ext, 'gutentags') + endif + + if (get(g:, 'airline#extensions#grepper#enabled', 1) && get(g:, 'loaded_grepper', 0)) + call airline#extensions#grepper#init(s:ext) + call add(s:loaded_ext, 'grepper') + endif + + if (get(g:, 'airline#extensions#xkblayout#enabled', 1) && exists('g:XkbSwitchLib')) + call airline#extensions#xkblayout#init(s:ext) + call add(s:loaded_ext, 'xkblayout') + endif + + if (get(g:, 'airline#extensions#keymap#enabled', 1) && has('keymap')) + call airline#extensions#keymap#init(s:ext) + call add(s:loaded_ext, 'keymap') + endif + + if (get(g:, 'airline#extensions#windowswap#enabled', 1) && get(g:, 'loaded_windowswap', 0)) + call airline#extensions#windowswap#init(s:ext) + call add(s:loaded_ext, 'windowswap') + endif + + if (get(g:, 'airline#extensions#obsession#enabled', 1) && exists('*ObsessionStatus')) + call airline#extensions#obsession#init(s:ext) + call add(s:loaded_ext, 'obsession') + endif + + if get(g:, 'airline#extensions#vimtex#enabled', 1) + runtime autoload/vimtex.vim + if exists('*vimtex#init') + call airline#extensions#vimtex#init(s:ext) + call add(s:loaded_ext, 'vimtex') + endif + endif + + if (get(g:, 'airline#extensions#cursormode#enabled', 0)) + call airline#extensions#cursormode#init(s:ext) + call add(s:loaded_ext, 'cursormode') + endif + + if !get(g:, 'airline#extensions#disable_rtp_load', 0) + " load all other extensions, which are not part of the default distribution. + " (autoload/airline/extensions/*.vim outside of our s:script_path). + for file in split(globpath(&rtp, "autoload/airline/extensions/*.vim"), "\n") + " we have to check both resolved and unresolved paths, since it's possible + " that they might not get resolved properly (see #187) + if stridx(tolower(resolve(fnamemodify(file, ':p'))), s:script_path) < 0 + \ && stridx(tolower(fnamemodify(file, ':p')), s:script_path) < 0 + let name = fnamemodify(file, ':t:r') + if !get(g:, 'airline#extensions#'.name.'#enabled', 1) || + \ index(s:loaded_ext, name) > -1 + continue + endif + try + call airline#extensions#{name}#init(s:ext) + catch + endtry + endif + endfor + endif +endfunction + +function! airline#extensions#get_loaded_extensions() + return s:loaded_ext +endfunction diff --git a/.vim/autoload/airline/extensions/ale.vim b/.vim/autoload/airline/extensions/ale.vim new file mode 100644 index 0000000..71f6317 --- /dev/null +++ b/.vim/autoload/airline/extensions/ale.vim @@ -0,0 +1,88 @@ +" MIT License. Copyright (c) 2013-2018 Bjorn Neergaard, w0rp et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! s:airline_ale_count(cnt, symbol) + return a:cnt ? a:symbol. a:cnt : '' +endfunction + +function! s:airline_ale_get_line_number(cnt, type) abort + if a:cnt == 0 + return '' + endif + + let buffer = bufnr('') + let problem_type = (a:type ==# 'error') ? 'E' : 'W' + let problems = copy(ale#engine#GetLoclist(buffer)) + + call filter(problems, 'v:val.bufnr is buffer && v:val.type is# problem_type') + + if empty(problems) + return '' + endif + + let open_lnum_symbol = get(g:, 'airline#extensions#ale#open_lnum_symbol', '(L') + let close_lnum_symbol = get(g:, 'airline#extensions#ale#close_lnum_symbol', ')') + + return open_lnum_symbol . problems[0].lnum . close_lnum_symbol +endfunction + +function! airline#extensions#ale#get(type) + if !exists(':ALELint') + return '' + endif + + let error_symbol = get(g:, 'airline#extensions#ale#error_symbol', 'E:') + let warning_symbol = get(g:, 'airline#extensions#ale#warning_symbol', 'W:') + let checking_symbol = get(g:, 'airline#extensions#ale#checking_symbol', '...') + let show_line_numbers = get(g:, 'airline#extensions#ale#show_line_numbers', 1) + + let is_err = a:type ==# 'error' + + if ale#engine#IsCheckingBuffer(bufnr('')) == 1 + return is_err ? '' : checking_symbol + endif + + let symbol = is_err ? error_symbol : warning_symbol + + let counts = ale#statusline#Count(bufnr('')) + if type(counts) == type({}) && has_key(counts, 'error') + " Use the current Dictionary format. + let errors = counts.error + counts.style_error + let num = is_err ? errors : counts.total - errors + else + " Use the old List format. + let num = is_err ? counts[0] : counts[1] + endif + + if show_line_numbers == 1 + return s:airline_ale_count(num, symbol) . <sid>airline_ale_get_line_number(num, a:type) + else + return s:airline_ale_count(num, symbol) + endif +endfunction + +function! airline#extensions#ale#get_warning() + return airline#extensions#ale#get('warning') +endfunction + +function! airline#extensions#ale#get_error() + return airline#extensions#ale#get('error') +endfunction + +function! airline#extensions#ale#init(ext) + call airline#parts#define_function('ale_error_count', 'airline#extensions#ale#get_error') + call airline#parts#define_function('ale_warning_count', 'airline#extensions#ale#get_warning') + augroup airline_ale + autocmd! + autocmd CursorHold,BufWritePost * call <sid>ale_refresh() + autocmd User ALEJobStarted,ALELintPost call <sid>ale_refresh() + augroup END +endfunction + +function! s:ale_refresh() + if get(g:, 'airline_skip_empty_sections', 0) + exe ':AirlineRefresh' + endif +endfunction diff --git a/.vim/autoload/airline/extensions/branch.vim b/.vim/autoload/airline/extensions/branch.vim new file mode 100644 index 0000000..fcf4d3a --- /dev/null +++ b/.vim/autoload/airline/extensions/branch.vim @@ -0,0 +1,312 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +" s:vcs_config contains static configuration of VCSes and their status relative +" to the active file. +" 'branch' - The name of currently active branch. This field is empty iff it +" has not been initialized yet or the current file is not in +" an active branch. +" 'untracked' - Cache of untracked files represented as a dictionary with files +" as keys. A file has a not exists symbol set as its value if it +" is untracked. A file is present in this dictionary iff its +" status is considered up to date. +" 'untracked_mark' - used as regexp to test against the output of 'cmd' +let s:vcs_config = { +\ 'git': { +\ 'exe': 'git', +\ 'cmd': 'git status --porcelain -- ', +\ 'untracked_mark': '??', +\ 'exclude': '\.git', +\ 'update_branch': 's:update_git_branch', +\ 'display_branch': 's:display_git_branch', +\ 'branch': '', +\ 'untracked': {}, +\ }, +\ 'mercurial': { +\ 'exe': 'hg', +\ 'cmd': 'hg status -u -- ', +\ 'untracked_mark': '?', +\ 'exclude': '\.hg', +\ 'update_branch': 's:update_hg_branch', +\ 'display_branch': 's:display_hg_branch', +\ 'branch': '', +\ 'untracked': {}, +\ }, +\} + +" Initializes b:buffer_vcs_config. b:buffer_vcs_config caches the branch and +" untracked status of the file in the buffer. Caching those fields is necessary, +" because s:vcs_config may be updated asynchronously and s:vcs_config fields may +" be invalid during those updates. b:buffer_vcs_config fields are updated +" whenever corresponding fields in s:vcs_config are updated or an inconsistency +" is detected during update_* operation. +" +" b:airline_head caches the head string it is empty iff it needs to be +" recalculated. b:airline_head is recalculated based on b:buffer_vcs_config. +function! s:init_buffer() + let b:buffer_vcs_config = {} + for vcs in keys(s:vcs_config) + let b:buffer_vcs_config[vcs] = { + \ 'branch': '', + \ 'untracked': '', + \ } + endfor + unlet! b:airline_head +endfunction + +let s:head_format = get(g:, 'airline#extensions#branch#format', 0) +if s:head_format == 1 + function! s:format_name(name) + return fnamemodify(a:name, ':t') + endfunction +elseif s:head_format == 2 + function! s:format_name(name) + return pathshorten(a:name) + endfunction +elseif type(s:head_format) == type('') + function! s:format_name(name) + return call(s:head_format, [a:name]) + endfunction +else + function! s:format_name(name) + return a:name + endfunction +endif + + +" Fugitive special revisions. call '0' "staging" ? +let s:names = {'0': 'index', '1': 'orig', '2':'fetch', '3':'merge'} +let s:sha1size = get(g:, 'airline#extensions#branch#sha1_len', 7) + +function! s:update_git_branch() + if !airline#util#has_fugitive() + let s:vcs_config['git'].branch = '' + return + endif + + let s:vcs_config['git'].branch = exists("*FugitiveHead") ? + \ FugitiveHead(s:sha1size) : fugitive#head(s:sha1size) + if s:vcs_config['git'].branch is# 'master' && winwidth(0) < 81 + " Shorten default a bit + let s:vcs_config['git'].branch='mas' + endif +endfunction + +function! s:display_git_branch() + let name = b:buffer_vcs_config['git'].branch + try + let commit = fugitive#buffer().commit() + + if has_key(s:names, commit) + let name = get(s:names, commit)."(".name.")" + elseif !empty(commit) + let ref = fugitive#repo().git_chomp('describe', '--all', '--exact-match', commit) + if ref !~ "^fatal: no tag exactly matches" + let name = s:format_name(substitute(ref, '\v\C^%(heads/|remotes/|tags/)=','',''))."(".name.")" + else + let name = matchstr(commit, '.\{'.s:sha1size.'}')."(".name.")" + endif + endif + catch + endtry + + return name +endfunction + +function! s:update_hg_branch() + if airline#util#has_lawrencium() + let cmd='LC_ALL=C hg qtop' + let stl=lawrencium#statusline() + let file=expand('%:p') + if !empty(stl) && get(b:, 'airline_do_mq_check', 1) + if g:airline#init#vim_async + noa call airline#async#get_mq_async(cmd, file) + elseif has("nvim") + noa call airline#async#nvim_get_mq_async(cmd, file) + else + " remove \n at the end of the command + let output=system(cmd)[0:-2] + noa call airline#async#mq_output(output, file) + endif + endif + " do not do mq check anymore + let b:airline_do_mq_check = 0 + if exists("b:mq") && !empty(b:mq) + if stl is# 'default' + " Shorten default a bit + let stl='def' + endif + let stl.=' ['.b:mq.']' + endif + let s:vcs_config['mercurial'].branch = stl + else + let s:vcs_config['mercurial'].branch = '' + endif +endfunction + +function! s:display_hg_branch() + return b:buffer_vcs_config['mercurial'].branch +endfunction + +function! s:update_branch() + for vcs in keys(s:vcs_config) + call {s:vcs_config[vcs].update_branch}() + if b:buffer_vcs_config[vcs].branch != s:vcs_config[vcs].branch + let b:buffer_vcs_config[vcs].branch = s:vcs_config[vcs].branch + unlet! b:airline_head + endif + endfor +endfunction + +function! airline#extensions#branch#update_untracked_config(file, vcs) + if !has_key(s:vcs_config[a:vcs].untracked, a:file) + return + elseif s:vcs_config[a:vcs].untracked[a:file] != b:buffer_vcs_config[a:vcs].untracked + let b:buffer_vcs_config[a:vcs].untracked = s:vcs_config[a:vcs].untracked[a:file] + unlet! b:airline_head + endif +endfunction + +function! s:update_untracked() + let file = expand("%:p") + if empty(file) || isdirectory(file) + return + endif + + let needs_update = 1 + for vcs in keys(s:vcs_config) + if file =~ s:vcs_config[vcs].exclude + " Skip check for files that live in the exclude directory + let needs_update = 0 + endif + if has_key(s:vcs_config[vcs].untracked, file) + let needs_update = 0 + call airline#extensions#branch#update_untracked_config(file, vcs) + endif + endfor + + if !needs_update + return + endif + + for vcs in keys(s:vcs_config) + let config = s:vcs_config[vcs] + if g:airline#init#vim_async + " Note that asynchronous update updates s:vcs_config only, and only + " s:update_untracked updates b:buffer_vcs_config. If s:vcs_config is + " invalidated again before s:update_untracked is called, then we lose the + " result of the previous call, i.e. the head string is not updated. It + " doesn't happen often in practice, so we let it be. + noa call airline#async#vim_vcs_untracked(config, file) + else + " nvim async or vim without job-feature + noa call airline#async#nvim_vcs_untracked(config, file, vcs) + endif + endfor +endfunction + +function! airline#extensions#branch#head() + if !exists('b:buffer_vcs_config') + call s:init_buffer() + endif + + call s:update_branch() + call s:update_untracked() + + if exists('b:airline_head') && !empty(b:airline_head) + return b:airline_head + endif + + let b:airline_head = '' + let vcs_priority = get(g:, "airline#extensions#branch#vcs_priority", ["git", "mercurial"]) + + let heads = [] + for vcs in vcs_priority + if !empty(b:buffer_vcs_config[vcs].branch) + let heads += [vcs] + endif + endfor + + for vcs in heads + if !empty(b:airline_head) + let b:airline_head .= ' | ' + endif + if len(heads) > 1 + let b:airline_head .= s:vcs_config[vcs].exe .':' + endif + let b:airline_head .= s:format_name({s:vcs_config[vcs].display_branch}()) + let b:airline_head .= b:buffer_vcs_config[vcs].untracked + endfor + + if empty(heads) + if airline#util#has_vcscommand() + noa call VCSCommandEnableBufferSetup() + if exists('b:VCSCommandBufferInfo') + let b:airline_head = s:format_name(get(b:VCSCommandBufferInfo, 0, '')) + endif + endif + endif + + if empty(heads) + if airline#util#has_custom_scm() + try + let Fn = function(g:airline#extensions#branch#custom_head) + let b:airline_head = Fn() + endtry + endif + endif + + if exists("g:airline#extensions#branch#displayed_head_limit") + let w:displayed_head_limit = g:airline#extensions#branch#displayed_head_limit + if len(b:airline_head) > w:displayed_head_limit - 1 + let b:airline_head = b:airline_head[0:(w:displayed_head_limit - 1)].(&encoding ==? 'utf-8' ? '…' : '.') + endif + endif + + let minwidth = empty(get(b:, 'airline_hunks', '')) ? 14 : 7 + let b:airline_head = airline#util#shorten(b:airline_head, 120, minwidth) + return b:airline_head +endfunction + +function! airline#extensions#branch#get_head() + let head = airline#extensions#branch#head() + let empty_message = get(g:, 'airline#extensions#branch#empty_message', '') + let symbol = get(g:, 'airline#extensions#branch#symbol', g:airline_symbols.branch) + return empty(head) + \ ? empty_message + \ : printf('%s%s', empty(symbol) ? '' : symbol.(g:airline_symbols.space), head) +endfunction + +function! s:reset_untracked_cache(shellcmdpost) + " shellcmdpost - whether function was called as a result of ShellCmdPost hook + if !g:airline#init#vim_async && !has('nvim') + if a:shellcmdpost + " Clear cache only if there was no error or the script uses an + " asynchronous interface. Otherwise, cache clearing would overwrite + " v:shell_error with a system() call inside get_*_untracked. + if v:shell_error + return + endif + endif + endif + + let file = expand("%:p") + for vcs in keys(s:vcs_config) + " Dump the value of the cache for the current file. Partially mitigates the + " issue of cache invalidation happening before a call to + " s:update_untracked() + call airline#extensions#branch#update_untracked_config(file, vcs) + let s:vcs_config[vcs].untracked = {} + endfor +endfunction + +function! airline#extensions#branch#init(ext) + call airline#parts#define_function('branch', 'airline#extensions#branch#get_head') + + autocmd ShellCmdPost,CmdwinLeave * unlet! b:airline_head b:airline_do_mq_check + autocmd User AirlineBeforeRefresh unlet! b:airline_head b:airline_do_mq_check + autocmd BufWritePost * call s:reset_untracked_cache(0) + autocmd ShellCmdPost * call s:reset_untracked_cache(1) +endfunction diff --git a/.vim/autoload/airline/extensions/bufferline.vim b/.vim/autoload/airline/extensions/bufferline.vim new file mode 100644 index 0000000..b7ccc09 --- /dev/null +++ b/.vim/autoload/airline/extensions/bufferline.vim @@ -0,0 +1,29 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists('*bufferline#get_status_string') + finish +endif + +let s:overwrite = get(g:, 'airline#extensions#bufferline#overwrite_variables', 1) + +function! airline#extensions#bufferline#init(ext) + if s:overwrite + highlight bufferline_selected gui=bold cterm=bold term=bold + highlight link bufferline_selected_inactive airline_c_inactive + let g:bufferline_inactive_highlight = 'airline_c' + let g:bufferline_active_highlight = 'bufferline_selected' + let g:bufferline_active_buffer_left = '' + let g:bufferline_active_buffer_right = '' + let g:bufferline_separator = g:airline_symbols.space + endif + + if exists("+autochdir") && &autochdir == 1 + " if 'acd' is set, vim-airline uses the path section, so we need ot redefine this here as well + call airline#parts#define_raw('path', '%{bufferline#refresh_status()}'.bufferline#get_status_string()) + else + call airline#parts#define_raw('file', '%{bufferline#refresh_status()}'.bufferline#get_status_string()) + endif +endfunction diff --git a/.vim/autoload/airline/extensions/capslock.vim b/.vim/autoload/airline/extensions/capslock.vim new file mode 100644 index 0000000..55b28da --- /dev/null +++ b/.vim/autoload/airline/extensions/capslock.vim @@ -0,0 +1,16 @@ +" MIT License. Copyright (c) 2014-2018 Mathias Andersson et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists('*CapsLockStatusline') + finish +endif + +function! airline#extensions#capslock#status() + return tolower(CapsLockStatusline()) == '[caps]' ? 'CAPS' : '' +endfunction + +function! airline#extensions#capslock#init(ext) + call airline#parts#define_function('capslock', 'airline#extensions#capslock#status') +endfunction diff --git a/.vim/autoload/airline/extensions/commandt.vim b/.vim/autoload/airline/extensions/commandt.vim new file mode 100644 index 0000000..1e05a58 --- /dev/null +++ b/.vim/autoload/airline/extensions/commandt.vim @@ -0,0 +1,18 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'command_t_loaded', 0) + finish +endif + +function! airline#extensions#commandt#apply(...) + if bufname('%') ==# 'GoToFile' + call airline#extensions#apply_left_override('CommandT', '') + endif +endfunction + +function! airline#extensions#commandt#init(ext) + call a:ext.add_statusline_func('airline#extensions#commandt#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/csv.vim b/.vim/autoload/airline/extensions/csv.vim new file mode 100644 index 0000000..d0eb64b --- /dev/null +++ b/.vim/autoload/airline/extensions/csv.vim @@ -0,0 +1,32 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_csv', 0) && !exists(':Table') + finish +endif + +let s:column_display = get(g:, 'airline#extensions#csv#column_display', 'Number') + +function! airline#extensions#csv#get_column() + if exists('*CSV_WCol') + if s:column_display ==# 'Name' + return '['.CSV_WCol('Name').CSV_WCol().']' + else + return '['.CSV_WCol().']' + endif + endif + return '' +endfunction + +function! airline#extensions#csv#apply(...) + if &ft ==# "csv" + call airline#extensions#prepend_to_section('gutter', + \ g:airline_left_alt_sep.' %{airline#extensions#csv#get_column()}') + endif +endfunction + +function! airline#extensions#csv#init(ext) + call a:ext.add_statusline_func('airline#extensions#csv#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/ctrlp.vim b/.vim/autoload/airline/extensions/ctrlp.vim new file mode 100644 index 0000000..c477a6a --- /dev/null +++ b/.vim/autoload/airline/extensions/ctrlp.vim @@ -0,0 +1,81 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_ctrlp', 0) + finish +endif + +let s:color_template = get(g:, 'airline#extensions#ctrlp#color_template', 'insert') + +function! airline#extensions#ctrlp#generate_color_map(dark, light, white) + return { + \ 'CtrlPdark' : a:dark, + \ 'CtrlPlight' : a:light, + \ 'CtrlPwhite' : a:white, + \ 'CtrlParrow1' : [ a:light[1] , a:white[1] , a:light[3] , a:white[3] , '' ] , + \ 'CtrlParrow2' : [ a:white[1] , a:light[1] , a:white[3] , a:light[3] , '' ] , + \ 'CtrlParrow3' : [ a:light[1] , a:dark[1] , a:light[3] , a:dark[3] , '' ] , + \ } +endfunction + +function! airline#extensions#ctrlp#load_theme(palette) + if exists('a:palette.ctrlp') + let theme = a:palette.ctrlp + else + let s:color_template = has_key(a:palette, s:color_template) ? s:color_template : 'insert' + let theme = airline#extensions#ctrlp#generate_color_map( + \ a:palette[s:color_template]['airline_c'], + \ a:palette[s:color_template]['airline_b'], + \ a:palette[s:color_template]['airline_a']) + endif + for key in keys(theme) + call airline#highlighter#exec(key, theme[key]) + endfor +endfunction + +" Arguments: focus, byfname, regexp, prv, item, nxt, marked +function! airline#extensions#ctrlp#ctrlp_airline(...) + let b = airline#builder#new({'active': 1}) + if a:2 == 'file' + call b.add_section_spaced('CtrlPlight', 'by fname') + endif + if a:3 + call b.add_section_spaced('CtrlPlight', 'regex') + endif + if get(g:, 'airline#extensions#ctrlp#show_adjacent_modes', 1) + call b.add_section_spaced('CtrlPlight', a:4) + call b.add_section_spaced('CtrlPwhite', a:5) + call b.add_section_spaced('CtrlPlight', a:6) + else + call b.add_section_spaced('CtrlPwhite', a:5) + endif + call b.add_section_spaced('CtrlPdark', a:7) + call b.split() + call b.add_section_spaced('CtrlPdark', a:1) + call b.add_section_spaced('CtrlPdark', a:2) + call b.add_section_spaced('CtrlPlight', '%{getcwd()}') + return b.build() +endfunction + +" Argument: len +function! airline#extensions#ctrlp#ctrlp_airline_status(...) + let len = '%#CtrlPdark# '.a:1 + let dir = '%=%<%#CtrlParrow3#'.g:airline_right_sep.'%#CtrlPlight# '.getcwd().' %*' + return len.dir +endfunction + +function! airline#extensions#ctrlp#apply(...) + " disable statusline overwrite if ctrlp already did it + return match(&statusline, 'CtrlPwhite') >= 0 ? -1 : 0 +endfunction + +function! airline#extensions#ctrlp#init(ext) + let g:ctrlp_status_func = { + \ 'main': 'airline#extensions#ctrlp#ctrlp_airline', + \ 'prog': 'airline#extensions#ctrlp#ctrlp_airline_status', + \ } + call a:ext.add_statusline_func('airline#extensions#ctrlp#apply') + call a:ext.add_theme_func('airline#extensions#ctrlp#load_theme') +endfunction diff --git a/.vim/autoload/airline/extensions/ctrlspace.vim b/.vim/autoload/airline/extensions/ctrlspace.vim new file mode 100644 index 0000000..66f29a5 --- /dev/null +++ b/.vim/autoload/airline/extensions/ctrlspace.vim @@ -0,0 +1,20 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:spc = g:airline_symbols.space +let s:padding = s:spc . s:spc . s:spc +let s:cs = ctrlspace#context#Configuration().Symbols.CS + +function! airline#extensions#ctrlspace#statusline(...) + let b = airline#builder#new({ 'active': 1 }) + call b.add_section('airline_b', s:cs . s:padding . ctrlspace#api#StatuslineModeSegment(s:padding)) + call b.split() + call b.add_section('airline_x', s:spc . ctrlspace#api#StatuslineTabSegment() . s:spc) + return b.build() +endfunction + +function! airline#extensions#ctrlspace#init(ext) + let g:CtrlSpaceStatuslineFunction = "airline#extensions#ctrlspace#statusline()" +endfunction diff --git a/.vim/autoload/airline/extensions/cursormode.vim b/.vim/autoload/airline/extensions/cursormode.vim new file mode 100644 index 0000000..097ddd8 --- /dev/null +++ b/.vim/autoload/airline/extensions/cursormode.vim @@ -0,0 +1,132 @@ +" Copyright (C) 2014 Andrea Cedraro <a.cedraro@gmail.com> +" Copyright (C) 2017 Eduardo Suarez-Santana <e.suarezsantana@gmail.com> +" +" 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. + +scriptencoding utf-8 + +let s:is_win = has('win32') || has('win64') +let s:is_iTerm = exists('$TERM_PROGRAM') && $TERM_PROGRAM =~# 'iTerm.app' +let s:is_AppleTerminal = exists('$TERM_PROGRAM') && $TERM_PROGRAM =~# 'Apple_Terminal' + +let s:is_good = !has('gui_running') && !s:is_win && !s:is_AppleTerminal + +let s:last_mode = '' + +if !exists('g:cursormode_exit_mode') + let g:cursormode_exit_mode='n' +endif + +function! airline#extensions#cursormode#tmux_escape(escape) + return '\033Ptmux;'.substitute(a:escape, '\\033', '\\033\\033', 'g').'\033\\' +endfunction + +let s:iTerm_escape_template = '\033]Pl%s\033\\' +let s:xterm_escape_template = '\033]12;%s\007' + +function! s:get_mode() + return call(get(g:, 'cursormode_mode_func', 'mode'), []) +endfunction + +function! airline#extensions#cursormode#set(...) + let mode = s:get_mode() + if mode !=# s:last_mode + let s:last_mode = mode + call s:set_cursor_color_for(mode) + endif + return '' +endfunction + +function! s:set_cursor_color_for(mode) + let mode = a:mode + for mode in [a:mode, a:mode.&background] + if has_key(s:color_map, mode) + try + let save_eventignore = &eventignore + set eventignore=all + let save_shelltemp = &shelltemp + set noshelltemp + + silent call system(s:build_command(s:color_map[mode])) + return + finally + let &shelltemp = save_shelltemp + let &eventignore = save_eventignore + endtry + endif + endfor +endfunction + +function! s:build_command(color) + if s:is_iTerm + let color = substitute(a:color, '^#', '', '') + let escape_template = s:iTerm_escape_template + else + let color = a:color + let escape_template = s:xterm_escape_template + endif + + let escape = printf(escape_template, color) + if exists('$TMUX') + let escape = airline#extensions#cursormode#tmux_escape(escape) + endif + return "printf '".escape."' > /dev/tty" +endfunction + +function! s:get_color_map() + if exists('g:cursormode_color_map') + return g:cursormode_color_map + endif + + try + let map = g:cursormode#{g:colors_name}#color_map + return map + catch + return { + \ "nlight": "#000000", + \ "ndark": "#BBBBBB", + \ "i": "#0000BB", + \ "v": "#FF5555", + \ "V": "#BBBB00", + \ "\<C-V>": "#BB00BB", + \ } + endtry +endfunction + +augroup airline#extensions#cursormode + autocmd! + autocmd VimLeave * nested call s:set_cursor_color_for(g:cursormode_exit_mode) + " autocmd VimEnter * call airline#extensions#cursormode#activate() + autocmd Colorscheme * call airline#extensions#cursormode#activate() +augroup END + +function! airline#extensions#cursormode#activate() + let s:color_map = s:get_color_map() + call airline#extensions#cursormode#set() +endfunction + +function! airline#extensions#cursormode#apply(...) + let w:airline_section_a = get(w:, 'airline_section_a', g:airline_section_a) + let w:airline_section_a .= '%{airline#extensions#cursormode#set()}' +endfunction + +function! airline#extensions#cursormode#init(ext) + let s:color_map = s:get_color_map() + call a:ext.add_statusline_func('airline#extensions#cursormode#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/default.vim b/.vim/autoload/airline/extensions/default.vim new file mode 100644 index 0000000..f9ca3d4 --- /dev/null +++ b/.vim/autoload/airline/extensions/default.vim @@ -0,0 +1,100 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:section_use_groups = get(g:, 'airline#extensions#default#section_use_groupitems', 1) +let s:section_truncate_width = get(g:, 'airline#extensions#default#section_truncate_width', { + \ 'b': 79, + \ 'x': 60, + \ 'y': 88, + \ 'z': 45, + \ 'warning': 80, + \ 'error': 80, + \ }) +let s:layout = get(g:, 'airline#extensions#default#layout', [ + \ [ 'a', 'b', 'c' ], + \ [ 'x', 'y', 'z', 'warning', 'error' ] + \ ]) + +function! s:get_section(winnr, key, ...) + if has_key(s:section_truncate_width, a:key) + if winwidth(a:winnr) < s:section_truncate_width[a:key] + return '' + endif + endif + let spc = g:airline_symbols.space + if !exists('g:airline_section_{a:key}') + return '' + endif + let text = airline#util#getwinvar(a:winnr, 'airline_section_'.a:key, g:airline_section_{a:key}) + let [prefix, suffix] = [get(a:000, 0, '%('.spc), get(a:000, 1, spc.'%)')] + return empty(text) ? '' : prefix.text.suffix +endfunction + +function! s:build_sections(builder, context, keys) + for key in a:keys + if (key == 'warning' || key == 'error') && !a:context.active + continue + endif + call s:add_section(a:builder, a:context, key) + endfor +endfunction + +" There still is a highlighting bug when using groups %(%) in the statusline, +" deactivate it, unless it is fixed (7.4.1511) +if s:section_use_groups && (v:version >= 704 || (v:version >= 703 && has('patch81'))) + function! s:add_section(builder, context, key) + let condition = (a:key is# "warning" || a:key is# "error") && + \ (v:version == 704 && !has("patch1511")) + " i have no idea why the warning section needs special treatment, but it's + " needed to prevent separators from showing up + if ((a:key == 'error' || a:key == 'warning') && empty(s:get_section(a:context.winnr, a:key))) + return + endif + if condition + call a:builder.add_raw('%(') + endif + call a:builder.add_section('airline_'.a:key, s:get_section(a:context.winnr, a:key)) + if condition + call a:builder.add_raw('%)') + endif + endfunction +else + " older version don't like the use of %(%) + function! s:add_section(builder, context, key) + if ((a:key == 'error' || a:key == 'warning') && empty(s:get_section(a:context.winnr, a:key))) + return + endif + if a:key == 'warning' + call a:builder.add_raw('%#airline_warning#'.s:get_section(a:context.winnr, a:key)) + elseif a:key == 'error' + call a:builder.add_raw('%#airline_error#'.s:get_section(a:context.winnr, a:key)) + else + call a:builder.add_section('airline_'.a:key, s:get_section(a:context.winnr, a:key)) + endif + endfunction +endif + +function! airline#extensions#default#apply(builder, context) + let winnr = a:context.winnr + let active = a:context.active + + if airline#util#getwinvar(winnr, 'airline_render_left', active || (!active && !g:airline_inactive_collapse)) + call s:build_sections(a:builder, a:context, s:layout[0]) + else + let text = s:get_section(winnr, 'c') + if empty(text) + let text = ' %f%m ' + endif + call a:builder.add_section('airline_c'.(a:context.bufnr), text) + endif + + call a:builder.split(s:get_section(winnr, 'gutter', '', '')) + + if airline#util#getwinvar(winnr, 'airline_render_right', 1) + call s:build_sections(a:builder, a:context, s:layout[1]) + endif + + return 1 +endfunction diff --git a/.vim/autoload/airline/extensions/denite.vim b/.vim/autoload/airline/extensions/denite.vim new file mode 100644 index 0000000..e3c1f3b --- /dev/null +++ b/.vim/autoload/airline/extensions/denite.vim @@ -0,0 +1,41 @@ +" MIT License. Copyright (c) 2017-2018 Thomas Dy et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_denite', 0) + finish +endif + +" Denite does not use vim's built-in modal editing but has a custom prompt +" that implements its own insert/normal mode so we have to handle changing the +" highlight +function! airline#extensions#denite#check_denite_mode(bufnr) + if &filetype != 'denite' + return '' + endif + let mode = split(denite#get_status_mode(), ' ') + let mode = tolower(mode[1]) + if !exists('b:denite_mode_cache') || mode != b:denite_mode_cache + call airline#highlighter#highlight([mode], a:bufnr) + let b:denite_mode_cache = mode + endif + return '' +endfunction + +function! airline#extensions#denite#apply(...) + if &ft == 'denite' + let w:airline_skip_empty_sections = 0 + call a:1.add_section('airline_a', ' Denite %{airline#extensions#denite#check_denite_mode('.a:2['bufnr'].')}') + call a:1.add_section('airline_c', ' %{denite#get_status_sources()}') + call a:1.split() + call a:1.add_section('airline_y', ' %{denite#get_status_path()} ') + call a:1.add_section('airline_z', ' %{denite#get_status_linenr()} ') + return 1 + endif +endfunction + +function! airline#extensions#denite#init(ext) + call denite#custom#option('_', 'statusline', 0) + call a:ext.add_statusline_func('airline#extensions#denite#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/eclim.vim b/.vim/autoload/airline/extensions/eclim.vim new file mode 100644 index 0000000..3c48d75 --- /dev/null +++ b/.vim/autoload/airline/extensions/eclim.vim @@ -0,0 +1,61 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':ProjectCreate') + finish +endif + +function! airline#extensions#eclim#creat_line(...) + if &filetype == "tree" + let builder = a:1 + call builder.add_section('airline_a', ' Project ') + call builder.add_section('airline_b', ' %f ') + call builder.add_section('airline_c', '') + return 1 + endif +endfunction + +function! airline#extensions#eclim#get_warnings() + " Cache vavlues, so that it isn't called too often + if exists("s:eclim_errors") && + \ get(b:, 'airline_changenr', 0) == changenr() + return s:eclim_errors + endif + let eclimList = eclim#display#signs#GetExisting() + let s:eclim_errors = '' + + if !empty(eclimList) + " Remove any non-eclim signs (see eclim#display#signs#Update) + " First check for just errors since they are more important. + " If there are no errors, then check for warnings. + let errorList = filter(copy(eclimList), 'v:val.name =~ "^\\(qf_\\)\\?\\(error\\)$"') + + if (empty(errorList)) + " use the warnings + call filter(eclimList, 'v:val.name =~ "^\\(qf_\\)\\?\\(warning\\)$"') + let type = 'W' + else + " Use the errors + let eclimList = errorList + let type = 'E' + endif + + if !empty(eclimList) + let errorsLine = eclimList[0]['line'] + let errorsNumber = len(eclimList) + let errors = "[Eclim:" . type . " line:".string(errorsLine)." (".string(errorsNumber).")]" + if !exists(':SyntasticCheck') || SyntasticStatuslineFlag() == '' + let s:eclim_errors = errors.(g:airline_symbols.space) + endif + endif + endif + let b:airline_changenr = changenr() + return s:eclim_errors +endfunction + +function! airline#extensions#eclim#init(ext) + call airline#parts#define_function('eclim', 'airline#extensions#eclim#get_warnings') + call a:ext.add_statusline_func('airline#extensions#eclim#creat_line') +endfunction diff --git a/.vim/autoload/airline/extensions/example.vim b/.vim/autoload/airline/extensions/example.vim new file mode 100644 index 0000000..50a327d --- /dev/null +++ b/.vim/autoload/airline/extensions/example.vim @@ -0,0 +1,55 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +" we don't actually want this loaded :P +finish + +" Due to some potential rendering issues, the use of the `space` variable is +" recommended. +let s:spc = g:airline_symbols.space + +" Extension specific variables can be defined the usual fashion. +if !exists('g:airline#extensions#example#number_of_cats') + let g:airline#extensions#example#number_of_cats = 42 +endif + +" First we define an init function that will be invoked from extensions.vim +function! airline#extensions#example#init(ext) + + " Here we define a new part for the plugin. This allows users to place this + " extension in arbitrary locations. + call airline#parts#define_raw('cats', '%{airline#extensions#example#get_cats()}') + + " Next up we add a funcref so that we can run some code prior to the + " statusline getting modifed. + call a:ext.add_statusline_func('airline#extensions#example#apply') + + " You can also add a funcref for inactive statuslines. + " call a:ext.add_inactive_statusline_func('airline#extensions#example#unapply') +endfunction + +" This function will be invoked just prior to the statusline getting modified. +function! airline#extensions#example#apply(...) + " First we check for the filetype. + if &filetype == "nyancat" + + " Let's say we want to append to section_c, first we check if there's + " already a window-local override, and if not, create it off of the global + " section_c. + let w:airline_section_c = get(w:, 'airline_section_c', g:airline_section_c) + + " Then we just append this extenion to it, optionally using separators. + let w:airline_section_c .= s:spc.g:airline_left_alt_sep.s:spc.'%{airline#extensions#example#get_cats()}' + endif +endfunction + +" Finally, this function will be invoked from the statusline. +function! airline#extensions#example#get_cats() + let cats = '' + for i in range(1, g:airline#extensions#example#number_of_cats) + let cats .= ' (,,,)=(^.^)=(,,,) ' + endfor + return cats +endfunction diff --git a/.vim/autoload/airline/extensions/fugitiveline.vim b/.vim/autoload/airline/extensions/fugitiveline.vim new file mode 100644 index 0000000..5dab995 --- /dev/null +++ b/.vim/autoload/airline/extensions/fugitiveline.vim @@ -0,0 +1,49 @@ +" MIT License. Copyright (c) 2017-2018 Cimbali et al +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !airline#util#has_fugitive() + finish +endif + + +if exists("+autochdir") && &autochdir == 1 + let s:fmod = ':p' +else + let s:fmod = ':.' +endif + +function! airline#extensions#fugitiveline#bufname() + if !exists('b:fugitive_name') + let b:fugitive_name = '' + try + if bufname('%') =~? '^fugitive:' && exists('*FugitiveReal') + let b:fugitive_name = FugitiveReal(bufname('%')) + elseif exists('b:git_dir') + let buffer = fugitive#buffer() + if buffer.type('blob') + let b:fugitive_name = buffer.repo().translate(buffer.path('/')) + endif + endif + catch + endtry + endif + + if empty(b:fugitive_name) + return fnamemodify(bufname('%'), s:fmod) + else + return fnamemodify(b:fugitive_name, s:fmod) + endif +endfunction + +function! airline#extensions#fugitiveline#init(ext) + if exists("+autochdir") && &autochdir == 1 + " if 'acd' is set, vim-airline uses the path section, so we need to redefine this here as well + call airline#parts#define_raw('path', '%<%{airline#extensions#fugitiveline#bufname()}%m') + else + call airline#parts#define_raw('file', '%<%{airline#extensions#fugitiveline#bufname()}%m') + endif + autocmd ShellCmdPost,CmdwinLeave * unlet! b:fugitive_name + autocmd User AirlineBeforeRefresh unlet! b:fugitive_name +endfunction diff --git a/.vim/autoload/airline/extensions/grepper.vim b/.vim/autoload/airline/extensions/grepper.vim new file mode 100644 index 0000000..3e5debf --- /dev/null +++ b/.vim/autoload/airline/extensions/grepper.vim @@ -0,0 +1,19 @@ +" MIT License. Copyright (c) 2014-2018 Mathias Andersson et al. +" vim: et ts=2 sts=2 sw=2 + +" Heavily derived from the Gutentags extension + +scriptencoding utf-8 + +if !get(g:, 'loaded_grepper', 0) + finish +endif + +function! airline#extensions#grepper#status() + let msg = grepper#statusline() + return empty(msg) ? '' : 'grepper' +endfunction + +function! airline#extensions#grepper#init(ext) + call airline#parts#define_function('grepper', 'airline#extensions#grepper#status') +endfunction diff --git a/.vim/autoload/airline/extensions/gutentags.vim b/.vim/autoload/airline/extensions/gutentags.vim new file mode 100644 index 0000000..4af2d78 --- /dev/null +++ b/.vim/autoload/airline/extensions/gutentags.vim @@ -0,0 +1,17 @@ +" MIT License. Copyright (c) 2014-2018 Mathias Andersson et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_gutentags', 0) + finish +endif + +function! airline#extensions#gutentags#status() + let msg = gutentags#statusline() + return empty(msg) ? '' : 'Gen. ' . msg +endfunction + +function! airline#extensions#gutentags#init(ext) + call airline#parts#define_function('gutentags', 'airline#extensions#gutentags#status') +endfunction diff --git a/.vim/autoload/airline/extensions/hunks.vim b/.vim/autoload/airline/extensions/hunks.vim new file mode 100644 index 0000000..aba84cc --- /dev/null +++ b/.vim/autoload/airline/extensions/hunks.vim @@ -0,0 +1,93 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_signify', 0) && !get(g:, 'loaded_gitgutter', 0) && !get(g:, 'loaded_changes', 0) && !get(g:, 'loaded_quickfixsigns', 0) + finish +endif + +let s:non_zero_only = get(g:, 'airline#extensions#hunks#non_zero_only', 0) +let s:hunk_symbols = get(g:, 'airline#extensions#hunks#hunk_symbols', ['+', '~', '-']) + +function! s:get_hunks_signify() + let hunks = sy#repo#get_stats() + if hunks[0] >= 0 + return hunks + endif + return [] +endfunction + +function! s:is_branch_empty() + return exists('*airline#extensions#branch#head') && + \ empty(get(b:, 'airline_head', '')) +endfunction + +function! s:get_hunks_gitgutter() + if !get(g:, 'gitgutter_enabled', 0) || s:is_branch_empty() + return '' + endif + return GitGutterGetHunkSummary() +endfunction + +function! s:get_hunks_changes() + if !get(b:, 'changes_view_enabled', 0) || s:is_branch_empty() + return [] + endif + let hunks = changes#GetStats() + return hunks == [0, 0, 0] ? [] : hunks +endfunction + +function! s:get_hunks_empty() + return '' +endfunction + +function! s:get_hunks() + if !exists('b:source_func') || get(b:, 'source_func', '') is# 's:get_hunks_empty' + if get(g:, 'loaded_signify') && sy#buffer_is_active() + let b:source_func = 's:get_hunks_signify' + elseif exists('*GitGutterGetHunkSummary') + let b:source_func = 's:get_hunks_gitgutter' + elseif exists('*changes#GetStats') + let b:source_func = 's:get_hunks_changes' + elseif exists('*quickfixsigns#vcsdiff#GetHunkSummary') + let b:source_func = 'quickfixsigns#vcsdiff#GetHunkSummary' + else + let b:source_func = 's:get_hunks_empty' + endif + endif + return {b:source_func}() +endfunction + +function! airline#extensions#hunks#get_hunks() + if !get(w:, 'airline_active', 0) + return '' + endif + " Cache values, so that it isn't called too often + if exists("b:airline_hunks") && + \ get(b:, 'airline_changenr', 0) == b:changedtick && + \ winwidth(0) == get(s:, 'airline_winwidth', 0) && + \ get(b:, 'source_func', '') isnot# 's:get_hunks_signify' && + \ get(b:, 'source_func', '') isnot# 's:get_hunks_gitgutter' && + \ get(b:, 'source_func', '') isnot# 's:get_hunks_empty' && + \ get(b:, 'source_func', '') isnot# 's:get_hunks_changes' + return b:airline_hunks + endif + let hunks = s:get_hunks() + let string = '' + if !empty(hunks) + for i in [0, 1, 2] + if (s:non_zero_only == 0 && winwidth(0) > 100) || hunks[i] > 0 + let string .= printf('%s%s ', s:hunk_symbols[i], hunks[i]) + endif + endfor + endif + let b:airline_hunks = string + let b:airline_changenr = b:changedtick + let s:airline_winwidth = winwidth(0) + return string +endfunction + +function! airline#extensions#hunks#init(ext) + call airline#parts#define_function('hunks', 'airline#extensions#hunks#get_hunks') +endfunction diff --git a/.vim/autoload/airline/extensions/keymap.vim b/.vim/autoload/airline/extensions/keymap.vim new file mode 100644 index 0000000..c09c68b --- /dev/null +++ b/.vim/autoload/airline/extensions/keymap.vim @@ -0,0 +1,20 @@ +" MIT License. Copyright (c) 2013-2018 Doron Behar, C.Brabandt et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !has('keymap') + finish +endif + +function! airline#extensions#keymap#status() + if (get(g:, 'airline#extensions#keymap#enabled', 1) && has('keymap')) + return printf('%s', (!empty(&keymap) ? (g:airline_symbols.keymap . ' '. &keymap) : '')) + else + return '' + endif +endfunction + +function! airline#extensions#keymap#init(ext) + call airline#parts#define_function('keymap', 'airline#extensions#keymap#status') +endfunction diff --git a/.vim/autoload/airline/extensions/languageclient.vim b/.vim/autoload/airline/extensions/languageclient.vim new file mode 100644 index 0000000..82fed28 --- /dev/null +++ b/.vim/autoload/airline/extensions/languageclient.vim @@ -0,0 +1,101 @@ +" MIT License. Copyright (c) 2013-2018 Bjorn Neergaard, w0rp, hallettj et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:error_symbol = get(g:, 'airline#extensions#languageclient#error_symbol', 'E:') +let s:warning_symbol = get(g:, 'airline#extensions#languageclient#warning_symbol', 'W:') +let s:show_line_numbers = get(g:, 'airline#extensions#languageclient#show_line_numbers', 1) + +" Severity codes from the LSP spec +let s:severity_error = 1 +let s:severity_warning = 2 +let s:severity_info = 3 +let s:severity_hint = 4 + +" After each LanguageClient state change `s:diagnostics` will be populated with +" a map from file names to lists of errors, warnings, informational messages, +" and hints. +let s:diagnostics = {} + +function! s:languageclient_refresh() + if get(g:, 'airline_skip_empty_sections', 0) + exe ':AirlineRefresh' + endif +endfunction + +function! s:record_diagnostics(state) + let result = json_decode(a:state.result) + let s:diagnostics = result.diagnostics + call s:languageclient_refresh() +endfunction + +function! s:get_diagnostics() + call LanguageClient#getState(function("s:record_diagnostics")) +endfunction + +function! s:diagnostics_for_buffer() + return get(s:diagnostics, expand('%:p'), []) +endfunction + +function! s:airline_languageclient_count(cnt, symbol) + return a:cnt ? a:symbol. a:cnt : '' +endfunction + +function! s:airline_languageclient_get_line_number(type) abort + let linenumber_of_first_problem = 0 + for d in s:diagnostics_for_buffer() + if has_key(d, 'severity') && d.severity == a:type + let linenumber_of_first_problem = d.range.start.line + break + endif + endfor + + if linenumber_of_first_problem == 0 + return '' + endif + + let open_lnum_symbol = get(g:, 'airline#extensions#languageclient#open_lnum_symbol', '(L') + let close_lnum_symbol = get(g:, 'airline#extensions#languageclient#close_lnum_symbol', ')') + + return open_lnum_symbol . linenumber_of_first_problem . close_lnum_symbol +endfunction + +function! airline#extensions#languageclient#get(type) + let is_err = a:type == s:severity_error + let symbol = is_err ? s:error_symbol : s:warning_symbol + + let cnt = 0 + for d in s:diagnostics_for_buffer() + if has_key(d, 'severity') && d.severity == a:type + let cnt += 1 + endif + endfor + + if cnt == 0 + return '' + endif + + if s:show_line_numbers == 1 + return s:airline_languageclient_count(cnt, symbol) . <sid>airline_languageclient_get_line_number(a:type) + else + return s:airline_languageclient_count(cnt, symbol) + endif +endfunction + +function! airline#extensions#languageclient#get_warning() + return airline#extensions#languageclient#get(s:severity_warning) +endfunction + +function! airline#extensions#languageclient#get_error() + return airline#extensions#languageclient#get(s:severity_error) +endfunction + +function! airline#extensions#languageclient#init(ext) + call airline#parts#define_function('languageclient_error_count', 'airline#extensions#languageclient#get_error') + call airline#parts#define_function('languageclient_warning_count', 'airline#extensions#languageclient#get_warning') + augroup airline_languageclient + autocmd! + autocmd User LanguageClientDiagnosticsChanged call <sid>get_diagnostics() + augroup END +endfunction diff --git a/.vim/autoload/airline/extensions/localsearch.vim b/.vim/autoload/airline/extensions/localsearch.vim new file mode 100644 index 0000000..685be47 --- /dev/null +++ b/.vim/autoload/airline/extensions/localsearch.vim @@ -0,0 +1,35 @@ +" MIT License. Copyright (c) 2018 mox et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:enabled = get(g:, 'airline#extensions#localsearch#enabled', 1) +if !get(g:, 'loaded_localsearch', 0) || !s:enabled || get(g:, 'airline#extensions#localsearch#loaded', 0) + finish +endif +let g:airline#extensions#localsearch#loaded = 001 + +let s:spc = g:airline_symbols.space + +function! airline#extensions#localsearch#load_theme(palette) + call airline#highlighter#exec('localsearch_dark', [ '#ffffff' , '#000000' , 15 , 1 , '']) +endfunction + + +function! airline#extensions#localsearch#init(ext) + call a:ext.add_theme_func('airline#extensions#localsearch#load_theme') + call a:ext.add_statusline_func('airline#extensions#localsearch#apply') +endfunction + + +function! airline#extensions#localsearch#apply(...) + " first variable is the statusline builder + let builder = a:1 + + """"" WARNING: the API for the builder is not finalized and may change + if exists('#localsearch#WinEnter') " If localsearch mode is enabled + call builder.add_section('localsearch_dark', s:spc.airline#section#create('LS').s:spc) + endif + return 0 +endfunction + diff --git a/.vim/autoload/airline/extensions/neomake.vim b/.vim/autoload/airline/extensions/neomake.vim new file mode 100644 index 0000000..b82d6c3 --- /dev/null +++ b/.vim/autoload/airline/extensions/neomake.vim @@ -0,0 +1,36 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +if !exists(':Neomake') + finish +endif + +let s:error_symbol = get(g:, 'airline#extensions#neomake#error_symbol', 'E:') +let s:warning_symbol = get(g:, 'airline#extensions#neomake#warning_symbol', 'W:') + +function! s:get_counts() + let l:counts = neomake#statusline#LoclistCounts() + + if empty(l:counts) + return neomake#statusline#QflistCounts() + else + return l:counts + endif +endfunction + +function! airline#extensions#neomake#get_warnings() + let counts = s:get_counts() + let warnings = get(counts, 'W', 0) + return warnings ? s:warning_symbol.warnings : '' +endfunction + +function! airline#extensions#neomake#get_errors() + let counts = s:get_counts() + let errors = get(counts, 'E', 0) + return errors ? s:error_symbol.errors : '' +endfunction + +function! airline#extensions#neomake#init(ext) + call airline#parts#define_function('neomake_warning_count', 'airline#extensions#neomake#get_warnings') + call airline#parts#define_function('neomake_error_count', 'airline#extensions#neomake#get_errors') +endfunction diff --git a/.vim/autoload/airline/extensions/netrw.vim b/.vim/autoload/airline/extensions/netrw.vim new file mode 100644 index 0000000..10f024a --- /dev/null +++ b/.vim/autoload/airline/extensions/netrw.vim @@ -0,0 +1,34 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':NetrwSettings') + finish +endif + +function! airline#extensions#netrw#apply(...) + if &ft == 'netrw' + let spc = g:airline_symbols.space + + call a:1.add_section('airline_a', spc.'netrw'.spc) + if exists('*airline#extensions#branch#get_head') + call a:1.add_section('airline_b', spc.'%{airline#extensions#branch#get_head()}'.spc) + endif + call a:1.add_section('airline_c', spc.'%f'.spc) + call a:1.split() + call a:1.add_section('airline_y', spc.'%{airline#extensions#netrw#sortstring()}'.spc) + return 1 + endif +endfunction + +function! airline#extensions#netrw#init(ext) + let g:netrw_force_overwrite_statusline = 0 + call a:ext.add_statusline_func('airline#extensions#netrw#apply') +endfunction + + +function! airline#extensions#netrw#sortstring() + let order = (get(g:, 'netrw_sort_direction', 'n') =~ 'n') ? '+' : '-' + return g:netrw_sort_by . (g:airline_symbols.space) . '[' . order . ']' +endfunction diff --git a/.vim/autoload/airline/extensions/nrrwrgn.vim b/.vim/autoload/airline/extensions/nrrwrgn.vim new file mode 100644 index 0000000..e97c8a5 --- /dev/null +++ b/.vim/autoload/airline/extensions/nrrwrgn.vim @@ -0,0 +1,57 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_nrrw_rgn', 0) + finish +endif + +function! airline#extensions#nrrwrgn#apply(...) + if exists(":WidenRegion") == 2 + let spc = g:airline_symbols.space + if !exists("*nrrwrgn#NrrwRgnStatus()") || empty(nrrwrgn#NrrwRgnStatus()) + call a:1.add_section('airline_a', printf('%s[Narrowed%s#%d]', spc, spc, b:nrrw_instn)) + let bufname=(get(b:, 'orig_buf', 0) ? bufname(b:orig_buf) : substitute(bufname('%'), '^Nrrwrgn_\zs.*\ze_\d\+$', submatch(0), '')) + call a:1.add_section('airline_c', spc.bufname.spc) + call a:1.split() + else + let dict=nrrwrgn#NrrwRgnStatus() + let vmode = { 'v': 'Char ', 'V': 'Line ', '': 'Block '} + let mode = dict.visual ? vmode[dict.visual] : vmode['V'] + let winwidth = winwidth(0) + if winwidth < 80 + let mode = mode[0] + endif + let title = (winwidth < 80 ? "Nrrw" : "Narrowed ") + let multi = (winwidth < 80 ? 'M' : 'Multi') + call a:1.add_section('airline_a', printf('[%s%s%s#%d]%s', (dict.multi ? multi : ""), + \ title, mode, b:nrrw_instn, spc)) + let name = dict.fullname + if name !=# '[No Name]' + if winwidth > 100 + " need some space + let name = fnamemodify(dict.fullname, ':~') + if strlen(name) > 8 + " shorten name + let name = substitute(name, '\(.\)[^/\\]*\([/\\]\)', '\1\2', 'g') + endif + else + let name = fnamemodify(dict.fullname, ':t') + endif + endif + let range=(dict.multi ? '' : printf("[%d-%d]", dict.start[1], dict.end[1])) + call a:1.add_section('airline_c', printf("%s %s %s", name, range, + \ dict.enabled ? (&encoding ==? 'utf-8' ? "\u2713" : '') : '!')) + call a:1.split() + call a:1.add_section('airline_x', get(g:, 'airline_section_x').spc) + call a:1.add_section('airline_y', spc.get(g:, 'airline_section_y').spc) + call a:1.add_section('airline_z', spc.get(g:, 'airline_section_z')) + endif + return 1 + endif +endfunction + +function! airline#extensions#nrrwrgn#init(ext) + call a:ext.add_statusline_func('airline#extensions#nrrwrgn#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/obsession.vim b/.vim/autoload/airline/extensions/obsession.vim new file mode 100644 index 0000000..04105d0 --- /dev/null +++ b/.vim/autoload/airline/extensions/obsession.vim @@ -0,0 +1,22 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists('*ObsessionStatus') + finish +endif + +let s:spc = g:airline_symbols.space + +if !exists('g:airline#extensions#obsession#indicator_text') + let g:airline#extensions#obsession#indicator_text = '$' +endif + +function! airline#extensions#obsession#init(ext) + call airline#parts#define_function('obsession', 'airline#extensions#obsession#get_status') +endfunction + +function! airline#extensions#obsession#get_status() + return ObsessionStatus((g:airline#extensions#obsession#indicator_text . s:spc), '') +endfunction diff --git a/.vim/autoload/airline/extensions/po.vim b/.vim/autoload/airline/extensions/po.vim new file mode 100644 index 0000000..3ec2942 --- /dev/null +++ b/.vim/autoload/airline/extensions/po.vim @@ -0,0 +1,81 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#po#shorten() + " Format and shorte the output of msgfmt + let b:airline_po_stats = substitute(get(b:, 'airline_po_stats', ''), ' \(message\|translation\)s*\.*', '', 'g') + let b:airline_po_stats = substitute(b:airline_po_stats, ', ', '/', 'g') + if exists("g:airline#extensions#po#displayed_limit") + let w:displayed_po_limit = g:airline#extensions#po#displayed_limit + if len(b:airline_po_stats) > w:displayed_po_limit - 1 + let b:airline_po_stats = b:airline_po_stats[0:(w:displayed_po_limit - 2)].(&encoding==?'utf-8' ? '…' : '.'). ']' + endif + endif + if strlen(get(b:, 'airline_po_stats', '')) >= 30 && winwidth(0) < 150 + let fuzzy = '' + let untranslated = '' + let messages = '' + " Shorten [120 translated, 50 fuzzy, 4 untranslated] to [120T/50F/4U] + if b:airline_po_stats =~ 'fuzzy' + let fuzzy = substitute(b:airline_po_stats, '.*\(\d\+\) fuzzy.*', '\1F', '') + endif + if b:airline_po_stats =~ 'untranslated' + let untranslated = substitute(b:airline_po_stats, '.*\(\d\+\) untranslated.*', '\1U', '') + endif + let messages = substitute(b:airline_po_stats, '\(\d\+\) translated.*', '\1T', '') + let b:airline_po_stats = printf('%s%s%s', fuzzy, (empty(fuzzy) || empty(untranslated) ? '' : '/'), untranslated) + if strlen(b:airline_po_stats) < 8 + let b:airline_po_stats = messages. (!empty(b:airline_po_stats) ? '/':''). b:airline_po_stats + endif + endif + let b:airline_po_stats = '['.b:airline_po_stats. ']' +endfunction + +function! airline#extensions#po#on_winenter() + " only reset cache, if the window size changed + if get(b:, 'airline_winwidth', 0) != winwidth(0) + let b:airline_winwidth = winwidth(0) + " needs re-formatting + unlet! b:airline_po_stats + endif +endfunction + +function! airline#extensions#po#apply(...) + if &ft ==# 'po' + call airline#extensions#prepend_to_section('z', '%{airline#extensions#po#stats()}') + " Also reset the cache variable, if a window has been split, e.g. the winwidth changed + autocmd airline BufWritePost * unlet! b:airline_po_stats + autocmd airline WinEnter * call airline#extensions#po#on_winenter() + endif +endfunction + +function! airline#extensions#po#stats() + if exists('b:airline_po_stats') && !empty(b:airline_po_stats) + return b:airline_po_stats + endif + + let cmd = 'msgfmt --statistics -o /dev/null -- ' + if g:airline#init#vim_async + call airline#async#get_msgfmt_stat(cmd, expand('%:p')) + elseif has("nvim") + call airline#async#nvim_get_msgfmt_stat(cmd, expand('%:p')) + else + let airline_po_stats = system(cmd. shellescape(expand('%:p'))) + if v:shell_error + return '' + endif + try + let b:airline_po_stats = split(airline_po_stats, '\n')[0] + catch + let b:airline_po_stats = '' + endtry + call airline#extensions#po#shorten() + endif + return get(b:, 'airline_po_stats', '') +endfunction + +function! airline#extensions#po#init(ext) + call a:ext.add_statusline_func('airline#extensions#po#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/promptline.vim b/.vim/autoload/airline/extensions/promptline.vim new file mode 100644 index 0000000..7c90b7c --- /dev/null +++ b/.vim/autoload/airline/extensions/promptline.vim @@ -0,0 +1,35 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':PromptlineSnapshot') + finish +endif + +if !exists('airline#extensions#promptline#snapshot_file') || !len('airline#extensions#promptline#snapshot_file') + finish +endif + +let s:prompt_snapshot_file = get(g:, 'airline#extensions#promptline#snapshot_file', '') +let s:color_template = get(g:, 'airline#extensions#promptline#color_template', 'normal') + +function! airline#extensions#promptline#init(ext) + call a:ext.add_theme_func('airline#extensions#promptline#set_prompt_colors') +endfunction + +function! airline#extensions#promptline#set_prompt_colors(palette) + let color_template = has_key(a:palette, s:color_template) ? s:color_template : 'normal' + let mode_palette = a:palette[color_template] + + if !has_key(g:, 'promptline_symbols') + let g:promptline_symbols = { + \ 'left' : g:airline_left_sep, + \ 'right' : g:airline_right_sep, + \ 'left_alt' : g:airline_left_alt_sep, + \ 'right_alt' : g:airline_right_alt_sep} + endif + + let promptline_theme = promptline#api#create_theme_from_airline(mode_palette) + call promptline#api#create_snapshot_with_theme(s:prompt_snapshot_file, promptline_theme) +endfunction diff --git a/.vim/autoload/airline/extensions/quickfix.vim b/.vim/autoload/airline/extensions/quickfix.vim new file mode 100644 index 0000000..2680371 --- /dev/null +++ b/.vim/autoload/airline/extensions/quickfix.vim @@ -0,0 +1,58 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists('g:airline#extensions#quickfix#quickfix_text') + let g:airline#extensions#quickfix#quickfix_text = 'Quickfix' +endif + +if !exists('g:airline#extensions#quickfix#location_text') + let g:airline#extensions#quickfix#location_text = 'Location' +endif + +function! airline#extensions#quickfix#apply(...) + if &buftype == 'quickfix' + let w:airline_section_a = airline#extensions#quickfix#get_type() + let w:airline_section_b = '%{get(w:, "quickfix_title", "")}' + let w:airline_section_c = '' + let w:airline_section_x = '' + endif +endfunction + +function! airline#extensions#quickfix#init(ext) + call a:ext.add_statusline_func('airline#extensions#quickfix#apply') + call a:ext.add_inactive_statusline_func('airline#extensions#quickfix#inactive_qf_window') +endfunction + +function! airline#extensions#quickfix#inactive_qf_window(...) + if getbufvar(a:2.bufnr, '&filetype') is# 'qf' && !empty(airline#util#getwinvar(a:2.winnr, 'quickfix_title', '')) + call setwinvar(a:2.winnr, 'airline_section_c', '[%{get(w:, "quickfix_title", "")}] %f %m') + endif +endfunction + +function! airline#extensions#quickfix#get_type() + if exists("*win_getid") && exists("*getwininfo") + let dict = getwininfo(win_getid()) + if len(dict) > 0 && get(dict[0], 'quickfix', 0) && !get(dict[0], 'loclist', 0) + return g:airline#extensions#quickfix#quickfix_text + elseif len(dict) > 0 && get(dict[0], 'quickfix', 0) && get(dict[0], 'loclist', 0) + return g:airline#extensions#quickfix#location_text + endif + endif + redir => buffers + silent ls + redir END + + let nr = bufnr('%') + for buf in split(buffers, '\n') + if match(buf, '\v^\s*'.nr) > -1 + if match(buf, '\cQuickfix') > -1 + return g:airline#extensions#quickfix#quickfix_text + else + return g:airline#extensions#quickfix#location_text + endif + endif + endfor + return '' +endfunction diff --git a/.vim/autoload/airline/extensions/syntastic.vim b/.vim/autoload/airline/extensions/syntastic.vim new file mode 100644 index 0000000..be21fb4 --- /dev/null +++ b/.vim/autoload/airline/extensions/syntastic.vim @@ -0,0 +1,43 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':SyntasticCheck') + finish +endif + +let s:error_symbol = get(g:, 'airline#extensions#syntastic#error_symbol', 'E:') +let s:warning_symbol = get(g:, 'airline#extensions#syntastic#warning_symbol', 'W:') + +function! airline#extensions#syntastic#get_warning() + return airline#extensions#syntastic#get('warning') +endfunction + +function! airline#extensions#syntastic#get_error() + return airline#extensions#syntastic#get('error') +endfunction + +function! airline#extensions#syntastic#get(type) + let _backup = get(g:, 'syntastic_stl_format', '') + let is_err = (a:type is# 'error') + if is_err + let g:syntastic_stl_format = get(g:, 'airline#extensions#syntastic#stl_format_err', '%E{[%e(#%fe)]}') + else + let g:syntastic_stl_format = get(g:, 'airline#extensions#syntastic#stl_format_warn', '%W{[%w(#%fw)]}') + endif + let cnt = SyntasticStatuslineFlag() + if !empty(_backup) + let g:syntastic_stl_format = _backup + endif + if empty(cnt) + return '' + else + return (is_err ? s:error_symbol : s:warning_symbol).cnt + endif +endfunction + +function! airline#extensions#syntastic#init(ext) + call airline#parts#define_function('syntastic-warn', 'airline#extensions#syntastic#get_warning') + call airline#parts#define_function('syntastic-err', 'airline#extensions#syntastic#get_error') +endfunction diff --git a/.vim/autoload/airline/extensions/tabline.vim b/.vim/autoload/airline/extensions/tabline.vim new file mode 100644 index 0000000..10e235e --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline.vim @@ -0,0 +1,213 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + + +let s:taboo = get(g:, 'airline#extensions#taboo#enabled', 1) && get(g:, 'loaded_taboo', 0) +if s:taboo + let g:taboo_tabline = 0 +endif + +let s:ctrlspace = get(g:, 'CtrlSpaceLoaded', 0) + +function! airline#extensions#tabline#init(ext) + if has('gui_running') + set guioptions-=e + endif + + autocmd User AirlineToggledOn call s:toggle_on() + autocmd User AirlineToggledOff call s:toggle_off() + + call s:toggle_on() + call a:ext.add_theme_func('airline#extensions#tabline#load_theme') +endfunction + +function! s:toggle_off() + call airline#extensions#tabline#autoshow#off() + call airline#extensions#tabline#tabs#off() + call airline#extensions#tabline#buffers#off() + if s:ctrlspace + call airline#extensions#tabline#ctrlspace#off() + endif +endfunction + +function! s:toggle_on() + call airline#extensions#tabline#autoshow#on() + call airline#extensions#tabline#tabs#on() + call airline#extensions#tabline#buffers#on() + if s:ctrlspace + call airline#extensions#tabline#ctrlspace#on() + endif + + set tabline=%!airline#extensions#tabline#get() +endfunction + +function! s:update_tabline() + if get(g:, 'airline#extensions#tabline#disable_refresh', 0) + return + endif + let match = expand('<afile>') + if pumvisible() + return + elseif !get(g:, 'airline#extensions#tabline#enabled', 0) + return + " return, if buffer matches ignore pattern or is directory (netrw) + elseif empty(match) || airline#util#ignore_buf(match) + \ || isdirectory(expand("<afile>")) + return + endif + call airline#util#doautocmd('BufMRUChange') + " sometimes, the tabline is not correctly updated see #1580 + " so force redraw here + if exists(":redrawtabline") == 2 + redrawtabline + else + let &tabline = &tabline + endif +endfunction + +function! airline#extensions#tabline#load_theme(palette) + if pumvisible() + return + endif + let colors = get(a:palette, 'tabline', {}) + let tablabel = get(colors, 'airline_tablabel', a:palette.normal.airline_b) + " Theme for tabs on the left + let tab = get(colors, 'airline_tab', a:palette.normal.airline_b) + let tabsel = get(colors, 'airline_tabsel', a:palette.normal.airline_a) + let tabtype = get(colors, 'airline_tabtype', a:palette.visual.airline_a) + let tabfill = get(colors, 'airline_tabfill', a:palette.normal.airline_c) + let tabmod = get(colors, 'airline_tabmod', a:palette.insert.airline_a) + let tabhid = get(colors, 'airline_tabhid', a:palette.normal.airline_c) + if has_key(a:palette, 'normal_modified') && has_key(a:palette.normal_modified, 'airline_c') + let tabmodu = get(colors, 'airline_tabmod_unsel', a:palette.normal_modified.airline_c) + else + "Fall back to normal airline_c if modified airline_c isn't present + let tabmodu = get(colors, 'airline_tabmod_unsel', a:palette.normal.airline_c) + endif + call airline#highlighter#exec('airline_tablabel', tablabel) + call airline#highlighter#exec('airline_tab', tab) + call airline#highlighter#exec('airline_tabsel', tabsel) + call airline#highlighter#exec('airline_tabtype', tabtype) + call airline#highlighter#exec('airline_tabfill', tabfill) + call airline#highlighter#exec('airline_tabmod', tabmod) + call airline#highlighter#exec('airline_tabmod_unsel', tabmodu) + call airline#highlighter#exec('airline_tabhid', tabhid) + + " Theme for tabs on the right + let tabsel_right = get(colors, 'airline_tabsel_right', a:palette.normal.airline_a) + let tab_right = get(colors, 'airline_tab_right', a:palette.inactive.airline_c) + let tabmod_right = get(colors, 'airline_tabmod_right', a:palette.insert.airline_a) + let tabhid_right = get(colors, 'airline_tabhid_right', a:palette.normal.airline_c) + if has_key(a:palette, 'normal_modified') && has_key(a:palette.normal_modified, 'airline_c') + let tabmodu_right = get(colors, 'airline_tabmod_unsel_right', a:palette.normal_modified.airline_c) + else + "Fall back to normal airline_c if modified airline_c isn't present + let tabmodu_right = get(colors, 'airline_tabmod_unsel_right', a:palette.normal.airline_c) + endif + call airline#highlighter#exec('airline_tab_right', tab_right) + call airline#highlighter#exec('airline_tabsel_right', tabsel_right) + call airline#highlighter#exec('airline_tabmod_right', tabmod_right) + call airline#highlighter#exec('airline_tabhid_right', tabhid_right) + call airline#highlighter#exec('airline_tabmod_unsel_right', tabmodu_right) +endfunction + +let s:current_tabcnt = -1 + +function! airline#extensions#tabline#get() + let show_buffers = get(g:, 'airline#extensions#tabline#show_buffers', 1) + let show_tabs = get(g:, 'airline#extensions#tabline#show_tabs', 1) + + let curtabcnt = tabpagenr('$') + if curtabcnt != s:current_tabcnt + let s:current_tabcnt = curtabcnt + call airline#extensions#tabline#tabs#invalidate() + call airline#extensions#tabline#buffers#invalidate() + call airline#extensions#tabline#ctrlspace#invalidate() + endif + + if !exists('#airline#BufAdd#*') + autocmd airline BufAdd * call <sid>update_tabline() + endif + if s:ctrlspace + return airline#extensions#tabline#ctrlspace#get() + elseif show_buffers && curtabcnt == 1 || !show_tabs + return airline#extensions#tabline#buffers#get() + else + return airline#extensions#tabline#tabs#get() + endif +endfunction + +function! airline#extensions#tabline#title(n) + let title = '' + if s:taboo + let title = TabooTabTitle(a:n) + endif + + if empty(title) && exists('*gettabvar') + let title = gettabvar(a:n, 'title') + endif + + if empty(title) + let buflist = tabpagebuflist(a:n) + let winnr = tabpagewinnr(a:n) + let all_buffers = airline#extensions#tabline#buflist#list() + return airline#extensions#tabline#get_buffer_name( + \ buflist[winnr - 1], + \ filter(buflist, 'index(all_buffers, v:val) != -1')) + endif + + return title +endfunction + +function! airline#extensions#tabline#get_buffer_name(nr, ...) + let buffers = a:0 ? a:1 : airline#extensions#tabline#buflist#list() + let formatter = get(g:, 'airline#extensions#tabline#formatter', 'default') + return airline#extensions#tabline#formatters#{formatter}#format(a:nr, buffers) +endfunction + +function! airline#extensions#tabline#new_builder() + let builder_context = { + \ 'active' : 1, + \ 'tabline' : 1, + \ 'right_sep' : get(g:, 'airline#extensions#tabline#right_sep' , g:airline_right_sep), + \ 'right_alt_sep' : get(g:, 'airline#extensions#tabline#right_alt_sep', g:airline_right_alt_sep), + \ } + if get(g:, 'airline_powerline_fonts', 0) + let builder_context.left_sep = get(g:, 'airline#extensions#tabline#left_sep' , g:airline_left_sep) + let builder_context.left_alt_sep = get(g:, 'airline#extensions#tabline#left_alt_sep' , g:airline_left_alt_sep) + else + let builder_context.left_sep = get(g:, 'airline#extensions#tabline#left_sep' , ' ') + let builder_context.left_alt_sep = get(g:, 'airline#extensions#tabline#left_alt_sep' , '|') + endif + + return airline#extensions#tabline#builder#new(builder_context) +endfunction + +function! airline#extensions#tabline#group_of_bufnr(tab_bufs, bufnr) + let cur = bufnr('%') + if cur == a:bufnr + if g:airline_detect_modified && getbufvar(a:bufnr, '&modified') + let group = 'airline_tabmod' + else + let group = 'airline_tabsel' + endif + else + if g:airline_detect_modified && getbufvar(a:bufnr, '&modified') + let group = 'airline_tabmod_unsel' + elseif index(a:tab_bufs, a:bufnr) > -1 + let group = 'airline_tab' + else + let group = 'airline_tabhid' + endif + endif + return group +endfunction + +function! airline#extensions#tabline#add_label(dict, type) + if get(g:, 'airline#extensions#tabline#show_tab_type', 1) + call a:dict.add_section_spaced('airline_tablabel', + \ get(g:, 'airline#extensions#tabline#'.a:type.'_label', a:type)) + endif +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/autoshow.vim b/.vim/autoload/airline/extensions/tabline/autoshow.vim new file mode 100644 index 0000000..ac1413f --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/autoshow.vim @@ -0,0 +1,55 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:show_buffers = get(g:, 'airline#extensions#tabline#show_buffers', 1) +let s:buf_min_count = get(g:, 'airline#extensions#tabline#buffer_min_count', 0) +let s:tab_min_count = get(g:, 'airline#extensions#tabline#tab_min_count', 0) + +function! airline#extensions#tabline#autoshow#off() + if exists('s:original_tabline') + let &tabline = s:original_tabline + let &showtabline = s:original_showtabline + endif + + augroup airline_tabline_autoshow + autocmd! + augroup END +endfunction + +function! airline#extensions#tabline#autoshow#on() + let [ s:original_tabline, s:original_showtabline ] = [ &tabline, &showtabline ] + + augroup airline_tabline_autoshow + autocmd! + if s:buf_min_count <= 0 && s:tab_min_count <= 1 + if &lines > 3 + set showtabline=2 + endif + else + if s:show_buffers == 1 + autocmd BufEnter * call <sid>show_tabline(s:buf_min_count, len(airline#extensions#tabline#buflist#list())) + autocmd BufUnload * call <sid>show_tabline(s:buf_min_count, len(airline#extensions#tabline#buflist#list()) - 1) + else + autocmd TabEnter * call <sid>show_tabline(s:tab_min_count, tabpagenr('$')) + endif + endif + + " Invalidate cache. This has to come after the BufUnload for + " s:show_buffers, to invalidate the cache for BufEnter. + autocmd BufLeave,BufAdd,BufUnload * call airline#extensions#tabline#buflist#invalidate() + augroup END +endfunction + +function! s:show_tabline(min_count, total_count) + if a:total_count >= a:min_count + if &showtabline != 2 && &lines > 3 + set showtabline=2 + endif + else + if &showtabline != 0 + set showtabline=0 + endif + endif +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/buffers.vim b/.vim/autoload/airline/extensions/tabline/buffers.vim new file mode 100644 index 0000000..88ebe5c --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/buffers.vim @@ -0,0 +1,246 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:spc = g:airline_symbols.space + +let s:current_bufnr = -1 +let s:current_modified = 0 +let s:current_tabline = '' +let s:current_visible_buffers = [] + +let s:number_map = { + \ '0': '⁰', + \ '1': '¹', + \ '2': '²', + \ '3': '³', + \ '4': '⁴', + \ '5': '⁵', + \ '6': '⁶', + \ '7': '⁷', + \ '8': '⁸', + \ '9': '⁹' + \ } +let s:number_map = &encoding == 'utf-8' + \ ? get(g:, 'airline#extensions#tabline#buffer_idx_format', s:number_map) + \ : {} + +function! airline#extensions#tabline#buffers#off() + augroup airline_tabline_buffers + autocmd! + augroup END +endfunction + +function! airline#extensions#tabline#buffers#on() + augroup airline_tabline_buffers + autocmd! + autocmd BufDelete * call airline#extensions#tabline#buflist#clean() + autocmd User BufMRUChange call airline#extensions#tabline#buflist#clean() + augroup END +endfunction + +function! airline#extensions#tabline#buffers#invalidate() + let s:current_bufnr = -1 +endfunction + +function! airline#extensions#tabline#buffers#get() + try + call <sid>map_keys() + catch + " no-op + endtry + let cur = bufnr('%') + if cur == s:current_bufnr && &columns == s:column_width + if !g:airline_detect_modified || getbufvar(cur, '&modified') == s:current_modified + return s:current_tabline + endif + endif + + let b = airline#extensions#tabline#new_builder() + let tab_bufs = tabpagebuflist(tabpagenr()) + let show_buf_label_first = 0 + + if get(g:, 'airline#extensions#tabline#buf_label_first', 0) + let show_buf_label_first = 1 + endif + if show_buf_label_first + call airline#extensions#tabline#add_label(b, 'buffers') + endif + + let b.tab_bufs = tabpagebuflist(tabpagenr()) + + let b.overflow_group = 'airline_tabhid' + let b.buffers = airline#extensions#tabline#buflist#list() + if get(g:, 'airline#extensions#tabline#current_first', 0) + if index(b.buffers, cur) > -1 + call remove(b.buffers, index(b.buffers, cur)) + endif + let b.buffers = [cur] + b.buffers + endif + + function! b.get_group(i) dict + let bufnum = get(self.buffers, a:i, -1) + if bufnum == -1 + return '' + endif + let group = airline#extensions#tabline#group_of_bufnr(self.tab_bufs, bufnum) + if bufnum == bufnr('%') + let s:current_modified = (group == 'airline_tabmod') ? 1 : 0 + endif + return group + endfunction + + if has("tablineat") + function! b.get_pretitle(i) dict + let bufnum = get(self.buffers, a:i, -1) + return '%'.bufnum.'@airline#extensions#tabline#buffers#clickbuf@' + endfunction + + function! b.get_posttitle(i) dict + return '%X' + endfunction + endif + + function! b.get_title(i) dict + let bufnum = get(self.buffers, a:i, -1) + let group = self.get_group(a:i) + let pgroup = self.get_group(a:i - 1) + " always add a space when powerline_fonts are used + " or for the very first item + if get(g:, 'airline_powerline_fonts', 0) || a:i == 0 + let space = s:spc + else + let space= (pgroup == group ? s:spc : '') + endif + + if get(g:, 'airline#extensions#tabline#buffer_idx_mode', 0) + if len(s:number_map) > 0 + return space. get(s:number_map, a:i+1, '') . '%(%{airline#extensions#tabline#get_buffer_name('.bufnum.')}%)' . s:spc + else + return '['.(a:i+1).s:spc.'%(%{airline#extensions#tabline#get_buffer_name('.bufnum.')}%)'.']' + endif + else + return space.'%(%{airline#extensions#tabline#get_buffer_name('.bufnum.')}%)'.s:spc + endif + endfunction + + let current_buffer = max([index(b.buffers, cur), 0]) + let last_buffer = len(b.buffers) - 1 + call b.insert_titles(current_buffer, 0, last_buffer) + + call b.add_section('airline_tabfill', '') + call b.split() + call b.add_section('airline_tabfill', '') + if !show_buf_label_first + call airline#extensions#tabline#add_label(b, 'buffers') + endif + + if tabpagenr('$') > 1 + call b.add_section_spaced('airline_tabmod', printf('%s %d/%d', "tab", tabpagenr(), tabpagenr('$'))) + endif + + let s:current_bufnr = cur + let s:column_width = &columns + let s:current_tabline = b.build() + let s:current_visible_buffers = copy(b.buffers) + if b._right_title <= last_buffer + call remove(s:current_visible_buffers, b._right_title, last_buffer) + endif + if b._left_title > 0 + call remove(s:current_visible_buffers, 0, b._left_title) + endif + return s:current_tabline +endfunction + +function! s:select_tab(buf_index) + " no-op when called in 'keymap_ignored_filetypes' + if count(get(g:, 'airline#extensions#tabline#keymap_ignored_filetypes', + \ ['vimfiler', 'nerdtree']), &ft) + return + endif + + let idx = a:buf_index + if s:current_visible_buffers[0] == -1 + let idx = idx + 1 + endif + + let buf = get(s:current_visible_buffers, idx, 0) + if buf != 0 + exec 'b!' . buf + endif +endfunction + +function! s:jump_to_tab(offset) + let l = airline#extensions#tabline#buflist#list() + let i = index(l, bufnr('%')) + if i > -1 + exec 'b!' . l[(i + a:offset) % len(l)] + endif +endfunction + +function! s:map_keys() + if get(g:, 'airline#extensions#tabline#buffer_idx_mode', 1) + noremap <silent> <Plug>AirlineSelectTab1 :call <SID>select_tab(0)<CR> + noremap <silent> <Plug>AirlineSelectTab2 :call <SID>select_tab(1)<CR> + noremap <silent> <Plug>AirlineSelectTab3 :call <SID>select_tab(2)<CR> + noremap <silent> <Plug>AirlineSelectTab4 :call <SID>select_tab(3)<CR> + noremap <silent> <Plug>AirlineSelectTab5 :call <SID>select_tab(4)<CR> + noremap <silent> <Plug>AirlineSelectTab6 :call <SID>select_tab(5)<CR> + noremap <silent> <Plug>AirlineSelectTab7 :call <SID>select_tab(6)<CR> + noremap <silent> <Plug>AirlineSelectTab8 :call <SID>select_tab(7)<CR> + noremap <silent> <Plug>AirlineSelectTab9 :call <SID>select_tab(8)<CR> + noremap <silent> <Plug>AirlineSelectPrevTab :<C-u>call <SID>jump_to_tab(-v:count1)<CR> + noremap <silent> <Plug>AirlineSelectNextTab :<C-u>call <SID>jump_to_tab(v:count1)<CR> + endif +endfunction + +function! airline#extensions#tabline#buffers#clickbuf(minwid, clicks, button, modifiers) abort + " Clickable buffers + " works only in recent NeoVim with has('tablineat') + + " single mouse button click without modifiers pressed + if a:clicks == 1 && a:modifiers !~# '[^ ]' + if a:button is# 'l' + " left button - switch to buffer + silent execute 'buffer' a:minwid + elseif a:button is# 'm' + " middle button - delete buffer + + if get(g:, 'airline#extensions#tabline#middle_click_preserves_windows', 0) == 0 || winnr('$') == 1 + " just simply delete the clicked buffer. This will cause windows + " associated with the clicked buffer to be closed. + silent execute 'bdelete' a:minwid + else + " find windows displaying the clicked buffer and open an new + " buffer in them. + let current_window = bufwinnr("%") + let window_number = bufwinnr(a:minwid) + let last_window_visited = -1 + + " Set to 1 if the clicked buffer was open in any windows. + let buffer_in_window = 0 + + " Find the next window with the clicked buffer open. If bufwinnr() + " returns the same window number, this is because we clicked a new + " buffer, and then tried editing a new buffer. Vim won't create a + " new empty buffer for the same window, so we get the same window + " number from bufwinnr(). In this case we just give up and don't + " delete the buffer. + " This could be made cleaner if we could check if the clicked buffer + " is a new buffer, but I don't know if there is a way to do that. + while window_number != -1 && window_number != last_window_visited + let buffer_in_window = 1 + silent execute window_number . 'wincmd w' + silent execute 'enew' + let last_window_visited = window_number + let window_number = bufwinnr(a:minwid) + endwhile + silent execute current_window . 'wincmd w' + if window_number != last_window_visited || buffer_in_window == 0 + silent execute 'bdelete' a:minwid + endif + endif + endif + endif +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/buflist.vim b/.vim/autoload/airline/extensions/tabline/buflist.vim new file mode 100644 index 0000000..a944cb9 --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/buflist.vim @@ -0,0 +1,77 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#tabline#buflist#invalidate() + unlet! s:current_buffer_list +endfunction + +function! airline#extensions#tabline#buflist#clean() + call airline#extensions#tabline#buflist#invalidate() + call airline#extensions#tabline#buffers#invalidate() +endfunction + +" paths in excludes list +function! s:ExcludePaths(nr, exclude_paths) + let bpath = fnamemodify(bufname(a:nr), ":p") + for f in a:exclude_paths + if bpath =~# f | return 1 | endif + endfor +endfunction + +" other types to exclude +function! s:ExcludeOther(nr, exclude_preview) + if (getbufvar(a:nr, 'current_syntax') == 'qf') || + \ (a:exclude_preview && getbufvar(a:nr, '&bufhidden') == 'wipe' + \ && getbufvar(a:nr, '&buftype') == 'nofile') + return 1 | endif +endfunction + +function! airline#extensions#tabline#buflist#list() + if exists('s:current_buffer_list') + return s:current_buffer_list + endif + + let exclude_buffers = get(g:, 'airline#extensions#tabline#exclude_buffers', []) + let exclude_paths = get(g:, 'airline#extensions#tabline#excludes', []) + let exclude_preview = get(g:, 'airline#extensions#tabline#exclude_preview', 1) + + let list = (exists('g:did_bufmru') && g:did_bufmru) ? BufMRUList() : range(1, bufnr("$")) + + let buffers = [] + " If this is too slow, we can switch to a different algorithm. + " Basically branch 535 already does it, but since it relies on + " BufAdd autocommand, I'd like to avoid this if possible. + for nr in list + if buflisted(nr) + " Do not add to the bufferlist, if either + " 1) bufnr is exclude_buffers list + " 2) buffername matches one of exclude_paths patterns + " 3) buffer is a quickfix buffer + " 4) when excluding preview windows: + " 'bufhidden' == wipe + " 'buftype' == nofile + " 5) ignore buffers matching airline#extensions#tabline#ignore_bufadd_pat + + " check buffer numbers first + if index(exclude_buffers, nr) >= 0 + continue + " check paths second + elseif !empty(exclude_paths) && s:ExcludePaths(nr, exclude_paths) + continue + " ignore buffers matching airline#extensions#tabline#ignore_bufadd_pat + elseif airline#util#ignore_buf(bufname(nr)) + continue + " check other types last + elseif s:ExcludeOther(nr, exclude_preview) + continue + endif + + call add(buffers, nr) + endif + endfor + + let s:current_buffer_list = buffers + return buffers +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/builder.vim b/.vim/autoload/airline/extensions/tabline/builder.vim new file mode 100644 index 0000000..20964b1 --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/builder.vim @@ -0,0 +1,232 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:prototype = {} + +" Set the point in the tabline where the builder should insert the titles. +" +" Subsequent calls will overwrite the previous ones, so only the last call +" determines to location to insert titles. +" +" NOTE: The titles are not inserted until |build| is called, so that the +" remaining contents of the tabline can be taken into account. +" +" Callers should define at least |get_title| and |get_group| on the host +" object before calling |build|. +function! s:prototype.insert_titles(current, first, last) dict + let self._first_title = a:first " lowest index + let self._last_title = a:last " highest index + let self._left_title = a:current " next index to add on the left + let self._right_title = a:current + 1 " next index to add on the right + let self._left_position = self.get_position() " left end of titles + let self._right_position = self._left_position " right end of the titles +endfunction + +" Insert a title for entry number |index|, of group |group| at position |pos|, +" if there is space for it. Returns 1 if it is inserted, 0 otherwise +" +" |force| inserts the title even if there isn't enough space left for it. +" |sep_size| adjusts the size change that the title is considered to take up, +" to account for changes to the separators +" +" The title is defined by |get_title| on the hosting object, called with +" |index| as its only argument. +" |get_pretitle| and |get_posttitle| may be defined on the host object to +" insert some formatting before or after the title. These should be 0-width. +" +" This method updates |_right_position| and |_remaining_space| on the host +" object, if the title is inserted. +function! s:prototype.try_insert_title(index, group, pos, sep_size, force) dict + let title = self.get_title(a:index) + let title_size = s:tabline_evaluated_length(title) + a:sep_size + if a:force || self._remaining_space >= title_size + let pos = a:pos + if has_key(self, "get_pretitle") + call self.insert_raw(self.get_pretitle(a:index), pos) + let self._right_position += 1 + let pos += 1 + endif + + call self.insert_section(a:group, title, pos) + let self._right_position += 1 + let pos += 1 + + if has_key(self, "get_posttitle") + call self.insert_raw(self.get_posttitle(a:index), pos) + let self._right_position += 1 + let pos += 1 + endif + + let self._remaining_space -= title_size + return 1 + endif + return 0 +endfunction + +function! s:get_separator_change(new_group, old_group, end_group, sep_size, alt_sep_size) + return s:get_separator_change_with_end(a:new_group, a:old_group, a:end_group, a:end_group, a:sep_size, a:alt_sep_size) +endfunction + +" Compute the change in size of the tabline caused by separators +" +" This should be kept up-to-date with |s:get_transitioned_seperator| and +" |s:get_separator| in autoload/airline/builder.vim +function! s:get_separator_change_with_end(new_group, old_group, new_end_group, old_end_group, sep_size, alt_sep_size) + let sep_change = 0 + if !empty(a:new_end_group) " Separator between title and the end + let sep_change += airline#builder#should_change_group(a:new_group, a:new_end_group) ? a:sep_size : a:alt_sep_size + endif + if !empty(a:old_group) " Separator between the title and the one adjacent + let sep_change += airline#builder#should_change_group(a:new_group, a:old_group) ? a:sep_size : a:alt_sep_size + if !empty(a:old_end_group) " Remove mis-predicted separator + let sep_change -= airline#builder#should_change_group(a:old_group, a:old_end_group) ? a:sep_size : a:alt_sep_size + endif + endif + return sep_change +endfunction + +" This replaces the build function of the |airline#builder#new| object, to +" insert titles as specified by the last call to |insert_titles| before +" passing to the original build function. +" +" Callers should define at least |get_title| and |get_group| on the host +" object if |insert_titles| has been called on it. +function! s:prototype.build() dict + if has_key(self, '_left_position') && self._first_title <= self._last_title + let self._remaining_space = &columns - s:tabline_evaluated_length(self._build()) + + let center_active = get(g:, 'airline#extensions#tabline#center_active', 0) + + let sep_size = s:tabline_evaluated_length(self._context.left_sep) + let alt_sep_size = s:tabline_evaluated_length(self._context.left_alt_sep) + + let outer_left_group = airline#builder#get_prev_group(self._sections, self._left_position) + let outer_right_group = airline#builder#get_next_group(self._sections, self._right_position) + + let overflow_marker = get(g:, 'airline#extensions#tabline#overflow_marker', g:airline_symbols.ellipsis) + let overflow_marker_size = s:tabline_evaluated_length(overflow_marker) + " Allow space for the markers before we begin filling in titles. + if self._left_title > self._first_title + let self._remaining_space -= overflow_marker_size + + \ s:get_separator_change(self.overflow_group, "", outer_left_group, sep_size, alt_sep_size) + endif + if self._left_title < self._last_title + let self._remaining_space -= overflow_marker_size + + \ s:get_separator_change(self.overflow_group, "", outer_right_group, sep_size, alt_sep_size) + endif + + " Add the current title + let group = self.get_group(self._left_title) + if self._left_title == self._first_title + let sep_change = s:get_separator_change(group, "", outer_left_group, sep_size, alt_sep_size) + else + let sep_change = s:get_separator_change(group, "", self.overflow_group, sep_size, alt_sep_size) + endif + if self._left_title == self._last_title + let sep_change += s:get_separator_change(group, "", outer_right_group, sep_size, alt_sep_size) + else + let sep_change += s:get_separator_change(group, "", self.overflow_group, sep_size, alt_sep_size) + endif + let left_group = group + let right_group = group + let self._left_title -= + \ self.try_insert_title(self._left_title, group, self._left_position, sep_change, 1) + + if get(g:, 'airline#extensions#tabline#current_first', 0) + " always have current title first + let self._left_position += 1 + endif + + if !center_active && self._right_title <= self._last_title + " Add the title to the right + let group = self.get_group(self._right_title) + if self._right_title == self._last_title + let sep_change = s:get_separator_change_with_end(group, right_group, outer_right_group, self.overflow_group, sep_size, alt_sep_size) - overflow_marker_size + else + let sep_change = s:get_separator_change(group, right_group, self.overflow_group, sep_size, alt_sep_size) + endif + let right_group = group + let self._right_title += + \ self.try_insert_title(self._right_title, group, self._right_position, sep_change, 1) + endif + + while self._remaining_space > 0 + let done = 0 + if self._left_title >= self._first_title + " Insert next title to the left + let group = self.get_group(self._left_title) + if self._left_title == self._first_title + let sep_change = s:get_separator_change_with_end(group, left_group, outer_left_group, self.overflow_group, sep_size, alt_sep_size) - overflow_marker_size + else + let sep_change = s:get_separator_change(group, left_group, self.overflow_group, sep_size, alt_sep_size) + endif + let left_group = group + let done = self.try_insert_title(self._left_title, group, self._left_position, sep_change, 0) + let self._left_title -= done + endif + " If center_active is set, this |if| operates as an independent |if|, + " otherwise as an |elif|. + if self._right_title <= self._last_title && (center_active || !done) + " Insert next title to the right + let group = self.get_group(self._right_title) + if self._right_title == self._last_title + let sep_change = s:get_separator_change_with_end(group, right_group, outer_right_group, self.overflow_group, sep_size, alt_sep_size) - overflow_marker_size + else + let sep_change = s:get_separator_change(group, right_group, self.overflow_group, sep_size, alt_sep_size) + endif + let right_group = group + let done = self.try_insert_title(self._right_title, group, self._right_position, sep_change, 0) + let self._right_title += done + endif + if !done + break + endif + endwhile + + if self._left_title >= self._first_title + if get(g:, 'airline#extensions#tabline#current_first', 0) + let self._left_position -= 1 + endif + call self.insert_section(self.overflow_group, overflow_marker, self._left_position) + let self._right_position += 1 + endif + + if self._right_title <= self._last_title + call self.insert_section(self.overflow_group, overflow_marker, self._right_position) + endif + endif + + return self._build() +endfunction + +let s:prototype.overflow_group = 'airline_tab' + +" Extract the text content a tabline will render. (Incomplete). +" +" See :help 'statusline' for the list of fields. +function! s:evaluate_tabline(tabline) + let tabline = a:tabline + let tabline = substitute(tabline, '%{\([^}]\+\)}', '\=eval(submatch(1))', 'g') + let tabline = substitute(tabline, '%#[^#]\+#', '', 'g') + let tabline = substitute(tabline, '%(\([^)]\+\)%)', '\1', 'g') + let tabline = substitute(tabline, '%\d\+[TX]', '', 'g') + let tabline = substitute(tabline, '%=', '', 'g') + let tabline = substitute(tabline, '%\d*\*', '', 'g') + if has('tablineat') + let tabline = substitute(tabline, '%@[^@]\+@', '', 'g') + endif + return tabline +endfunction + +function! s:tabline_evaluated_length(tabline) + return airline#util#strchars(s:evaluate_tabline(a:tabline)) +endfunction + +function! airline#extensions#tabline#builder#new(context) + let builder = airline#builder#new(a:context) + let builder._build = builder.build + call extend(builder, s:prototype, 'force') + return builder +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/ctrlspace.vim b/.vim/autoload/airline/extensions/tabline/ctrlspace.vim new file mode 100644 index 0000000..bb2d518 --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/ctrlspace.vim @@ -0,0 +1,157 @@ +" MIT License. Copyright (c) 2016-2018 Kevin Sapper et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:current_bufnr = -1 +let s:current_modified = 0 +let s:current_tabnr = -1 +let s:current_tabline = '' +let s:highlight_groups = ['hid', 0, '', 'sel', 'mod_unsel', 0, 'mod_unsel', 'mod'] + +function! airline#extensions#tabline#ctrlspace#off() + augroup airline_tabline_ctrlspace + autocmd! + augroup END +endfunction + +function! airline#extensions#tabline#ctrlspace#on() + augroup airline_tabline_ctrlspace + autocmd! + autocmd BufDelete * call airline#extensions#tabline#ctrlspace#invalidate() + augroup END +endfunction + +function! airline#extensions#tabline#ctrlspace#invalidate() + let s:current_bufnr = -1 + let s:current_tabnr = -1 +endfunction + +function! airline#extensions#tabline#ctrlspace#add_buffer_section(builder, cur_tab, cur_buf, pull_right) + let pos_extension = (a:pull_right ? '_right' : '') + let buffer_list = ctrlspace#api#BufferList(a:cur_tab) + + " add by tenfy(tenfyzhong@qq.com) + " if the current buffer no in the buffer list + " return false and no redraw tabline. + " Fixes #1515. if there a BufEnter autocmd execute redraw. The tabline may no update. + let bufnr_list = map(copy(buffer_list), 'v:val["index"]') + if index(bufnr_list, a:cur_buf) == -1 && a:cur_tab == s:current_tabnr + return 0 + endif + + let s:current_modified = getbufvar(a:cur_buf, '&modified') + + for buffer in buffer_list + let group = 'airline_tab' + \ .s:highlight_groups[(4 * buffer.modified) + (2 * buffer.visible) + (a:cur_buf == buffer.index)] + \ .pos_extension + + let buf_name = '%(%{airline#extensions#tabline#get_buffer_name('.buffer.index.')}%)' + + if has("tablineat") + let buf_name = '%'.buffer.index.'@airline#extensions#tabline#buffers#clickbuf@'.buf_name.'%X' + endif + + call a:builder.add_section_spaced(group, buf_name) + endfor + + " add by tenfy(tenfyzhong@qq.com) + " if the selected buffer was updated + " return true + return 1 +endfunction + +function! airline#extensions#tabline#ctrlspace#add_tab_section(builder, pull_right) + let pos_extension = (a:pull_right ? '_right' : '') + let tab_list = ctrlspace#api#TabList() + + for tab in tab_list + let group = 'airline_tab' + \ .s:highlight_groups[(4 * tab.modified) + (3 * tab.current)] + \ .pos_extension + + if get(g:, 'airline#extensions#tabline#ctrlspace_show_tab_nr', 0) == 0 + call a:builder.add_section_spaced(group, '%'.tab.index.'T'.tab.title.ctrlspace#api#TabBuffersNumber(tab.index).'%T') + else + call a:builder.add_section_spaced(group, '%'.(tab.index).'T'.(tab.index).(g:airline_symbols.space).(tab.title).ctrlspace#api#TabBuffersNumber(tab.index).'%T') + endif + endfor +endfunction + +function! airline#extensions#tabline#ctrlspace#get() + let cur_buf = bufnr('%') + let buffer_label = get(g:, 'airline#extensions#tabline#buffers_label', 'buffers') + let tab_label = get(g:, 'airline#extensions#tabline#tabs_label', 'tabs') + let switch_buffers_and_tabs = get(g:, 'airline#extensions#tabline#switch_buffers_and_tabs', 0) + + try + call airline#extensions#tabline#tabs#map_keys() + endtry + + let cur_tab = tabpagenr() + + if cur_buf == s:current_bufnr && cur_tab == s:current_tabnr + if !g:airline_detect_modified || getbufvar(cur_buf, '&modified') == s:current_modified + return s:current_tabline + endif + endif + + let builder = airline#extensions#tabline#new_builder() + + let show_buffers = get(g:, 'airline#extensions#tabline#show_buffers', 1) + let show_tabs = get(g:, 'airline#extensions#tabline#show_tabs', 1) + + let AppendBuffers = function('airline#extensions#tabline#ctrlspace#add_buffer_section', [builder, cur_tab, cur_buf]) + let AppendTabs = function('airline#extensions#tabline#ctrlspace#add_tab_section', [builder]) + let AppendLabel = function(builder.add_section_spaced, ['airline_tabtype'], builder) + + " <= 1: |{Tabs} <tab| + " == 2: |{Buffers} <buffers| + " == 3: |buffers> {Buffers} {Tabs} <tabs| + let showing_mode = (2 * show_buffers) + (show_tabs) + let ignore_update = 0 + + " Add left tabline content + if showing_mode <= 1 " Tabs only mode + call AppendTabs(0) + elseif showing_mode == 2 " Buffers only mode + let ignore_update = !AppendBuffers(0) + else + if !switch_buffers_and_tabs + call AppendLabel(buffer_label) + let ignore_update = !AppendBuffers(0) + else + call AppendLabel(tab_label) + call AppendTabs(0) + endif + endif + + if ignore_update | return s:current_tabline | endif + + call builder.add_section('airline_tabfill', '') + call builder.split() + call builder.add_section('airline_tabfill', '') + + " Add right tabline content + if showing_mode <= 1 " Tabs only mode + call AppendLabel(tab_label) + elseif showing_mode == 2 " Buffers only mode + call AppendLabel(buffer_label) + else + if !switch_buffers_and_tabs + call AppendTabs(1) + call AppendLabel(tab_label) + else + let ignore_update = AppendBuffers(1) + call AppendLabel(buffer_label) + endif + endif + + if ignore_update | return s:current_tabline | endif + + let s:current_bufnr = cur_buf + let s:current_tabnr = cur_tab + let s:current_tabline = builder.build() + return s:current_tabline +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/formatters/default.vim b/.vim/autoload/airline/extensions/tabline/formatters/default.vim new file mode 100644 index 0000000..c98d7ef --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/formatters/default.vim @@ -0,0 +1,43 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:fnamecollapse = get(g:, 'airline#extensions#tabline#fnamecollapse', 1) +let s:fnametruncate = get(g:, 'airline#extensions#tabline#fnametruncate', 0) +let s:buf_nr_format = get(g:, 'airline#extensions#tabline#buffer_nr_format', '%s: ') +let s:buf_nr_show = get(g:, 'airline#extensions#tabline#buffer_nr_show', 0) +let s:buf_modified_symbol = g:airline_symbols.modified + +function! airline#extensions#tabline#formatters#default#format(bufnr, buffers) + let fmod = get(g:, 'airline#extensions#tabline#fnamemod', ':~:.') + let _ = '' + + let name = bufname(a:bufnr) + if empty(name) + let _ .= '[No Name]' + else + if s:fnamecollapse + " Does not handle non-ascii characters like Cyrillic: 'D/Учёба/t.c' + "let _ .= substitute(fnamemodify(name, fmod), '\v\w\zs.{-}\ze(\\|/)', '', 'g') + let _ .= pathshorten(fnamemodify(name, fmod)) + else + let _ .= fnamemodify(name, fmod) + endif + if a:bufnr != bufnr('%') && s:fnametruncate && strlen(_) > s:fnametruncate + let _ = strpart(_, 0, s:fnametruncate) + endif + endif + + return airline#extensions#tabline#formatters#default#wrap_name(a:bufnr, _) +endfunction + +function! airline#extensions#tabline#formatters#default#wrap_name(bufnr, buffer_name) + let _ = s:buf_nr_show ? printf(s:buf_nr_format, a:bufnr) : '' + let _ .= substitute(a:buffer_name, '\\', '/', 'g') + + if getbufvar(a:bufnr, '&modified') == 1 + let _ .= s:buf_modified_symbol + endif + return _ +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/formatters/jsformatter.vim b/.vim/autoload/airline/extensions/tabline/formatters/jsformatter.vim new file mode 100644 index 0000000..b16d06f --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/formatters/jsformatter.vim @@ -0,0 +1,15 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#tabline#formatters#jsformatter#format(bufnr, buffers) + let buf = bufname(a:bufnr) + let filename = fnamemodify(buf, ':t') + + if filename == 'index.js' || filename == 'index.jsx' || filename == 'index.ts' || filename == 'index.tsx' + return fnamemodify(buf, ':p:h:t') . '/i' + else + return airline#extensions#tabline#formatters#unique_tail_improved#format(a:bufnr, a:buffers) + endif +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/formatters/tabnr.vim b/.vim/autoload/airline/extensions/tabline/formatters/tabnr.vim new file mode 100644 index 0000000..fa71014 --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/formatters/tabnr.vim @@ -0,0 +1,14 @@ +" MIT License. Copyright (c) 2017-2018 C.Brabandt et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#tabline#formatters#tabnr#format(tab_nr_type, nr) + if a:tab_nr_type == 0 " nr of splits + return (g:airline_symbols.space).'%{len(tabpagebuflist('.a:nr.'))}' + elseif a:tab_nr_type == 1 " tab number + return (g:airline_symbols.space).a:nr + else "== 2 splits and tab number + return (g:airline_symbols.space).a:nr.'.%{len(tabpagebuflist('.a:nr.'))}' + endif +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/formatters/unique_tail.vim b/.vim/autoload/airline/extensions/tabline/formatters/unique_tail.vim new file mode 100644 index 0000000..3e61b60 --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/formatters/unique_tail.vim @@ -0,0 +1,41 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#tabline#formatters#unique_tail#format(bufnr, buffers) + let duplicates = {} + let tails = {} + let map = {} + for nr in a:buffers + let name = bufname(nr) + if empty(name) + let map[nr] = '[No Name]' + else + let tail = fnamemodify(name, ':s?/\+$??:t') + if has_key(tails, tail) + let duplicates[nr] = nr + endif + let tails[tail] = 1 + let map[nr] = airline#extensions#tabline#formatters#default#wrap_name(nr, tail) + endif + endfor + + let fmod = get(g:, 'airline#extensions#tabline#fnamemod', ':p:.') + for nr in values(duplicates) + let name = bufname(nr) + let fnamecollapse = get(g:, 'airline#extensions#tabline#fnamecollapse', 1) + if fnamecollapse + let map[nr] = airline#extensions#tabline#formatters#default#wrap_name(nr, substitute(fnamemodify(name, fmod), '\v\w\zs.{-}\ze(\\|/)', '', 'g')) + else + let map[nr] = airline#extensions#tabline#formatters#default#wrap_name(nr, fnamemodify(name, fmod)) + endif + endfor + + if has_key(map, a:bufnr) + return map[a:bufnr] + endif + + " if we get here, the buffer list isn't in sync with the selected buffer yet, fall back to the default + return airline#extensions#tabline#formatters#default#format(a:bufnr, a:buffers) +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/formatters/unique_tail_improved.vim b/.vim/autoload/airline/extensions/tabline/formatters/unique_tail_improved.vim new file mode 100644 index 0000000..c48174b --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/formatters/unique_tail_improved.vim @@ -0,0 +1,91 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:skip_symbol = '…' + +function! airline#extensions#tabline#formatters#unique_tail_improved#format(bufnr, buffers) + if len(a:buffers) <= 1 " don't need to compare bufnames if has less than one buffer opened + return airline#extensions#tabline#formatters#default#format(a:bufnr, a:buffers) + endif + + let curbuf_tail = fnamemodify(bufname(a:bufnr), ':t') + let do_deduplicate = 0 + let path_tokens = {} + + for nr in a:buffers + let name = bufname(nr) + if !empty(name) && nr != a:bufnr && fnamemodify(name, ':t') == curbuf_tail " only perform actions if curbuf_tail isn't unique + let do_deduplicate = 1 + let tokens = reverse(split(substitute(fnamemodify(name, ':p:h'), '\\', '/', 'g'), '/')) + let token_index = 0 + for token in tokens + if token == '' | continue | endif + if token == '.' | break | endif + if !has_key(path_tokens, token_index) + let path_tokens[token_index] = {} + endif + let path_tokens[token_index][token] = 1 + let token_index += 1 + endfor + endif + endfor + + if do_deduplicate == 1 + let path = [] + let token_index = 0 + for token in reverse(split(substitute(fnamemodify(bufname(a:bufnr), ':p:h'), '\\', '/', 'g'), '/')) + if token == '.' | break | endif + let duplicated = 0 + let uniq = 1 + let single = 1 + if has_key(path_tokens, token_index) + let duplicated = 1 + if len(keys(path_tokens[token_index])) > 1 | let single = 0 | endif + if has_key(path_tokens[token_index], token) | let uniq = 0 | endif + endif + call insert(path, {'token': token, 'duplicated': duplicated, 'uniq': uniq, 'single': single}) + let token_index += 1 + endfor + + let buf_name = [curbuf_tail] + let has_uniq = 0 + let has_skipped = 0 + for token1 in reverse(path) + if !token1['duplicated'] && len(buf_name) > 1 + call insert(buf_name, s:skip_symbol) + let has_skipped = 0 + break + endif + + if has_uniq == 1 + call insert(buf_name, s:skip_symbol) + let has_skipped = 0 + break + endif + + if token1['uniq'] == 0 && token1['single'] == 1 + let has_skipped = 1 + else + if has_skipped == 1 + call insert(buf_name, s:skip_symbol) + let has_skipped = 0 + endif + call insert(buf_name, token1['token']) + endif + + if token1['uniq'] == 1 + let has_uniq = 1 + endif + endfor + + if has_skipped == 1 + call insert(buf_name, s:skip_symbol) + endif + + return airline#extensions#tabline#formatters#default#wrap_name(a:bufnr, join(buf_name, '/')) + else + return airline#extensions#tabline#formatters#default#format(a:bufnr, a:buffers) + endif +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/tabs.vim b/.vim/autoload/airline/extensions/tabline/tabs.vim new file mode 100644 index 0000000..a74ab5b --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/tabs.vim @@ -0,0 +1,124 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:spc = g:airline_symbols.space +let s:current_bufnr = -1 +let s:current_tabnr = -1 +let s:current_modified = 0 + +function! airline#extensions#tabline#tabs#off() + augroup airline_tabline_tabs + autocmd! + augroup END +endfunction + +function! airline#extensions#tabline#tabs#on() + augroup airline_tabline_tabs + autocmd! + autocmd BufDelete * call airline#extensions#tabline#tabs#invalidate() + augroup END +endfunction + +function! airline#extensions#tabline#tabs#invalidate() + let s:current_bufnr = -1 +endfunction + +function! airline#extensions#tabline#tabs#get() + let curbuf = bufnr('%') + let curtab = tabpagenr() + try + call airline#extensions#tabline#tabs#map_keys() + catch + " no-op + endtry + if curbuf == s:current_bufnr && curtab == s:current_tabnr && &columns == s:column_width + if !g:airline_detect_modified || getbufvar(curbuf, '&modified') == s:current_modified + return s:current_tabline + endif + endif + + let b = airline#extensions#tabline#new_builder() + + call airline#extensions#tabline#add_label(b, 'tabs') + + function! b.get_group(i) dict + let curtab = tabpagenr() + let group = 'airline_tab' + if a:i == curtab + let group = 'airline_tabsel' + if g:airline_detect_modified + for bi in tabpagebuflist(curtab) + if getbufvar(bi, '&modified') + let group = 'airline_tabmod' + endif + endfor + endif + let s:current_modified = (group == 'airline_tabmod') ? 1 : 0 + endif + return group + endfunction + + function! b.get_title(i) dict + let val = '%(' + + if get(g:, 'airline#extensions#tabline#show_tab_nr', 1) + let tab_nr_type = get(g:, 'airline#extensions#tabline#tab_nr_type', 0) + let val .= airline#extensions#tabline#tabs#tabnr_formatter(tab_nr_type, a:i) + endif + + return val.'%'.a:i.'T %{airline#extensions#tabline#title('.a:i.')} %)' + endfunction + + call b.insert_titles(curtab, 1, tabpagenr('$')) + + call b.add_section('airline_tabfill', '') + call b.split() + call b.add_section('airline_tabfill', '') + + if get(g:, 'airline#extensions#tabline#show_close_button', 1) + call b.add_section('airline_tab_right', ' %999X'. + \ get(g:, 'airline#extensions#tabline#close_symbol', 'X').' ') + endif + + if get(g:, 'airline#extensions#tabline#show_splits', 1) == 1 + let buffers = tabpagebuflist(curtab) + for nr in buffers + let group = airline#extensions#tabline#group_of_bufnr(buffers, nr) . "_right" + call b.add_section_spaced(group, '%(%{airline#extensions#tabline#get_buffer_name('.nr.')}%)') + endfor + if get(g:, 'airline#extensions#tabline#show_buffers', 1) + call airline#extensions#tabline#add_label(b, 'buffers') + endif + endif + + let s:current_bufnr = curbuf + let s:current_tabnr = curtab + let s:column_width = &columns + let s:current_tabline = b.build() + return s:current_tabline +endfunction + +function! airline#extensions#tabline#tabs#map_keys() + if maparg('<Plug>AirlineSelectTab1', 'n') is# ':1tabn<CR>' + return + endif + noremap <silent> <Plug>AirlineSelectTab1 :1tabn<CR> + noremap <silent> <Plug>AirlineSelectTab2 :2tabn<CR> + noremap <silent> <Plug>AirlineSelectTab3 :3tabn<CR> + noremap <silent> <Plug>AirlineSelectTab4 :4tabn<CR> + noremap <silent> <Plug>AirlineSelectTab5 :5tabn<CR> + noremap <silent> <Plug>AirlineSelectTab6 :6tabn<CR> + noremap <silent> <Plug>AirlineSelectTab7 :7tabn<CR> + noremap <silent> <Plug>AirlineSelectTab8 :8tabn<CR> + noremap <silent> <Plug>AirlineSelectTab9 :9tabn<CR> + noremap <silent> <Plug>AirlineSelectPrevTab gT + " tabn {count} goes to count tab does not go {count} tab pages forward! + noremap <silent> <Plug>AirlineSelectNextTab :<C-U>exe repeat(':tabn\|', v:count1)<cr> +endfunction + +function! airline#extensions#tabline#tabs#tabnr_formatter(nr, i) + let formatter = get(g:, 'airline#extensions#tabline#tabnr_formatter', 'tabnr') + return airline#extensions#tabline#formatters#{formatter}#format(a:nr, a:i) +endfunction diff --git a/.vim/autoload/airline/extensions/tabline/xtabline.vim b/.vim/autoload/airline/extensions/tabline/xtabline.vim new file mode 100644 index 0000000..4d1cdec --- /dev/null +++ b/.vim/autoload/airline/extensions/tabline/xtabline.vim @@ -0,0 +1,397 @@ +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" xTabline - Reduced version for vim-airline +" Copyright (C) 2018 Gianmaria Bajo <mg1979.git@gmail.com> +" License: MIT License +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + +function! airline#extensions#tabline#xtabline#init() + + let s:state = 0 + + " initialize mappings + call airline#extensions#tabline#xtabline#maps() + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + " Variables + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + let g:loaded_xtabline = 1 + let s:most_recent = -1 + let s:xtabline_filtering = 1 + + let t:xtl_excluded = get(g:, 'airline#extensions#tabline#exclude_buffers', []) + let t:xtl_accepted = [] + + let g:xtabline_include_previews = get(g:, 'xtabline_include_previews', 1) + + let g:xtabline_alt_action = get(g:, 'xtabline_alt_action', "buffer #") + + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + " Autocommands + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + augroup plugin-xtabline + autocmd! + + autocmd TabNew * call s:Do('new') + autocmd TabEnter * call s:Do('enter') + autocmd TabLeave * call s:Do('leave') + autocmd TabClosed * call s:Do('close') + + autocmd BufEnter * let g:xtabline_changing_buffer = 0 + autocmd BufAdd,BufDelete,BufWrite * call airline#extensions#tabline#xtabline#filter_buffers() + augroup END + + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + " Commands + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + com! XTabReopen call airline#extensions#tabline#xtabline#reopen_last_tab() + +endfunction + + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Mappings +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#maps() + + if !exists('g:xtabline_disable_keybindings') + + fun! s:mapkeys(keys, plug) + if empty(mapcheck(a:keys)) && !hasmapto(a:plug) + silent! execute 'nmap <unique> '.a:keys.' '.a:plug + endif + endfun + + call s:mapkeys('<F5>','<Plug>XTablineToggleTabs') + call s:mapkeys('<leader><F5>','<Plug>XTablineToggleFiltering') + call s:mapkeys('<BS>','<Plug>XTablineSelectBuffer') + call s:mapkeys(']l','<Plug>XTablineNextBuffer') + call s:mapkeys('[l','<Plug>XTablinePrevBuffer') + call s:mapkeys('<leader>tr','<Plug>XTablineReopen') + endif + + nnoremap <unique> <script> <Plug>XTablineToggleTabs <SID>ToggleTabs + nnoremap <silent> <SID>ToggleTabs :call airline#extensions#tabline#xtabline#toggle_tabs()<cr> + + nnoremap <unique> <script> <Plug>XTablineToggleFiltering <SID>ToggleFiltering + nnoremap <silent> <SID>ToggleFiltering :call airline#extensions#tabline#xtabline#toggle_buffers()<cr> + + nnoremap <unique> <script> <Plug>XTablineSelectBuffer <SID>SelectBuffer + nnoremap <silent> <expr> <SID>SelectBuffer g:xtabline_changing_buffer ? "\<C-c>" : ":<C-u>call airline#extensions#tabline#xtabline#select_buffer(v:count)\<cr>" + + nnoremap <unique> <script> <Plug>XTablineNextBuffer <SID>NextBuffer + nnoremap <silent> <expr> <SID>NextBuffer airline#extensions#tabline#xtabline#next_buffer(v:count1) + + nnoremap <unique> <script> <Plug>XTablinePrevBuffer <SID>PrevBuffer + nnoremap <silent> <expr> <SID>PrevBuffer airline#extensions#tabline#xtabline#prev_buffer(v:count1) + + nnoremap <unique> <script> <Plug>XTablineReopen <SID>ReopenLastTab + nnoremap <silent> <SID>ReopenLastTab :XTabReopen<cr> + + if get(g:, 'xtabline_cd_commands', 0) + map <unique> <leader>cdc <Plug>XTablineCdCurrent + map <unique> <leader>cdd <Plug>XTablineCdDown1 + map <unique> <leader>cd2 <Plug>XTablineCdDown2 + map <unique> <leader>cd3 <Plug>XTablineCdDown3 + map <unique> <leader>cdh <Plug>XTablineCdHome + nnoremap <unique> <script> <Plug>XTablineCdCurrent :cd %:p:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr> + nnoremap <unique> <script> <Plug>XTablineCdDown1 :cd %:p:h:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr> + nnoremap <unique> <script> <Plug>XTablineCdDown2 :cd %:p:h:h:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr> + nnoremap <unique> <script> <Plug>XTablineCdDown3 :cd %:p:h:h:h:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr> + nnoremap <unique> <script> <Plug>XTablineCdHome :cd ~<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr> + endif +endfunction + + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Commands functions +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#toggle_tabs() + """Toggle between tabs/buffers tabline.""" + + if tabpagenr("$") == 1 | call airline#util#warning("There is only one tab.") | return | endif + + if g:airline#extensions#tabline#show_tabs + let g:airline#extensions#tabline#show_tabs = 0 + call airline#util#warning("Showing buffers") + else + let g:airline#extensions#tabline#show_tabs = 1 + call airline#util#warning("Showing tabs") + endif + + doautocmd BufAdd +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#toggle_buffers() + """Toggle buffer filtering in the tabline.""" + + if s:xtabline_filtering + let s:xtabline_filtering = 0 + let g:airline#extensions#tabline#exclude_buffers = [] + call airline#util#warning("Buffer filtering turned off") + doautocmd BufAdd + else + let s:xtabline_filtering = 1 + call airline#extensions#tabline#xtabline#filter_buffers() + call airline#util#warning("Buffer filtering turned on") + doautocmd BufAdd + endif +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#reopen_last_tab() + """Reopen the last closed tab.""" + + if !exists('s:most_recently_closed_tab') + call airline#util#warning("No recent tabs.") + return + endif + + let tab = s:most_recently_closed_tab + tabnew + let empty = bufnr("%") + let t:cwd = tab['cwd'] + cd `=t:cwd` + let t:name = tab['name'] + for buf in tab['buffers'] | execute "badd ".buf | endfor + execute "edit ".tab['buffers'][0] + execute "bdelete ".empty +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#filter_buffers() + """Filter buffers so that only the ones within the tab's cwd will show up. + + " 'accepted' is a list of buffer numbers, for quick access. + " 'excluded' is a list of buffer numbers, it will be used by Airline to hide buffers. + + if !s:xtabline_filtering | return | endif + + let g:airline#extensions#tabline#exclude_buffers = [] + let t:xtl_excluded = g:airline#extensions#tabline#exclude_buffers + let t:xtl_accepted = [] | let accepted = t:xtl_accepted + let previews = g:xtabline_include_previews + + " bufnr(0) is the alternate buffer + for buf in range(1, bufnr("$")) + + if !buflisted(buf) | continue | endif + + " get the path + let path = expand("#".buf.":p") + + " confront with the cwd + if !previews && path =~ "^".getcwd() + call add(accepted, buf) + elseif previews && path =~ getcwd() + call add(accepted, buf) + else + call add(t:xtl_excluded, buf) + endif + endfor + + call s:RefreshTabline() +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#next_buffer(nr) + """Switch to next visible buffer.""" + + if ( s:NotEnoughBuffers() || !s:xtabline_filtering ) | return | endif + let accepted = t:xtl_accepted + + let ix = index(accepted, bufnr("%")) + let target = ix + a:nr + let total = len(accepted) + + if ix == -1 + " not in index, go back to most recent or back to first + if s:most_recent == -1 || s:most_recent >= total + let s:most_recent = 0 + endif + + elseif target >= total + " over last buffer + while target >= total | let target -= total | endwhile + let s:most_recent = target + + else + let s:most_recent = target + endif + + return ":buffer " . accepted[s:most_recent] . "\<cr>" +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#prev_buffer(nr) + """Switch to previous visible buffer.""" + + if ( s:NotEnoughBuffers() || !s:xtabline_filtering ) | return | endif + let accepted = t:xtl_accepted + + let ix = index(accepted, bufnr("%")) + let target = ix - a:nr + let total = len(accepted) + + if ix == -1 + " not in index, go back to most recent or back to first + if s:most_recent == -1 || s:most_recent >= total + let s:most_recent = 0 + endif + + elseif target < 0 + " before first buffer + while target < 0 | let target += total | endwhile + let s:most_recent = target + + else + let s:most_recent = target + endif + + return ":buffer " . accepted[s:most_recent] . "\<cr>" +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#select_buffer(nr) + """Switch to visible buffer in the tabline with [count].""" + + if ( a:nr == 0 || !s:xtabline_filtering ) | execute g:xtabline_alt_action | return | endif + let accepted = t:xtl_accepted + + if (a:nr > len(accepted)) || s:NotEnoughBuffers() || accepted[a:nr - 1] == bufnr("%") + return + else + let g:xtabline_changing_buffer = 1 + execute "buffer ".accepted[a:nr - 1] + endif +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! s:TabBuffers() + """Return a list of buffers names for this tab.""" + + return map(copy(t:xtl_accepted), 'bufname(v:val)') +endfunction + + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Helper functions +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! s:NotEnoughBuffers() + """Just return if there aren't enough buffers.""" + + if len(t:xtl_accepted) < 2 + if index(t:xtl_accepted, bufnr("%")) == -1 + return + elseif !len(t:xtl_accepted) + call airline#util#warning("No available buffers for this tab.") + else + call airline#util#warning("No other available buffers for this tab.") + endif + return 1 + endif +endfunction + +function! s:RefreshTabline() + call airline#extensions#tabline#buflist#invalidate() +endfunction + + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" TabPageCd +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +" tabpagecd - Turn :cd into :tabpagecd, to use one tab page per project +" expanded version by mg979 +" Copyright (C) 2012-2013 Kana Natsuno <http://whileimautomaton.net/> +" Copyright (C) 2018 Gianmaria Bajo <mg1979.git@gmail.com> +" License: MIT License + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! s:InitCwds() + if !exists('g:xtab_cwds') | let g:xtab_cwds = [] | endif + + while len(g:xtab_cwds) < tabpagenr("$") + call add(g:xtab_cwds, getcwd()) + endwhile + let s:state = 1 + let t:cwd = getcwd() + let s:last_tab = 0 + call airline#extensions#tabline#xtabline#filter_buffers() +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! airline#extensions#tabline#xtabline#update_obsession() + let string = 'let g:xtab_cwds = '.string(g:xtab_cwds).' | call airline#extensions#tabline#xtabline#update_obsession()' + if !exists('g:obsession_append') + let g:obsession_append = [string] + else + call filter(g:obsession_append, 'v:val !~# "^let g:xtab_cwds"') + call add(g:obsession_append, string) + endif +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! s:Do(action) + let arg = a:action + if !s:state | call s:InitCwds() | return | endif + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + if arg == 'new' + + call insert(g:xtab_cwds, getcwd(), tabpagenr()-1) + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + elseif arg == 'enter' + + let t:cwd =g:xtab_cwds[tabpagenr()-1] + + cd `=t:cwd` + call airline#extensions#tabline#xtabline#filter_buffers() + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + elseif arg == 'leave' + + let t:cwd = getcwd() + let g:xtab_cwds[tabpagenr()-1] = t:cwd + let s:last_tab = tabpagenr() - 1 + + if !exists('t:name') | let t:name = t:cwd | endif + let s:most_recent_tab = {'cwd': t:cwd, 'name': t:name, 'buffers': s:TabBuffers()} + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + elseif arg == 'close' + + let s:most_recently_closed_tab = copy(s:most_recent_tab) + call remove(g:xtab_cwds, s:last_tab) + endif + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + call airline#extensions#tabline#xtabline#update_obsession() +endfunction + +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/.vim/autoload/airline/extensions/tagbar.vim b/.vim/autoload/airline/extensions/tagbar.vim new file mode 100644 index 0000000..5db53ee --- /dev/null +++ b/.vim/autoload/airline/extensions/tagbar.vim @@ -0,0 +1,58 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':TagbarToggle') + finish +endif + +let s:flags = get(g:, 'airline#extensions#tagbar#flags', '') +let s:spc = g:airline_symbols.space +let s:init=0 + +" Arguments: current, sort, fname +function! airline#extensions#tagbar#get_status(...) + let builder = airline#builder#new({ 'active': a:1 }) + call builder.add_section('airline_a', s:spc.'Tagbar'.s:spc) + call builder.add_section('airline_b', s:spc.a:2.s:spc) + call builder.add_section('airline_c', s:spc.a:3.s:spc) + return builder.build() +endfunction + +function! airline#extensions#tagbar#inactive_apply(...) + if getwinvar(a:2.winnr, '&filetype') == 'tagbar' + return -1 + endif +endfunction + +let s:airline_tagbar_last_lookup_time = 0 +let s:airline_tagbar_last_lookup_val = '' +function! airline#extensions#tagbar#currenttag() + if get(w:, 'airline_active', 0) + if !s:init + try + " try to load the plugin, if filetypes are disabled, + " this will cause an error, so try only once + let a=tagbar#currenttag('%', '', '') + catch + endtry + unlet! a + let s:init=1 + endif + " function tagbar#currenttag does not exist, if filetype is not enabled + if s:airline_tagbar_last_lookup_time != localtime() && exists("*tagbar#currenttag") + let s:airline_tagbar_last_lookup_val = tagbar#currenttag('%s', '', s:flags) + let s:airline_tagbar_last_lookup_time = localtime() + endif + return s:airline_tagbar_last_lookup_val + endif + return '' +endfunction + +function! airline#extensions#tagbar#init(ext) + call a:ext.add_inactive_statusline_func('airline#extensions#tagbar#inactive_apply') + let g:tagbar_status_func = 'airline#extensions#tagbar#get_status' + + call airline#parts#define_function('tagbar', 'airline#extensions#tagbar#currenttag') +endfunction diff --git a/.vim/autoload/airline/extensions/term.vim b/.vim/autoload/airline/extensions/term.vim new file mode 100644 index 0000000..c5b578e --- /dev/null +++ b/.vim/autoload/airline/extensions/term.vim @@ -0,0 +1,43 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#term#apply(...) + if &buftype == 'terminal' + let spc = g:airline_symbols.space + + let name=get(g:airline_mode_map, 't', 't') + call a:1.add_section('airline_a', spc.name.spc) + call a:1.add_section('airline_b', '') + call a:1.add_section('airline_term', spc.s:termname()) + call a:1.split() + call a:1.add_section('airline_y', '') + call a:1.add_section('airline_z', spc.airline#section#create_right(['linenr', 'maxlinenr'])) + return 1 + endif +endfunction + +function! airline#extensions#term#inactive_apply(...) + if getbufvar(a:2.bufnr, '&buftype') == 'terminal' + let spc = g:airline_symbols.space + call a:1.add_section('airline_a', spc.'TERMINAL'.spc) + call a:1.add_section('airline_b', spc.'%f') + return 1 + endif +endfunction + +function! s:termname() + let bufname = bufname('%') + if has('nvim') + return matchstr(bufname, 'term.*:\zs.*') + else + " get rid of leading '!' + return bufname[1:] + endif +endfunction + +function! airline#extensions#term#init(ext) + call a:ext.add_statusline_func('airline#extensions#term#apply') + call a:ext.add_inactive_statusline_func('airline#extensions#term#inactive_apply') +endfunction diff --git a/.vim/autoload/airline/extensions/tmuxline.vim b/.vim/autoload/airline/extensions/tmuxline.vim new file mode 100644 index 0000000..44c7ec2 --- /dev/null +++ b/.vim/autoload/airline/extensions/tmuxline.vim @@ -0,0 +1,27 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':Tmuxline') + finish +endif + +let s:tmuxline_snapshot_file = get(g:, 'airline#extensions#tmuxline#snapshot_file', '') +let s:color_template = get(g:, 'airline#extensions#tmuxline#color_template', 'normal') + +function! airline#extensions#tmuxline#init(ext) + call a:ext.add_theme_func('airline#extensions#tmuxline#set_tmux_colors') +endfunction + +function! airline#extensions#tmuxline#set_tmux_colors(palette) + let color_template = has_key(a:palette, s:color_template) ? s:color_template : 'normal' + let mode_palette = a:palette[color_template] + + let tmuxline_theme = tmuxline#api#create_theme_from_airline(mode_palette) + call tmuxline#api#set_theme(tmuxline_theme) + + if strlen(s:tmuxline_snapshot_file) + call tmuxline#api#snapshot(s:tmuxline_snapshot_file) + endif +endfunction diff --git a/.vim/autoload/airline/extensions/undotree.vim b/.vim/autoload/airline/extensions/undotree.vim new file mode 100644 index 0000000..9e43dfb --- /dev/null +++ b/.vim/autoload/airline/extensions/undotree.vim @@ -0,0 +1,28 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists(':UndotreeToggle') + finish +endif + +function! airline#extensions#undotree#apply(...) + if exists('t:undotree') + if &ft == 'undotree' + if exists('*t:undotree.GetStatusLine') + call airline#extensions#apply_left_override('undo', '%{t:undotree.GetStatusLine()}') + else + call airline#extensions#apply_left_override('undotree', '%f') + endif + endif + + if &ft == 'diff' && exists('*t:diffpanel.GetStatusLine') + call airline#extensions#apply_left_override('diff', '%{t:diffpanel.GetStatusLine()}') + endif + endif +endfunction + +function! airline#extensions#undotree#init(ext) + call a:ext.add_statusline_func('airline#extensions#undotree#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/unicode.vim b/.vim/autoload/airline/extensions/unicode.vim new file mode 100644 index 0000000..4afe129 --- /dev/null +++ b/.vim/autoload/airline/extensions/unicode.vim @@ -0,0 +1,24 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_unicodePlugin', 0) + finish +endif + +function! airline#extensions#unicode#apply(...) + if exists(":UnicodeTable") == 2 && bufname('') ==# 'UnicodeTable' + call airline#parts#define('unicode', { + \ 'text': '[UnicodeTable]', + \ 'accent': 'bold' }) + let w:airline_section_a = airline#section#create(['unicode']) + let w:airline_section_b = '' + let w:airline_section_c = ' ' + let w:airline_section_y = '' + endif +endfunction + +function! airline#extensions#unicode#init(ext) + call a:ext.add_statusline_func('airline#extensions#unicode#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/unite.vim b/.vim/autoload/airline/extensions/unite.vim new file mode 100644 index 0000000..c6a09f0 --- /dev/null +++ b/.vim/autoload/airline/extensions/unite.vim @@ -0,0 +1,24 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !get(g:, 'loaded_unite', 0) + finish +endif + +function! airline#extensions#unite#apply(...) + if &ft == 'unite' + call a:1.add_section('airline_a', ' Unite ') + call a:1.add_section('airline_b', ' %{get(unite#get_context(), "buffer_name", "")} ') + call a:1.add_section('airline_c', ' %{unite#get_status_string()} ') + call a:1.split() + call a:1.add_section('airline_y', ' %{get(unite#get_context(), "real_buffer_name", "")} ') + return 1 + endif +endfunction + +function! airline#extensions#unite#init(ext) + let g:unite_force_overwrite_statusline = 0 + call a:ext.add_statusline_func('airline#extensions#unite#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/vimagit.vim b/.vim/autoload/airline/extensions/vimagit.vim new file mode 100644 index 0000000..8c98ec9 --- /dev/null +++ b/.vim/autoload/airline/extensions/vimagit.vim @@ -0,0 +1,34 @@ +" MIT License. Copyright (c) 2016-2018 Jerome Reybert et al. +" vim: et ts=2 sts=2 sw=2 + +" This plugin replace the whole section_a when in vimagit buffer +scriptencoding utf-8 + +if !get(g:, 'loaded_magit', 0) + finish +endif + +function! airline#extensions#vimagit#init(ext) + call a:ext.add_statusline_func('airline#extensions#vimagit#apply') +endfunction + +function! airline#extensions#vimagit#get_mode() + if ( exists("*magit#get_current_mode") ) + return magit#get_current_mode() + else + if ( b:magit_current_commit_mode == '' ) + return "STAGING" + elseif ( b:magit_current_commit_mode == 'CC' ) + return "COMMIT" + elseif ( b:magit_current_commit_mode == 'CA' ) + return "AMEND" + else + return "???" + endif +endfunction + +function! airline#extensions#vimagit#apply(...) + if ( &filetype == 'magit' ) + let w:airline_section_a = '%{airline#extensions#vimagit#get_mode()}' + endif +endfunction diff --git a/.vim/autoload/airline/extensions/vimtex.vim b/.vim/autoload/airline/extensions/vimtex.vim new file mode 100644 index 0000000..9eda8d5 --- /dev/null +++ b/.vim/autoload/airline/extensions/vimtex.vim @@ -0,0 +1,84 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +" This plugin replace the whole section_a when in vimagit buffer +scriptencoding utf-8 + +let s:spc = g:airline_symbols.space + +function! s:SetDefault(var, val) + if !exists(a:var) + execute 'let ' . a:var . '=' . string(a:val) + endif +endfunction + +" Left and right delimiters (added only when status string is not empty) +call s:SetDefault( 'g:airline#extensions#vimtex#left', "{") +call s:SetDefault( 'g:airline#extensions#vimtex#right', "}") + +" The current tex file is the main project file +call s:SetDefault( 'g:airline#extensions#vimtex#main', "" ) +" +" The current tex file is a subfile of the project +" and the compilation is set for the main file +call s:SetDefault( 'g:airline#extensions#vimtex#sub_main', "m") +" +" The current tex file is a subfile of the project +" and the compilation is set for this subfile +call s:SetDefault( 'g:airline#extensions#vimtex#sub_local', "l") +" +" Compilation is running and continuous compilation is off +call s:SetDefault( 'g:airline#extensions#vimtex#compiled', "c₁") + +" Compilation is running and continuous compilation is on +call s:SetDefault( 'g:airline#extensions#vimtex#continuous', "c") + +" Viewer is opened +call s:SetDefault( 'g:airline#extensions#vimtex#viewer', "v") + +function! airline#extensions#vimtex#init(ext) + call airline#parts#define_raw('vimtex', '%{airline#extensions#vimtex#get_scope()}') + call a:ext.add_statusline_func('airline#extensions#vimtex#apply') +endfunction + +function! airline#extensions#vimtex#apply(...) + if exists("b:vimtex") + let w:airline_section_x = get(w:, 'airline_section_x', g:airline_section_x) + let w:airline_section_x.=s:spc.g:airline_left_alt_sep.s:spc.'%{airline#extensions#vimtex#get_scope()}' + endif +endfunction + +function! airline#extensions#vimtex#get_scope() + let l:status = '' + + let vt_local = get(b:, 'vimtex_local', {}) + if empty(vt_local) + let l:status .= g:airline#extensions#vimtex#main + else + if get(vt_local, 'active') + let l:status .= g:airline#extensions#vimtex#sub_local + else + let l:status .= g:airline#extensions#vimtex#sub_main + endif + endif + + if get(get(get(b:, 'vimtex', {}), 'viewer', {}), 'xwin_id') + let l:status .= g:airline#extensions#vimtex#viewer + endif + + let l:compiler = get(get(b:, 'vimtex', {}), 'compiler', {}) + if !empty(l:compiler) + if has_key(l:compiler, 'is_running') && b:vimtex.compiler.is_running() + if get(l:compiler, 'continuous') + let l:status .= g:airline#extensions#vimtex#continuous + else + let l:status .= g:airline#extensions#vimtex#compiled + endif + endif + endif + + if !empty(l:status) + let l:status = g:airline#extensions#vimtex#left . l:status . g:airline#extensions#vimtex#right + endif + return l:status +endfunction diff --git a/.vim/autoload/airline/extensions/virtualenv.vim b/.vim/autoload/airline/extensions/virtualenv.vim new file mode 100644 index 0000000..b494d85 --- /dev/null +++ b/.vim/autoload/airline/extensions/virtualenv.vim @@ -0,0 +1,31 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:spc = g:airline_symbols.space + +function! airline#extensions#virtualenv#init(ext) + call a:ext.add_statusline_func('airline#extensions#virtualenv#apply') +endfunction + +function! airline#extensions#virtualenv#apply(...) + if &filetype =~# "python" + if get(g:, 'virtualenv_loaded', 0) + let statusline = virtualenv#statusline() + else + let statusline = fnamemodify($VIRTUAL_ENV, ':t') + endif + if !empty(statusline) + call airline#extensions#append_to_section('x', + \ s:spc.g:airline_right_alt_sep.s:spc.statusline) + endif + endif +endfunction + +function! airline#extensions#virtualenv#update() + if &filetype =~# "python" + call airline#extensions#virtualenv#apply() + call airline#update_statusline() + endif +endfunction diff --git a/.vim/autoload/airline/extensions/whitespace.vim b/.vim/autoload/airline/extensions/whitespace.vim new file mode 100644 index 0000000..c9b5a2a --- /dev/null +++ b/.vim/autoload/airline/extensions/whitespace.vim @@ -0,0 +1,171 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +" http://got-ravings.blogspot.com/2008/10/vim-pr0n-statusline-whitespace-flags.html + +scriptencoding utf-8 + +let s:show_message = get(g:, 'airline#extensions#whitespace#show_message', 1) +let s:symbol = get(g:, 'airline#extensions#whitespace#symbol', g:airline_symbols.whitespace) +let s:default_checks = ['indent', 'trailing', 'mixed-indent-file'] + +let s:enabled = get(g:, 'airline#extensions#whitespace#enabled', 1) +let s:skip_check_ft = {'make': ['indent', 'mixed-indent-file']} + +function! s:check_mixed_indent() + let indent_algo = get(g:, 'airline#extensions#whitespace#mixed_indent_algo', 0) + if indent_algo == 1 + " [<tab>]<space><tab> + " spaces before or between tabs are not allowed + let t_s_t = '(^\t* +\t\s*\S)' + " <tab>(<space> x count) + " count of spaces at the end of tabs should be less than tabstop value + let t_l_s = '(^\t+ {' . &ts . ',}' . '\S)' + return search('\v' . t_s_t . '|' . t_l_s, 'nw') + elseif indent_algo == 2 + return search('\v(^\t* +\t\s*\S)', 'nw') + else + return search('\v(^\t+ +)|(^ +\t+)', 'nw') + endif +endfunction + +function! s:check_mixed_indent_file() + let c_like_langs = get(g:, 'airline#extensions#c_like_langs', + \ [ 'arduino', 'c', 'cpp', 'cuda', 'go', 'javascript', 'ld', 'php' ]) + if index(c_like_langs, &ft) > -1 + " for C-like languages: allow /** */ comment style with one space before the '*' + let head_spc = '\v(^ +\*@!)' + else + let head_spc = '\v(^ +)' + endif + let indent_tabs = search('\v(^\t+)', 'nw') + let indent_spc = search(head_spc, 'nw') + if indent_tabs > 0 && indent_spc > 0 + return printf("%d:%d", indent_tabs, indent_spc) + else + return '' + endif +endfunction + +function! airline#extensions#whitespace#check() + let max_lines = get(g:, 'airline#extensions#whitespace#max_lines', 20000) + if &readonly || !&modifiable || !s:enabled || line('$') > max_lines + \ || get(b:, 'airline_whitespace_disabled', 0) + return '' + endif + let skip_check_ft = extend(s:skip_check_ft, + \ get(g:, 'airline#extensions#whitespace#skip_indent_check_ft', {}), 'force') + + if !exists('b:airline_whitespace_check') + let b:airline_whitespace_check = '' + let checks = get(b:, 'airline_whitespace_checks', get(g:, 'airline#extensions#whitespace#checks', s:default_checks)) + + let trailing = 0 + let check = 'trailing' + if index(checks, check) > -1 && index(get(skip_check_ft, &ft, []), check) < 0 + try + let regexp = get(g:, 'airline#extensions#whitespace#trailing_regexp', '\s$') + let trailing = search(regexp, 'nw') + catch + call airline#util#warning(printf('Whitespace: error occurred evaluating "%s"', regexp)) + echomsg v:exception + return '' + endtry + endif + + let mixed = 0 + let check = 'indent' + if index(checks, check) > -1 && index(get(skip_check_ft, &ft, []), check) < 0 + let mixed = s:check_mixed_indent() + endif + + let mixed_file = '' + let check = 'mixed-indent-file' + if index(checks, check) > -1 && index(get(skip_check_ft, &ft, []), check) < 0 + let mixed_file = s:check_mixed_indent_file() + endif + + let long = 0 + if index(checks, 'long') > -1 && &tw > 0 + let long = search('\%>'.&tw.'v.\+', 'nw') + endif + + if trailing != 0 || mixed != 0 || long != 0 || !empty(mixed_file) + let b:airline_whitespace_check = s:symbol + if strlen(s:symbol) > 0 + let space = (g:airline_symbols.space) + else + let space = '' + endif + + if s:show_message + if trailing != 0 + let trailing_fmt = get(g:, 'airline#extensions#whitespace#trailing_format', '[%s]trailing') + let b:airline_whitespace_check .= space.printf(trailing_fmt, trailing) + endif + if mixed != 0 + let mixed_indent_fmt = get(g:, 'airline#extensions#whitespace#mixed_indent_format', '[%s]mixed-indent') + let b:airline_whitespace_check .= space.printf(mixed_indent_fmt, mixed) + endif + if long != 0 + let long_fmt = get(g:, 'airline#extensions#whitespace#long_format', '[%s]long') + let b:airline_whitespace_check .= space.printf(long_fmt, long) + endif + if !empty(mixed_file) + let mixed_indent_file_fmt = get(g:, 'airline#extensions#whitespace#mixed_indent_file_format', '[%s]mix-indent-file') + let b:airline_whitespace_check .= space.printf(mixed_indent_file_fmt, mixed_file) + endif + endif + endif + endif + return airline#util#shorten(b:airline_whitespace_check, 120, 9) +endfunction + +function! airline#extensions#whitespace#toggle() + if s:enabled + augroup airline_whitespace + autocmd! + augroup END + augroup! airline_whitespace + let s:enabled = 0 + else + call airline#extensions#whitespace#init() + let s:enabled = 1 + endif + + if exists("g:airline#extensions#whitespace#enabled") + let g:airline#extensions#whitespace#enabled = s:enabled + if s:enabled && match(g:airline_section_warning, '#whitespace#check') < 0 + let g:airline_section_warning .= airline#section#create(['whitespace']) + call airline#update_statusline() + endif + endif + call airline#util#warning(printf('Whitespace checking: %s',(s:enabled ? 'Enabled' : 'Disabled'))) +endfunction + +function! airline#extensions#whitespace#disable() + if s:enabled + call airline#extensions#whitespace#toggle() + endif +endfunction + +function! airline#extensions#whitespace#init(...) + call airline#parts#define_function('whitespace', 'airline#extensions#whitespace#check') + + unlet! b:airline_whitespace_check + augroup airline_whitespace + autocmd! + autocmd CursorHold,BufWritePost * call <sid>ws_refresh() + augroup END +endfunction + +function! s:ws_refresh() + if get(b:, 'airline_ws_changedtick', 0) == b:changedtick + return + endif + unlet! b:airline_whitespace_check + if get(g:, 'airline_skip_empty_sections', 0) + exe ':AirlineRefresh' + endif + let b:airline_ws_changedtick = b:changedtick +endfunction diff --git a/.vim/autoload/airline/extensions/windowswap.vim b/.vim/autoload/airline/extensions/windowswap.vim new file mode 100644 index 0000000..5ef531e --- /dev/null +++ b/.vim/autoload/airline/extensions/windowswap.vim @@ -0,0 +1,29 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists('g:loaded_windowswap') + finish +endif + +let s:spc = g:airline_symbols.space + +if !exists('g:airline#extensions#windowswap#indicator_text') + let g:airline#extensions#windowswap#indicator_text = 'WS' +endif + +function! airline#extensions#windowswap#init(ext) + call airline#parts#define_function('windowswap', 'airline#extensions#windowswap#get_status') +endfunction + +function! airline#extensions#windowswap#get_status() + " use new tab-aware api if WS is up to date + let s:mark = exists('*WindowSwap#IsCurrentWindowMarked') ? + \WindowSwap#IsCurrentWindowMarked() : + \(WindowSwap#HasMarkedWindow() && WindowSwap#GetMarkedWindowNum() == winnr()) + if s:mark + return g:airline#extensions#windowswap#indicator_text.s:spc + endif + return '' +endfunction diff --git a/.vim/autoload/airline/extensions/wordcount.vim b/.vim/autoload/airline/extensions/wordcount.vim new file mode 100644 index 0000000..a9b9aac --- /dev/null +++ b/.vim/autoload/airline/extensions/wordcount.vim @@ -0,0 +1,117 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 fdm=marker + +scriptencoding utf-8 + +" get wordcount {{{1 +if exists('*wordcount') + function! s:get_wordcount(visual_mode_active) + let query = a:visual_mode_active ? 'visual_words' : 'words' + return get(wordcount(), query, 0) + endfunction +else " Pull wordcount from the g_ctrl-g stats + function! s:get_wordcount(visual_mode_active) + let pattern = a:visual_mode_active + \ ? '^.\D*\d\+\D\+\d\+\D\+\zs\d\+' + \ : '^.\D*\%(\d\+\D\+\)\{5}\zs\d\+' + + let save_status = v:statusmsg + if !a:visual_mode_active && col('.') == col('$') + let save_pos = getpos('.') + execute "silent normal! g\<c-g>" + call setpos('.', save_pos) + else + execute "silent normal! g\<c-g>" + endif + let stats = v:statusmsg + let v:statusmsg = save_status + + return str2nr(matchstr(stats, pattern)) + endfunction +endif + +" format {{{1 +let s:formatter = get(g:, 'airline#extensions#wordcount#formatter', 'default') + +" wrapper function for compatibility; redefined below for old-style formatters +function! s:format_wordcount(wordcount) + return airline#extensions#wordcount#formatters#{s:formatter}#to_string(a:wordcount) +endfunction + +" check user-defined formatter exists with appropriate functions, otherwise +" fall back to default +if s:formatter !=# 'default' + execute 'runtime! autoload/airline/extensions/wordcount/formatters/'.s:formatter + if !exists('*airline#extensions#wordcount#formatters#{s:formatter}#to_string') + if !exists('*airline#extensions#wordcount#formatters#{s:formatter}#format') + let s:formatter = 'default' + else + " redefine for backwords compatibility + function! s:format_wordcount(_) + if mode() ==? 'v' + return b:airline_wordcount + else + return airline#extensions#wordcount#formatters#{s:formatter}#format() + endif + endfunction + endif + endif +endif + +" update {{{1 +let s:wordcount_cache = 0 " cache wordcount for performance when force_update=0 +function! s:update_wordcount(force_update) + let wordcount = s:get_wordcount(0) + if wordcount != s:wordcount_cache || a:force_update + let s:wordcount_cache = wordcount + let b:airline_wordcount = s:format_wordcount(wordcount) + endif +endfunction + +let s:visual_active = 0 " Boolean: for when to get visual wordcount +function airline#extensions#wordcount#get() + if s:visual_active + return s:format_wordcount(s:get_wordcount(1)) + else + if get(b:, 'airline_changedtick', 0) != b:changedtick + call s:update_wordcount(0) + let b:airline_changedtick = b:changedtick + endif + return get(b:, 'airline_wordcount', '') + endif +endfunction + +" airline functions {{{1 +" default filetypes: +let s:filetypes = ['help', 'markdown', 'rst', 'org', 'text', 'asciidoc', 'tex', 'mail'] +function! airline#extensions#wordcount#apply(...) + let filetypes = get(g:, 'airline#extensions#wordcount#filetypes', s:filetypes) + + " Check if filetype needs testing + if did_filetype() || filetypes isnot s:filetypes + let s:filetypes = filetypes + + " Select test based on type of "filetypes": new=list, old=string + if type(filetypes) == get(v:, 't_list', type([])) + \ ? index(filetypes, &filetype) > -1 || index(filetypes, 'all') > -1 + \ : match(&filetype, filetypes) > -1 + let b:airline_changedtick = -1 + call s:update_wordcount(1) " force update: ensures initial worcount exists + elseif exists('b:airline_wordcount') " cleanup when filetype is removed + unlet b:airline_wordcount + endif + endif + + if exists('b:airline_wordcount') + call airline#extensions#prepend_to_section( + \ 'z', '%{airline#extensions#wordcount#get()}') + endif +endfunction + +function! airline#extensions#wordcount#init(ext) + augroup airline_wordcount + autocmd! User AirlineModeChanged nested + \ let s:visual_active = (mode() ==? 'v' || mode() ==? 's') + augroup END + call a:ext.add_statusline_func('airline#extensions#wordcount#apply') +endfunction diff --git a/.vim/autoload/airline/extensions/wordcount/formatters/default.vim b/.vim/autoload/airline/extensions/wordcount/formatters/default.vim new file mode 100644 index 0000000..5682921 --- /dev/null +++ b/.vim/autoload/airline/extensions/wordcount/formatters/default.vim @@ -0,0 +1,39 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! airline#extensions#wordcount#formatters#default#update_fmt(...) + let s:fmt = get(g:, 'airline#extensions#wordcount#formatter#default#fmt', '%s words') + let s:fmt_short = get(g:, 'airline#extensions#wordcount#formatter#default#fmt_short', s:fmt == '%s words' ? '%sW' : s:fmt) +endfunction + +" Reload format when statusline is rebuilt +call airline#extensions#wordcount#formatters#default#update_fmt() +if index(g:airline_statusline_funcrefs, function('airline#extensions#wordcount#formatters#default#update_fmt')) == -1 + " only add it, if not already done + call airline#add_statusline_funcref(function('airline#extensions#wordcount#formatters#default#update_fmt')) +endif + +if match(get(v:, 'lang', ''), '\v\cC|en') > -1 + let s:decimal_group = ',' +elseif match(get(v:, 'lang', ''), '\v\cde|dk|fr|pt') > -1 + let s:decimal_group = '.' +else + let s:decimal_group = '' +endif + +function! airline#extensions#wordcount#formatters#default#to_string(wordcount) + if winwidth(0) >= 80 + if a:wordcount > 999 + " Format number according to locale, e.g. German: 1.245 or English: 1,245 + let wordcount = substitute(a:wordcount, '\d\@<=\(\(\d\{3\}\)\+\)$', s:decimal_group.'&', 'g') + else + let wordcount = a:wordcount + endif + let str = printf(s:fmt, wordcount) + else + let str = printf(s:fmt_short, a:wordcount) + endif + return str . g:airline_symbols.space . g:airline_right_alt_sep . g:airline_symbols.space +endfunction diff --git a/.vim/autoload/airline/extensions/xkblayout.vim b/.vim/autoload/airline/extensions/xkblayout.vim new file mode 100644 index 0000000..b9d56a1 --- /dev/null +++ b/.vim/autoload/airline/extensions/xkblayout.vim @@ -0,0 +1,24 @@ +" MIT License. Copyright (c) 2017-2018 YoungHoon Rhiu et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +if !exists('g:XkbSwitchLib') + finish +endif + +function! airline#extensions#xkblayout#status() + let keyboard_layout = libcall(g:XkbSwitchLib, 'Xkb_Switch_getXkbLayout', '') + let keyboard_layout = split(keyboard_layout, '\.')[-1] + let short_codes = get(g:, 'airline#extensions#xkblayout#short_codes', {'2SetKorean': 'KR', 'Chinese': 'CN', 'Japanese': 'JP'}) + + if has_key(short_codes, keyboard_layout) + let keyboard_layout = short_codes[keyboard_layout] + endif + + return keyboard_layout +endfunction + +function! airline#extensions#xkblayout#init(ext) + call airline#parts#define_function('xkblayout', 'airline#extensions#xkblayout#status') +endfunction diff --git a/.vim/autoload/airline/extensions/ycm.vim b/.vim/autoload/airline/extensions/ycm.vim new file mode 100644 index 0000000..677ba03 --- /dev/null +++ b/.vim/autoload/airline/extensions/ycm.vim @@ -0,0 +1,37 @@ +" MIT License. Copyright (c) 2015-2018 Evgeny Firsov et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:spc = g:airline_symbols.space +let s:error_symbol = get(g:, 'airline#extensions#ycm#error_symbol', 'E:') +let s:warning_symbol = get(g:, 'airline#extensions#ycm#warning_symbol', 'W:') + +function! airline#extensions#ycm#init(ext) + call airline#parts#define_function('ycm_error_count', 'airline#extensions#ycm#get_error_count') + call airline#parts#define_function('ycm_warning_count', 'airline#extensions#ycm#get_warning_count') +endfunction + +function! airline#extensions#ycm#get_error_count() + if exists(':YcmDiag') && exists("*youcompleteme#GetErrorCount") + let cnt = youcompleteme#GetErrorCount() + + if cnt != 0 + return s:error_symbol.cnt + endif + endif + + return '' +endfunction + +function! airline#extensions#ycm#get_warning_count() + if exists(':YcmDiag') && exists("*youcompleteme#GetWarningCount") + let cnt = youcompleteme#GetWarningCount() + + if cnt != 0 + return s:warning_symbol.cnt.s:spc + endif + endif + + return '' +endfunction diff --git a/.vim/autoload/airline/highlighter.vim b/.vim/autoload/airline/highlighter.vim new file mode 100644 index 0000000..5d4a7d7 --- /dev/null +++ b/.vim/autoload/airline/highlighter.vim @@ -0,0 +1,319 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:is_win32term = (has('win32') || has('win64')) && + \ !has('gui_running') && + \ (empty($CONEMUBUILD) || &term !=? 'xterm') && + \ !(exists("+termguicolors") && &termguicolors) + +let s:separators = {} +let s:accents = {} +let s:hl_groups = {} + +function! s:gui2cui(rgb, fallback) + if a:rgb == '' + return a:fallback + elseif match(a:rgb, '^\%(NONE\|[fb]g\)$') > -1 + return a:rgb + endif + let rgb = map(split(a:rgb[1:], '..\zs'), '0 + ("0x".v:val)') + return airline#msdos#round_msdos_colors(rgb) +endfunction + +function! s:group_not_done(list, name) + if index(a:list, a:name) == -1 + call add(a:list, a:name) + return 1 + else + if &vbs + echomsg printf("airline: group: %s already done, skipping", a:name) + endif + return 0 + endif +endfu + +function! s:get_syn(group, what) + if !exists("g:airline_gui_mode") + let g:airline_gui_mode = airline#init#gui_mode() + endif + let color = '' + if hlexists(a:group) + let color = synIDattr(synIDtrans(hlID(a:group)), a:what, g:airline_gui_mode) + endif + if empty(color) || color == -1 + " should always exists + let color = synIDattr(synIDtrans(hlID('Normal')), a:what, g:airline_gui_mode) + " however, just in case + if empty(color) || color == -1 + let color = 'NONE' + endif + endif + return color +endfunction + +function! s:get_array(fg, bg, opts) + let opts=empty(a:opts) ? '' : join(a:opts, ',') + return g:airline_gui_mode ==# 'gui' + \ ? [ a:fg, a:bg, '', '', opts ] + \ : [ '', '', a:fg, a:bg, opts ] +endfunction + +function! airline#highlighter#reset_hlcache() + let s:hl_groups = {} +endfunction + +function! airline#highlighter#get_highlight(group, ...) + let reverse = get(g:, 'airline_gui_mode', '') ==# 'gui' + \ ? synIDattr(synIDtrans(hlID(a:group)), 'reverse', 'gui') + \ : synIDattr(synIDtrans(hlID(a:group)), 'reverse', 'cterm') + \|| synIDattr(synIDtrans(hlID(a:group)), 'reverse', 'term') + if get(g:, 'airline_highlighting_cache', 0) && has_key(s:hl_groups, a:group) + let res = s:hl_groups[a:group] + return reverse ? [ res[1], res[0], res[3], res[2], res[4] ] : res + else + let fg = s:get_syn(a:group, 'fg') + let bg = s:get_syn(a:group, 'bg') + let bold = synIDattr(synIDtrans(hlID(a:group)), 'bold') + if reverse + let res = s:get_array(bg, fg, bold ? ['bold'] : a:000) + else + let res = s:get_array(fg, bg, bold ? ['bold'] : a:000) + endif + endif + let s:hl_groups[a:group] = res + return res +endfunction + +function! airline#highlighter#get_highlight2(fg, bg, ...) + let fg = s:get_syn(a:fg[0], a:fg[1]) + let bg = s:get_syn(a:bg[0], a:bg[1]) + return s:get_array(fg, bg, a:000) +endfunction + +function! s:hl_group_exists(group) + if !hlexists(a:group) + return 0 + elseif empty(synIDattr(hlID(a:group), 'fg')) + return 0 + endif + return 1 +endfunction + +function! airline#highlighter#exec(group, colors) + if pumvisible() + return + endif + let colors = a:colors + if s:is_win32term + let colors[2] = s:gui2cui(get(colors, 0, ''), get(colors, 2, '')) + let colors[3] = s:gui2cui(get(colors, 1, ''), get(colors, 3, '')) + endif + let old_hi = airline#highlighter#get_highlight(a:group) + if len(colors) == 4 + call add(colors, '') + endif + if g:airline_gui_mode ==# 'gui' + let new_hi = [colors[0], colors[1], '', '', colors[4]] + else + let new_hi = ['', '', printf("%s", colors[2]), printf("%s", colors[3]), colors[4]] + endif + let colors = s:CheckDefined(colors) + if old_hi != new_hi || !s:hl_group_exists(a:group) + let cmd = printf('hi %s%s', a:group, s:GetHiCmd(colors)) + exe cmd + if has_key(s:hl_groups, a:group) + let s:hl_groups[a:group] = colors + endif + endif +endfunction + +function! s:CheckDefined(colors) + " Checks, whether the definition of the colors is valid and is not empty or NONE + " e.g. if the colors would expand to this: + " hi airline_c ctermfg=NONE ctermbg=NONE + " that means to clear that highlighting group, therefore, fallback to Normal + " highlighting group for the cterm values + + " This only works, if the Normal highlighting group is actually defined, so + " return early, if it has been cleared + if !exists("g:airline#highlighter#normal_fg_hi") + let g:airline#highlighter#normal_fg_hi = synIDattr(synIDtrans(hlID('Normal')), 'fg', 'cterm') + endif + if empty(g:airline#highlighter#normal_fg_hi) || g:airline#highlighter#normal_fg_hi < 0 + return a:colors + endif + + for val in a:colors + if !empty(val) && val !=# 'NONE' + return a:colors + endif + endfor + " this adds the bold attribute to the term argument of the :hi command, + " but at least this makes sure, the group will be defined + let fg = g:airline#highlighter#normal_fg_hi + let bg = synIDattr(synIDtrans(hlID('Normal')), 'bg', 'cterm') + if bg < 0 + " in case there is no background color defined for Normal + let bg = a:colors[3] + endif + return a:colors[0:1] + [fg, bg] + [a:colors[4]] +endfunction + +function! s:GetHiCmd(list) + " a:list needs to have 5 items! + let res = '' + let i = -1 + while i < 4 + let i += 1 + let item = get(a:list, i, '') + if item is '' + continue + endif + if i == 0 + let res .= ' guifg='.item + elseif i == 1 + let res .= ' guibg='.item + elseif i == 2 + let res .= ' ctermfg='.item + elseif i == 3 + let res .= ' ctermbg='.item + elseif i == 4 + let res .= printf(' gui=%s cterm=%s term=%s', item, item, item) + endif + endwhile + return res +endfunction + +function! s:exec_separator(dict, from, to, inverse, suffix) + if pumvisible() + return + endif + let group = a:from.'_to_'.a:to.a:suffix + let l:from = airline#themes#get_highlight(a:from.a:suffix) + let l:to = airline#themes#get_highlight(a:to.a:suffix) + if a:inverse + let colors = [ l:from[1], l:to[1], l:from[3], l:to[3] ] + else + let colors = [ l:to[1], l:from[1], l:to[3], l:from[3] ] + endif + let a:dict[group] = colors + call airline#highlighter#exec(group, colors) +endfunction + +function! airline#highlighter#load_theme() + if pumvisible() + return + endif + for winnr in filter(range(1, winnr('$')), 'v:val != winnr()') + call airline#highlighter#highlight_modified_inactive(winbufnr(winnr)) + endfor + call airline#highlighter#highlight(['inactive']) + if getbufvar( bufnr('%'), '&modified' ) + call airline#highlighter#highlight(['normal', 'modified']) + else + call airline#highlighter#highlight(['normal']) + endif +endfunction + +function! airline#highlighter#add_separator(from, to, inverse) + let s:separators[a:from.a:to] = [a:from, a:to, a:inverse] + call <sid>exec_separator({}, a:from, a:to, a:inverse, '') +endfunction + +function! airline#highlighter#add_accent(accent) + let s:accents[a:accent] = 1 +endfunction + +function! airline#highlighter#highlight_modified_inactive(bufnr) + if getbufvar(a:bufnr, '&modified') + let colors = exists('g:airline#themes#{g:airline_theme}#palette.inactive_modified.airline_c') + \ ? g:airline#themes#{g:airline_theme}#palette.inactive_modified.airline_c : [] + else + let colors = exists('g:airline#themes#{g:airline_theme}#palette.inactive.airline_c') + \ ? g:airline#themes#{g:airline_theme}#palette.inactive.airline_c : [] + endif + + if !empty(colors) + call airline#highlighter#exec('airline_c'.(a:bufnr).'_inactive', colors) + endif +endfunction + +function! airline#highlighter#highlight(modes, ...) + let bufnr = a:0 ? a:1 : '' + let p = g:airline#themes#{g:airline_theme}#palette + + " draw the base mode, followed by any overrides + let mapped = map(a:modes, 'v:val == a:modes[0] ? v:val : a:modes[0]."_".v:val') + let suffix = a:modes[0] == 'inactive' ? '_inactive' : '' + let airline_grouplist = [] + let buffers_in_tabpage = sort(tabpagebuflist()) + if exists("*uniq") + let buffers_in_tabpage = uniq(buffers_in_tabpage) + endif + " mapped might be something like ['normal', 'normal_modified'] + " if a group is in both modes available, only define the second + " that is how this was done previously overwrite the previous definition + for mode in reverse(mapped) + if exists('g:airline#themes#{g:airline_theme}#palette[mode]') + let dict = g:airline#themes#{g:airline_theme}#palette[mode] + for kvp in items(dict) + let mode_colors = kvp[1] + let name = kvp[0] + if name is# 'airline_c' && !empty(bufnr) && suffix is# '_inactive' + let name = 'airline_c'.bufnr + endif + " do not re-create highlighting for buffers that are no longer visible + " in the current tabpage + if name =~# 'airline_c\d\+' + let bnr = matchstr(name, 'airline_c\zs\d\+') + 0 + if bnr > 0 && index(buffers_in_tabpage, bnr) == -1 + continue + endif + elseif (name =~# '_to_') || (name[0:10] is# 'airline_tab' && !empty(suffix)) + " group will be redefined below at exec_separator + " or is not needed for tabline with '_inactive' suffix + " since active flag is 1 for builder) + continue + endif + if s:group_not_done(airline_grouplist, name.suffix) + call airline#highlighter#exec(name.suffix, mode_colors) + endif + + for accent in keys(s:accents) + if !has_key(p.accents, accent) + continue + endif + let colors = copy(mode_colors) + if p.accents[accent][0] != '' + let colors[0] = p.accents[accent][0] + endif + if p.accents[accent][2] != '' + let colors[2] = p.accents[accent][2] + endif + if len(colors) >= 5 + let colors[4] = get(p.accents[accent], 4, '') + else + call add(colors, get(p.accents[accent], 4, '')) + endif + if s:group_not_done(airline_grouplist, name.suffix.'_'.accent) + call airline#highlighter#exec(name.suffix.'_'.accent, colors) + endif + endfor + endfor + + if empty(s:separators) + " nothing to be done + continue + endif + " TODO: optimize this + for sep in items(s:separators) + " we cannot check, that the group already exists, else the separators + " might not be correctly defined. But perhaps we can skip above groups + " that match the '_to_' name, because they would be redefined here... + call <sid>exec_separator(dict, sep[1][0], sep[1][1], sep[1][2], suffix) + endfor + endif + endfor +endfunction diff --git a/.vim/autoload/airline/init.vim b/.vim/autoload/airline/init.vim new file mode 100644 index 0000000..18a59da --- /dev/null +++ b/.vim/autoload/airline/init.vim @@ -0,0 +1,209 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +function! s:check_defined(variable, default) + if !exists(a:variable) + let {a:variable} = a:default + endif +endfunction + +let s:loaded = 0 +function! airline#init#bootstrap() + if s:loaded + return + endif + let s:loaded = 1 + + let g:airline#init#bootstrapping = 1 + + let g:airline#init#vim_async = (v:version >= 800 && has('job')) + let g:airline#init#is_windows = has('win32') || has('win64') + + call s:check_defined('g:airline_detect_modified', 1) + call s:check_defined('g:airline_detect_paste', 1) + call s:check_defined('g:airline_detect_crypt', 1) + call s:check_defined('g:airline_detect_spell', 1) + call s:check_defined('g:airline_detect_spelllang', 1) + call s:check_defined('g:airline_detect_iminsert', 0) + call s:check_defined('g:airline_inactive_collapse', 1) + call s:check_defined('g:airline_exclude_filenames', ['DebuggerWatch','DebuggerStack','DebuggerStatus']) + call s:check_defined('g:airline_exclude_filetypes', []) + call s:check_defined('g:airline_exclude_preview', 0) + call s:check_defined('g:airline_gui_mode', airline#init#gui_mode()) + + call s:check_defined('g:airline_mode_map', {}) + call extend(g:airline_mode_map, { + \ '__' : '------', + \ 'c' : 'COMMAND', + \ 'i' : 'INSERT', + \ 'ic' : 'INSERT COMPL', + \ 'ix' : 'INSERT COMPL', + \ 'n' : 'NORMAL', + \ 'ni' : '(INSERT)', + \ 'no' : 'OP PENDING', + \ 'R' : 'REPLACE', + \ 'Rv' : 'V REPLACE', + \ 's' : 'SELECT', + \ 'S' : 'S-LINE', + \ '' : 'S-BLOCK', + \ 't' : 'TERMINAL', + \ 'v' : 'VISUAL', + \ 'V' : 'V-LINE', + \ '' : 'V-BLOCK', + \ }, 'keep') + + call s:check_defined('g:airline_theme_map', {}) + call extend(g:airline_theme_map, { + \ 'default': 'dark', + \ '\CTomorrow': 'tomorrow', + \ 'base16': 'base16', + \ 'mo[l|n]okai': 'molokai', + \ 'wombat': 'wombat', + \ 'zenburn': 'zenburn', + \ 'solarized': 'solarized', + \ 'flattened': 'solarized', + \ '\CNeoSolarized': 'solarized', + \ }, 'keep') + + call s:check_defined('g:airline_symbols', {}) + " First define the symbols, + " that are common in Powerline/Unicode/ASCII mode, + " then add specific symbols for either mode + call extend(g:airline_symbols, { + \ 'paste': 'PASTE', + \ 'spell': 'SPELL', + \ 'modified': '+', + \ 'space': ' ', + \ 'keymap': 'Keymap:', + \ 'ellipsis': '...' + \ }, 'keep') + + if get(g:, 'airline_powerline_fonts', 0) + " Symbols for Powerline terminals + call s:check_defined('g:airline_left_sep', "\ue0b0") " + call s:check_defined('g:airline_left_alt_sep', "\ue0b1") " + call s:check_defined('g:airline_right_sep', "\ue0b2") " + call s:check_defined('g:airline_right_alt_sep', "\ue0b3") " + " ro=, ws=☲, lnr=☰, mlnr=, br=, nx=Ɇ, crypt=🔒 + call extend(g:airline_symbols, { + \ 'readonly': "\ue0a2", + \ 'whitespace': "\u2632", + \ 'linenr': "\u2630 ", + \ 'maxlinenr': " \ue0a1", + \ 'branch': "\ue0a0", + \ 'notexists': "\u0246", + \ 'crypt': nr2char(0x1F512), + \ }, 'keep') + elseif &encoding==?'utf-8' && !get(g:, "airline_symbols_ascii", 0) + " Symbols for Unicode terminals + call s:check_defined('g:airline_left_sep', "") + call s:check_defined('g:airline_left_alt_sep', "") + call s:check_defined('g:airline_right_sep', "") + call s:check_defined('g:airline_right_alt_sep', "") + " ro=⊝, ws=☲, lnr=☰, mlnr=㏑, br=ᚠ, nx=Ɇ, crypt=🔒 + call extend(g:airline_symbols, { + \ 'readonly': "\u229D", + \ 'whitespace': "\u2632", + \ 'linenr': "\u2630 ", + \ 'maxlinenr': " \u33D1", + \ 'branch': "\u16A0", + \ 'notexists': "\u0246", + \ 'crypt': nr2char(0x1F512), + \ }, 'keep') + else + " Symbols for ASCII terminals + call s:check_defined('g:airline_left_sep', "") + call s:check_defined('g:airline_left_alt_sep', "") + call s:check_defined('g:airline_right_sep', "") + call s:check_defined('g:airline_right_alt_sep', "") + call extend(g:airline_symbols, { + \ 'readonly': 'RO', + \ 'whitespace': '!', + \ 'linenr': 'ln ', + \ 'maxlinenr': ' :', + \ 'branch': '', + \ 'notexists': '?', + \ 'crypt': 'cr', + \ }, 'keep') + endif + + call airline#parts#define('mode', { + \ 'function': 'airline#parts#mode', + \ 'accent': 'bold', + \ }) + call airline#parts#define_function('iminsert', 'airline#parts#iminsert') + call airline#parts#define_function('paste', 'airline#parts#paste') + call airline#parts#define_function('crypt', 'airline#parts#crypt') + call airline#parts#define_function('spell', 'airline#parts#spell') + call airline#parts#define_function('filetype', 'airline#parts#filetype') + call airline#parts#define('readonly', { + \ 'function': 'airline#parts#readonly', + \ 'accent': 'red', + \ }) + call airline#parts#define_raw('file', '%f%m') + call airline#parts#define_raw('path', '%F%m') + call airline#parts#define('linenr', { + \ 'raw': '%{g:airline_symbols.linenr}%4l', + \ 'accent': 'bold'}) + call airline#parts#define('maxlinenr', { + \ 'raw': '/%L%{g:airline_symbols.maxlinenr}', + \ 'accent': 'bold'}) + call airline#parts#define_function('ffenc', 'airline#parts#ffenc') + call airline#parts#define_empty(['hunks', 'branch', 'obsession', 'tagbar', + \ 'syntastic-warn', 'syntastic-err', 'eclim', 'whitespace','windowswap', + \ 'ycm_error_count', 'ycm_warning_count', 'neomake_error_count', + \ 'neomake_warning_count', 'ale_error_count', 'ale_warning_count', + \ 'languageclient_error_count', 'languageclient_warning_count']) + call airline#parts#define_text('capslock', '') + call airline#parts#define_text('gutentags', '') + call airline#parts#define_text('grepper', '') + call airline#parts#define_text('xkblayout', '') + call airline#parts#define_text('keymap', '') + + unlet g:airline#init#bootstrapping +endfunction + +function! airline#init#gui_mode() + return has('gui_running') || (has("termguicolors") && &termguicolors == 1) ? 'gui' : 'cterm' +endfunction + +function! airline#init#sections() + let spc = g:airline_symbols.space + if !exists('g:airline_section_a') + let g:airline_section_a = airline#section#create_left(['mode', 'crypt', 'paste', 'keymap', 'spell', 'capslock', 'xkblayout', 'iminsert']) + endif + if !exists('g:airline_section_b') + let g:airline_section_b = airline#section#create(['hunks', 'branch']) + endif + if !exists('g:airline_section_c') + if exists("+autochdir") && &autochdir == 1 + let g:airline_section_c = airline#section#create(['%<', 'path', spc, 'readonly']) + else + let g:airline_section_c = airline#section#create(['%<', 'file', spc, 'readonly']) + endif + endif + if !exists('g:airline_section_gutter') + let g:airline_section_gutter = airline#section#create(['%=']) + endif + if !exists('g:airline_section_x') + let g:airline_section_x = airline#section#create_right(['tagbar', 'gutentags', 'grepper', 'filetype']) + endif + if !exists('g:airline_section_y') + let g:airline_section_y = airline#section#create_right(['ffenc']) + endif + if !exists('g:airline_section_z') + if winwidth(0) > 80 + let g:airline_section_z = airline#section#create(['windowswap', 'obsession', '%3p%%'.spc, 'linenr', 'maxlinenr', spc.':%3v']) + else + let g:airline_section_z = airline#section#create(['%3p%%'.spc, 'linenr', ':%3v']) + endif + endif + if !exists('g:airline_section_error') + let g:airline_section_error = airline#section#create(['ycm_error_count', 'syntastic-err', 'eclim', 'neomake_error_count', 'ale_error_count', 'languageclient_error_count']) + endif + if !exists('g:airline_section_warning') + let g:airline_section_warning = airline#section#create(['ycm_warning_count', 'syntastic-warn', 'neomake_warning_count', 'ale_warning_count', 'languageclient_warning_count', 'whitespace']) + endif +endfunction diff --git a/.vim/autoload/airline/msdos.vim b/.vim/autoload/airline/msdos.vim new file mode 100644 index 0000000..2d2d4e8 --- /dev/null +++ b/.vim/autoload/airline/msdos.vim @@ -0,0 +1,59 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +" basic 16 msdos from MSDOS +" see output of color, should be +" 0 Black +" 1 DarkBlue +" 2 DarkGreen +" 3 DarkCyan +" 4 DarkRed +" 5 DarkMagenta +" 6 Brown +" 7 LightGray +" 8 DarkGray +" 9 Blue +" 10 Green +" 11 Cyan +" 12 Red +" 13 Magenta +" 14 Yellow +" 15 White + +let s:basic16 = [ + \ [ 0x00, 0x00, 0x00 ], + \ [ 0x00, 0x00, 0x80 ], + \ [ 0x00, 0x80, 0x00 ], + \ [ 0x00, 0x80, 0x80 ], + \ [ 0x80, 0x00, 0x00 ], + \ [ 0x80, 0x00, 0x80 ], + \ [ 0x80, 0x80, 0x00 ], + \ [ 0xC0, 0xC0, 0xC0 ], + \ [ 0x80, 0x80, 0x80 ], + \ [ 0x00, 0x00, 0xFF ], + \ [ 0x00, 0xFF, 0x00 ], + \ [ 0x00, 0xFF, 0xFF ], + \ [ 0xFF, 0x00, 0x00 ], + \ [ 0xFF, 0x00, 0xFF ], + \ [ 0xFF, 0xFF, 0x00 ], + \ [ 0xFF, 0xFF, 0xFF ] + \ ] + +function! airline#msdos#round_msdos_colors(rgblist) + " Check for values from MSDOS 16 color terminal + let best = [] + let min = 100000 + let list = s:basic16 + for value in list + let t = abs(value[0] - a:rgblist[0]) + + \ abs(value[1] - a:rgblist[1]) + + \ abs(value[2] - a:rgblist[2]) + if min > t + let min = t + let best = value + endif + endfor + return index(s:basic16, best) +endfunction diff --git a/.vim/autoload/airline/parts.vim b/.vim/autoload/airline/parts.vim new file mode 100644 index 0000000..b6625c6 --- /dev/null +++ b/.vim/autoload/airline/parts.vim @@ -0,0 +1,114 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +let s:parts = {} + +" PUBLIC API {{{ + +function! airline#parts#define(key, config) + let s:parts[a:key] = get(s:parts, a:key, {}) + if exists('g:airline#init#bootstrapping') + call extend(s:parts[a:key], a:config, 'keep') + else + call extend(s:parts[a:key], a:config, 'force') + endif +endfunction + +function! airline#parts#define_function(key, name) + call airline#parts#define(a:key, { 'function': a:name }) +endfunction + +function! airline#parts#define_text(key, text) + call airline#parts#define(a:key, { 'text': a:text }) +endfunction + +function! airline#parts#define_raw(key, raw) + call airline#parts#define(a:key, { 'raw': a:raw }) +endfunction + +function! airline#parts#define_minwidth(key, width) + call airline#parts#define(a:key, { 'minwidth': a:width }) +endfunction + +function! airline#parts#define_condition(key, predicate) + call airline#parts#define(a:key, { 'condition': a:predicate }) +endfunction + +function! airline#parts#define_accent(key, accent) + call airline#parts#define(a:key, { 'accent': a:accent }) +endfunction + +function! airline#parts#define_empty(keys) + for key in a:keys + call airline#parts#define_raw(key, '') + endfor +endfunction + +function! airline#parts#get(key) + return get(s:parts, a:key, {}) +endfunction + +" }}} + +function! airline#parts#mode() + return airline#util#shorten(get(w:, 'airline_current_mode', ''), 79, 1) +endfunction + +function! airline#parts#crypt() + return g:airline_detect_crypt && exists("+key") && !empty(&key) ? g:airline_symbols.crypt : '' +endfunction + +function! airline#parts#paste() + return g:airline_detect_paste && &paste ? g:airline_symbols.paste : '' +endfunction + +function! airline#parts#spell() + let spelllang = g:airline_detect_spelllang ? printf(" [%s]", toupper(substitute(&spelllang, ',', '/', 'g'))) : '' + if g:airline_detect_spell && &spell + if winwidth(0) >= 90 + return g:airline_symbols.spell . spelllang + elseif winwidth(0) >= 70 + return g:airline_symbols.spell + else + return split(g:airline_symbols.spell, '\zs')[0] + endif + endif + return '' +endfunction + +function! airline#parts#iminsert() + if g:airline_detect_iminsert && &iminsert && exists('b:keymap_name') + return toupper(b:keymap_name) + endif + return '' +endfunction + +function! airline#parts#readonly() + " only consider regular buffers (e.g. ones that represent actual files, + " but not special ones like e.g. NERDTree) + if !empty(&buftype) || airline#util#ignore_buf(bufname('%')) + return '' + endif + if &readonly && !filereadable(bufname('%')) + return '[noperm]' + else + return &readonly ? g:airline_symbols.readonly : '' + endif +endfunction + +function! airline#parts#filetype() + return winwidth(0) < 90 && strlen(&filetype) > 3 ? matchstr(&filetype, '...'). (&encoding is? 'utf-8' ? '…' : '>') : &filetype +endfunction + +function! airline#parts#ffenc() + let expected = get(g:, 'airline#parts#ffenc#skip_expected_string', '') + let bomb = &l:bomb ? '[BOM]' : '' + let ff = strlen(&ff) ? '['.&ff.']' : '' + if expected is# &fenc.bomb.ff + return '' + else + return &fenc.bomb.ff + endif +endfunction diff --git a/.vim/autoload/airline/section.vim b/.vim/autoload/airline/section.vim new file mode 100644 index 0000000..7d84faf --- /dev/null +++ b/.vim/autoload/airline/section.vim @@ -0,0 +1,84 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +call airline#init#bootstrap() +let s:spc = g:airline_symbols.space + +function! s:wrap_accent(part, value) + if exists('a:part.accent') + call airline#highlighter#add_accent(a:part.accent) + return '%#__accent_'.(a:part.accent).'#'.a:value.'%#__restore__#' + endif + return a:value +endfunction + +function! s:create(parts, append) + let _ = '' + for idx in range(len(a:parts)) + let part = airline#parts#get(a:parts[idx]) + let val = '' + let add_sep = get(l:, 'add_sep', 0) + + if exists('part.function') + let func = (part.function).'()' + elseif exists('part.text') + let func = '"'.(part.text).'"' + else + if a:append > 0 && idx != 0 + let val .= s:spc.g:airline_left_alt_sep.s:spc + endif + if a:append < 0 && idx != 0 + let t = '' + if !add_sep + let t = s:spc.g:airline_right_alt_sep.s:spc + endif + let val = t.val + endif + if exists('part.raw') + let _ .= s:wrap_accent(part, val.(part.raw)) + continue + else + let _ .= s:wrap_accent(part, val.a:parts[idx]) + continue + endif + endif + + let minwidth = get(part, 'minwidth', 0) + + if a:append > 0 && idx != 0 + let partval = printf('%%{airline#util#append(%s,%s)}', func, minwidth) + " will add an extra separator, if minwidth is zero + let add_sep = (minwidth == 0) + elseif a:append < 0 && idx != len(a:parts) - 1 + let partval = printf('%%{airline#util#prepend(%s,%s)}', func, minwidth) + " will add an extra separator, if minwidth is zero + let add_sep = (minwidth == 0) + else + let partval = printf('%%{airline#util#wrap(%s,%s)}', func, minwidth) + let add_sep = 0 + endif + + if exists('part.condition') + let partval = substitute(partval, '{', '\="{".(part.condition)." ? "', '') + let partval = substitute(partval, '}', ' : ""}', '') + endif + + let val .= s:wrap_accent(part, partval) + let _ .= val + endfor + return _ +endfunction + +function! airline#section#create(parts) + return s:create(a:parts, 0) +endfunction + +function! airline#section#create_left(parts) + return s:create(a:parts, 1) +endfunction + +function! airline#section#create_right(parts) + return s:create(a:parts, -1) +endfunction diff --git a/.vim/autoload/airline/themes.vim b/.vim/autoload/airline/themes.vim new file mode 100644 index 0000000..b757fe5 --- /dev/null +++ b/.vim/autoload/airline/themes.vim @@ -0,0 +1,78 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +scriptencoding utf-8 + +" generates a dictionary which defines the colors for each highlight group +function! airline#themes#generate_color_map(sect1, sect2, sect3, ...) + let palette = { + \ 'airline_a': [ a:sect1[0] , a:sect1[1] , a:sect1[2] , a:sect1[3] , get(a:sect1 , 4 , '') ] , + \ 'airline_b': [ a:sect2[0] , a:sect2[1] , a:sect2[2] , a:sect2[3] , get(a:sect2 , 4 , '') ] , + \ 'airline_c': [ a:sect3[0] , a:sect3[1] , a:sect3[2] , a:sect3[3] , get(a:sect3 , 4 , '') ] , + \ } + + if a:0 > 0 + call extend(palette, { + \ 'airline_x': [ a:1[0] , a:1[1] , a:1[2] , a:1[3] , get(a:1 , 4 , '' ) ] , + \ 'airline_y': [ a:2[0] , a:2[1] , a:2[2] , a:2[3] , get(a:2 , 4 , '' ) ] , + \ 'airline_z': [ a:3[0] , a:3[1] , a:3[2] , a:3[3] , get(a:3 , 4 , '' ) ] , + \ }) + else + call extend(palette, { + \ 'airline_x': [ a:sect3[0] , a:sect3[1] , a:sect3[2] , a:sect3[3] , '' ] , + \ 'airline_y': [ a:sect2[0] , a:sect2[1] , a:sect2[2] , a:sect2[3] , '' ] , + \ 'airline_z': [ a:sect1[0] , a:sect1[1] , a:sect1[2] , a:sect1[3] , '' ] , + \ }) + endif + + return palette +endfunction + +function! airline#themes#get_highlight(group, ...) + return call('airline#highlighter#get_highlight', [a:group] + a:000) +endfunction + +function! airline#themes#get_highlight2(fg, bg, ...) + return call('airline#highlighter#get_highlight2', [a:fg, a:bg] + a:000) +endfunction + +function! airline#themes#patch(palette) + for mode in keys(a:palette) + if mode == 'accents' + continue + endif + if !has_key(a:palette[mode], 'airline_warning') + let a:palette[mode]['airline_warning'] = [ '#000000', '#df5f00', 232, 166 ] + endif + if !has_key(a:palette[mode], 'airline_error') + let a:palette[mode]['airline_error'] = [ '#000000', '#990000', 232, 160 ] + endif + if !has_key(a:palette[mode], 'airline_term') + let a:palette[mode]['airline_term'] = [ '#9cffd3', '#202020', 85, 232] + endif + endfor + + let a:palette.accents = get(a:palette, 'accents', {}) + let a:palette.accents.none = [ '', '', '', '', '' ] + let a:palette.accents.bold = [ '', '', '', '', 'bold' ] + let a:palette.accents.italic = [ '', '', '', '', 'italic' ] + + if !has_key(a:palette.accents, 'red') + let a:palette.accents.red = [ '#ff0000' , '' , 160 , '' ] + endif + if !has_key(a:palette.accents, 'green') + let a:palette.accents.green = [ '#008700' , '' , 22 , '' ] + endif + if !has_key(a:palette.accents, 'blue') + let a:palette.accents.blue = [ '#005fff' , '' , 27 , '' ] + endif + if !has_key(a:palette.accents, 'yellow') + let a:palette.accents.yellow = [ '#dfff00' , '' , 190 , '' ] + endif + if !has_key(a:palette.accents, 'orange') + let a:palette.accents.orange = [ '#df5f00' , '' , 166 , '' ] + endif + if !has_key(a:palette.accents, 'purple') + let a:palette.accents.purple = [ '#af00df' , '' , 128 , '' ] + endif +endfunction diff --git a/.vim/autoload/airline/themes/base16.vim b/.vim/autoload/airline/themes/base16.vim new file mode 100644 index 0000000..0a7b442 --- /dev/null +++ b/.vim/autoload/airline/themes/base16.vim @@ -0,0 +1,181 @@ +let s:improved_contrast = get(g:, 'airline_base16_improved_contrast', 0) + +" Color palette +let s:gui_dark_gray = '#202020' +let s:cterm_dark_gray = 234 +let s:gui_med_gray_hi = '#303030' +let s:cterm_med_gray_hi = 236 +let s:gui_med_gray_lo = '#3a3a3a' +let s:cterm_med_gray_lo = 237 +let s:gui_light_gray = '#505050' +let s:cterm_light_gray = 239 +let s:gui_lightlight_gray = '#8A8A8A' +let s:cterm_lightlight_gray = 245 +let s:gui_green = '#99cc99' +let s:cterm_green = 151 +let s:gui_blue = '#6a9fb5' +let s:cterm_blue = 67 +let s:gui_purple = '#aa759f' +let s:cterm_purple = 139 +let s:gui_orange = '#d28445' +let s:cterm_orange = 173 +let s:gui_red = '#ac4142' +let s:cterm_red = 131 +let s:gui_pink = '#d7afd7' +let s:cterm_pink = 182 + +if get(g:, 'airline#themes#base16#constant', 0) + let g:airline#themes#base16#palette = {} + + " Normal mode + let s:N1 = [s:gui_dark_gray, s:gui_green, s:cterm_dark_gray, s:cterm_green] + if s:improved_contrast + let s:N2 = [s:gui_lightlight_gray, s:gui_med_gray_lo, s:cterm_lightlight_gray, s:cterm_med_gray_lo] + else + + let s:N2 = [s:gui_light_gray, s:gui_med_gray_lo, s:cterm_light_gray, s:cterm_med_gray_lo] + endif + let s:N3 = [s:gui_green, s:gui_med_gray_hi, s:cterm_green, s:cterm_med_gray_hi] + let g:airline#themes#base16#palette.normal = airline#themes#generate_color_map(s:N1, s:N2, s:N3) + let g:airline#themes#base16#palette.normal_modified = { + \ 'airline_c': [s:gui_orange, s:gui_med_gray_hi, s:cterm_orange, s:cterm_med_gray_hi, ''], + \ } + + " Insert mode + let s:I1 = [s:gui_med_gray_hi, s:gui_blue, s:cterm_med_gray_hi, s:cterm_blue] + let s:I3 = [s:gui_blue, s:gui_med_gray_hi, s:cterm_blue, s:cterm_med_gray_hi] + let g:airline#themes#base16#palette.insert = airline#themes#generate_color_map(s:I1, s:N2, s:I3) + let g:airline#themes#base16#palette.insert_modified = copy(g:airline#themes#base16#palette.normal_modified) + let g:airline#themes#base16#palette.insert_paste = { + \ 'airline_a': [s:gui_dark_gray, s:gui_orange, s:cterm_dark_gray, s:cterm_orange, ''], + \ } + + " Replace mode + let g:airline#themes#base16#palette.replace = { + \ 'airline_a': [s:gui_dark_gray, s:gui_red, s:cterm_dark_gray, s:cterm_red, ''], + \ 'airline_c': [s:gui_red, s:gui_med_gray_hi, s:cterm_red, s:cterm_med_gray_hi, ''], + \ } + let g:airline#themes#base16#palette.replace_modified = copy(g:airline#themes#base16#palette.insert_modified) + + " Visual mode + let s:V1 = [s:gui_dark_gray, s:gui_pink, s:cterm_dark_gray, s:cterm_pink] + let s:V3 = [s:gui_pink, s:gui_med_gray_hi, s:cterm_pink, s:cterm_med_gray_hi] + let g:airline#themes#base16#palette.visual = airline#themes#generate_color_map(s:V1, s:N2, s:V3) + let g:airline#themes#base16#palette.visual_modified = copy(g:airline#themes#base16#palette.insert_modified) + + " Inactive window + if s:improved_contrast + let s:IA = [s:gui_dark_gray, s:gui_med_gray_hi, s:cterm_lightlight_gray, s:cterm_med_gray_hi, ''] + else + let s:IA = [s:gui_dark_gray, s:gui_med_gray_hi, s:cterm_light_gray, s:cterm_med_gray_hi, ''] + endif + let g:airline#themes#base16#palette.inactive = airline#themes#generate_color_map(s:IA, s:IA, s:IA) + let g:airline#themes#base16#palette.inactive_modified = { + \ 'airline_c': [s:gui_orange, '', s:cterm_orange, '', ''], + \ } +else + function! airline#themes#base16#refresh() + let g:airline#themes#base16#palette = {} + + let g:airline#themes#base16#palette.accents = { + \ 'red': airline#themes#get_highlight('Constant'), + \ } + + let s:N1 = airline#themes#get_highlight2(['DiffText', 'bg'], ['DiffText', 'fg'], 'bold') + let s:N2 = airline#themes#get_highlight2(['Visual', 'fg'], ['Visual', 'bg']) + let s:N3 = airline#themes#get_highlight('CursorLine') + let g:airline#themes#base16#palette.normal = airline#themes#generate_color_map(s:N1, s:N2, s:N3) + + let group = airline#themes#get_highlight('Statement') + let g:airline#themes#base16#palette.normal_modified = { + \ 'airline_c': [ group[0], '', group[2], '', '' ] + \ } + + let s:I1 = airline#themes#get_highlight2(['DiffText', 'bg'], ['DiffAdded', 'fg'], 'bold') + let s:I2 = airline#themes#get_highlight2(['DiffAdded', 'fg'], ['Normal', 'bg']) + let s:I3 = s:N3 + let g:airline#themes#base16#palette.insert = airline#themes#generate_color_map(s:I1, s:I2, s:I3) + let g:airline#themes#base16#palette.insert_modified = g:airline#themes#base16#palette.normal_modified + + let s:R1 = airline#themes#get_highlight2(['DiffText', 'bg'], ['WarningMsg', 'fg'], 'bold') + let s:R2 = s:N2 + let s:R3 = s:N3 + let g:airline#themes#base16#palette.replace = airline#themes#generate_color_map(s:R1, s:R2, s:R3) + let g:airline#themes#base16#palette.replace_modified = g:airline#themes#base16#palette.normal_modified + + let s:V1 = airline#themes#get_highlight2(['DiffText', 'bg'], ['Constant', 'fg'], 'bold') + let s:V2 = airline#themes#get_highlight2(['Constant', 'fg'], ['Normal', 'bg']) + let s:V3 = s:N3 + let g:airline#themes#base16#palette.visual = airline#themes#generate_color_map(s:V1, s:V2, s:V3) + let g:airline#themes#base16#palette.visual_modified = g:airline#themes#base16#palette.normal_modified + + " Use VertSplit's bg and default fg (reversed) for inactive statusline. + let s:VS = airline#themes#get_highlight('VertSplit') + if s:improved_contrast + let s:IA = [ s:VS[1], 'NONE', s:VS[2], s:cterm_lightlight_gray, 'reverse'] + else + let s:IA = [ s:VS[1], 'NONE', s:VS[2], 'NONE', 'reverse'] + endif + let g:airline#themes#base16#palette.inactive = + \ airline#themes#generate_color_map(s:IA, s:IA, s:IA, s:IA, s:IA, s:IA) + let s:IM = [ s:VS[1], 'NONE', s:VS[2], 'NONE', 'reverse'] + let g:airline#themes#base16#palette.inactive_modified = + \ airline#themes#generate_color_map(s:IM, s:IM, s:IM, s:IM, s:IM, s:IM) + + " Warnings + let s:WI = airline#themes#get_highlight2(['WarningMsg', 'bg'], ['WarningMsg', 'fg'], 'bold') + let g:airline#themes#base16#palette.normal.airline_warning = [ + \ s:WI[0], s:WI[1], s:WI[2], s:WI[3] + \ ] + + let g:airline#themes#base16#palette.normal_modified.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + let g:airline#themes#base16#palette.insert.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + let g:airline#themes#base16#palette.insert_modified.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + let g:airline#themes#base16#palette.visual.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + let g:airline#themes#base16#palette.visual_modified.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + let g:airline#themes#base16#palette.replace.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + let g:airline#themes#base16#palette.replace_modified.airline_warning = + \ g:airline#themes#base16#palette.normal.airline_warning + + " Errors + let s:ER = airline#themes#get_highlight2(['ErrorMsg', 'bg'], ['ErrorMsg', 'fg'], 'bold') + let g:airline#themes#base16#palette.normal.airline_error = [ + \ s:ER[0], s:ER[1], s:ER[2], s:ER[3] + \ ] + + let g:airline#themes#base16#palette.normal_modified.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + let g:airline#themes#base16#palette.insert.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + let g:airline#themes#base16#palette.insert_modified.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + let g:airline#themes#base16#palette.visual.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + let g:airline#themes#base16#palette.visual_modified.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + let g:airline#themes#base16#palette.replace.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + let g:airline#themes#base16#palette.replace_modified.airline_error = + \ g:airline#themes#base16#palette.normal.airline_error + + endfunction + call airline#themes#base16#refresh() +endif diff --git a/.vim/autoload/airline/themes/bubblegum.vim b/.vim/autoload/airline/themes/bubblegum.vim new file mode 100644 index 0000000..f2378ce --- /dev/null +++ b/.vim/autoload/airline/themes/bubblegum.vim @@ -0,0 +1,70 @@ +" Color palette +let s:gui_dark_gray = '#303030' +let s:cterm_dark_gray = 236 +let s:gui_med_gray_hi = '#444444' +let s:cterm_med_gray_hi = 238 +let s:gui_med_gray_lo = '#3a3a3a' +let s:cterm_med_gray_lo = 237 +let s:gui_light_gray = '#b2b2b2' +let s:cterm_light_gray = 249 +let s:gui_green = '#afd787' +let s:cterm_green = 150 +let s:gui_blue = '#87afd7' +let s:cterm_blue = 110 +let s:gui_purple = '#afafd7' +let s:cterm_purple = 146 +let s:gui_orange = '#d7af5f' +let s:cterm_orange = 179 +let s:gui_red = '#d78787' +let s:cterm_red = 174 +let s:gui_pink = '#d7afd7' +let s:cterm_pink = 182 + +let g:airline#themes#bubblegum#palette = {} + +" Normal mode +let s:N1 = [s:gui_dark_gray, s:gui_green, s:cterm_dark_gray, s:cterm_green] +let s:N2 = [s:gui_light_gray, s:gui_med_gray_lo, s:cterm_light_gray, s:cterm_med_gray_lo] +let s:N3 = [s:gui_green, s:gui_med_gray_hi, s:cterm_green, s:cterm_med_gray_hi] +let g:airline#themes#bubblegum#palette.normal = airline#themes#generate_color_map(s:N1, s:N2, s:N3) +let g:airline#themes#bubblegum#palette.normal_modified = { + \ 'airline_c': [s:gui_orange, s:gui_med_gray_hi, s:cterm_orange, s:cterm_med_gray_hi, ''], + \ } + +" Insert mode +let s:I1 = [s:gui_med_gray_hi, s:gui_blue, s:cterm_med_gray_hi, s:cterm_blue] +let s:I3 = [s:gui_blue, s:gui_med_gray_hi, s:cterm_blue, s:cterm_med_gray_hi] +let g:airline#themes#bubblegum#palette.insert = airline#themes#generate_color_map(s:I1, s:N2, s:I3) +let g:airline#themes#bubblegum#palette.insert_modified = copy(g:airline#themes#bubblegum#palette.normal_modified) +let g:airline#themes#bubblegum#palette.insert_paste = { + \ 'airline_a': [s:gui_dark_gray, s:gui_orange, s:cterm_dark_gray, s:cterm_orange, ''], + \ } + +" Replace mode +let g:airline#themes#bubblegum#palette.replace = { + \ 'airline_a': [s:gui_dark_gray, s:gui_red, s:cterm_dark_gray, s:cterm_red, ''], + \ 'airline_c': [s:gui_red, s:gui_med_gray_hi, s:cterm_red, s:cterm_med_gray_hi, ''], + \ } +let g:airline#themes#bubblegum#palette.replace_modified = copy(g:airline#themes#bubblegum#palette.insert_modified) + +" Visual mode +let s:V1 = [s:gui_dark_gray, s:gui_pink, s:cterm_dark_gray, s:cterm_pink] +let s:V3 = [s:gui_pink, s:gui_med_gray_hi, s:cterm_pink, s:cterm_med_gray_hi] +let g:airline#themes#bubblegum#palette.visual = airline#themes#generate_color_map(s:V1, s:N2, s:V3) +let g:airline#themes#bubblegum#palette.visual_modified = copy(g:airline#themes#bubblegum#palette.insert_modified) + +" Inactive window +let s:IA = [s:gui_light_gray, s:gui_med_gray_hi, s:cterm_light_gray, s:cterm_med_gray_hi, ''] +let g:airline#themes#bubblegum#palette.inactive = airline#themes#generate_color_map(s:IA, s:IA, s:IA) +let g:airline#themes#bubblegum#palette.inactive_modified = { + \ 'airline_c': [s:gui_orange, '', s:cterm_orange, '', ''], + \ } + +" CtrlP +if !get(g:, 'loaded_ctrlp', 0) + finish +endif +let g:airline#themes#bubblegum#palette.ctrlp = airline#extensions#ctrlp#generate_color_map( + \ [ s:gui_orange, s:gui_med_gray_hi, s:cterm_orange, s:cterm_med_gray_hi, '' ] , + \ [ s:gui_orange, s:gui_med_gray_lo, s:cterm_orange, s:cterm_med_gray_lo, '' ] , + \ [ s:gui_dark_gray, s:gui_green, s:cterm_dark_gray, s:cterm_green, 'bold' ] ) diff --git a/.vim/autoload/airline/themes/dark.vim b/.vim/autoload/airline/themes/dark.vim new file mode 100644 index 0000000..94f3763 --- /dev/null +++ b/.vim/autoload/airline/themes/dark.vim @@ -0,0 +1,161 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 tw=80 + +scriptencoding utf-8 + +" Airline themes are generated based on the following concepts: +" * The section of the status line, valid Airline statusline sections are: +" * airline_a (left most section) +" * airline_b (section just to the right of airline_a) +" * airline_c (section just to the right of airline_b) +" * airline_x (first section of the right most sections) +" * airline_y (section just to the right of airline_x) +" * airline_z (right most section) +" * The mode of the buffer, as reported by the :mode() function. Airline +" converts the values reported by mode() to the following: +" * normal +" * insert +" * replace +" * visual +" * inactive +" The last one is actually no real mode as returned by mode(), but used by +" airline to style inactive statuslines (e.g. windows, where the cursor +" currently does not reside in). +" * In addition to each section and mode specified above, airline themes +" can also specify overrides. Overrides can be provided for the following +" scenarios: +" * 'modified' +" * 'paste' +" +" Airline themes are specified as a global viml dictionary using the above +" sections, modes and overrides as keys to the dictionary. The name of the +" dictionary is significant and should be specified as: +" * g:airline#themes#<theme_name>#palette +" where <theme_name> is substituted for the name of the theme.vim file where the +" theme definition resides. Airline themes should reside somewhere on the +" 'runtimepath' where it will be loaded at vim startup, for example: +" * autoload/airline/themes/theme_name.vim +" +" For this, the dark.vim, theme, this is defined as +let g:airline#themes#dark#palette = {} + +" Keys in the dictionary are composed of the mode, and if specified the +" override. For example: +" * g:airline#themes#dark#palette.normal +" * the colors for a statusline while in normal mode +" * g:airline#themes#dark#palette.normal_modified +" * the colors for a statusline while in normal mode when the buffer has +" been modified +" * g:airline#themes#dark#palette.visual +" * the colors for a statusline while in visual mode +" +" Values for each dictionary key is an array of color values that should be +" familiar for colorscheme designers: +" * [guifg, guibg, ctermfg, ctermbg, opts] +" See "help attr-list" for valid values for the "opt" value. +" +" Each theme must provide an array of such values for each airline section of +" the statusline (airline_a through airline_z). A convenience function, +" airline#themes#generate_color_map() exists to mirror airline_a/b/c to +" airline_x/y/z, respectively. + +" The dark.vim theme: +let s:airline_a_normal = [ '#00005f' , '#dfff00' , 17 , 190 ] +let s:airline_b_normal = [ '#ffffff' , '#444444' , 255 , 238 ] +let s:airline_c_normal = [ '#9cffd3' , '#202020' , 85 , 234 ] +let g:airline#themes#dark#palette.normal = airline#themes#generate_color_map(s:airline_a_normal, s:airline_b_normal, s:airline_c_normal) + +" It should be noted the above is equivalent to: +" let g:airline#themes#dark#palette.normal = airline#themes#generate_color_map( +" \ [ '#00005f' , '#dfff00' , 17 , 190 ], " section airline_a +" \ [ '#ffffff' , '#444444' , 255 , 238 ], " section airline_b +" \ [ '#9cffd3' , '#202020' , 85 , 234 ] " section airline_c +" \) +" +" In turn, that is equivalent to: +" let g:airline#themes#dark#palette.normal = { +" \ 'airline_a': [ '#00005f' , '#dfff00' , 17 , 190 ], "section airline_a +" \ 'airline_b': [ '#ffffff' , '#444444' , 255 , 238 ], "section airline_b +" \ 'airline_c': [ '#9cffd3' , '#202020' , 85 , 234 ], "section airline_c +" \ 'airline_x': [ '#9cffd3' , '#202020' , 85 , 234 ], "section airline_x +" \ 'airline_y': [ '#ffffff' , '#444444' , 255 , 238 ], "section airline_y +" \ 'airline_z': [ '#00005f' , '#dfff00' , 17 , 190 ] "section airline_z +" \} +" +" airline#themes#generate_color_map() also uses the values provided as +" parameters to create intermediary groups such as: +" airline_a_to_airline_b +" airline_b_to_airline_c +" etc... + +" Here we define overrides for when the buffer is modified. This will be +" applied after g:airline#themes#dark#palette.normal, hence why only certain keys are +" declared. +let g:airline#themes#dark#palette.normal_modified = { + \ 'airline_c': [ '#ffffff' , '#5f005f' , 255 , 53 , '' ] , + \ } + + +let s:airline_a_insert = [ '#00005f' , '#00dfff' , 17 , 45 ] +let s:airline_b_insert = [ '#ffffff' , '#005fff' , 255 , 27 ] +let s:airline_c_insert = [ '#ffffff' , '#000080' , 15 , 17 ] +let g:airline#themes#dark#palette.insert = airline#themes#generate_color_map(s:airline_a_insert, s:airline_b_insert, s:airline_c_insert) +let g:airline#themes#dark#palette.insert_modified = { + \ 'airline_c': [ '#ffffff' , '#5f005f' , 255 , 53 , '' ] , + \ } +let g:airline#themes#dark#palette.insert_paste = { + \ 'airline_a': [ s:airline_a_insert[0] , '#d78700' , s:airline_a_insert[2] , 172 , '' ] , + \ } + + +let g:airline#themes#dark#palette.replace = copy(g:airline#themes#dark#palette.insert) +let g:airline#themes#dark#palette.replace.airline_a = [ s:airline_b_insert[0] , '#af0000' , s:airline_b_insert[2] , 124 , '' ] +let g:airline#themes#dark#palette.replace_modified = g:airline#themes#dark#palette.insert_modified + + +let s:airline_a_visual = [ '#000000' , '#ffaf00' , 232 , 214 ] +let s:airline_b_visual = [ '#000000' , '#ff5f00' , 232 , 202 ] +let s:airline_c_visual = [ '#ffffff' , '#5f0000' , 15 , 52 ] +let g:airline#themes#dark#palette.visual = airline#themes#generate_color_map(s:airline_a_visual, s:airline_b_visual, s:airline_c_visual) +let g:airline#themes#dark#palette.visual_modified = { + \ 'airline_c': [ '#ffffff' , '#5f005f' , 255 , 53 , '' ] , + \ } + + +let s:airline_a_inactive = [ '#4e4e4e' , '#1c1c1c' , 239 , 234 , '' ] +let s:airline_b_inactive = [ '#4e4e4e' , '#262626' , 239 , 235 , '' ] +let s:airline_c_inactive = [ '#4e4e4e' , '#303030' , 239 , 236 , '' ] +let g:airline#themes#dark#palette.inactive = airline#themes#generate_color_map(s:airline_a_inactive, s:airline_b_inactive, s:airline_c_inactive) +let g:airline#themes#dark#palette.inactive_modified = { + \ 'airline_c': [ '#875faf' , '' , 97 , '' , '' ] , + \ } + +" For commandline mode, we use the colors from normal mode, except the mode +" indicator should be colored differently, e.g. blue on light green +let s:airline_a_commandline = [ '#0000ff' , '#0cff00' , 63 , 40 ] +let s:airline_b_commandline = [ '#ffffff' , '#444444' , 255 , 238 ] +let s:airline_c_commandline = [ '#9cffd3' , '#202020' , 85 , 234 ] +let g:airline#themes#dark#palette.commandline = airline#themes#generate_color_map(s:airline_a_commandline, s:airline_b_commandline, s:airline_c_commandline) + +" Accents are used to give parts within a section a slightly different look or +" color. Here we are defining a "red" accent, which is used by the 'readonly' +" part by default. Only the foreground colors are specified, so the background +" colors are automatically extracted from the underlying section colors. What +" this means is that regardless of which section the part is defined in, it +" will be red instead of the section's foreground color. You can also have +" multiple parts with accents within a section. +let g:airline#themes#dark#palette.accents = { + \ 'red': [ '#ff0000' , '' , 160 , '' ] + \ } + + +" Here we define the color map for ctrlp. We check for the g:loaded_ctrlp +" variable so that related functionality is loaded iff the user is using +" ctrlp. Note that this is optional, and if you do not define ctrlp colors +" they will be chosen automatically from the existing palette. +if get(g:, 'loaded_ctrlp', 0) + let g:airline#themes#dark#palette.ctrlp = airline#extensions#ctrlp#generate_color_map( + \ [ '#d7d7ff' , '#5f00af' , 189 , 55 , '' ], + \ [ '#ffffff' , '#875fd7' , 231 , 98 , '' ], + \ [ '#5f00af' , '#ffffff' , 55 , 231 , 'bold' ]) +endif diff --git a/.vim/autoload/airline/themes/gruvbox.vim b/.vim/autoload/airline/themes/gruvbox.vim new file mode 100644 index 0000000..6862a81 --- /dev/null +++ b/.vim/autoload/airline/themes/gruvbox.vim @@ -0,0 +1,79 @@ +" ----------------------------------------------------------------------------- +" File: gruvbox.vim +" Description: Retro groove color scheme for Airline +" Author: morhetz <morhetz@gmail.com> +" Source: https://github.com/morhetz/gruvbox +" Last Modified: 12 Aug 2017 +" ----------------------------------------------------------------------------- + +let g:airline#themes#gruvbox#palette = {} + +function! airline#themes#gruvbox#refresh() + + let M0 = airline#themes#get_highlight('Identifier') + let accents_group = airline#themes#get_highlight('Special') + let modified_group = [M0[0], '', M0[2], '', ''] + let warning_group = airline#themes#get_highlight2(['Normal', 'bg'], ['Question', 'fg']) + let error_group = airline#themes#get_highlight2(['Normal', 'bg'], ['WarningMsg', 'fg']) + + let s:N1 = airline#themes#get_highlight2(['Normal', 'bg'], ['StatusLineNC', 'bg']) + let s:N2 = airline#themes#get_highlight2(['StatusLineNC', 'bg'], ['Pmenu', 'bg']) + let s:N3 = airline#themes#get_highlight2(['StatusLineNC', 'bg'], ['CursorLine', 'bg']) + let g:airline#themes#gruvbox#palette.normal = airline#themes#generate_color_map(s:N1, s:N2, s:N3) + let g:airline#themes#gruvbox#palette.normal_modified = { 'airline_c': modified_group } + let g:airline#themes#gruvbox#palette.normal.airline_warning = warning_group + let g:airline#themes#gruvbox#palette.normal_modified.airline_warning = warning_group + let g:airline#themes#gruvbox#palette.normal.airline_error = error_group + let g:airline#themes#gruvbox#palette.normal_modified.airline_error = error_group + + let s:I1 = airline#themes#get_highlight2(['Normal', 'bg'], ['Identifier', 'fg']) + let s:I2 = s:N2 + let s:I3 = airline#themes#get_highlight2(['Normal', 'fg'], ['Pmenu', 'bg']) + let g:airline#themes#gruvbox#palette.insert = airline#themes#generate_color_map(s:I1, s:I2, s:I3) + let g:airline#themes#gruvbox#palette.insert_modified = g:airline#themes#gruvbox#palette.normal_modified + let g:airline#themes#gruvbox#palette.insert.airline_warning = g:airline#themes#gruvbox#palette.normal.airline_warning + let g:airline#themes#gruvbox#palette.insert_modified.airline_warning = g:airline#themes#gruvbox#palette.normal_modified.airline_warning + let g:airline#themes#gruvbox#palette.insert.airline_error = g:airline#themes#gruvbox#palette.normal.airline_error + let g:airline#themes#gruvbox#palette.insert_modified.airline_error = g:airline#themes#gruvbox#palette.normal_modified.airline_error + + let s:R1 = airline#themes#get_highlight2(['Normal', 'bg'], ['Structure', 'fg']) + let s:R2 = s:I2 + let s:R3 = s:I3 + let g:airline#themes#gruvbox#palette.replace = airline#themes#generate_color_map(s:R1, s:R2, s:R3) + let g:airline#themes#gruvbox#palette.replace_modified = g:airline#themes#gruvbox#palette.normal_modified + let g:airline#themes#gruvbox#palette.replace.airline_warning = g:airline#themes#gruvbox#palette.normal.airline_warning + let g:airline#themes#gruvbox#palette.replace_modified.airline_warning = g:airline#themes#gruvbox#palette.normal_modified.airline_warning + let g:airline#themes#gruvbox#palette.replace.airline_error = g:airline#themes#gruvbox#palette.normal.airline_error + let g:airline#themes#gruvbox#palette.replace_modified.airline_error = g:airline#themes#gruvbox#palette.normal_modified.airline_error + + let s:V1 = airline#themes#get_highlight2(['Normal', 'bg'], ['Question', 'fg']) + let s:V2 = s:N2 + let s:V3 = airline#themes#get_highlight2(['Normal', 'bg'], ['TabLine', 'fg']) + let g:airline#themes#gruvbox#palette.visual = airline#themes#generate_color_map(s:V1, s:V2, s:V3) + let g:airline#themes#gruvbox#palette.visual_modified = { 'airline_c': [ s:V3[0], '', s:V3[2], '', '' ] } + let g:airline#themes#gruvbox#palette.visual.airline_warning = g:airline#themes#gruvbox#palette.normal.airline_warning + let g:airline#themes#gruvbox#palette.visual_modified.airline_warning = g:airline#themes#gruvbox#palette.normal_modified.airline_warning + let g:airline#themes#gruvbox#palette.visual.airline_error = g:airline#themes#gruvbox#palette.normal.airline_error + let g:airline#themes#gruvbox#palette.visual_modified.airline_error = g:airline#themes#gruvbox#palette.normal_modified.airline_error + + let s:IA = airline#themes#get_highlight2(['TabLine', 'fg'], ['CursorLine', 'bg']) + let g:airline#themes#gruvbox#palette.inactive = airline#themes#generate_color_map(s:IA, s:IA, s:IA) + let g:airline#themes#gruvbox#palette.inactive_modified = { 'airline_c': modified_group } + + let g:airline#themes#gruvbox#palette.accents = { 'red': accents_group } + + let s:TF = airline#themes#get_highlight2(['Normal', 'bg'], ['Normal', 'bg']) + let g:airline#themes#gruvbox#palette.tabline = { + \ 'airline_tab': s:N2, + \ 'airline_tabsel': s:N1, + \ 'airline_tabtype': s:V1, + \ 'airline_tabfill': s:TF, + \ 'airline_tabhid': s:IA, + \ 'airline_tabmod': s:I1 + \ } + +endfunction + +call airline#themes#gruvbox#refresh() + +" vim: set sw=2 ts=2 sts=2 et tw=80 ft=vim fdm=marker: diff --git a/.vim/autoload/airline/util.vim b/.vim/autoload/airline/util.vim new file mode 100644 index 0000000..65e123c --- /dev/null +++ b/.vim/autoload/airline/util.vim @@ -0,0 +1,131 @@ +" MIT License. Copyright (c) 2013-2018 Bailey Ling et al. +" vim: et ts=2 sts=2 sw=2 + +" TODO: Try to cache winwidth(0) function +" e.g. store winwidth per window and access that, only update it, if the size +" actually changed. +scriptencoding utf-8 + +call airline#init#bootstrap() +let s:spc = g:airline_symbols.space +let s:nomodeline = (v:version > 703 || (v:version == 703 && has("patch438"))) ? '<nomodeline>' : '' + +function! airline#util#shorten(text, winwidth, minwidth, ...) + if winwidth(0) < a:winwidth && len(split(a:text, '\zs')) > a:minwidth + if get(a:000, 0, 0) + " shorten from tail + return '…'.matchstr(a:text, '.\{'.a:minwidth.'}$') + else + " shorten from beginning of string + return matchstr(a:text, '^.\{'.a:minwidth.'}').'…' + endif + else + return a:text + endif +endfunction + +function! airline#util#wrap(text, minwidth) + if a:minwidth > 0 && winwidth(0) < a:minwidth + return '' + endif + return a:text +endfunction + +function! airline#util#append(text, minwidth) + if a:minwidth > 0 && winwidth(0) < a:minwidth + return '' + endif + let prefix = s:spc == "\ua0" ? s:spc : s:spc.s:spc + return empty(a:text) ? '' : prefix.g:airline_left_alt_sep.s:spc.a:text +endfunction + +function! airline#util#warning(msg) + echohl WarningMsg + echomsg "airline: ".a:msg + echohl Normal +endfunction + +function! airline#util#prepend(text, minwidth) + if a:minwidth > 0 && winwidth(0) < a:minwidth + return '' + endif + return empty(a:text) ? '' : a:text.s:spc.g:airline_right_alt_sep.s:spc +endfunction + +if v:version >= 704 + function! airline#util#getwinvar(winnr, key, def) + return getwinvar(a:winnr, a:key, a:def) + endfunction +else + function! airline#util#getwinvar(winnr, key, def) + let winvals = getwinvar(a:winnr, '') + return get(winvals, a:key, a:def) + endfunction +endif + +if v:version >= 704 + function! airline#util#exec_funcrefs(list, ...) + for Fn in a:list + let code = call(Fn, a:000) + if code != 0 + return code + endif + endfor + return 0 + endfunction +else + function! airline#util#exec_funcrefs(list, ...) + " for 7.2; we cannot iterate the list, hence why we use range() + " for 7.3-[97, 328]; we cannot reuse the variable, hence the {} + for i in range(0, len(a:list) - 1) + let Fn{i} = a:list[i] + let code = call(Fn{i}, a:000) + if code != 0 + return code + endif + endfor + return 0 + endfunction +endif + +" Compatibility wrapper for strchars, in case this vim version does not +" have it natively +function! airline#util#strchars(str) + if exists('*strchars') + return strchars(a:str) + else + return strlen(substitute(a:str, '.', 'a', 'g')) + endif +endfunction + +function! airline#util#ignore_buf(name) + let pat = '\c\v'. get(g:, 'airline#ignore_bufadd_pat', ''). + \ get(g:, 'airline#extensions#tabline#ignore_bufadd_pat', + \ 'gundo|undotree|vimfiler|tagbar|nerd_tree|startify|!') + return match(a:name, pat) > -1 +endfunction + +function! airline#util#has_fugitive() + return exists('*fugitive#head') || exists('*FugitiveHead') +endfunction + +function! airline#util#has_lawrencium() + return exists('*lawrencium#statusline') +endfunction + +function! airline#util#has_vcscommand() + return get(g:, 'airline#extensions#branch#use_vcscommand', 0) && exists('*VCSCommandGetStatusLine') +endfunction + +function! airline#util#has_custom_scm() + return !empty(get(g:, 'airline#extensions#branch#custom_head', '')) +endfunction + +function! airline#util#doautocmd(event) + exe printf("silent doautocmd %s User %s", s:nomodeline, a:event) +endfunction + +function! airline#util#themes(match) + let files = split(globpath(&rtp, 'autoload/airline/themes/'.a:match.'*'), "\n") + return map(files, 'fnamemodify(v:val, ":t:r")') +endfunction diff --git a/.vim/autoload/neomake.vim b/.vim/autoload/neomake.vim new file mode 100644 index 0000000..6322a05 --- /dev/null +++ b/.vim/autoload/neomake.vim @@ -0,0 +1,2582 @@ +" vim: ts=4 sw=4 et +scriptencoding utf-8 + +if !exists('s:make_id') + let s:make_id = 0 +endif +" A map of make_id to options, e.g. cwd when jobs where started. +if !exists('s:make_info') + let s:make_info = {} +endif +if !exists('s:job_id') + let s:job_id = 1 +endif +if !exists('s:jobs') + let s:jobs = {} +endif +if !exists('s:map_job_ids') + let s:map_job_ids = {} +endif + +" Errors by [maker_type][bufnr][lnum] +let s:current_errors = {'project': {}, 'file': {}} + +if !has('nvim') + let s:kill_vim_timers = {} +endif + +" A list of references to keep when profiling. +" Workaround for https://github.com/vim/vim/issues/2350, where +" https://github.com/blueyed/vader.vim/commit/e66d91dea is not enough. +let s:hack_keep_refs_for_profiling = [] + +" Can Neovim buffer output? +let s:nvim_can_buffer_output = has('nvim-0.3.0') ? 1 : 0 + +" Private function to access script-local variables during tests. +function! neomake#_get_s() abort + return s: +endfunction + +" Sentinels. +let s:unset_list = [] +let s:unset_dict = {} +let s:unset = {} + +let s:can_use_env_in_job_opts = has('patch-8.0.0902') && has('patch-8.0.1832') + +let s:is_testing = exists('g:neomake_test_messages') + +let s:async = has('nvim') + \ || has('channel') && has('job') && has('patch-8.0.0027') +function! neomake#has_async_support() abort + return s:async +endfunction + +if v:version >= 704 || (v:version == 703 && has('patch1058')) + function! s:function(name) abort + return function(a:name) + endfunction +else + " Older Vim does not handle s: function references across files. + function! s:function(name) abort + return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '.*\zs<SNR>\d\+_'),'')) + endfunction +endif + +function! s:sort_jobs(a, b) abort + return a:a.id - a:b.id +endfunction + +function! neomake#GetJobs(...) abort + if empty(s:jobs) + return [] + endif + let jobs = copy(values(s:jobs)) + if a:0 + call filter(jobs, 'index(a:1, v:val.id) != -1') + endif + return sort(jobs, function('s:sort_jobs')) +endfunction + +function! neomake#GetJob(job_id) abort + return s:jobs[a:job_id] +endfunction + +" Not documented, only used in tests for now. +function! neomake#GetStatus() abort + return { + \ 'last_make_id': s:make_id, + \ 'make_info': s:make_info, + \ 'action_queue': g:neomake#action_queue#_s.action_queue, + \ } +endfunction + +" neomake#GetMakeOptions: not documented, only used internally for now. +" More lax when not being used in tests to avoid errors, but fail during tests. +if s:is_testing + function! neomake#GetMakeOptions(...) abort + let make_id = a:0 ? a:1 : s:make_id + try + let r = s:make_info[make_id] + catch + let msg = printf('GetMakeOptions failed: %s (in %s)', v:exception, v:throwpoint) + call vader#log(msg) + let g:neomake_test_errors += [msg] + return {'verbosity': 3} + endtry + return r + endfunction +else + function! neomake#GetMakeOptions(...) abort + let make_id = a:0 ? a:1 : s:make_id + if !has_key(s:make_info, make_id) + call neomake#log#warning('warning: missing make_info key: '.make_id.'.') + return {'verbosity': get(g:, 'neomake_verbose', 1)} + endif + return s:make_info[make_id] + endfunction +endif + +function! neomake#ListJobs() abort + if !s:async + echom 'This Vim version has no support for jobs.' + return + endif + let jobs = neomake#GetJobs() + if empty(jobs) + return + endif + echom 'make_id | job_id | name/maker' + for jobinfo in jobs + let desc = !empty(jobinfo.maker.name) && jobinfo.name != jobinfo.maker.name + \ ? jobinfo.name. ' ('.jobinfo.maker.name.')' + \ : jobinfo.name + echom printf('%7d | %6d | %s', jobinfo.make_id, jobinfo.id, desc) + endfor +endfunction + +function! neomake#CancelMake(...) abort + let make_id = a:0 ? a:1 : s:make_id + if !has_key(s:make_info, make_id) + call neomake#log#error('CancelMake: make not found: '.make_id.'.') + return 0 + endif + let bang = a:0 > 1 ? a:1 : 0 + let make_info = s:make_info[make_id] + call neomake#log#debug('Canceling make.', make_info) + let make_info.canceled = 1 + let jobs = filter(copy(values(s:jobs)), 'v:val.make_id == make_id') + call s:abort_next_makers(make_id) + for job in jobs + call neomake#CancelJob(job.id, bang) + endfor + call neomake#action_queue#clean(make_info) + " Ensure that make info gets cleaned really, e.g. if there were no jobs yet. + if has_key(s:make_info, make_id) + call s:clean_make_info(make_info, bang) + endif + return 1 +endfunction + +function! neomake#CancelAllMakes(...) abort + let bang = a:0 ? a:1 : 0 + for make_id in keys(s:make_info) + call neomake#CancelMake(make_id, bang) + endfor +endfunction + +" Returns 1 if a job was canceled, 0 otherwise. +function! neomake#CancelJob(job_id, ...) abort + let job_id = type(a:job_id) == type({}) ? a:job_id.id : +a:job_id + let remove_always = a:0 ? a:1 : 0 + let jobinfo = get(s:jobs, job_id, {}) + call neomake#log#debug('Canceling job.', jobinfo) + + call neomake#action_queue#clean(empty(jobinfo) ? {'id': job_id} : jobinfo) + + if empty(jobinfo) + call neomake#log#error('CancelJob: job not found: '.job_id.'.') + return 0 + endif + + if get(jobinfo, 'canceled', 0) + call neomake#log#info('Job was canceled already.', jobinfo) + if remove_always + call s:CleanJobinfo(jobinfo) + endif + return 0 + endif + let jobinfo.canceled = 1 + + let ret = 0 + if get(jobinfo, 'finished') + call neomake#log#debug('Removing already finished job.', jobinfo) + elseif has_key(jobinfo, 'exit_code') + call neomake#log#debug('Job exited already.', jobinfo) + elseif has_key(jobinfo.maker, 'get_list_entries') + call neomake#log#debug('Removing job for get_list_entries.', jobinfo) + elseif s:async + if has('nvim') + let job = jobinfo.nvim_job + call neomake#log#debug(printf('Stopping Neovim job: %s.', job), jobinfo) + else + let job = jobinfo.vim_job + call neomake#log#debug(printf('Stopping Vim job: %s.', job), jobinfo) + endif + if has('nvim') + try + call jobstop(job) + let ret = 1 + catch /^Vim\%((\a\+)\)\=:\(E474\|E900\):/ + call neomake#log#info(printf( + \ 'jobstop failed: %s.', v:exception), jobinfo) + endtry + else + " Use ch_status here, since job_status might be 'dead' already, + " without the exit handler being called yet. + if job_status(job) !=# 'run' + call neomake#log#info( + \ 'job_stop: job was not running anymore.', jobinfo) + else + " NOTE: might be "dead" already, but that is fine. + call job_stop(job) + let ret = 1 + if job_status(job) ==# 'run' + let timer = timer_start(1000, function('s:kill_vimjob_cb')) + let s:kill_vim_timers[timer] = jobinfo + endif + endif + endif + endif + + if ret == 0 || remove_always + call s:CleanJobinfo(jobinfo) + endif + return ret +endfunction + +function! s:kill_vimjob_cb(timer) abort + let jobinfo = s:kill_vim_timers[a:timer] + let vim_job = jobinfo.vim_job + if job_status(vim_job) ==# 'run' + call neomake#log#debug('Forcefully killing still running Vim job.', jobinfo) + call job_stop(vim_job, 'kill') + endif + unlet s:kill_vim_timers[a:timer] +endfunction + +function! neomake#CancelJobs(bang) abort + call neomake#log#debug(printf('Canceling %d jobs.', len(s:jobs))) + for job in neomake#GetJobs() + call neomake#CancelJob(job.id, a:bang) + endfor +endfunction + +function! s:handle_get_list_entries(jobinfo, ...) abort + if !a:0 + return s:pcall('s:handle_get_list_entries', [a:jobinfo]) + endif + let jobinfo = a:jobinfo + let jobinfo.serialize = 0 + let maker = jobinfo.maker + try + let entries = maker.get_list_entries(jobinfo) + catch /^\%(Vim\%((\a\+)\)\=:\%(E48\|E523\)\)\@!/ " everything, but E48/E523 (sandbox / not allowed here) + if v:exception ==# 'NeomakeTestsException' + throw v:exception + endif + call neomake#log#exception(printf( + \ 'Error during get_list_entries for %s: %s.', + \ jobinfo.maker.name, v:exception), jobinfo) + call s:CleanJobinfo(jobinfo) + return g:neomake#action_queue#processed + endtry + + if type(entries) != type([]) + call neomake#log#error(printf('The get_list_entries method for maker %s did not return a list, but: %s.', jobinfo.maker.name, string(entries)[:100]), jobinfo) + elseif !empty(entries) && type(entries[0]) != type({}) + call neomake#log#error(printf('The get_list_entries method for maker %s did not return a list of dicts, but: %s.', jobinfo.maker.name, string(entries)[:100]), jobinfo) + else + call s:ProcessEntries(jobinfo, entries) + endif + call s:CleanJobinfo(jobinfo) + return g:neomake#action_queue#processed +endfunction + +function! s:MakeJob(make_id, options) abort + let job_id = s:job_id + let s:job_id += 1 + + " Optional: + " - serialize (default: 0 for async (and get_list_entries), + " 1 for non-async) + " - serialize_abort_on_error (default: 0) + " - exit_callback (string/function, default: 0) + let jobinfo = extend(deepcopy(g:neomake#jobinfo#base), extend({ + \ 'id': job_id, + \ 'make_id': a:make_id, + \ 'name': empty(get(a:options.maker, 'name', '')) ? 'neomake_'.job_id : a:options.maker.name, + \ 'maker': a:options.maker, + \ 'bufnr': a:options.bufnr, + \ 'file_mode': a:options.file_mode, + \ 'ft': a:options.ft, + \ 'cwd': s:make_info[a:make_id].cwd, + \ }, a:options)) + + let maker = jobinfo.maker + + if has_key(maker, 'get_list_entries') + call neomake#log#info(printf( + \ '%s: getting entries via get_list_entries.', + \ maker.name), jobinfo) + let s:jobs[jobinfo.id] = jobinfo + let s:make_info[a:make_id].active_jobs += [jobinfo] + call s:handle_get_list_entries(jobinfo) + return jobinfo + endif + + call extend(jobinfo, { + \ 'output_stream': a:options.maker.output_stream, + \ 'buffer_output': a:options.maker.buffer_output, + \ }, 'keep') + + let error = '' + try + " Change to job's cwd (before args, for relative filename). + let cd_error = jobinfo.cd() + if !empty(cd_error) + throw printf("Neomake: %s: could not change to maker's cwd (%s): %s.", + \ maker.name, jobinfo.cd_from_setting, cd_error) + endif + let jobinfo.argv = maker._get_argv(jobinfo) + + call neomake#utils#hook('NeomakeJobInit', {'jobinfo': jobinfo}) + + let start_msg = s:async ? 'Starting async job' : 'Starting' + if type(jobinfo.argv) == type('') + let start_msg .= ' [string]: '.jobinfo.argv + else + let start_msg .= ': '.join(map(copy(jobinfo.argv), 'neomake#utils#shellescape(v:val)')) + endif + call neomake#log#info(start_msg.'.', jobinfo) + + let cwd = jobinfo.cwd + let changed = !empty(jobinfo.cd_back_cmd) + if changed + call neomake#log#debug('cwd: '.cwd.' (changed).', jobinfo) + else + call neomake#log#debug('cwd: '.cwd.'.', jobinfo) + endif + + let base_job_opts = {} + if has_key(jobinfo, 'filename') + if s:can_use_env_in_job_opts + let base_job_opts = { + \ 'env': { + \ 'NEOMAKE_FILE': jobinfo.filename + \ }} + else + let save_env_file = exists('$NEOMAKE_FILE') ? $NEOMAKE_FILE : s:unset + let $NEOMAKE_FILE = jobinfo.filename + endif + endif + + " Lock maker to make sure it does not get changed accidentally, but + " only with depth=1, so that a postprocess object can change itself. + lockvar 1 maker + if s:async + if has('nvim') + if jobinfo.buffer_output + let opts = extend(base_job_opts, { + \ 'stdout_buffered': 1, + \ 'stderr_buffered': 1, + \ }) + if s:nvim_can_buffer_output == 1 + let opts.on_exit = function('s:nvim_exit_handler_buffered') + else + call extend(opts, { + \ 'on_stdout': function('s:nvim_output_handler'), + \ 'on_stderr': function('s:nvim_output_handler'), + \ }) + let opts.on_exit = function('s:nvim_exit_handler') + endif + let jobinfo.jobstart_opts = opts + else + let opts = { + \ 'on_stdout': function('s:nvim_output_handler'), + \ 'on_stderr': function('s:nvim_output_handler'), + \ 'on_exit': function('s:nvim_exit_handler'), + \ } + endif + if has_key(maker, 'nvim_job_opts') + call extend(opts, maker.nvim_job_opts) + endif + if !has('nvim-0.3.0') + \ && !neomake#utils#IsRunningWindows() + \ && !has_key(opts, 'detach') + \ && !has_key(opts, 'pty') + " Always use detach to trigger setsid() with older Neovim. + let opts.detach = 1 + endif + try + let job = jobstart(jobinfo.argv, opts) + catch + let error = printf('Failed to start Neovim job: %s: %s.', + \ string(jobinfo.argv), v:exception) + endtry + if empty(error) + if job == 0 + let error = printf('Failed to start Neovim job: %s: %s.', + \ 'Job table is full or invalid arguments given', string(jobinfo.argv)) + elseif job == -1 + let error = printf('Failed to start Neovim job: %s: %s.', + \ 'Executable not found', string(jobinfo.argv)) + else + let s:map_job_ids[job] = jobinfo.id + let jobinfo.nvim_job = job + let s:jobs[jobinfo.id] = jobinfo + + if get(jobinfo, 'uses_stdin', 0) + call jobsend(job, s:make_info[a:make_id].buffer_lines) + call jobclose(job, 'stdin') + endif + endif + endif + else + " vim-async. + let opts = extend(base_job_opts, { + \ 'out_cb': function('s:vim_output_handler_stdout'), + \ 'err_cb': function('s:vim_output_handler_stderr'), + \ 'close_cb': function('s:vim_exit_handler'), + \ 'mode': 'raw', + \ }) + if has_key(maker, 'vim_job_opts') + call extend(opts, maker.vim_job_opts) + endif + try + let job = job_start(jobinfo.argv, opts) + " Get this as early as possible! + let channel_id = ch_info(job)['id'] + catch + " NOTE: not covered in tests. Vim seems to always return + " a job. Might be able to trigger this using custom opts?! + let error = printf('Failed to start Vim job: %s: %s.', + \ jobinfo.argv, v:exception) + endtry + if empty(error) + let jobinfo.vim_job = job + let s:map_job_ids[channel_id] = jobinfo.id + let s:jobs[jobinfo.id] = jobinfo + call neomake#log#debug(printf('Vim job: %s.', + \ string(job_info(job))), jobinfo) + call neomake#log#debug(printf('Vim channel: %s.', + \ string(ch_info(job))), jobinfo) + + if get(jobinfo, 'uses_stdin', 0) + call ch_sendraw(job, join(s:make_info[a:make_id].buffer_lines, "\n")) + call ch_close_in(job) + endif + endif + endif + + " Bail out on errors. + if !empty(error) + throw 'Neomake: '.error + endif + + call neomake#utils#hook('NeomakeJobStarted', {'jobinfo': jobinfo}) + else + " vim-sync. + " Use a temporary file to capture stderr. + let stderr_file = tempname() + let argv = jobinfo.argv . ' 2>'.stderr_file + + try + if get(jobinfo, 'uses_stdin', 0) + " Pass stdin to system(), but only if non-empty. + " Otherwise it might cause E677 (vim74-trusty at least). + let stdin = join(s:make_info[a:make_id].buffer_lines, "\n") + if !empty(stdin) + let output = system(argv, stdin) + else + let output = system(argv) + endif + else + let output = system(argv) + endif + catch /^Vim(let):E484:/ + throw printf('Neomake: Could not run %s: %s.', argv, v:exception) + endtry + + let jobinfo.id = job_id + let s:jobs[job_id] = jobinfo + let s:make_info[a:make_id].active_jobs += [jobinfo] + + call s:output_handler(jobinfo, split(output, '\r\?\n', 1), 'stdout', 0) + let stderr_output = readfile(stderr_file) + if !empty(stderr_output) + call s:output_handler(jobinfo, stderr_output, 'stderr', 1) + endif + call delete(stderr_file) + + call s:exit_handler(jobinfo, v:shell_error) + return jobinfo + endif + finally + call jobinfo.cd_back() + if exists('save_env_file') + call s:restore_env('NEOMAKE_FILE', save_env_file) + endif + endtry + let s:make_info[a:make_id].active_jobs += [jobinfo] + return jobinfo +endfunction + +if !s:can_use_env_in_job_opts + function! s:restore_env(var, value) abort + " Cannot unlet environment vars without patch 8.0.1832. + exe printf('let $%s = %s', a:var, string(a:value is s:unset ? '' : a:value)) + endfunction +endif + +let s:command_maker_base = copy(g:neomake#core#command_maker_base) +" Check if a temporary file is used, and set it in s:make_info in case it is. +function! s:command_maker_base._get_tempfilename(jobinfo) abort dict + let l:Supports_stdin = neomake#utils#GetSetting('supports_stdin', self, s:unset_dict, a:jobinfo.ft, a:jobinfo.bufnr) + if Supports_stdin isnot s:unset_dict + if type(Supports_stdin) == type(function('tr')) + let supports_stdin = call(Supports_stdin, [a:jobinfo], self) + else + let supports_stdin = Supports_stdin + endif + if supports_stdin + let a:jobinfo.uses_stdin = 1 + return get(self, 'tempfile_name', '-') + endif + endif + + if has_key(self, 'tempfile_name') + return self.tempfile_name + endif + + let tempfile_enabled = neomake#utils#GetSetting('tempfile_enabled', self, 1, a:jobinfo.ft, a:jobinfo.bufnr) + if !tempfile_enabled + return '' + endif + + let make_id = a:jobinfo.make_id + if !has_key(s:make_info[make_id], 'tempfile_name') + if !exists('s:pid') + let s:pid = getpid() + endif + let slash = neomake#utils#Slash() + + let dir = neomake#utils#GetSetting('tempfile_dir', self, '', a:jobinfo.ft, a:jobinfo.bufnr) + + " Use absolute path internally, which is important for removal. + let orig_fname = neomake#utils#fnamemodify(a:jobinfo.bufnr, ':p') + if empty(dir) + if empty(orig_fname) + let dir = tempname() + else + let dir = fnamemodify(orig_fname, ':h') + if filewritable(dir) != 2 + let dir = tempname() + let s:make_info[make_id].tempfile_dir = dir + call neomake#log#debug('Using temporary directory for non-writable parent directory.') + endif + endif + + if empty(orig_fname) + let filename = 'neomaketmp.'.a:jobinfo.ft + else + let filename = fnamemodify(orig_fname, ':t') + \ .'@neomake_'.s:pid.'_'.make_id + let ext = fnamemodify(orig_fname, ':e') + if !empty(ext) + let filename .= '.'.ext + endif + " Use hidden files to make e.g. pytest not trying to import it. + if filename[0] !=# '.' + let filename = '.' . filename + endif + endif + else + let dir = neomake#utils#ExpandArgs([dir], a:jobinfo)[0] + if empty(orig_fname) + let filename = 'neomaketmp.'.a:jobinfo.ft + else + let filename = fnamemodify(orig_fname, ':t') + endif + endif + + let temp_file = dir . slash . filename + let s:make_info[make_id].tempfile_name = temp_file + endif + return s:make_info[make_id].tempfile_name +endfunction + +" Get the filename to use for a:jobinfo's make/buffer. +function! s:command_maker_base._get_fname_for_buffer(jobinfo) abort + let bufnr = a:jobinfo.bufnr + let bufname = bufname(bufnr) + let temp_file = '' + let _uses_stdin = neomake#utils#GetSetting('uses_stdin', a:jobinfo.maker, s:unset_dict, a:jobinfo.ft, bufnr) + if _uses_stdin isnot s:unset_dict + let a:jobinfo.uses_stdin = _uses_stdin + let uses_stdin = _uses_stdin + call neomake#log#debug(printf('Using uses_stdin (%s) from setting.', + \ a:jobinfo.uses_stdin), a:jobinfo) + if a:jobinfo.uses_stdin + let temp_file = neomake#utils#GetSetting('tempfile_name', a:jobinfo.maker, '-', a:jobinfo.ft, bufnr) + endif + else + if empty(bufname) + let temp_file = self._get_tempfilename(a:jobinfo) + if !get(a:jobinfo, 'uses_stdin', 0) && empty(temp_file) + throw 'Neomake: no file name.' + endif + let used_for = 'unnamed' + elseif getbufvar(bufnr, '&modified') + let temp_file = self._get_tempfilename(a:jobinfo) + if !get(a:jobinfo, 'uses_stdin', 0) && empty(temp_file) + throw 'Neomake: skip_job: buffer is modified, but temporary files are disabled.' + endif + let used_for = 'modified' + elseif !filereadable(bufname) + let temp_file = self._get_tempfilename(a:jobinfo) + if !get(a:jobinfo, 'uses_stdin', 0) && empty(temp_file) + " Using ':p' as modifier is unpredictable as per doc, but OK. + throw printf('Neomake: file is not readable (%s)', fnamemodify(bufname, ':p')) + endif + let used_for = 'unreadable' + else + let bufname = fnamemodify(bufname, ':.') + let used_for = '' + endif + + let uses_stdin = get(a:jobinfo, 'uses_stdin', 0) + + if !empty(used_for) + if uses_stdin + call neomake#log#debug(printf( + \ 'Using stdin for %s buffer (%s).', used_for, temp_file), + \ a:jobinfo) + elseif !empty(temp_file) + call neomake#log#debug(printf( + \ 'Using tempfile for %s buffer: "%s".', used_for, temp_file), + \ a:jobinfo) + endif + endif + endif + + let make_info = s:make_info[a:jobinfo.make_id] + " Handle stdin when supports_stdin sets self.tempfile_name = ''. + if uses_stdin + if !has_key(make_info, 'buffer_lines') + let make_info.buffer_lines = neomake#utils#get_buffer_lines(bufnr) + endif + let bufname = temp_file + elseif !empty(temp_file) + " Use relative path for args. + let bufname = fnamemodify(temp_file, ':.') + let temp_file = fnamemodify(temp_file, ':p') + if !has_key(make_info, 'tempfiles') + let make_info.tempfiles = [temp_file] + let make_info.created_dirs = s:create_dirs_for_file(temp_file) + call neomake#utils#write_tempfile(bufnr, temp_file) + elseif temp_file !=# make_info.tempfiles[0] + call extend(make_info.created_dirs, s:create_dirs_for_file(temp_file)) + call writefile(readfile(make_info.tempfiles[0], 'b'), temp_file, 'b') + call add(make_info.tempfiles, temp_file) + endif + let a:jobinfo.tempfile = temp_file + endif + + let a:jobinfo.filename = bufname + return bufname +endfunction + +function! s:create_dirs_for_file(fpath) abort + let created_dirs = [] + let last_dir = a:fpath + while 1 + let temp_dir = fnamemodify(last_dir, ':h') + if isdirectory(temp_dir) || last_dir ==# temp_dir + break + endif + call insert(created_dirs, temp_dir) + let last_dir = temp_dir + endwhile + for dir in created_dirs + call mkdir(dir, '', 0700) + endfor + return created_dirs +endfunction + +function! s:command_maker_base._bind_args() abort dict + " Resolve args, which might be a function or dictionary. + if type(self.args) == type(function('tr')) + " Deprecated: use InitForJob + call neomake#log#warn_once(printf("Please use 'InitForJob' instead of 'args' for maker %s.", self.name), + \ printf('deprecated-args-%s', self.name)) + let args = call(self.args, []) + elseif type(self.args) == type({}) + " Deprecated: use InitForJob + call neomake#log#warn_once(printf("Please use 'InitForJob' instead of 'args.fn' for maker %s.", self.name), + \ printf('deprecated-args-fn-%s', self.name)) + let args = call(self.args.fn, [], self.args) + else + let args = copy(self.args) + endif + let self.args = args + return self +endfunction + +function! s:command_maker_base._get_argv(jobinfo) abort dict + let filename = self._get_fname_for_args(a:jobinfo) + let args_is_list = type(self.args) == type([]) + if args_is_list + let args = neomake#utils#ExpandArgs(self.args, a:jobinfo) + if !empty(filename) + call add(args, filename) + endif + elseif !empty(filename) + let args = copy(self.args) + let args .= (empty(args) ? '' : ' ').neomake#utils#shellescape(filename) + else + let args = self.args + endif + return neomake#compat#get_argv(self.exe, args, args_is_list) +endfunction + +function! s:GetMakerForFiletype(ft, maker_name) abort + for config_ft in neomake#utils#get_config_fts(a:ft) + call neomake#utils#load_ft_makers(config_ft) + let f = 'neomake#makers#ft#'.config_ft.'#'.a:maker_name + if exists('*'.f) + let maker = call(f, []) + return maker + endif + endfor + return s:unset_dict +endfunction + +function! neomake#get_maker_by_name(maker_name, ...) abort + let for_ft = a:0 ? a:1 : 0 + let ft_config = for_ft is# 0 ? &filetype : for_ft + let bufnr = bufnr('%') + if a:maker_name !~# '\v^\w+$' + throw printf('Neomake: Invalid maker name: "%s"', a:maker_name) + endif + + let maker = neomake#utils#GetSetting('maker', {'name': a:maker_name}, s:unset_dict, ft_config, bufnr) + if maker is# s:unset_dict + if a:maker_name ==# 'makeprg' + let maker = s:get_makeprg_maker() + elseif for_ft isnot# 0 + let maker = s:GetMakerForFiletype(for_ft, a:maker_name) + else + call neomake#utils#load_global_makers() + let f = 'neomake#makers#'.a:maker_name.'#'.a:maker_name + if exists('*'.f) + let maker = call(f, []) + endif + endif + endif + if type(maker) != type({}) + throw printf('Neomake: Got non-dict for maker %s: %s', + \ a:maker_name, maker) + endif + if maker isnot# s:unset_dict && !has_key(maker, 'name') + let maker.name = a:maker_name + endif + return maker +endfunction + +function! neomake#GetMaker(name_or_maker, ...) abort + let for_ft = a:0 ? a:1 : 0 + if type(a:name_or_maker) == type({}) + let maker = a:name_or_maker + if !has_key(maker, 'name') + let maker.name = 'unnamed_maker' + endif + else + let maker = neomake#get_maker_by_name(a:name_or_maker, for_ft) + if maker is# s:unset_dict + if !a:0 + " Check &filetype if no args where provided. + let maker = neomake#get_maker_by_name(a:name_or_maker, &filetype) + endif + endif + if maker is# s:unset_dict + if for_ft isnot# 0 + throw printf('Neomake: Maker not found (for %s): %s', + \ !empty(for_ft) ? 'filetype '.for_ft : 'empty filetype', + \ a:name_or_maker) + else + throw printf('Neomake: Maker not found (without filetype): %s', + \ a:name_or_maker) + endif + endif + endif + return neomake#create_maker_object(maker, a:0 ? a:1 : &filetype) +endfunction + +" NOTE: uses ft and bufnr for config only. +function! neomake#create_maker_object(maker, ft) abort + let [maker, ft, bufnr] = [a:maker, a:ft, bufnr('%')] + + " Create the maker object. + let l:GetEntries = neomake#utils#GetSetting('get_list_entries', maker, -1, ft, bufnr) + if GetEntries isnot# -1 + let maker = copy(maker) + let maker.get_list_entries = GetEntries + else + let maker = extend(copy(s:command_maker_base), copy(maker)) + endif + if !has_key(maker, 'get_list_entries') + " Set defaults for command/job based makers. + let defaults = extend( + \ copy(g:neomake#config#_defaults['maker_defaults']), + \ neomake#config#get('maker_defaults')) + call extend(defaults, { + \ 'exe': maker.name, + \ 'args': [], + \ }) + if !has_key(maker, 'process_output') && !has_key(maker, 'process_json') + call extend(defaults, { + \ 'errorformat': &errorformat, + \ }) + endif + for [key, default] in items(defaults) + let maker[key] = neomake#utils#GetSetting(key, {'name': maker.name}, get(maker, key, default), ft, bufnr, 1) + unlet default " for Vim without patch-7.4.1546 + endfor + endif + if v:profiling + call add(s:hack_keep_refs_for_profiling, maker) + endif + return maker +endfunction + +if exists('*getcompletion') + function! s:get_makers_for_pattern(pattern) abort + " Get function prefix based on pattern, until the first backslash. + let prefix = substitute(a:pattern, '\v\\.*', '', '') + + " NOTE: the pattern uses &ignorecase. + let funcs = getcompletion(prefix.'[a-z]', 'function') + call filter(funcs, 'v:val =~# a:pattern') + " Remove prefix. + call map(funcs, 'v:val['.len(prefix).':]') + " Only keep lowercase function names. + call filter(funcs, "v:val =~# '\\m^[a-z].*('") + " Remove parenthesis and #.* (for project makers). + return sort(map(funcs, "substitute(v:val, '\\v[(#].*', '', '')")) + endfunction +else + function! s:get_makers_for_pattern(pattern) abort + let funcs_output = neomake#utils#redir('fun /'.a:pattern) + return sort(map(split(funcs_output, '\n'), + \ "substitute(v:val, '\\v^.*#(.*)\\(.*$', '\\1', '')")) + endfunction +endif + +function! neomake#GetMakers(ft) abort + " Get all makers for a given filetype. This is used from completion. + " XXX: this should probably use a callback or some other more stable + " approach to get the list of makers (than looking at the lowercase + " functions)?! + + let makers = [] + " Do not use 'b:neomake_jsx_javascript_foo_maker' twice for + " ft=jsx.javascript. + let used_vars = [] + for ft in neomake#utils#get_config_fts(a:ft) + call neomake#utils#load_ft_makers(ft) + + " Add sorted list per filetype. + let add = [] + + let maker_names = s:get_makers_for_pattern('neomake#makers#ft#'.ft.'#\l') + for maker_name in maker_names + if index(makers, maker_name) == -1 && index(add, maker_name) == -1 + let add += [maker_name] + endif + endfor + + " Get makers from g:/b: variables. + for v in sort(extend(keys(g:), keys(b:))) + if index(used_vars, v) != -1 + continue + endif + let maker_name = matchstr(v, '\v^neomake_'.ft.'_\zs[0-9a-z_]+\ze_maker$') + if !empty(maker_name) + \ && index(makers, maker_name) == -1 + \ && index(add, maker_name) == -1 + let used_vars += [v] + let add += [maker_name] + endif + endfor + + " Get makers from new-style config. + for [maker_name, val] in items(neomake#config#get('ft.'.ft)) + if has_key(val, 'maker') + \ && index(makers, maker_name) == -1 + \ && index(add, maker_name) == -1 + let add += [maker_name] + endif + endfor + + call sort(add) + call extend(makers, add) + endfor + return makers +endfunction + +function! neomake#GetProjectMakers() abort + call neomake#utils#load_global_makers() + return s:get_makers_for_pattern('neomake#makers#\(ft#\)\@!\l') +endfunction + +function! neomake#GetEnabledMakers(...) abort + let file_mode = a:0 + if !file_mode + " If we have no filetype, use the global default makers. + " This variable is also used for project jobs, so it has no + " buffer local ('b:') counterpart for now. + let enabled_makers = copy(get(g:, 'neomake_enabled_makers', [])) + if empty(enabled_makers) + let makeprg_maker = s:get_makeprg_maker() + if !empty(makeprg_maker) + let makeprg_maker = neomake#GetMaker(makeprg_maker) + let makeprg_maker.auto_enabled = 1 + let enabled_makers = [makeprg_maker] + endif + else + call map(enabled_makers, "extend(neomake#GetMaker(v:val), + \ {'auto_enabled': 0}, 'error')") + endif + else + let enabled_makers = [] + let bufnr = bufnr('%') + let makers = neomake#utils#GetSetting('enabled_makers', {}, s:unset_list, a:1, bufnr) + if makers is# s:unset_list + let auto_enabled = 1 + for config_ft in neomake#utils#get_config_fts(a:1) + call neomake#utils#load_ft_makers(config_ft) + let fnname = 'neomake#makers#ft#'.config_ft.'#EnabledMakers' + if exists('*'.fnname) + try + let makers = call(fnname, []) + catch /^Vim(let):E119:/ " Not enough arguments for function + let makers = call(fnname, [{'file_mode': file_mode, 'bufnr': bufnr}]) + endtry + break + endif + endfor + else + let auto_enabled = 0 + endif + + let makers = neomake#map_makers(makers, a:1, auto_enabled) + for maker in makers + let maker.auto_enabled = auto_enabled + let enabled_makers += [maker] + endfor + endif + return enabled_makers +endfunction + +" a:1: override "open_list" setting. +function! s:HandleLoclistQflistDisplay(jobinfo, loc_or_qflist, ...) abort + let open_list_default = a:0 ? a:1 : 0 + let open_val = neomake#utils#GetSetting('open_list', a:jobinfo.maker, open_list_default, a:jobinfo.ft, a:jobinfo.bufnr) + if !open_val + return + endif + let height = neomake#utils#GetSetting('list_height', a:jobinfo.maker, 10, a:jobinfo.ft, a:jobinfo.bufnr) + if !height + return + endif + let height = min([len(a:loc_or_qflist), height]) + if a:jobinfo.file_mode + call neomake#log#debug('Handling location list: executing lwindow.', a:jobinfo) + let cmd = 'lwindow' + else + call neomake#log#debug('Handling quickfix list: executing cwindow.', a:jobinfo) + let cmd = 'botright cwindow' + endif + if open_val == 2 + let make_id = a:jobinfo.make_id + let make_info = s:make_info[make_id] + let g:neomake#core#_ignore_autocommands += 1 + try + call neomake#compat#save_prev_windows() + + let win_count = winnr('$') + exe cmd height + let new_win_count = winnr('$') + if win_count == new_win_count + " No new window, adjust height eventually. + let found = 0 + + if get(make_info, '_did_lwindow', 0) + for w in range(1, winnr('$')) + if getwinvar(w, 'neomake_window_for_make_id') == make_id + let found = w + break + endif + endfor + if found + let cmd = printf('%dresize %d', found, height) + if winheight(found) != height + call neomake#log#debug(printf( + \ 'Resizing existing quickfix window: %s.', + \ cmd), a:jobinfo) + exe cmd + endif + else + call neomake#log#debug( + \ 'Could not find corresponding quickfix window.', + \ a:jobinfo) + endif + endif + elseif new_win_count > win_count + if &filetype !=# 'qf' + call neomake#log#debug(printf( + \ 'WARN: unexpected filetype for new window: %s', + \ &filetype), a:jobinfo) + else + call neomake#log#debug(printf( + \ 'list window has been opened (old count: %d, new count: %d, height: %d).', + \ win_count, new_win_count, winheight(0)), a:jobinfo) + let w:neomake_window_for_make_id = a:jobinfo.make_id + endif + else + call neomake#log#debug(printf( + \ 'list window has been closed (old count: %d, new count: %d).', + \ win_count, new_win_count), a:jobinfo) + endif + call neomake#compat#restore_prev_windows() + let make_info._did_lwindow = 1 + finally + let g:neomake#core#_ignore_autocommands -= 1 + endtry + else + exe cmd height + endif +endfunction + +" Experimental/private wrapper. +function! neomake#_handle_list_display(jobinfo, ...) abort + if a:0 + let list = a:1 + else + let list = a:jobinfo.file_mode ? getloclist(0) : getqflist() + endif + call s:HandleLoclistQflistDisplay(a:jobinfo, list, 2) +endfunction + +" Get a maker for &makeprg. +" This could be cached, but needs to take into account / set &errorformat, +" and other settings that are handled by neomake#GetMaker. +function! s:get_makeprg_maker() abort + if empty(&makeprg) + return {} + elseif &makeprg =~# '\s' + let maker = neomake#utils#MakerFromCommand(&makeprg) + else + let maker = neomake#utils#MakerFromCommand([&makeprg]) + endif + let maker.name = 'makeprg' + " Do not append file. &makeprg should contain %/# for this instead. + let maker.append_file = 0 + return neomake#GetMaker(maker) +endfunction + +function! s:Make(options) abort + let is_automake = get(a:options, 'automake', !empty(expand('<abuf>'))) + if is_automake + if g:neomake#core#_ignore_autocommands + call neomake#log#debug(printf( + \ 'Ignoring Make through autocommand due to ignore_autocommands=%d.', g:neomake#core#_ignore_autocommands), {'winnr': winnr()}) + return [] + endif + let disabled = neomake#config#get_with_source('disabled', 0) + if disabled[0] + call neomake#log#debug(printf( + \ 'Make through autocommand disabled via %s.', disabled[1])) + return [] + endif + endif + + let s:make_id += 1 + let make_id = s:make_id + let options = extend(copy(a:options), { + \ 'file_mode': 1, + \ 'ft': &filetype, + \ }, 'keep') + let options.make_id = make_id " Deprecated. + let file_mode = options.file_mode + + " Require winid/winnr with non-current buffer in file_mode. + if has_key(options, 'bufnr') + if options.bufnr != bufnr('%') + if !has_key(options, 'winid') && !has_key(options, 'winnr') + throw 'Neomake: winid or winnr are required for non-current buffer.' + endif + endif + if !bufexists(options.bufnr) + throw printf('Neomake: buffer %d does not exist.', options.bufnr) + endif + else + let options.bufnr = bufnr('%') + endif + + " Validate winid/winnr (required for location list windows). + let file_mode_win = 0 + if file_mode + if has_key(options, 'winid') + if win_id2tabwin(options.winid) == [0, 0] + throw printf('Neomake: window id %d does not exist.', options.winid) + endif + let file_mode_win = options.winid + elseif has_key(options, 'winnr') + if winbufnr(options.winnr) == -1 + throw printf('Neomake: window %d does not exist.', options.winnr) + endif + let file_mode_win = options.winnr + elseif exists('*win_getid') + let options.winid = win_getid() + endif + elseif has_key(options, 'winid') + throw 'Neomake: do not use winid with file_mode=0.' + elseif has_key(options, 'winnr') + throw 'Neomake: do not use winnr with file_mode=0.' + endif + + lockvar 1 options + let s:make_info[make_id] = { + \ 'make_id': make_id, + \ 'cwd': getcwd(), + \ 'verbosity': get(g:, 'neomake_verbose', 1), + \ 'active_jobs': [], + \ 'finished_jobs': [], + \ 'options': options, + \ } + let make_info = s:make_info[make_id] + let bufnr = options.bufnr + if &verbose + let make_info.verbosity += &verbose + call neomake#log#debug(printf( + \ 'Adding &verbose (%d) to verbosity level: %d.', + \ &verbose, make_info.verbosity), make_info) + endif + if make_info.verbosity >= 3 + call neomake#log#debug(printf( + \ 'Calling Make with options %s.', + \ string(filter(copy(options), "index(['bufnr', 'make_id'], v:key) == -1"))), {'make_id': make_id, 'bufnr': bufnr}) + endif + + " Use pre-compiled jobs (used with automake). + if has_key(options, 'jobs') + let jobs = map(copy(options.jobs), "extend(v:val, {'make_id': make_id})") + else + if has_key(options, 'enabled_makers') + if file_mode + let makers = neomake#map_makers(options.enabled_makers, options.ft, 0) + else + let makers = neomake#map_makers(options.enabled_makers, -1, 0) + endif + else + let makers = call('neomake#GetEnabledMakers', file_mode ? [options.ft] : []) + if empty(makers) + if file_mode + let msg = printf('Nothing to make: no enabled file mode makers (filetype=%s).', options.ft) + if is_automake + call neomake#log#debug(msg, make_info) + else + call neomake#log#warning(msg, make_info) + endif + unlet s:make_info[make_id] + return [] + endif + endif + endif + let job_options = copy(options) + let job_options.make_id = make_id " Used for logging. + let jobs = neomake#core#create_jobs(job_options, makers) + endif + + if empty(jobs) + call neomake#log#debug('Nothing to make: no valid makers.', make_info) + call s:clean_make_info(make_info) + return [] + endif + let make_info.jobs = copy(jobs) + + let maker_info = join(map(copy(jobs), + \ "v:val.maker.name . (get(v:val.maker, 'auto_enabled', 0) ? ' (auto)' : '')"), ', ') + call neomake#log#debug(printf('Running makers: %s.', maker_info), make_info) + + let make_info.jobs_queue = jobs + + if file_mode + " XXX: this clears counts for job's buffer only, but we add counts for + " the entry's buffers, which might be different! + call neomake#statusline#ResetCountsForBuf(bufnr) + if g:neomake_place_signs + call neomake#signs#Reset(bufnr, 'file') + endif + else + call neomake#statusline#ResetCountsForProject() + if g:neomake_place_signs + call neomake#signs#ResetProject() + endif + endif + + " Store make_id on window (used to find window for location lists (without + " winid, but also used to check the current window via w: directly)). + if file_mode + call setwinvar(file_mode_win, 'neomake_make_ids', + \ neomake#compat#getwinvar(file_mode_win, 'neomake_make_ids', []) + [make_id]) + endif + + let use_list = get(options, 'use_list', 1) + if use_list + let any_job_uses_list = 0 + for job in jobs + if get(job.maker, 'use_list', 1) + let any_job_uses_list = 1 + break + endif + endfor + if !any_job_uses_list + let use_list = 0 + endif + endif + + if use_list + let make_info.entries_list = neomake#list#ListForMake(make_info) + + " Reuse existing location list window with automake. + if is_automake && has('patch-7.4.2200') + if file_mode + let title = get(getloclist(0, {'title': 1}), 'title') + else + let title = get(getqflist({'title': 1}), 'title') + endif + if title =~# '\V\^Neomake[auto]' + let make_info.entries_list.reset_existing_qflist = 1 + endif + endif + endif + + " Cancel any already running jobs for the makers from these jobs. + if !empty(s:jobs) + " @vimlint(EVL102, 1, l:job) + for job in jobs + let running_already = values(filter(copy(s:jobs), + \ 'v:val.maker == job.maker' + \ .' && v:val.bufnr == job.bufnr' + \ .' && v:val.file_mode == job.file_mode' + \ ." && !get(v:val, 'canceled')")) + if !empty(running_already) + let jobinfo = running_already[0] + call neomake#log#info(printf( + \ 'Canceling already running job (%d.%d) for the same maker.', + \ jobinfo.make_id, jobinfo.id), {'make_id': make_id}) + call neomake#CancelJob(jobinfo.id, 1) + endif + endfor + endif + + " Update automake tick (used to skip unchanged buffers). + call neomake#configure#_update_automake_tick(bufnr, options.ft) + + " Start all jobs in the queue (until serialized). + let jobinfos = [] + while 1 + if empty(make_info.jobs_queue) + break + endif + let jobinfo = s:handle_next_job({}) + if empty(jobinfo) + break + endif + call add(jobinfos, jobinfo) + if jobinfo.serialize + let make_info.serializing_for_job = jobinfo.id + " Break and continue through exit handler. + break + endif + endwhile + return jobinfos +endfunction + +function! s:AddExprCallback(jobinfo, lines) abort + if s:need_to_postpone_loclist(a:jobinfo) + return neomake#action_queue#add(['BufEnter', 'WinEnter'], [s:function('s:AddExprCallback'), + \ [a:jobinfo, a:lines] + a:000]) + endif + + " Create location/quickfix list and add lines to it. + let cd_error = a:jobinfo.cd() + if !empty(cd_error) + call neomake#log#debug(printf( + \ "Could not change to job's cwd (%s): %s.", + \ a:jobinfo.cd_from_setting, cd_error), a:jobinfo) + endif + + let make_list = s:make_info[a:jobinfo.make_id].entries_list + let prev_list = copy(make_list.entries) + + let added_entries = make_list.add_lines_with_efm(a:lines, a:jobinfo) + return s:ProcessEntries(a:jobinfo, added_entries, prev_list) +endfunction + +function! s:CleanJobinfo(jobinfo, ...) abort + if get(a:jobinfo, '_in_exit_handler', 0) + " Do not clean job yet. + return + endif + if !empty(a:jobinfo.pending_output) && !get(a:jobinfo, 'canceled', 0) + call neomake#log#debug( + \ 'Output left to be processed, not cleaning job yet.', a:jobinfo) + return g:neomake#action_queue#not_processed + endif + + let queued_actions = neomake#action_queue#get_queued_actions(a:jobinfo) + if !empty(queued_actions) + call neomake#log#debug(printf( + \ 'Skipping cleaning of job info because of queued actions: %s.', + \ join(queued_actions, ', ')), a:jobinfo) + return neomake#action_queue#add(['WinEnter'], [s:function('s:CleanJobinfo'), [a:jobinfo]]) + endif + + call neomake#log#debug('Cleaning jobinfo.', a:jobinfo) + let a:jobinfo.finished = 1 + + if !has_key(s:make_info, a:jobinfo.make_id) + return g:neomake#action_queue#processed + endif + let make_info = s:make_info[a:jobinfo.make_id] + + if has_key(s:jobs, get(a:jobinfo, 'id', -1)) + call remove(s:jobs, a:jobinfo.id) + call filter(s:map_job_ids, 'v:val != a:jobinfo.id') + endif + + if exists('s:kill_vim_timers') + for [timer, job] in items(s:kill_vim_timers) + if job == a:jobinfo + call timer_stop(+timer) + unlet s:kill_vim_timers[timer] + break + endif + endfor + endif + + if !get(a:jobinfo, 'canceled', 0) + \ && !get(a:jobinfo, 'failed_to_start', 0) + let make_info.finished_jobs += [a:jobinfo] + call neomake#utils#hook('NeomakeJobFinished', {'jobinfo': a:jobinfo}) + endif + + call filter(make_info.active_jobs, 'v:val != a:jobinfo') + + " Trigger cleanup (and autocommands) if all jobs have finished. + if empty(make_info.active_jobs) && empty(make_info.jobs_queue) + call s:clean_make_info(make_info) + endif + return g:neomake#action_queue#processed +endfunction + +function! s:clean_make_info(make_info, ...) abort + let make_id = a:make_info.make_id + let bang = a:0 ? a:1 : 0 + if !bang && !empty(a:make_info.active_jobs) + call neomake#log#debug(printf( + \ 'Skipping cleaning of make info: %d active jobs: %s.', + \ len(a:make_info.active_jobs), + \ string(map(copy(a:make_info.active_jobs), 'v:val.as_string()'))), + \ a:make_info) + return + endif + + " Queue cleanup in case of queued actions, e.g. NeomakeJobFinished hook. + let queued = [] + for [_, v] in g:neomake#action_queue#_s.action_queue + if has_key(v[1][0], 'id') + let jobinfo = v[1][0] + if jobinfo.make_id == make_id + let queued += ['job '.jobinfo.id] + endif + else + if v[1][0] == a:make_info + let queued += ['make '.make_id] + endif + endif + endfor + if !empty(queued) + call neomake#log#debug(printf('Queuing clean_make_info for already queued actions: %s', string(queued))) + return neomake#action_queue#add( + \ g:neomake#action_queue#any_event, + \ [s:function('s:clean_make_info'), [a:make_info]]) + endif + + if exists('*neomake#statusline#make_finished') + call neomake#statusline#make_finished(a:make_info) + endif + + if !empty(a:make_info.finished_jobs) + " Clean old signs after all jobs have finished, so that they can be + " reused, avoiding flicker and keeping them for longer in general. + if g:neomake_place_signs + if a:make_info.options.file_mode + call neomake#signs#CleanOldSigns(a:make_info.options.bufnr, 'file') + else + call neomake#signs#CleanAllOldSigns('project') + endif + endif + call s:clean_for_new_make(a:make_info) + + call neomake#EchoCurrentError(1) + call neomake#virtualtext#handle_current_error() + + if get(a:make_info, 'canceled', 0) + call neomake#log#debug('Skipping final processing for canceled make.', a:make_info) + call s:do_clean_make_info(a:make_info) + elseif has_key(a:make_info, 'entries_list') " use_list option + return s:handle_locqf_list_for_finished_jobs(a:make_info) + else + call s:handle_finished_make(a:make_info) + endif + else + call s:do_clean_make_info(a:make_info) + endif + return g:neomake#action_queue#processed +endfunction + +function! s:do_clean_make_info(make_info) abort + call neomake#log#debug('Cleaning make info.', a:make_info) + let make_id = a:make_info.make_id + + " Remove make_id from its window. + let [t, w] = neomake#core#get_tabwin_for_makeid(make_id) + if [t, w] != [-1, -1] + let make_ids = neomake#compat#gettabwinvar(t, w, 'neomake_make_ids', []) + let idx = index(make_ids, make_id) + if idx != -1 + call remove(make_ids, idx) + call settabwinvar(t, w, 'neomake_make_ids', make_ids) + endif + endif + + " Clean up temporary files and buffers. + let wipe_unlisted_buffers = get(a:make_info, '_wipe_unlisted_buffers', []) + let tempfiles = get(a:make_info, 'tempfiles') + if !empty(tempfiles) + for tempfile in tempfiles + let delete_ret = delete(tempfile) + if delete_ret == 0 + call neomake#log#debug(printf('Removing temporary file: "%s".', + \ tempfile)) + else + call neomake#log#warning(printf('Failed to remove temporary file: "%s" (%d).', + \ tempfile, delete_ret)) + endif + let bufnr_tempfile = bufnr(tempfile) + if bufnr_tempfile != -1 && !buflisted(bufnr_tempfile) + let wipe_unlisted_buffers += [bufnr_tempfile] + endif + endfor + + " Only delete the dir, if Vim supports it. + if v:version >= 705 || (v:version == 704 && has('patch1107')) + for dir in reverse(copy(get(a:make_info, 'created_dirs'))) + call delete(dir, 'd') + endfor + endif + endif + if !empty(wipe_unlisted_buffers) + if !empty(wipe_unlisted_buffers) + call neomake#compat#uniq(sort(wipe_unlisted_buffers)) + endif + call neomake#log#debug(printf('Wiping out %d unlisted/remapped buffers: %s.', + \ len(wipe_unlisted_buffers), + \ string(wipe_unlisted_buffers))) + " NOTE: needs to be silent with more than a single buffer. + exe 'silent bwipeout '.join(wipe_unlisted_buffers) + endif + + let buf_prev_makes = getbufvar(a:make_info.options.bufnr, '_neomake_automake_make_ids') + if !empty(buf_prev_makes) + call filter(buf_prev_makes, 'v:val != make_id') + call setbufvar(a:make_info.options.bufnr, '_neomake_automake_make_ids', buf_prev_makes) + endif + + unlet s:make_info[make_id] +endfunction + +function! s:handle_locqf_list_for_finished_jobs(make_info) abort + let file_mode = a:make_info.options.file_mode + let create_list = a:make_info.entries_list.need_init + + let open_val = get(g:, 'neomake_open_list', 0) + let height = open_val ? get(g:, 'neomake_list_height', 10) : 0 + if height + let close_list = create_list || empty(file_mode ? getloclist(0) : getqflist()) + else + let close_list = 0 + endif + + if file_mode + if create_list && !bufexists(a:make_info.options.bufnr) + call neomake#log#info('No buffer found for location list!', a:make_info) + let create_list = 0 + let close_list = 0 + elseif (create_list || close_list) + if index(get(w:, 'neomake_make_ids', []), a:make_info.make_id) == -1 + call neomake#log#debug( + \ 'Postponing final location list handling (in another window).', + \ a:make_info) + return neomake#action_queue#add(['WinEnter'], [s:function('s:handle_locqf_list_for_finished_jobs'), + \ [a:make_info] + a:000]) + endif + + " TODO: merge with s:need_to_postpone_output_processing. + if neomake#compat#in_completion() + call neomake#log#debug( + \ 'Postponing final location list handling during completion.', + \ a:make_info) + return neomake#action_queue#add(['CompleteDone'], [s:function('s:handle_locqf_list_for_finished_jobs'), + \ [a:make_info] + a:000]) + endif + let mode = neomake#compat#get_mode() + if index(['n', 'i'], mode) == -1 + call neomake#log#debug(printf( + \ 'Postponing final location list handling for mode "%s".', mode), + \ a:make_info) + return neomake#action_queue#add(['CursorHold', 'WinEnter'], [s:function('s:handle_locqf_list_for_finished_jobs'), + \ [a:make_info] + a:000]) + endif + endif + endif + + " Update list title. + " This has to be done currently by itself to reflect running/finished + " state properly. + if create_list || !a:make_info.entries_list.need_init + if has_key(a:make_info, 'entries_list') + call a:make_info.entries_list.finish_for_make() + endif + endif + + " Close empty list. + if close_list + if file_mode + call neomake#log#debug('Handling location list: executing lclose.', {'winnr': winnr()}) + lclose + else + call neomake#log#debug('Handling quickfix list: executing cclose.') + cclose + endif + endif + + call s:handle_finished_make(a:make_info) + + return g:neomake#action_queue#processed +endfunction + +function! s:handle_finished_make(make_info) abort + let hook_context = { + \ 'make_info': a:make_info, + \ 'make_id': a:make_info.make_id, + \ 'options': a:make_info.options, + \ 'finished_jobs': a:make_info.finished_jobs, + \ } + call neomake#utils#hook('NeomakeFinished', hook_context) + + call neomake#configure#_reset_automake_cancelations(a:make_info.options.bufnr) + + call s:do_clean_make_info(a:make_info) +endfunction + +function! neomake#VimLeave() abort + call neomake#log#debug('Calling VimLeave.') + for make_id in keys(s:make_info) + call neomake#CancelMake(make_id) + endfor +endfunction + +function! s:clean_for_new_make(make_info) abort + if get(a:make_info, 'cleaned_for_make', 0) + return + endif + " XXX: needs to handle buffers for list entries?! + " See "get_list_entries: minimal example (from doc)" in + " tests/makers.vader. + call neomake#_clean_errors(extend(copy(a:make_info.options), {'make_id': a:make_info.make_id})) + let a:make_info.cleaned_for_make = 1 +endfunction + +" a:context: dictionary with keys: +" - file_mode +" - bufnr (required for file_mode) +" - make_id (used for logging) +function! neomake#_clean_errors(context) abort + if a:context.file_mode + let bufnr = a:context.bufnr + if has_key(s:current_errors['file'], bufnr) + unlet s:current_errors['file'][bufnr] + endif + call neomake#highlights#ResetFile(bufnr) + call neomake#log#debug('File-level errors cleaned.', a:context) + else + let s:current_errors['project'] = {} + call neomake#highlights#ResetProject() + call neomake#log#debug('Project-level errors cleaned.', a:context) + endif +endfunction + +" Change to a job's cwd, if any. +" Returns: a list: +" - error (empty for success) +" - directory changed into (empty if skipped) +" - command to change back to the current workding dir (might be empty) + +" Call a:fn with a:args and queue it, in case if fails with E48/E523. +function! s:pcall(fn, args) abort + let jobinfo = a:args[0] + try + return call(a:fn, a:args + [1]) + catch /^\%(Vim\%((\a\+)\)\=:\%(E48\|E523\)\)/ " only E48/E523 (sandbox / not allowed here) + call neomake#log#debug('Error during pcall: '.v:exception.'.', jobinfo) + call neomake#log#debug(printf('(in %s)', v:throwpoint), jobinfo) + " Might throw in case of X failed attempts. + call neomake#action_queue#add(['Timer', 'WinEnter'], [s:function(a:fn), a:args]) + endtry + return g:neomake#action_queue#not_processed +endfunction + +function! s:ProcessEntries(jobinfo, entries, ...) abort + if empty(a:entries) + return + endif + if get(a:jobinfo, 'canceled') + return + endif + if s:need_to_postpone_loclist(a:jobinfo) + return neomake#action_queue#add(['BufEnter', 'WinEnter'], [s:function('s:ProcessEntries'), + \ [a:jobinfo, a:entries] + a:000]) + endif + if !a:0 || type(a:[len(a:000)]) != 0 + return s:pcall('s:ProcessEntries', [a:jobinfo, a:entries] + a:000) + endif + let file_mode = a:jobinfo.file_mode + + call neomake#log#debug(printf( + \ 'Processing %d entries.', len(a:entries)), a:jobinfo) + + let make_info = s:make_info[a:jobinfo.make_id] + let make_list = make_info.entries_list + let maker_name = a:jobinfo.maker.name + if a:0 > 1 + " Via errorformat processing, where the list has been set already. + let prev_list = a:1 + let parsed_entries = a:entries + else + " Fix entries with get_list_entries/process_output/process_json. + " @vimlint(EVL102, 1, l:default_type) + let default_type = neomake#utils#GetSetting('default_entry_type', a:jobinfo.maker, 'W', a:jobinfo.ft, a:jobinfo.bufnr) + call map(a:entries, 'extend(v:val, {' + \ . "'bufnr': str2nr(get(v:val, 'bufnr', 0))," + \ . "'lnum': str2nr(get(v:val, 'lnum', 0))," + \ . "'col': str2nr(get(v:val, 'col', 0))," + \ . "'vcol': str2nr(get(v:val, 'vcol', 0))," + \ . "'type': get(v:val, 'type', default_type)," + \ . "'nr': get(v:val, 'nr', has_key(v:val, 'text') ? -1 : 0)," + \ . "'text': get(v:val, 'text', '')," + \ . '})') + + let cd_error = a:jobinfo.cd() + if !empty(cd_error) + call neomake#log#debug(printf( + \ "Could not change to job's cwd (%s): %s.", + \ a:jobinfo.cd_from_setting, cd_error), a:jobinfo) + endif + + let prev_list = file_mode ? getloclist(0) : getqflist() + try + let parsed_entries = make_list.add_entries_for_job(a:entries, a:jobinfo) + if exists(':Assert') && !empty(a:entries) + Assert get(a:entries[0], 'text', '') !~# 'nmcfg:' + endif + finally + call a:jobinfo.cd_back() + endtry + endif + call s:clean_for_new_make(make_info) + + let counts_changed = 0 + let maker_type = file_mode ? 'file' : 'project' + let do_highlight = get(g:, 'neomake_highlight_columns', 1) + \ || get(g:, 'neomake_highlight_lines', 0) + let signs_by_bufnr = {} + let debug = neomake#utils#get_verbosity(a:jobinfo) >= 3 || !empty(get(g:, 'neomake_logfile')) || s:is_testing + let entries_with_lnum_by_bufnr = {} + let skipped_without_bufnr = [] + let skipped_without_lnum = [] + + let idx = -1 + for entry in parsed_entries + let idx += 1 + if !file_mode + if neomake#statusline#AddQflistCount(entry) + let counts_changed = 1 + endif + endif + + if !entry.bufnr + if debug + let skipped_without_bufnr += [idx] + endif + continue + endif + + if file_mode + if neomake#statusline#AddLoclistCount(entry.bufnr, entry) + let counts_changed = 1 + endif + endif + + if !entry.lnum + if debug + let skipped_without_lnum += [idx] + endif + continue + endif + + if !has_key(entries_with_lnum_by_bufnr, entry.bufnr) + let entries_with_lnum_by_bufnr[entry.bufnr] = [] + let signs_by_bufnr[entry.bufnr] = [] + endif + + if do_highlight || g:neomake_place_signs + " NOTE: only lnum/type required for signs. Similar for do_highlight?! + call add(entries_with_lnum_by_bufnr[entry.bufnr], entry) + endif + + " Track all errors by buffer and line + let entry.maker_name = maker_name + call neomake#_add_error(maker_type, entry) + endfor + + " Handle placing signs and highlights. + for [b, entries] in items(entries_with_lnum_by_bufnr) + if g:neomake_place_signs + call neomake#signs#PlaceSigns(b, entries, maker_type) + endif + if do_highlight + for entry in entries + call neomake#highlights#AddHighlight(entry, maker_type) + endfor + endif + endfor + + if !empty(skipped_without_bufnr) + call neomake#log#debug(printf('Skipped %d entries without bufnr: %s.', + \ len(skipped_without_bufnr), + \ string(map(skipped_without_bufnr, 'a:entries[v:val]'))), a:jobinfo) + endif + + if !empty(skipped_without_lnum) + call neomake#log#debug(printf( + \ 'Could not place signs for %d entries without line number: %s.', + \ len(skipped_without_lnum), + \ string(map(skipped_without_lnum, 'a:entries[v:val]'))), a:jobinfo) + endif + + let new_list = make_list.entries + if !counts_changed + let counts_changed = new_list != prev_list + endif + if counts_changed + call neomake#utils#hook('NeomakeCountsChanged', {'reset': 0, 'jobinfo': a:jobinfo}) + endif + + if has_key(a:jobinfo, '_delayed_qf_autocmd') && exists('#QuickfixCmdPost') + " NOTE: need to use :silent, since we can only check the event, but + " not the pattern - `exists()` for 'laddexpr' will not match '*'. + silent call neomake#compat#doautocmd(a:jobinfo._delayed_qf_autocmd) + unlet a:jobinfo._delayed_qf_autocmd + endif + + if !empty(new_list) + call s:HandleLoclistQflistDisplay(a:jobinfo, new_list) + endif + call neomake#highlights#ShowHighlights() + return g:neomake#action_queue#processed +endfunction + +function! s:ProcessJobOutput(jobinfo, lines, source, ...) abort + if s:need_to_postpone_loclist(a:jobinfo) + return neomake#action_queue#add(['BufEnter', 'WinEnter'], [s:function('s:ProcessJobOutput'), + \ [a:jobinfo, a:lines, a:source]]) + endif + if !a:0 + return s:pcall('s:ProcessJobOutput', [a:jobinfo, a:lines, a:source]) + endif + + let maker = a:jobinfo.maker + call neomake#log#debug(printf('Processing %d lines of output.', + \ len(a:lines)), a:jobinfo) + let cd_error = a:jobinfo.cd() + if !empty(cd_error) + call neomake#log#debug(printf( + \ "Could not change to job's cwd (%s): %s.", + \ a:jobinfo.cd_from_setting, cd_error), a:jobinfo) + endif + try + if has_key(maker, 'process_json') || has_key(maker, 'process_output') + if has_key(maker, 'process_json') + let method = 'process_json' + let output = join(a:lines, "\n") + try + let json = neomake#compat#json_decode(output) + catch + let error = printf( + \ 'Failed to decode JSON: %s (output: %s).', + \ substitute(v:exception, '^Neomake: ', '', ''), string(output)) + call neomake#log#exception(error, a:jobinfo) + return g:neomake#action_queue#not_processed + endtry + call neomake#log#debug(printf( + \ "Calling maker's process_json method with %d JSON entries.", + \ len(json)), a:jobinfo) + let entries = call(maker.process_json, [{ + \ 'json': json, + \ 'source': a:source, + \ 'jobinfo': a:jobinfo}], maker) + else + call neomake#log#debug(printf( + \ "Calling maker's process_output method with %d lines of output on %s.", + \ len(a:lines), a:source), a:jobinfo) + let method = 'process_output' + let entries = call(maker.process_output, [{ + \ 'output': a:lines, + \ 'source': a:source, + \ 'jobinfo': a:jobinfo}], maker) + endif + if type(entries) != type([]) + call neomake#log#error(printf('The %s method for maker %s did not return a list, but: %s.', + \ method, maker.name, string(entries)[:100]), a:jobinfo) + return g:neomake#action_queue#not_processed + elseif !empty(entries) && type(entries[0]) != type({}) + call neomake#log#error(printf('The %s method for maker %s did not return a list of dicts, but: %s.', + \ method, maker.name, string(entries)[:100]), a:jobinfo) + return g:neomake#action_queue#not_processed + endif + return s:ProcessEntries(a:jobinfo, entries) + endif + + " Old-school handling through errorformat. + if has_key(maker, 'mapexpr') + let neomake_bufname = fnamemodify(bufname(a:jobinfo.bufnr), ':p') + " @vimlint(EVL102, 1, l:neomake_bufdir) + let neomake_bufdir = fnamemodify(neomake_bufname, ':h') + " @vimlint(EVL102, 1, l:neomake_output_source) + let neomake_output_source = a:source + call map(a:lines, maker.mapexpr) + endif + + if !empty(a:lines) + call s:AddExprCallback(a:jobinfo, a:lines) + endif + catch /^\%(Vim\%((\a\+)\)\=:\%(E48\|E523\)\)\@!/ " everything, but E48/E523 (sandbox / not allowed here) + if v:exception ==# 'NeomakeTestsException' + throw v:exception + endif + call neomake#log#exception(printf( + \ 'Error during output processing for %s: %s.', + \ a:jobinfo.maker.name, v:exception), a:jobinfo) + return + finally + call a:jobinfo.cd_back() + endtry + return g:neomake#action_queue#processed +endfunction + +function! s:process_pending_output(jobinfo, lines, source, ...) abort + let retry_events = s:need_to_postpone_output_processing(a:jobinfo) + if empty(retry_events) + let retry_events = s:ProcessPendingOutput(a:jobinfo, a:lines, a:source) + if empty(retry_events) + return g:neomake#action_queue#processed + endif + endif + call add(a:jobinfo.pending_output, [a:lines, a:source]) + if index(neomake#action_queue#get_queued_actions(a:jobinfo), + \ ['process_pending_output', retry_events]) == -1 + return neomake#action_queue#add(retry_events, [s:function('s:process_pending_output'), [a:jobinfo, [], a:source, retry_events]]) + endif + return g:neomake#action_queue#not_processed +endfunction + +function! s:ProcessPendingOutput(jobinfo, lines, source) abort + if a:jobinfo.file_mode + let window_make_ids = get(w:, 'neomake_make_ids', []) + if index(window_make_ids, a:jobinfo.make_id) == -1 + if !bufexists(a:jobinfo.bufnr) + call neomake#log#info('No buffer found for output!', a:jobinfo) + return [] + endif + + if a:jobinfo.bufnr != bufnr('%') + call neomake#log#debug(printf('Skipped pending job output for another buffer (current=%d).', bufnr('%')), a:jobinfo) + return ['BufEnter', 'WinEnter'] + elseif neomake#core#get_tabwin_for_makeid(a:jobinfo.make_id) != [-1, -1] + call neomake#log#debug('Skipped pending job output (not in origin window).', a:jobinfo) + return ['WinEnter'] + else + call neomake#log#debug("Processing pending output for job's buffer in new window.", a:jobinfo) + let w:neomake_make_ids = add(get(w:, 'neomake_make_ids', []), a:jobinfo.make_id) + endif + endif + endif + + " Process any pending output first. + if !empty(a:jobinfo.pending_output) + let outputs = {'stdout': [], 'stderr': []} + for [lines, source] in a:jobinfo.pending_output + call extend(outputs[source], lines) + endfor + for [source, lines] in items(outputs) + if !empty(lines) + call s:ProcessJobOutput(a:jobinfo, lines, source) + endif + endfor + call neomake#log#debug(printf( + \ 'Processed %d pending outputs.', len(a:jobinfo.pending_output)), + \ a:jobinfo) + call neomake#action_queue#remove(a:jobinfo, s:function('s:process_pending_output')) + endif + + if !empty(a:lines) + call s:ProcessJobOutput(a:jobinfo, a:lines, a:source) + endif + + " Clean job if it had exited already. + if !empty(a:jobinfo.pending_output) + let a:jobinfo.pending_output = [] + if has_key(a:jobinfo, 'exit_code') + " XXX: add test (tested manually) + call s:CleanJobinfo(a:jobinfo) + endif + endif + return [] +endfunction + +" Do we need to postpone location list processing (creation and :laddexpr)? +function! s:need_to_postpone_loclist(jobinfo) abort + if !a:jobinfo.file_mode + return 0 + endif + if index(get(w:, 'neomake_make_ids', []), a:jobinfo.make_id) != -1 + return 0 + endif + call neomake#log#debug('Postponing location list processing.', a:jobinfo) + return 1 +endfunction + +" TODO: merge with s:handle_locqf_list_for_finished_jobs. +let s:has_getcmdwintype = exists('*getcmdwintype') +function! s:need_to_postpone_output_processing(jobinfo) abort + " We can only process output (change the location/quickfix list) in + " certain modes, otherwise e.g. the visual selection gets lost. + if neomake#compat#in_completion() + call neomake#log#debug('Not processing output during completion.', a:jobinfo) + return ['CompleteDone'] + endif + let mode = neomake#compat#get_mode() + if index(['n', 'i'], mode) == -1 + call neomake#log#debug('Not processing output for mode "'.mode.'".', a:jobinfo) + return ['BufEnter', 'WinEnter', 'InsertLeave', 'CursorHold', 'CursorHoldI'] + endif + if s:has_getcmdwintype && !empty(getcmdwintype()) + call neomake#log#debug('Not processing output from command-line window "'.getcmdwintype().'".', a:jobinfo) + return ['InsertLeave', 'CursorHold', 'CursorHoldI'] + endif + return [] +endfunction + +function! s:RegisterJobOutput(jobinfo, lines, source) abort + " Allow to filter output (storing the setting on the jobinfo lazily). + if !has_key(a:jobinfo, 'filter_output') + let a:jobinfo.filter_output = neomake#utils#GetSetting('filter_output', a:jobinfo.maker, '', a:jobinfo.ft, a:jobinfo.bufnr) + endif + if !empty(a:jobinfo.filter_output) + call call(a:jobinfo.filter_output, [ + \ a:lines, {'source': a:source, 'jobinfo': a:jobinfo}], + \ a:jobinfo.maker) + endif + + if empty(a:lines) + return + endif + + " Register unexpected output. + if a:jobinfo.output_stream !=# 'both' && a:jobinfo.output_stream !=# a:source + if !has_key(a:jobinfo, 'unexpected_output') + let a:jobinfo.unexpected_output = {} + endif + if !has_key(a:jobinfo.unexpected_output, a:source) + let a:jobinfo.unexpected_output[a:source] = [] + endif + let a:jobinfo.unexpected_output[a:source] += a:lines + return + endif + + let make_info = s:make_info[a:jobinfo.make_id] + if has_key(make_info, 'entries_list') " use_list option + " Process output for list processing. + call s:process_pending_output(a:jobinfo, a:lines, a:source) + endif +endfunction + +function! s:vim_output_handler(channel, output, event_type) abort + let channel_id = ch_info(a:channel)['id'] + let jobinfo = get(s:jobs, get(s:map_job_ids, channel_id, -1), {}) + if empty(jobinfo) + call neomake#log#debug(printf("warn: job '%s' not found for output on %s.", + \ a:channel, a:event_type)) + return + endif + let data = split(a:output, '\r\?\n', 1) + call s:output_handler_queued(jobinfo, data, a:event_type, 0) +endfunction + +function! s:vim_output_handler_stdout(channel, output) abort + call s:vim_output_handler(a:channel, a:output, 'stdout') +endfunction + +function! s:vim_output_handler_stderr(channel, output) abort + call s:vim_output_handler(a:channel, a:output, 'stderr') +endfunction + +function! s:vim_exit_handler(channel) abort + let channel_id = ch_info(a:channel)['id'] + let jobinfo = get(s:jobs, get(s:map_job_ids, channel_id, -1), {}) + if empty(jobinfo) + try + let job_info = job_info(ch_getjob(a:channel)) + catch /^Vim(let):E916:/ + " Might happen with older Vim (8.0.69, but not 8.0.586). + call neomake#log#debug(printf('exit: job not found: %s.', a:channel)) + return + endtry + call neomake#log#debug(printf('exit: job not found: %s (%s).', a:channel, job_info)) + return + endif + let job_info = job_info(ch_getjob(a:channel)) + + " Handle failing starts from Vim here. + let status = job_info['exitval'] + if status == 122 " Vim uses EXEC_FAILED, but only on Unix?! + let jobinfo.failed_to_start = 1 + " The error is on stderr. + let error = 'Vim job failed to run: '.substitute(join(jobinfo.stderr), '\v\s+$', '', '').'.' + let jobinfo.stderr = [] + call neomake#log#error(error) + call s:CleanJobinfo(jobinfo) + else + call s:exit_handler(jobinfo, status) + endif +endfunction + +" @vimlint(EVL108, 1) +if has('nvim-0.2.0') +" @vimlint(EVL108, 0) + function! s:nvim_output_handler(job_id, data, event_type) abort + let jobinfo = get(s:jobs, get(s:map_job_ids, a:job_id, -1), {}) + if empty(jobinfo) + call neomake#log#debug(printf('output [%s]: job %d not found.', a:event_type, a:job_id)) + return + endif + if a:data == [''] && !exists('jobinfo[a:event_type]') + " EOF in Neovim (see :h on_data). + return + endif + call s:output_handler_queued(jobinfo, copy(a:data), a:event_type, 1) + endfunction +else + " Neovim: register output from jobs as quick as possible, and trigger + " processing through a timer. + " This works around https://github.com/neovim/neovim/issues/5889). + " NOTE: a:data is never [''] here (like with other/newer Neovim + " handlers) + let s:nvim_output_handler_queue = [] + function! s:nvim_output_handler(job_id, data, event_type) abort + let jobinfo = get(s:jobs, get(s:map_job_ids, a:job_id, -1), {}) + if empty(jobinfo) + call neomake#log#debug(printf('output [%s]: job %d not found.', a:event_type, a:job_id)) + return + endif + let args = [jobinfo, copy(a:data), a:event_type, 1] + call add(s:nvim_output_handler_queue, args) + if !exists('jobinfo._nvim_in_handler') + let jobinfo._nvim_in_handler = 1 + else + let jobinfo._nvim_in_handler += 1 + endif + if !exists('s:nvim_output_handler_timer') + let s:nvim_output_handler_timer = timer_start(0, function('s:nvim_output_handler_cb')) + endif + endfunction + + function! s:nvim_output_handler_cb(_timer) abort + while !empty(s:nvim_output_handler_queue) + let args = remove(s:nvim_output_handler_queue, 0) + let jobinfo = args[0] + call call('s:output_handler', args) + let jobinfo._nvim_in_handler -= 1 + + if !jobinfo._nvim_in_handler + " Trigger previously delayed exit handler. + unlet jobinfo._nvim_in_handler + if exists('jobinfo._exited_while_in_handler') + call neomake#log#debug('Trigger delayed exit.', jobinfo) + call s:exit_handler(jobinfo, jobinfo._exited_while_in_handler) + endif + endif + endwhile + unlet! s:nvim_output_handler_timer + endfunction +endif + +" Exit handler for buffered output with Neovim. +" In this case the output gets stored on the jobstart-options dict. +function! s:nvim_exit_handler_buffered(job_id, data, _event_type) abort + let jobinfo = get(s:jobs, get(s:map_job_ids, a:job_id, -1), {}) + if empty(jobinfo) + call neomake#log#debug(printf('exit: job not found: %d.', a:job_id)) + return + endif + + for stream in ['stdout', 'stderr'] + if has_key(jobinfo.jobstart_opts, stream) + let data = copy(jobinfo.jobstart_opts[stream]) + if data == [''] + " EOF in Neovim (see :h on_data). + continue + endif + call s:output_handler(jobinfo, data, stream, 1) + endif + endfor + + call s:exit_handler(jobinfo, a:data) +endfunction + +function! s:nvim_exit_handler(job_id, data, _event_type) abort + let jobinfo = get(s:jobs, get(s:map_job_ids, a:job_id, -1), {}) + if empty(jobinfo) + call neomake#log#debug(printf('exit: job not found: %d.', a:job_id)) + return + endif + call s:exit_handler(jobinfo, a:data) +endfunction + +function! s:exit_handler(jobinfo, data) abort + let jobinfo = a:jobinfo + let jobinfo.exit_code = a:data + if get(jobinfo, 'canceled') + call neomake#log#debug('exit: job was canceled.', jobinfo) + call s:CleanJobinfo(jobinfo) + return + endif + let maker = jobinfo.maker + + if exists('jobinfo._output_while_in_handler') || exists('jobinfo._nvim_in_handler') + let jobinfo._exited_while_in_handler = a:data + call neomake#log#debug(printf('exit (delayed): %s: %s.', + \ maker.name, string(a:data)), jobinfo) + return + endif + call neomake#log#debug(printf('exit: %s: %s.', + \ maker.name, string(a:data)), jobinfo) + + let jobinfo._in_exit_handler = 1 + try + " Handle any unfinished lines from stdout/stderr callbacks. + for event_type in ['stdout', 'stderr'] + if has_key(jobinfo, event_type) + let lines = jobinfo[event_type] + if !empty(lines) + if lines[-1] ==# '' + call remove(lines, -1) + endif + if !empty(lines) + call s:RegisterJobOutput(jobinfo, lines, event_type) + endif + unlet jobinfo[event_type] + endif + endif + endfor + + if !get(jobinfo, 'failed_to_start') + let l:ExitCallback = neomake#utils#GetSetting('exit_callback', + \ extend(copy(jobinfo), maker), 0, jobinfo.ft, jobinfo.bufnr) + if ExitCallback isnot# 0 + let callback_dict = { 'status': jobinfo.exit_code, + \ 'name': maker.name, + \ 'has_next': !empty(s:make_info[jobinfo.make_id].jobs_queue) } + try + if type(ExitCallback) == type('') + let l:ExitCallback = function(ExitCallback) + endif + call call(ExitCallback, [callback_dict], jobinfo) + catch + call neomake#log#error(printf( + \ 'Error during exit_callback: %s.', v:exception), + \ jobinfo) + endtry + endif + endif + + if s:async + if has('nvim') || jobinfo.exit_code != 122 + call neomake#log#debug(printf( + \ '%s: completed with exit code %d.', + \ maker.name, jobinfo.exit_code), jobinfo) + endif + let jobinfo.finished = 1 + endif + + if has_key(jobinfo, 'unexpected_output') + redraw + for [source, output] in items(jobinfo.unexpected_output) + let msg = printf('%s: unexpected output on %s: ', maker.name, source) + call neomake#log#debug(msg . join(output, '\n') . '.', jobinfo) + + echohl WarningMsg + echom printf('Neomake: %s%s', msg, output[0]) + for line in output[1:-1] + echom line + endfor + echohl None + endfor + call neomake#log#error(printf( + \ '%s: unexpected output. See :messages for more information.', maker.name), jobinfo) + endif + finally + unlet jobinfo._in_exit_handler + endtry + call s:handle_next_job(jobinfo) +endfunction + +function! s:output_handler_queued(jobinfo, data, event_type, trim_CR) abort + let jobinfo = a:jobinfo + if exists('jobinfo._output_while_in_handler') + call neomake#log#debug(printf('Queuing: %s: %s: %s.', + \ a:event_type, jobinfo.maker.name, string(a:data)), jobinfo) + let jobinfo._output_while_in_handler += [[jobinfo, a:data, a:event_type, a:trim_CR]] + return + else + let jobinfo._output_while_in_handler = [] + endif + + call s:output_handler(jobinfo, a:data, a:event_type, a:trim_CR) + + " Process queued events that might have arrived by now. + " The attribute might be unset here, since output_handler might have + " been interrupted. + if exists('jobinfo._output_while_in_handler') + while has_key(jobinfo, '_output_while_in_handler') && !empty(jobinfo._output_while_in_handler) + let args = remove(jobinfo._output_while_in_handler, 0) + call call('s:output_handler', args) + endwhile + unlet! jobinfo._output_while_in_handler + endif + " Trigger previously delayed exit handler. + if exists('jobinfo._exited_while_in_handler') + call neomake#log#debug('Trigger delayed exit.', jobinfo) + call s:exit_handler(jobinfo, jobinfo._exited_while_in_handler) + endif +endfunction + +function! s:output_handler(jobinfo, data, event_type, trim_CR) abort + let jobinfo = a:jobinfo + call neomake#log#debug(printf('output on %s: %s.', + \ a:event_type, string(a:data)), jobinfo) + if get(jobinfo, 'canceled') + call neomake#log#debug('Ignoring output (job was canceled).', jobinfo) + return + endif + let data = copy(a:data) + if a:trim_CR && !empty(a:data) + call map(data, "substitute(v:val, '\\r$', '', '')") + endif + let last_event_type = get(jobinfo, 'event_type', a:event_type) + + " data is a list of 'lines' read. Each element *after* the first + " element represents a newline. + if has_key(jobinfo, a:event_type) + let jobinfo[a:event_type][-1] .= data[0] + call extend(jobinfo[a:event_type], data[1:]) + else + let jobinfo[a:event_type] = data + endif + + if !jobinfo.buffer_output || last_event_type !=# a:event_type + let lines = jobinfo[a:event_type][:-2] + let jobinfo[a:event_type] = jobinfo[a:event_type][-1:] + + if !empty(lines) + call s:RegisterJobOutput(jobinfo, lines, a:event_type) + endif + endif +endfunction + +function! s:abort_next_makers(make_id) abort + let jobs_queue = s:make_info[a:make_id].jobs_queue + if !empty(jobs_queue) + let next_makers = join(map(copy(jobs_queue), 'v:val.maker.name'), ', ') + call neomake#log#info('Aborting next makers: '.next_makers.'.', {'make_id': a:make_id}) + let s:make_info[a:make_id].aborted_jobs = copy(s:make_info[a:make_id].jobs_queue) + let s:make_info[a:make_id].jobs_queue = [] + endif +endfunction + +function! s:handle_next_job(prev_jobinfo) abort + let make_id = get(a:prev_jobinfo, 'make_id', s:make_id) + if !has_key(s:make_info, make_id) + return {} + endif + let make_info = s:make_info[make_id] + + if !empty(a:prev_jobinfo) + let status = get(a:prev_jobinfo, 'exit_code', 0) + if status != 0 && index([122, 127], status) == -1 + " TODO: mark maker.exe as non-executable with status 127, and + " maybe re-introduce a wrapper for `executable()` to handle it. + " Ref: https://github.com/neomake/neomake/issues/1699 + if neomake#utils#GetSetting('serialize_abort_on_error', a:prev_jobinfo.maker, 0, a:prev_jobinfo.ft, a:prev_jobinfo.bufnr) + let a:prev_jobinfo.aborted = 1 + call s:abort_next_makers(make_id) + call s:CleanJobinfo(a:prev_jobinfo) + return {} + endif + endif + call s:CleanJobinfo(a:prev_jobinfo) + if !has_key(s:make_info, make_id) + " Last job was cleaned. + return {} + endif + + let serializing_for_job = get(make_info, 'serializing_for_job') + if serializing_for_job + if serializing_for_job != a:prev_jobinfo.id + call neomake#log#debug(printf('waiting for job %d to finish.', serializing_for_job)) + return {} + endif + unlet make_info.serializing_for_job + endif + endif + + " Create job from the start of the queue, returning it. + while !empty(make_info.jobs_queue) + let options = remove(make_info.jobs_queue, 0) + let maker = options.maker + if empty(maker) + continue + endif + + " Serialization of jobs, always for non-async Vim. + if !has_key(options, 'serialize') + if !s:async || neomake#utils#GetSetting('serialize', maker, 0, options.ft, options.bufnr) + let options.serialize = 1 + else + let options.serialize = 0 + endif + endif + try + let jobinfo = s:MakeJob(make_id, options) + catch /^Neomake: / + let log_context = extend(options, {'make_id': make_id}) + if v:exception =~# '\v^Neomake: skip_job: ' + let msg = substitute(v:exception, '^Neomake: skip_job: ', '', '') + call neomake#log#debug(printf('Skipping job: %s', msg), log_context) + else + let error = substitute(v:exception, '^Neomake: ', '', '') + call neomake#log#exception(error, log_context) + + if options.serialize + if neomake#utils#GetSetting('serialize_abort_on_error', maker, 0, options.ft, options.bufnr) + call s:abort_next_makers(make_id) + break + endif + endif + endif + continue + endtry + if !empty(jobinfo) + return jobinfo + endif + endwhile + + " Cleanup make info, but only if there are no queued actions. + for [_, v] in g:neomake#action_queue#_s.action_queue + if v[1][0] == make_info + call neomake#log#debug('Skipping cleaning of make info for queued actions.', make_info) + return {} + endif + endfor + call s:clean_make_info(make_info) + return {} +endfunction + +function! neomake#_add_error(maker_type, entry) abort + if !has_key(s:current_errors[a:maker_type], a:entry.bufnr) + let s:current_errors[a:maker_type][a:entry.bufnr] = {} + endif + if !has_key(s:current_errors[a:maker_type][a:entry.bufnr], a:entry.lnum) + let s:current_errors[a:maker_type][a:entry.bufnr][a:entry.lnum] = [a:entry] + else + call add(s:current_errors[a:maker_type][a:entry.bufnr][a:entry.lnum], a:entry) + endif +endfunction + +function! neomake#get_nearest_error() abort + let buf = bufnr('%') + let ln = line('.') + let ln_errors = [] + + for maker_type in ['file', 'project'] + let buf_errors = get(s:current_errors[maker_type], buf, {}) + let ln_errors += get(buf_errors, ln, []) + endfor + + if empty(ln_errors) + return {} + endif + + if len(ln_errors) > 1 + call sort(ln_errors, function('neomake#utils#sort_by_col')) + endif + return ln_errors[0] +endfunction + +function! neomake#GetCurrentErrorMsg() abort + let entry = neomake#get_nearest_error() + if empty(entry) + return '' + endif + let r = entry.maker_name . ': ' . entry.text + let suffix = entry.type . (entry.nr != -1 ? entry.nr : '') + if !empty(suffix) + let r .= ' ('.suffix.')' + endif + return r +endfunction + +function! neomake#EchoCurrentError(...) abort + if !get(g:, 'neomake_echo_current_error', 1) + return + endif + " a:1 might be a timer from the VimResized event. + let force = a:0 ? a:1 : 0 + + let message = neomake#GetCurrentErrorMsg() + if empty(message) + if exists('s:neomake_last_echoed_error') + echon '' + unlet s:neomake_last_echoed_error + endif + return + endif + if !force && exists('s:neomake_last_echoed_error') + \ && s:neomake_last_echoed_error == message + return + endif + let s:neomake_last_echoed_error = message + call neomake#utils#WideMessage(message) +endfunction + +function! neomake#CursorMoved() abort + call neomake#EchoCurrentError() + call neomake#virtualtext#handle_current_error() +endfunction + +function! s:cursormoved_delayed_cb(...) abort + if getpos('.') == s:cursormoved_last_pos + call neomake#CursorMoved() + endif +endfunction +function! neomake#CursorMovedDelayed() abort + if exists('s:cursormoved_timer') + call timer_stop(s:cursormoved_timer) + endif + let delay = get(g:, 'neomake_cursormoved_delay', 100) + let s:cursormoved_timer = timer_start(delay, function('s:cursormoved_delayed_cb')) + let s:cursormoved_last_pos = getpos('.') +endfunction + +function! neomake#Make(file_mode_or_options, ...) abort + if type(a:file_mode_or_options) == type({}) + return s:Make(a:file_mode_or_options) + endif + + let file_mode = a:file_mode_or_options + let options = {'file_mode': file_mode} + if file_mode + let options.ft = &filetype + endif + if a:0 + if !empty(a:1) + let maker_names = a:1 + " Split names on non-breaking space (annotation from completion). + call map(maker_names, "type(v:val) == 1 ? split(v:val, ' (')[0] : v:val") + let options.enabled_makers = a:1 + endif + if a:0 > 1 + let options.exit_callback = a:2 + endif + endif + return map(copy(s:Make(options)), 'v:val.id') +endfunction + +function! neomake#ShCommand(bang, sh_command, ...) abort + let maker = neomake#utils#MakerFromCommand(a:sh_command) + let maker.name = 'sh: '.a:sh_command + let maker.errorformat = '%m' + let maker.default_entry_type = '' + let options = { + \ 'enabled_makers': [maker], + \ 'file_mode': 0, + \ 'output_stream': 'both', + \ 'buffer_output': !a:bang, + \ } + if a:0 + call extend(options, a:1) + endif + let jobinfos = s:Make(options) + return empty(jobinfos) ? -1 : jobinfos[0].id +endfunction + +function! neomake#Sh(sh_command, ...) abort + " Deprecated, but documented. + let options = a:0 ? { 'exit_callback': a:1 } : {} + return neomake#ShCommand(0, a:sh_command, options) +endfunction + +function! neomake#map_makers(makers, ft, auto_enabled) abort + let makers = [] + let errors = [] + let get_args = a:ft is# -1 ? [] : [a:ft] + for maker in a:makers + try + let m = call('neomake#GetMaker', [maker] + get_args) + catch /^Neomake: / + call add(errors, substitute(v:exception, '^Neomake: ', '', '').'.') + unlet maker " vim73/vim-trusty + continue + endtry + call add(makers, m) + unlet maker " vim73/vim-trusty + endfor + if !empty(errors) + let log_context = get(s:make_info, s:make_id, {}) + for error in errors + if a:auto_enabled + call neomake#log#debug(error, log_context) + else + call neomake#log#error(error, log_context) + endif + endfor + endif + return makers +endfunction diff --git a/.vim/autoload/neomake/action_queue.vim b/.vim/autoload/neomake/action_queue.vim new file mode 100644 index 0000000..4fc3fc1 --- /dev/null +++ b/.vim/autoload/neomake/action_queue.vim @@ -0,0 +1,307 @@ +if !exists('s:action_queue') + let s:action_queue = [] +endif +if !exists('s:action_queue_registered_events') + let s:action_queue_registered_events = [] +endif +let s:action_queue_timer_timeouts = get(g:, 'neomake_action_queue_timeouts', {1: 100, 2: 200, 3: 500}) + +let g:neomake#action_queue#processed = {} +let g:neomake#action_queue#not_processed = {} +let g:neomake#action_queue#any_event = [] + +let g:neomake#action_queue#_s = s: + +function! s:actionname(funcref) abort + let s = string(a:funcref) + let r = matchstr(s, '\v^^function\(''\zs.*\ze''\)$') + if empty(r) + return s + endif + return substitute(r, '\v^(\<SNR\>\d+_|s:)', '', '') +endfunction + +" Queue an action to be processed later for autocmd a:event or through a timer +" for a:event=Timer. +" It will call a:data[0], with a:data[1] as args (where the first should be +" a jobinfo object). The callback should return 1 if it was successful, +" with 0 it will be re-queued. +" When called recursively (queuing the same event/data again, it will be +" re-queued also). +function! neomake#action_queue#add(events, data) abort + let job_or_make_info = a:data[1][0] + if a:events is# g:neomake#action_queue#any_event + call neomake#log#debug(printf('Queuing action %s for any event.', + \ s:actionname(a:data[0])), job_or_make_info) + else + call neomake#log#debug(printf('Queuing action %s for %s.', + \ s:actionname(a:data[0]), join(a:events, ', ')), job_or_make_info) + endif + + for event in a:events + if event ==# 'Timer' + if !has_key(job_or_make_info, 'action_queue_timer_tries') + let job_or_make_info.action_queue_timer_tries = {'count': 1, 'data': a:data[0]} + else + let job_or_make_info.action_queue_timer_tries.count += 1 + endif + if has_key(s:action_queue_timer_timeouts, job_or_make_info.action_queue_timer_tries.count) + let timeout = s:action_queue_timer_timeouts[job_or_make_info.action_queue_timer_tries.count] + else + throw printf('Neomake: Giving up handling Timer callbacks after %d attempts. Please report this. See :messages for more information.', len(s:action_queue_timer_timeouts)) + endif + if has('timers') + if exists('s:action_queue_timer') + call timer_stop(s:action_queue_timer) + endif + let s:action_queue_timer = timer_start(timeout, function('s:process_action_queue_timer_cb')) + call neomake#log#debug(printf( + \ 'Retrying Timer event in %dms (timer %d).', + \ timeout, s:action_queue_timer), job_or_make_info) + else + call neomake#log#debug('Retrying Timer event on CursorHold(I).', job_or_make_info) + if !exists('#neomake_event_queue#CursorHold') + let s:action_queue_registered_events += ['CursorHold', 'CursorHoldI'] + augroup neomake_event_queue + exe 'autocmd CursorHold,CursorHoldI * call s:process_action_queue('''.event.''')' + augroup END + endif + endif + else + if !exists('#neomake_event_queue#'.event) + let s:action_queue_registered_events += [event] + augroup neomake_event_queue + exe 'autocmd '.event.' * call s:process_action_queue('''.event.''')' + augroup END + endif + endif + endfor + call add(s:action_queue, [a:events, a:data]) + return g:neomake#action_queue#not_processed +endfunction + +" Remove any queued actions for a jobinfo or make_info object. +function! neomake#action_queue#clean(job_or_make_info) abort + let len_before = len(s:action_queue) + call filter(s:action_queue, 'v:val[1][1][0] != a:job_or_make_info') + let removed = len_before - len(s:action_queue) + if removed + call s:clean_action_queue_events() + call neomake#log#debug(printf( + \ 'Removed %d action queue entries.', + \ removed), a:job_or_make_info) + endif +endfunction + +" Remove given action for a jobinfo or make_info object. +function! neomake#action_queue#remove(job_or_make_info, action) abort + let len_before = len(s:action_queue) + call filter(s:action_queue, 'v:val[1][1][0] != a:job_or_make_info || v:val[1][0] != a:action') + let removed = len_before - len(s:action_queue) + if removed + call s:clean_action_queue_events() + call neomake#log#debug(printf( + \ 'Removed %d action queue entries for %s.', + \ removed, s:actionname(a:action)), a:job_or_make_info) + endif +endfunction + +function! s:process_action_queue_timer_cb(...) abort + call neomake#log#debug(printf( + \ 'action queue: callback for Timer queue (%d).', s:action_queue_timer)) + unlet s:action_queue_timer + call s:process_action_queue('Timer') +endfunction + +function! s:process_action_queue(event) abort + let queue = s:action_queue + let q_for_this_event = [] + let i = 0 + if g:neomake#core#_ignore_autocommands + call neomake#log#debug(printf('action queue: skip processing for %s (ignore_autocommands=%d).', + \ a:event, g:neomake#core#_ignore_autocommands), + \ {'bufnr': bufnr('%'), 'winnr': winnr()}) + return + endif + for [events, v] in queue + if index(events, a:event) != -1 || events is# g:neomake#action_queue#any_event + call add(q_for_this_event, [i, v]) + endif + let i += 1 + endfor + call neomake#log#debug(printf('action queue: processing for %s (%d items).', + \ a:event, len(q_for_this_event)), {'bufnr': bufnr('%'), 'winnr': winnr()}) + + let processed = [] + let removed = 0 + let stop_processing = {'make_id': [], 'job_id': []} + for [idx_q_for_this_event, data] in q_for_this_event + let job_or_make_info = data[1][0] + let current_event = remove(queue, idx_q_for_this_event - removed) + let removed += 1 + + let make_id_job_id = {} " make_id/job_id relevant to re-queue following. + if has_key(job_or_make_info, 'make_id') + if has_key(job_or_make_info, 'options') + let make_id_job_id = { + \ 'make_id': job_or_make_info.make_id, + \ } + else + let make_id_job_id = { + \ 'make_id': job_or_make_info.make_id, + \ 'job_id': job_or_make_info.id, + \ } + endif + endif + + " Skip/re-queue entries for same make/job. + let skip = 0 + for [prop_name, prop_value] in items(make_id_job_id) + if index(stop_processing[prop_name], prop_value) != -1 + call neomake#log#debug(printf('action queue: skipping %s for not processed %s.', + \ s:actionname(data[0]), prop_name), job_or_make_info) + call add(queue, current_event) + let skip = 1 + break + endif + endfor + if skip + continue + endif + + call neomake#log#debug(printf('action queue: calling %s.', + \ s:actionname(data[0])), job_or_make_info) + let queue_before_call = copy(queue) + try + " Call the queued action. On failure they should have requeued + " themselves already. + let rv = call(data[0], data[1]) + catch + if v:exception =~# '^Neomake: ' + let error = substitute(v:exception, '^Neomake: ', '', '') + else + let error = printf('Error during action queue processing: %s.', + \ v:exception) + endif + call neomake#log#exception(error, job_or_make_info) + + " Cancel job in case its action failed to get re-queued after X + " attempts. + if has_key(job_or_make_info, 'id') + call neomake#CancelJob(job_or_make_info.id) + endif + continue + endtry + if rv is# g:neomake#action_queue#processed + let processed += [data] + continue + endif + + if rv is# g:neomake#action_queue#not_processed + if a:event !=# 'Timer' && has_key(job_or_make_info, 'action_queue_timer_tries') + call neomake#log#debug('s:process_action_queue: decrementing timer tries for non-Timer event.', job_or_make_info) + let job_or_make_info.action_queue_timer_tries.count -= 1 + endif + + " Requeue any entries for the same job. + let i = 0 + for q in queue_before_call + for [prop_name, prop_value] in items(make_id_job_id) + " Assert current_event != q + if get(q[1][1][0], prop_name) == prop_value + call neomake#log#debug(printf('action queue: re-queuing %s for not processed %s.', + \ s:actionname(q[1][0]), prop_name), job_or_make_info) + call add(queue, remove(queue, i)) + let i -= 1 + break + endif + endfor + let i += 1 + endfor + for [prop_name, prop_value] in items(make_id_job_id) + call add(stop_processing[prop_name], prop_value) + endfor + else + let args_str = neomake#utils#Stringify(data[1]) + throw printf('Internal Neomake error: hook function %s(%s) returned unexpected value (%s)', data[0], args_str, rv) + endif + endfor + call neomake#log#debug(printf('action queue: processed %d items.', + \ len(processed)), {'bufnr': bufnr('%')}) + + call s:clean_action_queue_events() +endfunction + +if has('timers') + function! s:get_left_events() abort + let r = {} + for [events, _] in s:action_queue + for event in events + let r[event] = 1 + endfor + endfor + return keys(r) + endfunction +else + function! s:get_left_events() abort + let r = {} + for [events, _] in s:action_queue + for event in events + if event ==# 'Timer' + let r['CursorHold'] = 1 + let r['CursorHoldI'] = 1 + else + let r[event] = 1 + endif + endfor + endfor + return keys(r) + endfunction +endif + +function! neomake#action_queue#get_queued_actions(jobinfo) abort + " Check if there are any queued actions for this job. + let queued_actions = [] + for [events, v] in s:action_queue + if v[1][0] == a:jobinfo + let queued_actions += [[s:actionname(v[0]), events]] + endif + endfor + return queued_actions +endfunction + +function! s:clean_action_queue_events() abort + let left_events = s:get_left_events() + + if empty(left_events) + if exists('#neomake_event_queue') + autocmd! neomake_event_queue + augroup! neomake_event_queue + endif + else + let clean_events = [] + for event in s:action_queue_registered_events + if index(left_events, event) == -1 + let clean_events += [event] + endif + endfor + if !empty(clean_events) + augroup neomake_event_queue + for event in clean_events + if exists('#neomake_event_queue#'.event) + exe 'au! '.event + endif + endfor + augroup END + endif + endif + let s:action_queue_registered_events = left_events + + if index(left_events, 'Timer') == -1 + if exists('s:action_queue_timer') + call timer_stop(s:action_queue_timer) + unlet s:action_queue_timer + endif + endif +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/cmd.vim b/.vim/autoload/neomake/cmd.vim new file mode 100644 index 0000000..35806dc --- /dev/null +++ b/.vim/autoload/neomake/cmd.vim @@ -0,0 +1,192 @@ +scriptencoding utf8 + +let s:last_completion = [] +function! neomake#cmd#complete_makers(ArgLead, CmdLine, ...) abort + if a:CmdLine !~# '\s' + " Just 'Neomake!' without following space. + return [' '] + endif + + " Filter only by name before non-breaking space. + let filter_name = split(a:ArgLead, ' ', 1)[0] + + let file_mode = a:CmdLine =~# '\v^(Neomake|NeomakeFile)\s' + + let compl_info = [bufnr('%'), &filetype, a:CmdLine] + if empty(&filetype) + let maker_names = neomake#GetProjectMakers() + else + let maker_names = neomake#GetMakers(&filetype) + + " Prefer (only) makers for the current filetype. + if file_mode + if !empty(filter_name) + call filter(maker_names, 'v:val[:len(filter_name)-1] ==# filter_name') + endif + if empty(maker_names) || s:last_completion == compl_info + call extend(maker_names, neomake#GetProjectMakers()) + endif + else + call extend(maker_names, neomake#GetProjectMakers()) + endif + endif + + " Only display executable makers. + let makers = [] + for maker_name in maker_names + try + let maker = neomake#GetMaker(maker_name) + catch /^Neomake: / + let error = substitute(v:exception, '^Neomake: ', '', '').'.' + call neomake#log#debug(printf('Could not get maker %s: %s', + \ maker_name, error)) + continue + endtry + if type(get(maker, 'exe', 0)) != type('') || executable(maker.exe) + let makers += [[maker_name, maker]] + endif + endfor + + " Append maker.name if it differs, uses non-breaking-space. + let r = [] + for [maker_name, maker] in makers + if maker.name !=# maker_name + \ && (empty(a:ArgLead) || stridx(maker_name, a:ArgLead) != 0) + let r += [printf('%s (%s)', maker_name, maker.name)] + else + let r += [maker_name] + endif + endfor + + let s:last_completion = compl_info + if !empty(filter_name) + call filter(r, 'v:val[:len(filter_name)-1] ==# filter_name') + endif + return r +endfunction + +function! neomake#cmd#complete_jobs(...) abort + return join(map(neomake#GetJobs(), "v:val.id.': '.v:val.maker.name"), "\n") +endfunction + +function! s:is_neomake_list(list) abort + if empty(a:list) + return 0 + endif + return a:list[0].text =~# ' nmcfg:{.\{-}}$' +endfunction + +function! neomake#cmd#clean(file_mode) abort + let buf = bufnr('%') + call neomake#_clean_errors({ + \ 'file_mode': a:file_mode, + \ 'bufnr': buf, + \ }) + if a:file_mode + if s:is_neomake_list(getloclist(0)) + call setloclist(0, [], 'r') + lclose + endif + call neomake#signs#ResetFile(buf) + call neomake#statusline#ResetCountsForBuf(buf) + else + if s:is_neomake_list(getqflist()) + call setqflist([], 'r') + cclose + endif + call neomake#signs#ResetProject() + call neomake#statusline#ResetCountsForProject() + endif + call neomake#EchoCurrentError(1) +endfunction + +" Enable/disable/toggle commands. {{{ +function! s:handle_disabled_status(scope, disabled) abort + if a:scope is# g: + if a:disabled + if exists('#neomake') + autocmd! neomake + augroup! neomake + endif + call neomake#configure#disable_automake() + else + call neomake#setup#setup_autocmds() + endif + elseif a:scope is# t: + let buffers = neomake#compat#uniq(sort(tabpagebuflist())) + if a:disabled + for b in buffers + call neomake#configure#disable_automake_for_buffer(b) + endfor + else + for b in buffers + call neomake#configure#enable_automake_for_buffer(b) + endfor + endif + elseif a:scope is# b: + let bufnr = bufnr('%') + if a:disabled + call neomake#configure#disable_automake_for_buffer(bufnr) + else + call neomake#configure#enable_automake_for_buffer(bufnr) + endif + endif + call neomake#cmd#display_status() + call neomake#configure#automake() + call neomake#statusline#clear_cache() +endfunction + +function! neomake#cmd#disable(scope) abort + let old = get(get(a:scope, 'neomake', {}), 'disabled', -1) + if old ==# 1 + return + endif + call neomake#config#set_dict(a:scope, 'neomake.disabled', 1) + call s:handle_disabled_status(a:scope, 1) +endfunction + +function! neomake#cmd#enable(scope) abort + let old = get(get(a:scope, 'neomake', {}), 'disabled', -1) + if old != 1 + return + endif + call neomake#config#set_dict(a:scope, 'neomake.disabled', 0) + call s:handle_disabled_status(a:scope, 0) +endfunction + +function! neomake#cmd#toggle(scope) abort + let new = !get(get(a:scope, 'neomake', {}), 'disabled', 0) + if new + call neomake#config#set_dict(a:scope, 'neomake.disabled', 1) + call s:handle_disabled_status(a:scope, 1) + else + call neomake#config#unset_dict(a:scope, 'neomake.disabled') + call s:handle_disabled_status(a:scope, 0) + endif +endfunction + +function! neomake#cmd#display_status() abort + let [disabled, source] = neomake#config#get_with_source('disabled', 0) + let msg = 'Neomake is ' . (disabled ? 'disabled' : 'enabled') + if source !=# 'default' + let msg .= ' ('.source.')' + endif + + " Add information from different scopes (if explicitly configured there). + for [scope_name, scope] in [['buffer', b:], ['tab', t:], ['global', g:]] + if scope_name ==# source + continue + endif + let disabled = get(get(scope, 'neomake', {}), 'disabled', -1) + if disabled != -1 + let msg .= printf(' [%s: %s]', scope_name, disabled ? 'disabled' : 'enabled') + endif + endfor + let msg .= '.' + + echom msg + call neomake#log#debug(msg) +endfunction +" }}} + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/compat.vim b/.vim/autoload/neomake/compat.vim new file mode 100644 index 0000000..d558bf7 --- /dev/null +++ b/.vim/autoload/neomake/compat.vim @@ -0,0 +1,322 @@ +" Compatibility wrappers for different (Neo)Vim versions and platforms. + +if neomake#utils#IsRunningWindows() + let g:neomake#compat#dev_null = 'NUL' +else + let g:neomake#compat#dev_null = '/dev/null' +endif + +if v:version >= 704 + function! neomake#compat#getbufvar(buf, key, def) abort + return getbufvar(a:buf, a:key, a:def) + endfunction + function! neomake#compat#getwinvar(win, key, def) abort + return getwinvar(a:win, a:key, a:def) + endfunction +else + function! neomake#compat#getbufvar(buf, key, def) abort + return get(getbufvar(a:buf, ''), a:key, a:def) + endfunction + function! neomake#compat#getwinvar(win, key, def) abort + return get(getwinvar(a:win, ''), a:key, a:def) + endfunction +endif + +unlockvar neomake#compat#json_true +unlockvar neomake#compat#json_false +unlockvar neomake#compat#json_null +unlockvar neomake#compat#json_none + +if exists('v:none') + let neomake#compat#json_none = v:none +else + let neomake#compat#json_none = [] +endif + +if exists('*json_decode') + let neomake#compat#json_true = v:true + let neomake#compat#json_false = v:false + let neomake#compat#json_null = v:null + + if has('nvim') + function! neomake#compat#json_decode(json) abort + if a:json is# '' + " Prevent Neovim from throwing E474: Attempt to decode a blank string. + return g:neomake#compat#json_none + endif + return json_decode(a:json) + endfunction + else + function! neomake#compat#json_decode(json) abort + return json_decode(a:json) + endfunction + endif +else + let neomake#compat#json_true = 1 + let neomake#compat#json_false = 0 + function! s:json_null() abort + endfunction + let neomake#compat#json_null = [function('s:json_null')] + + " Via Syntastic (https://github.com/vim-syntastic/syntastic/blob/6fb14d624b6081459360fdbba743f82cf84c8f92/autoload/syntastic/preprocess.vim#L576-L607), + " based on https://github.com/MarcWeber/vim-addon-json-encoding/blob/master/autoload/json_encoding.vim. + " @vimlint(EVL102, 1, l:true) + " @vimlint(EVL102, 1, l:false) + " @vimlint(EVL102, 1, l:null) + function! neomake#compat#json_decode(json) abort " {{{2 + if a:json ==# '' + return g:neomake#compat#json_none + endif + + " The following is inspired by https://github.com/MarcWeber/vim-addon-manager and + " http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763 + " A hat tip to Marc Weber for this trick + " Replace newlines, which eval() does not like. + let json = substitute(a:json, "\n", '', 'g') + if substitute(json, '\v\"%(\\.|[^"\\])*\"|true|false|null|[+-]?\d+%(\.\d+%([Ee][+-]?\d+)?)?', '', 'g') !~# "[^,:{}[\\] \t]" + " JSON artifacts + let true = g:neomake#compat#json_true + let false = g:neomake#compat#json_false + let null = g:neomake#compat#json_null + + try + let object = eval(json) + catch + throw 'Neomake: Failed to parse JSON input: '.v:exception + endtry + else + throw 'Neomake: Failed to parse JSON input: invalid input' + endif + + return object + endfunction " }}}2 + " @vimlint(EVL102, 0, l:true) + " @vimlint(EVL102, 0, l:false) + " @vimlint(EVL102, 0, l:null) +endif + +lockvar neomake#compat#json_true +lockvar neomake#compat#json_false +lockvar neomake#compat#json_null + +if exists('*uniq') + function! neomake#compat#uniq(l) abort + return uniq(a:l) + endfunction +else + function! neomake#compat#uniq(l) abort + let n = len(a:l) + if n < 2 + return a:l + endif + let prev = a:l[0] + let idx = 1 + while idx < n + if a:l[idx] ==# prev && type(a:l[idx]) == type(prev) + call remove(a:l, idx) + let n -= 1 + else + let prev = a:l[idx] + let idx += 1 + endif + endwhile + return a:l + endfunction +endif + +if exists('*reltimefloat') + function! neomake#compat#reltimefloat() abort + return reltimefloat(reltime()) + endfunction +else + function! neomake#compat#reltimefloat() abort + let t = split(reltimestr(reltime()), '\V.') + return str2float(t[0] . '.' . t[1]) + endfunction +endif + +" Wrapper around systemlist() that supports a list for a:cmd. +" It returns an empty string on error. +" NOTE: Neovim before 0.2.0 would throw an error (which is caught), but it +" does not set v:shell_error! +function! neomake#compat#systemlist(cmd) abort + if empty(a:cmd) + return [] + endif + if has('nvim') && exists('*systemlist') + " @vimlint(EVL108, 1) + if !has('nvim-0.2.0') + try + return systemlist(a:cmd) + catch /^Vim\%((\a\+)\)\=:E902/ + return '' + endtry + endif + " @vimlint(EVL108, 0) + return systemlist(a:cmd) + endif + + if type(a:cmd) == type([]) + let cmd = join(map(a:cmd, 'neomake#utils#shellescape(v:val)')) + else + let cmd = a:cmd + endif + if exists('*systemlist') + return systemlist(cmd) + endif + return split(system(cmd), '\n') +endfunction + +function! neomake#compat#globpath_list(path, pattern, suf) abort + if v:version >= 705 || (v:version == 704 && has('patch279')) + return globpath(a:path, a:pattern, a:suf, 1) + endif + return split(globpath(a:path, a:pattern, a:suf), '\n') +endfunction + +function! neomake#compat#glob_list(pattern) abort + if v:version <= 703 + return split(glob(a:pattern, 1), '\n') + endif + return glob(a:pattern, 1, 1) +endfunction + +if neomake#utils#IsRunningWindows() + " Windows needs a shell to handle PATH/%PATHEXT% etc. + function! neomake#compat#get_argv(exe, args, args_is_list) abort + let prefix = &shell.' '.&shellcmdflag.' ' + if a:args_is_list + if a:exe ==# &shell && get(a:args, 0) ==# &shellcmdflag + " Remove already existing &shell/&shellcmdflag from e.g. NeomakeSh. + let argv = join(a:args[1:]) + else + let argv = join(map(copy([a:exe] + a:args), 'neomake#utils#shellescape(v:val)')) + endif + else + let argv = a:exe . (empty(a:args) ? '' : ' '.a:args) + if argv[0:len(prefix)-1] ==# prefix + return argv + endif + endif + return prefix.argv + endfunction +elseif has('nvim') + function! neomake#compat#get_argv(exe, args, args_is_list) abort + if a:args_is_list + return [a:exe] + a:args + endif + return a:exe . (empty(a:args) ? '' : ' '.a:args) + endfunction +elseif neomake#has_async_support() " Vim-async. + function! neomake#compat#get_argv(exe, args, args_is_list) abort + if a:args_is_list + return [a:exe] + a:args + endif + " Use a shell to handle argv properly (Vim splits at spaces). + let argv = a:exe . (empty(a:args) ? '' : ' '.a:args) + return [&shell, &shellcmdflag, argv] + endfunction +else + " Vim (synchronously), via system(). + function! neomake#compat#get_argv(exe, args, args_is_list) abort + if a:args_is_list + return join(map(copy([a:exe] + a:args), 'neomake#utils#shellescape(v:val)')) + endif + return a:exe . (empty(a:args) ? '' : ' '.a:args) + endfunction +endif + +if v:version >= 704 || (v:version == 703 && has('patch831')) + function! neomake#compat#gettabwinvar(t, w, v, d) abort + return gettabwinvar(a:t, a:w, a:v, a:d) + endfunction +else + " Wrapper around gettabwinvar that has no default (older Vims). + function! neomake#compat#gettabwinvar(t, w, v, d) abort + let r = gettabwinvar(a:t, a:w, a:v) + if r is# '' + unlet r + let r = a:d + endif + return r + endfunction +endif + +" Not really necessary for now, but allows to overwriting and extending. +if exists('*nvim_get_mode') + function! neomake#compat#get_mode() abort + let mode = nvim_get_mode() + return mode.mode + endfunction +else + function! neomake#compat#get_mode() abort + return mode(1) + endfunction +endif + +function! neomake#compat#in_completion() abort + if pumvisible() + return 1 + endif + if has('patch-8.0.0283') + let mode = mode(1) + if mode[1] ==# 'c' || mode[1] ==# 'x' + return 1 + endif + endif + return 0 +endfunction + +let s:prev_windows = [] +if exists('*win_getid') + function! neomake#compat#save_prev_windows() abort + call add(s:prev_windows, [win_getid(winnr('#')), win_getid(winnr())]) + endfunction + + function! neomake#compat#restore_prev_windows() abort + " Go back, maintaining the '#' window (CTRL-W_p). + let [aw_id, pw_id] = remove(s:prev_windows, 0) + let pw = win_id2win(pw_id) + if !pw + call neomake#log#debug(printf( + \ 'Cannot restore previous windows (previous window with ID %d not found).', + \ pw_id)) + elseif winnr() != pw + let aw = win_id2win(aw_id) + if aw + exec aw . 'wincmd w' + endif + exec pw . 'wincmd w' + endif + endfunction +else + function! neomake#compat#save_prev_windows() abort + call add(s:prev_windows, [winnr('#'), winnr()]) + endfunction + + function! neomake#compat#restore_prev_windows() abort + " Go back, maintaining the '#' window (CTRL-W_p). + let [aw, pw] = remove(s:prev_windows, 0) + if pw > winnr('$') + call neomake#log#debug(printf( + \ 'Cannot restore previous windows (%d > %d).', + \ pw, winnr('$'))) + elseif winnr() != pw + if aw + exec aw . 'wincmd w' + endif + exec pw . 'wincmd w' + endif + endfunction +endif + +if v:version >= 704 || (v:version == 703 && has('patch442')) + function! neomake#compat#doautocmd(event) abort + exec 'doautocmd <nomodeline> ' . a:event + endfunction +else + function! neomake#compat#doautocmd(event) abort + exec 'doautocmd ' . a:event + endfunction +endif +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/config.vim b/.vim/autoload/neomake/config.vim new file mode 100644 index 0000000..5f03cd1 --- /dev/null +++ b/.vim/autoload/neomake/config.vim @@ -0,0 +1,192 @@ +" Config API. + +let g:neomake#config#_defaults = { + \ 'maker_defaults': { + \ 'buffer_output': 1, + \ 'output_stream': 'both', + \ 'remove_invalid_entries': 0, + \ }} +lockvar g:neomake#config#_defaults + +let g:neomake#config#undefined = {} +lockvar! g:neomake#config#undefined + +" Resolve a:name (split on dots) and (optionally) init a:dict accordingly. +function! s:resolve_name(dict, name, init) abort + let parts = type(a:name) == type([]) ? a:name : split(a:name, '\.') + let c = a:dict + for p in parts[0:-2] + if !has_key(c, p) + if !a:init + return [g:neomake#config#undefined, ''] + endif + let c[p] = {} + endif + if type(c[p]) != type({}) + return [g:neomake#config#undefined, ''] + endif + let c = c[p] + endfor + return [c, parts[-1]] +endfunction + +" Get a:name (list of keys) from a:dict, using a:prefixes. +function! s:get(dict, parts, prefixes) abort + for prefix in a:prefixes + let [c, k] = s:resolve_name(a:dict, prefix + a:parts[0:-1], 0) + if has_key(c, k) + return [prefix, get(c, k)] + endif + endfor + return [[], g:neomake#config#undefined] +endfunction + +" Get a:name (string (split on dots), or list of keys) from config. +" See neomake#config#get_with_source for args. +function! neomake#config#get(name, ...) abort + return call('neomake#config#get_with_source', [a:name] + a:000)[0] +endfunction + +" Get a:name (string (split on dots), or list of keys) from config, with +" information about the setting's source ('buffer', 'tab', 'global', 'maker', +" 'default'). +" Optional args: +" - a:1: default value +" - a:2: context: defaults to {'ft': &filetype} +" - maker: a maker dict (where maker.name is used from for prefixes, and +" as a lookup itself) +" - ft: filetype string (use an empty string to ignore it) +" - bufnr: buffer number (use an empty string to ignore it) +" - maker_only: should settings get looked up only in the maker context? +" (i.e. with maker.name prefix in general and in context.maker) +" - log_source: additional information to log. +function! neomake#config#get_with_source(name, ...) abort + let context = a:0 > 1 ? a:2 : {'ft': &filetype, 'bufnr': bufnr('%')} + let parts = type(a:name) == type([]) ? a:name : split(a:name, '\.') + + let prefixes = [[]] + if has_key(context, 'ft') && !empty(context.ft) + for ft in neomake#utils#get_config_fts(context.ft, '.') + call insert(prefixes, ['ft', ft], 0) + endfor + endif + + let maker_name = get(get(context, 'maker', {}), 'name', '') + let maker_only = get(context, 'maker_only', 0) + if parts[0][0:1] ==# 'b:' + if !has_key(context, 'bufnr') + let context.bufnr = bufnr('%') + endif + let parts[0] = parts[0][2:-1] + if context.bufnr is# '' + let lookups = [] + else + let lookups = [['buffer', getbufvar(context.bufnr, 'neomake')]] + endif + call add(lookups, ['maker', get(context, 'maker', {})]) + elseif empty(maker_name) && maker_only + let lookups = [['maker', get(context, 'maker', {})]] + else + let lookups = (has_key(context, 'bufnr') && context.bufnr isnot# '' + \ ? [['buffer', getbufvar(context.bufnr, 'neomake')]] + \ : []) + [ + \ ['tab', get(t:, 'neomake', {})], + \ ['global', get(g:, 'neomake', {})], + \ ['maker', get(context, 'maker', {})]] + if !empty(maker_name) + if maker_only + if parts[0] !=# maker_name + call map(prefixes, 'add(v:val, maker_name)') + endif + else + for prefix in reverse(copy(prefixes)) + call insert(prefixes, prefix + [maker_name], 0) + endfor + endif + endif + endif + + for [source, lookup] in lookups + if !empty(lookup) + if source ==# 'maker' + let maker_prefixes = map(copy(prefixes), '!empty(v:val) && v:val[-1] ==# maker_name ? v:val[:-2] : v:val') + let maker_setting_parts = parts[0] == maker_name ? parts[1:] : parts + let [prefix, l:R] = s:get(lookup, maker_setting_parts, maker_prefixes) + else + let [prefix, l:R] = s:get(lookup, parts, prefixes) + endif + if R isnot# g:neomake#config#undefined + let log_name = join(map(copy(parts), "substitute(v:val, '\\.', '|', '')"), '.') + let log_source = get(context, 'log_source', '') + call neomake#log#debug(printf( + \ "Using setting %s=%s from '%s'%s%s.", + \ log_name, string(R), source, + \ empty(prefix) ? '' : ' (prefix: '.string(prefix).')', + \ empty(log_source) ? '' : ' ('.log_source.')'), + \ context) + return [R, source] + endif + unlet R " for Vim without patch-7.4.1546 + endif + unlet lookup " for Vim without patch-7.4.1546 + endfor + + " Return default. + if a:0 + return [a:1, 'default'] + elseif has_key(g:neomake#config#_defaults, a:name) + return [copy(g:neomake#config#_defaults[a:name]), 'default'] + endif + return [g:neomake#config#undefined, 'default'] +endfunction + + +" Set a:name in a:dict to a:value, after resolving it (split on dots). +function! s:set(dict, name, value) abort + let [c, k] = s:resolve_name(a:dict, a:name, 1) + let c[k] = a:value + return c +endfunction + +" Set a:name (resolved on dots) to a:value in the config. +function! neomake#config#set(name, value) abort + let parts = type(a:name) == type([]) ? a:name : split(a:name, '\.') + if parts[0] =~# '^b:' + let parts[0] = parts[0][2:-1] + return neomake#config#set_buffer(bufnr('%'), parts, a:value) + endif + if !has_key(g:, 'neomake') + let g:neomake = {} + endif + return s:set(g:neomake, parts, a:value) +endfunction + +" Set a:name (resolved on dots) to a:value for buffer a:bufnr. +function! neomake#config#set_buffer(bufnr, name, value) abort + let bufnr = +a:bufnr + let bneomake = getbufvar(bufnr, 'neomake') + if bneomake is# '' + unlet bneomake " for Vim without patch-7.4.1546 + let bneomake = {} + call setbufvar(bufnr, 'neomake', bneomake) + endif + return s:set(bneomake, a:name, a:value) +endfunction + +" Set a:name (resolved on dots) to a:value in a:scope. +" This is meant for advanced usage, e.g.: +" set_scope(t:, 'neomake.disabled', 1) +function! neomake#config#set_dict(dict, name, value) abort + return s:set(a:dict, a:name, a:value) +endfunction + +" Unset a:name (resolved on dots). +" This is meant for advanced usage, e.g.: +" unset_dict(t:, 'neomake.disabled', 1) +function! neomake#config#unset_dict(dict, name) abort + let [c, k] = s:resolve_name(a:dict, a:name, 0) + if has_key(c, k) + unlet c[k] + endif +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/configure.vim b/.vim/autoload/neomake/configure.vim new file mode 100644 index 0000000..f802d7f --- /dev/null +++ b/.vim/autoload/neomake/configure.vim @@ -0,0 +1,785 @@ +" Default settings, setup in global config dict. +let s:default_settings = { + \ 'ignore_filetypes': ['startify'], + \ } +let g:neomake = get(g:, 'neomake', {}) +let g:neomake.automake = get(g:neomake, 'automake', {}) +call extend(g:neomake.automake, s:default_settings, 'keep') + +if !exists('s:timer_info') + let s:timer_info = {} + let s:timer_by_bufnr = {} +endif + +let s:default_delay = has('timers') ? 500 : 0 + +" A mapping of configured buffers with cached settings (maker_jobs). +let s:configured_buffers = {} +" A list of configured/used autocommands. +let s:registered_events = [] + +" TextChanged gets triggered in this case when loading a buffer (Vim +" issue #2742). +let s:need_to_skip_first_textchanged = !has('nvim-0.3.2') && has('patch-8.0.1494') && !has('patch-8.0.1633') + + +" TODO: allow for namespaces, and prefer 'automake' here. +" TODO: handle bufnr! (getbufvar) +function! s:get_setting(name, default) abort + return get(get(b:, 'neomake', {}), a:name, + \ get(get(t:, 'neomake', {}), a:name, + \ get(get(g:, 'neomake', {}), a:name, a:default))) +endfunction + + +function! s:debug_log(msg, ...) abort + let context = {'bufnr': bufnr('%')} + if a:0 + call extend(context, a:1) + endif + call neomake#log#debug(printf('automake: %s.', a:msg), context) +endfunction + +" Check if buffer's tick (or ft) changed. +function! s:tick_changed(context) abort + let bufnr = +a:context.bufnr + let ft = get(a:context, 'ft', getbufvar(bufnr, '&filetype')) + let prev_tick = getbufvar(bufnr, '_neomake_automake_tick') + let r = 1 + if empty(prev_tick) + call s:debug_log('tick changed (new)') + else + let cur_tick = [getbufvar(bufnr, 'changedtick'), ft] + if cur_tick == prev_tick + call s:debug_log('tick is unchanged') + return 0 + endif + + " NOTE: every write (BufWritePost) increments b:changedtick. + if a:context.event ==# 'BufWritePost' + let adjusted_prev_tick = [prev_tick[0]+1, prev_tick[1]] + if adjusted_prev_tick == cur_tick + let r = 0 + call setbufvar(bufnr, '_neomake_automake_tick', adjusted_prev_tick) + call s:debug_log('tick is unchanged with BufWritePost adjustment') + endif + endif + endif + return r +endfunction + +function! neomake#configure#_update_automake_tick(bufnr, ft) abort + if has_key(s:configured_buffers, a:bufnr) + let tick = getbufvar(a:bufnr, 'changedtick') + call s:debug_log('updating tick: '.tick) + call setbufvar(a:bufnr, '_neomake_automake_tick', [tick, a:ft]) + endif +endfunction + +function! neomake#configure#_reset_automake_cancelations(bufnr) abort + if has_key(s:configured_buffers, a:bufnr) + call setbufvar(a:bufnr, '_neomake_cancelations', [0, 0]) + endif +endfunction + +function! s:update_cancel_rate(bufnr, via_timer) abort + let canceled = getbufvar(a:bufnr, '_neomake_cancelations', [0, 0]) + if a:via_timer + let canceled[0] += 1 + else + let canceled[1] += 1 + endif + call setbufvar(a:bufnr, '_neomake_cancelations', canceled) + return canceled +endfunction + +function! s:handle_changed_buffer(make_id, event) abort + " Cleanup always. + if exists('b:_neomake_automake_changed_context') + let [make_id, prev_tick, changedtick, context] = b:_neomake_automake_changed_context + + if s:need_to_skip_first_textchanged && a:event ==# 'TextChanged' + if !get(b:, '_neomake_seen_TextChanged', 0) + call s:debug_log('ignoring first TextChanged') + let b:_neomake_seen_TextChanged = 1 + return + endif + endif + + if changedtick == b:changedtick + call s:debug_log(printf('handle_changed_buffer: %s: tick was not changed', a:event)) + return + endif + + unlet b:_neomake_automake_changed_context + augroup neomake_automake_abort + au! * <buffer> + augroup END + else + return + endif + + if make_id != a:make_id + call neomake#log#warning(printf('automake: handle_changed_buffer: mismatched make_id: %d != %d.', make_id, a:make_id)) + return + endif + + let window_make_ids = get(w:, 'neomake_make_ids', []) + if index(window_make_ids, a:make_id) == -1 + return + endif + + call setbufvar(context.bufnr, '_neomake_automake_tick', prev_tick) + call filter(b:_neomake_automake_make_ids, 'v:val != '.a:make_id) + call s:update_cancel_rate(context.bufnr, 0) + + call s:debug_log(printf('buffer was changed (%s), canceling make', a:event), {'make_id': a:make_id}) + call neomake#CancelMake(a:make_id) + + if a:event ==# 'TextChangedI' + call s:debug_log('queueing make restart for InsertLeave', {'make_id': a:make_id}) + let b:_neomake_postponed_automake_context = [1, context] + augroup neomake_automake_retry + au! * <buffer> + autocmd InsertLeave <buffer> call s:do_postponed_automake(2) + augroup END + elseif context.delay + call s:debug_log(printf('restarting timer for original event %s', context.event), {'make_id': a:make_id}) + if has_key(context, '_via_timer_cb') + unlet context._via_timer_cb + endif + if has_key(context, 'pos') + unlet context.pos + endif + call s:neomake_do_automake(context) + else + call s:debug_log(printf('restarting for original event (%s) without delay', context.event)) + call s:neomake_do_automake(context) + endif +endfunction + +function! s:neomake_do_automake(context) abort + let bufnr = +a:context.bufnr + + if !get(a:context, '_via_timer_cb') && a:context.delay + if exists('s:timer_by_bufnr[bufnr]') + let timer = s:timer_by_bufnr[bufnr] + call s:stop_timer(timer) + call s:debug_log(printf('stopped existing timer: %d', timer), {'bufnr': bufnr}) + call s:update_cancel_rate(bufnr, 1) + endif + if !s:tick_changed(a:context) + call s:debug_log('buffer was not changed', {'bufnr': bufnr}) + return + endif + + " Cancel any already running automake runs. + let prev_make_ids = getbufvar(bufnr, '_neomake_automake_make_ids') + if !empty(prev_make_ids) + call s:debug_log(printf('stopping previous make runs: %s', join(prev_make_ids, ', '))) + for prev_make_id in prev_make_ids + call neomake#CancelMake(prev_make_id) + endfor + let canceled = s:update_cancel_rate(bufnr, 0) + else + let canceled = getbufvar(bufnr, '_neomake_cancelations', [0, 0]) + endif + + let delay = a:context.delay + + " Increase delay for canceled/restarted timers, and canceled makes. + " IDEA: take into account the mean duration of this make run. + if canceled[0] || canceled[1] + let [mult_timers, mult_makes, max_delay] = neomake#config#get('automake.cancelation_delay', [0.2, 0.5, 3000], {'bufnr': bufnr}) + let cancel_rate = 1 + (canceled[0]*mult_timers + canceled[1]*mult_makes) + let delay = min([max_delay, float2nr(ceil(delay * cancel_rate))]) + call s:debug_log(printf('increasing delay (%d/%d canceled timers/makes, rate=%.2f): %d => %d/%d', canceled[0], canceled[1], cancel_rate, a:context.delay, delay, max_delay)) + endif + + let timer = timer_start(delay, function('s:automake_delayed_cb')) + let s:timer_info[timer] = a:context + if !has_key(a:context, 'pos') + let s:timer_info[timer].pos = s:get_position_context() + endif + let s:timer_by_bufnr[bufnr] = timer + call s:debug_log(printf('started timer (%dms): %d', delay, timer), + \ {'bufnr': a:context.bufnr}) + return + endif + + let ft = getbufvar(bufnr, '&filetype') + let event = a:context.event + + call s:debug_log('neomake_do_automake: '.event, {'bufnr': bufnr}) + if !s:tick_changed({'event': event, 'bufnr': bufnr, 'ft': ft}) + call s:debug_log('buffer was not changed', {'bufnr': bufnr}) + return + endif + let prev_tick = getbufvar(bufnr, '_neomake_automake_tick') + + call s:debug_log(printf('enabled makers: %s', join(map(copy(a:context.maker_jobs), 'v:val.maker.name'), ', '))) + let make_options = { + \ 'file_mode': 1, + \ 'jobs': deepcopy(a:context.maker_jobs), + \ 'ft': ft, + \ 'automake': 1} + let jobinfos = neomake#Make(make_options) + + let started_jobs = filter(copy(jobinfos), "!get(v:val, 'finished', 0)") + call s:debug_log(printf('started jobs: %s', string(map(copy(started_jobs), 'v:val.id')))) + if !empty(started_jobs) + let make_id = jobinfos[0].make_id + call setbufvar(bufnr, '_neomake_automake_make_ids', + \ neomake#compat#getbufvar(bufnr, '_neomake_automake_make_ids', []) + [make_id]) + + " Setup buffer autocmd to cancel/restart make for changed buffer. + let events = [] + for event in ['TextChangedI', 'TextChanged'] + if a:context.event !=# event + call add(events, event) + endif + endfor + call setbufvar(bufnr, '_neomake_automake_changed_context', [make_id, prev_tick, getbufvar(bufnr, 'changedtick'), a:context]) + augroup neomake_automake_abort + exe printf('au! * <buffer=%d>', bufnr) + for event in events + exe printf('autocmd %s <buffer=%d> call s:handle_changed_buffer(%s, %s)', + \ event, bufnr, string(make_id), string(event)) + endfor + augroup END + endif +endfunction + +function! s:get_position_context() abort + let w = exists('*win_getid') ? win_getid() : winnr() + return [w, getpos('.'), neomake#compat#get_mode()] +endfunction + +function! s:automake_delayed_cb(timer) abort + let timer_info = s:timer_info[a:timer] + unlet s:timer_info[a:timer] + unlet s:timer_by_bufnr[timer_info.bufnr] + + if !bufexists(timer_info.bufnr) + call s:debug_log(printf('buffer does not exist anymore for timer %d', a:timer), + \ {'bufnr': timer_info.bufnr}) + return + endif + + call s:debug_log(printf('callback for timer %d (via %s)', string(a:timer), timer_info.event), + \ {'bufnr': timer_info.bufnr}) + + let bufnr = bufnr('%') + if timer_info.bufnr != bufnr + call s:debug_log(printf('buffer changed: %d => %d, queueing make restart for BufEnter,WinEnter', + \ timer_info.bufnr, bufnr)) + let restart_context = copy(timer_info) + call setbufvar(restart_context.bufnr, '_neomake_postponed_automake_context', [1, restart_context]) + let b:_neomake_postponed_automake_context = [1, restart_context] + augroup neomake_automake_retry + exe 'au! * <buffer='.timer_info.bufnr.'>' + exe 'autocmd BufEnter,WinEnter <buffer='.restart_context.bufnr.'> call s:do_postponed_automake(2)' + augroup END + return + endif + + if neomake#compat#in_completion() + call s:debug_log('postponing automake during completion') + if has_key(timer_info, 'pos') + unlet timer_info.pos + endif + let b:_neomake_postponed_automake_context = [0, timer_info] + + augroup neomake_automake_retry + au! * <buffer> + autocmd CompleteDone <buffer> call s:do_postponed_automake(1) + autocmd InsertLeave <buffer> call s:do_postponed_automake(2) + augroup END + return + endif + + " Verify context/position is the same. + " This is meant to give an additional delay after e.g. TextChanged. + " Only events with delay are coming here, so this does not affect + " BufWritePost etc typically. + if !empty(timer_info.pos) + let current_context = s:get_position_context() + if current_context != timer_info.pos + if current_context[2] != timer_info.pos[2] + " Mode was changed. + if current_context[2][0] ==# 'i' && timer_info.event !=# 'TextChangedI' + " Changed to insert mode, trigger on InsertLeave. + call s:debug_log(printf('context/position changed: %s => %s, restarting on InsertLeave', + \ string(timer_info.pos), string(current_context))) + let context = copy(timer_info) + let context.delay = 0 + unlet context.pos + call s:update_cancel_rate(bufnr, 1) + let b:_neomake_postponed_automake_context = [1, context] + augroup neomake_automake_retry + au! * <buffer> + autocmd InsertLeave <buffer> call s:do_postponed_automake(2) + augroup END + return + endif + endif + call s:debug_log(printf('context/position changed: %s => %s, restarting', + \ string(timer_info.pos), string(current_context))) + unlet timer_info.pos + call s:update_cancel_rate(bufnr, 1) + call s:neomake_do_automake(timer_info) + return + endif + endif + " endif + + let context = copy(timer_info) + let context._via_timer_cb = 1 + call s:neomake_do_automake(context) +endfunction + +function! s:do_postponed_automake(step) abort + if exists('b:_neomake_postponed_automake_context') + let context = b:_neomake_postponed_automake_context + + if context[0] == a:step - 1 + if a:step == 2 + call s:debug_log('re-starting postponed automake') + let context[1].pos = s:get_position_context() + call s:neomake_do_automake(context[1]) + else + let context[0] = a:step + return + endif + else + call s:debug_log('postponed automake: unexpected step '.a:step.', cleaning up') + endif + unlet b:_neomake_postponed_automake_context + else + call s:debug_log('missing context information for postponed automake') + endif + " Cleanup. + augroup neomake_automake_retry + autocmd! * <buffer> + augroup END +endfunction + +" Parse/get events dict from args. +" a:config: config dict to write into. +" a:string_or_dict_config: a string or dict describing the config. +" a:1: default delay. +function! s:parse_events_from_args(config, string_or_dict_config, ...) abort + " Get default delay from a:1. + if a:0 + if has('timers') + let delay = a:1 + else + if a:1 != 0 + call neomake#log#warning('automake: timer support is required for delayed events.') + endif + let delay = 0 + endif + else + let delay = s:default_delay + endif + + if type(a:string_or_dict_config) == type({}) + let events = copy(a:string_or_dict_config) + + " Validate events. + for [event, config] in items(events) + if !exists('##'.event) + call neomake#log#error(printf( + \ 'automake: event %s does not exist.', event)) + unlet events[event] + continue + endif + + if get(config, 'delay', 0) && !has('timers') + call neomake#log#error(printf( + \ 'automake: timer support is required for automaking, removing event %s.', + \ event)) + unlet events[event] + endif + endfor + call neomake#config#set_dict(a:config, 'automake.events', events) + if a:0 + let a:config.automake_delay = a:1 + endif + else + " Map string config to events dict. + let modes = a:string_or_dict_config + let events = {} + let default_with_delay = {} + + " Insert mode. + if modes =~# 'i' + if exists('##TextChangedI') && has('timers') + let events['TextChangedI'] = default_with_delay + else + call s:debug_log('using CursorHoldI instead of TextChangedI') + let events['CursorHoldI'] = (delay != 0 ? {'delay': 0} : {}) + endif + endif + " Normal mode. + if modes =~# 'n' + if exists('##TextChanged') && has('timers') + let events['TextChanged'] = default_with_delay + if !has_key(events, 'TextChangedI') + " Run when leaving insert mode, since only TextChangedI would be triggered + " for `ciw` etc. + let events['InsertLeave'] = default_with_delay + endif + else + call s:debug_log('using CursorHold instead of TextChanged') + let events['CursorHold'] = (delay != 0 ? {'delay': 0} : {}) + let events['InsertLeave'] = (delay != 0 ? {'delay': 0} : {}) + endif + endif + " On writes. + if modes =~# 'w' + let events['BufWritePost'] = (delay != 0 ? {'delay': 0} : {}) + endif + " On reads. + if modes =~# 'r' + let events['BufWinEnter'] = {} + let events['FileType'] = {} + + " When a file was changed outside of Vim. + " TODO: test + let events['FileChangedShellPost'] = {} + " XXX: FileType might work better, at least when wanting to skip filetypes. + " let events['FileType'] = {'delay': a:0 > 1 ? delay : 0} + endif + endif + + call neomake#config#set_dict(a:config, 'automake.events', events) + if a:0 + let a:config.automake_delay = delay + endif +endfunction + +" Setup automake for buffer (current, or options.bufnr). +" a:1: delay +" a:2: options ('bufnr', 'makers') / or list of makers TODO +function! neomake#configure#automake_for_buffer(string_or_dict_config, ...) abort + let options = {} + if a:0 + let options.delay = a:1 + endif + let bufnr = bufnr('%') + if a:0 > 1 + if type(a:2) == type([]) + let options.makers = a:2 + else + call extend(options, a:2) + if has_key(options, 'bufnr') + let bufnr = options.bufnr + unlet options.bufnr + endif + endif + endif + return call('s:configure_buffer', [bufnr, a:string_or_dict_config, options]) +endfunction + +" Workaround for getbufvar not having support for defaults. +function! s:getbufvar(bufnr, name, default) abort + let b_dict = getbufvar(+a:bufnr, '') + if empty(b_dict) + " NOTE: it is an empty string for non-existing buffers. + return a:default + endif + return get(b_dict, a:name, a:default) +endfunction + +function! s:is_buffer_ignored(bufnr) abort + " TODO: blacklist/whitelist. + let bufnr = +a:bufnr + let buftype = getbufvar(bufnr, '&buftype') + if !empty(buftype) + call s:debug_log(printf('ignoring buffer with buftype=%s', buftype), {'bufnr': bufnr}) + return 1 + endif + + let ft = getbufvar(bufnr, '&filetype') + if index(neomake#config#get('automake.ignore_filetypes', []), ft) != -1 + call s:debug_log(printf('ignoring buffer with filetype=%s', ft), {'bufnr': bufnr}) + return 1 + endif +endfunction + +if exists('##OptionSet') + function! s:update_buffer_options() abort + let bufnr = bufnr('%') + call s:maybe_reconfigure_buffer(bufnr) + endfunction + augroup neomake_automake_update + au! + au OptionSet buftype call s:update_buffer_options() + augroup END +endif + +" a:1: string or dict describing the events +" a:2: options ('delay', 'makers') +function! s:configure_buffer(bufnr, ...) abort + let bufnr = +a:bufnr + let ft = getbufvar(bufnr, '&filetype') + let config = s:getbufvar(bufnr, 'neomake', {}) + let old_config = deepcopy(config) + if a:0 + let args = [config, a:1] + if a:0 > 1 && has_key(a:2, 'delay') + let args += [a:2.delay] + endif + call call('s:parse_events_from_args', args) + call setbufvar(bufnr, 'neomake', config) + + let implicit_config = {'custom': 1, 'ignore': 0} + else + let implicit_config = {'custom': 0, 'ignore': s:is_buffer_ignored(bufnr)} + endif + + " Register the buffer, and remember if it is custom. + if has_key(s:configured_buffers, bufnr) + let old_registration = copy(get(s:configured_buffers, bufnr, {})) + call extend(s:configured_buffers[bufnr], implicit_config, 'force') + else + let s:configured_buffers[bufnr] = implicit_config + + augroup neomake_automake_clean + autocmd BufWipeout <buffer> call s:neomake_automake_clean(expand('<abuf>')) + augroup END + endif + + if implicit_config.ignore + return s:configured_buffers[bufnr] + endif + + let s:configured_buffers[bufnr].events_config = neomake#config#get('automake.events', {}) + + " Create jobs. + let options = a:0 > 1 ? a:2 : {} + if has_key(options, 'makers') + let makers = neomake#map_makers(options.makers, ft, 0) + let source = 'options' + else + let [makers, source] = neomake#config#get_with_source('automake.enabled_makers') + if makers is g:neomake#config#undefined + unlet makers + let makers = neomake#GetEnabledMakers(ft) + else + let makers = neomake#map_makers(makers, ft, 0) + endif + endif + let options = {'file_mode': 1, 'ft': ft, 'bufnr': bufnr, 'automake': 1} + let jobs = neomake#core#create_jobs(options, makers) + let s:configured_buffers[bufnr].maker_jobs = jobs + call s:debug_log(printf('configured buffer for ft=%s (%s)', + \ ft, empty(jobs) ? 'no enabled makers' : join(map(copy(jobs), 'v:val.maker.name'), ', ').' ('.source.')'), {'bufnr': bufnr}) + if old_config != config + call s:debug_log('resetting tick because of config changes') + call setbufvar(bufnr, '_neomake_automake_tick', []) + elseif exists('old_registration') + if old_registration != s:configured_buffers[bufnr] + call s:debug_log('resetting tick because of registration changes') + call setbufvar(bufnr, '_neomake_automake_tick', []) + endif + else + call s:debug_log('setting tick for new buffer') + call setbufvar(bufnr, '_neomake_automake_tick', []) + endif + + if a:0 + " Setup autocommands etc (when called manually)?! + call neomake#configure#automake() + endif + return config +endfunction + +function! s:maybe_reconfigure_buffer(bufnr) abort + if has_key(s:configured_buffers, a:bufnr) && !s:configured_buffers[a:bufnr].custom + call s:configure_buffer(a:bufnr) + endif +endfunction + +" Called from autocommands. +function! s:neomake_automake(event, bufnr) abort + let disabled = neomake#config#get_with_source('disabled', 0) + if disabled[0] + call s:debug_log(printf('disabled (%s)', disabled[1])) + return + endif + let bufnr = +a:bufnr + + if has_key(s:configured_buffers, bufnr) + let buffer_config = s:configured_buffers[bufnr] + else + " Register the buffer, and remember that it's automatic. + let buffer_config = s:configure_buffer(bufnr) + endif + if get(buffer_config, 'ignore', 0) + " NOTE: might be too verbose. + call s:debug_log('buffer is ignored') + return + endif + + if s:need_to_skip_first_textchanged && a:event ==# 'TextChanged' + if !getbufvar(bufnr, '_neomake_seen_TextChanged', 0) + call s:debug_log('ignoring first TextChanged') + call setbufvar(bufnr, '_neomake_seen_TextChanged', 1) + return + endif + endif + + call s:debug_log(printf('handling event %s', a:event), {'bufnr': bufnr}) + + if empty(s:configured_buffers[bufnr].maker_jobs) + call s:debug_log('no enabled makers', {'bufnr': bufnr}) + return + endif + + call s:debug_log(printf('automake for event %s', a:event), {'bufnr': bufnr}) + let config = s:configured_buffers[bufnr].events_config + if !has_key(config, a:event) + call s:debug_log('event is not registered', {'bufnr': bufnr}) + return + endif + let config = config[a:event] + + let event = a:event + let bufnr = +a:bufnr + " TODO: rename to neomake.automake.delay + let delay = get(config, 'delay', s:get_setting('automake_delay', s:default_delay)) + let context = { + \ 'delay': delay, + \ 'bufnr': bufnr, + \ 'event': a:event, + \ 'maker_jobs': s:configured_buffers[bufnr].maker_jobs, + \ } + if event ==# 'BufWinEnter' + " Ignore context, so that e.g. with vim-stay restoring the view + " (cursor position), it will still be triggered. + let context.pos = [] + endif + call s:neomake_do_automake(context) +endfunction + +function! s:stop_timer(timer) abort + let timer_info = s:timer_info[a:timer] + unlet s:timer_info[a:timer] + unlet s:timer_by_bufnr[timer_info.bufnr] + call timer_stop(+a:timer) +endfunction + +function! s:stop_timers() abort + let timers = keys(s:timer_info) + if !empty(timers) + call s:debug_log(printf('stopping timers: %s', join(timers, ', '))) + for timer in timers + call s:stop_timer(timer) + endfor + endif +endfunction + +function! neomake#configure#reset_automake() abort + for bufnr in keys(s:configured_buffers) + call s:neomake_automake_clean(bufnr) + endfor + let s:registered_events = [] + call s:stop_timers() + call neomake#configure#automake() +endfunction + +function! s:neomake_automake_clean(bufnr) abort + if has_key(s:timer_by_bufnr, a:bufnr) + let timer = s:timer_by_bufnr[a:bufnr] + call s:stop_timer(timer) + call s:debug_log('stopped timer for cleaned buffer: '.timer) + endif + if has_key(s:configured_buffers, a:bufnr) + unlet s:configured_buffers[a:bufnr] + augroup neomake_automake_clean + exe printf('au! * <buffer=%d>', a:bufnr) + augroup END + endif +endfunction + +function! neomake#configure#disable_automake() abort + call s:debug_log('disabling globally') + call s:stop_timers() +endfunction + +function! neomake#configure#disable_automake_for_buffer(bufnr) abort + call s:debug_log(printf('disabling buffer %d', a:bufnr)) + if has_key(s:timer_by_bufnr, a:bufnr) + let timer = s:timer_by_bufnr[a:bufnr] + call s:stop_timer(timer) + call s:debug_log('stopped timer for buffer: '.timer) + endif + if has_key(s:configured_buffers, a:bufnr) + let s:configured_buffers[a:bufnr].disabled = 1 + endif +endfunction + +function! neomake#configure#enable_automake_for_buffer(bufnr) abort + if exists('s:configured_buffers[a:bufnr].disabled') + call s:debug_log(printf('Re-enabled buffer %d', a:bufnr)) + unlet s:configured_buffers[a:bufnr].disabled + endif +endfunction + +function! neomake#configure#reset_automake_for_buffer(...) abort + let bufnr = a:0 ? +a:1 : bufnr('%') + call s:neomake_automake_clean(bufnr) +endfunction + +function! neomake#configure#automake(...) abort + call s:debug_log(printf('configuring automake: %s', string(a:000))) + if !exists('g:neomake') + let g:neomake = {} + endif + if a:0 + call call('s:parse_events_from_args', [g:neomake] + a:000) + endif + + let disabled_globally = get(get(g:, 'neomake', {}), 'disabled', 0) + if disabled_globally + let s:registered_events = [] + else + let s:registered_events = keys(get(get(g:neomake, 'automake', {}), 'events', {})) + endif + " Keep custom configured buffers. + call filter(s:configured_buffers, 'v:val.custom') + for b in keys(s:configured_buffers) + if empty(s:configured_buffers[b].maker_jobs) + continue + endif + if get(s:configured_buffers[b], 'disabled', 0) + continue + endif + let b_cfg = neomake#config#get('b:automake.events', {}) + for event_config in items(b_cfg) + let event = event_config[0] + if index(s:registered_events, event) == -1 + call add(s:registered_events, event) + endif + endfor + endfor + call s:debug_log('registered events: '.join(s:registered_events, ', ')) + + augroup neomake_automake + au! + for event in s:registered_events + exe 'autocmd '.event." * call s:neomake_automake('".event."', expand('<abuf>'))" + endfor + augroup END + if empty(s:registered_events) + augroup! neomake_automake + endif +endfunction + +augroup neomake_automake_base + au! + autocmd FileType * call s:maybe_reconfigure_buffer(expand('<abuf>')) +augroup END +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/core.vim b/.vim/autoload/neomake/core.vim new file mode 100644 index 0000000..b61a351 --- /dev/null +++ b/.vim/autoload/neomake/core.vim @@ -0,0 +1,120 @@ +let g:neomake#core#valid_maker_name_pattern = '\v^\w+$' + +let g:neomake#core#_ignore_autocommands = 0 + +function! neomake#core#create_jobs(options, makers) abort + let args = [a:options, a:makers] + let jobs = call('s:bind_makers_for_job', args) + return jobs +endfunction + +" Map/bind a:makers to a list of job options, using a:options. +function! s:bind_makers_for_job(options, makers) abort + let r = [] + for maker in a:makers + let options = copy(a:options) + try + let maker = neomake#core#instantiate_maker(maker, options, 1) + catch /^Neomake: skip_job: / + let msg = substitute(v:exception, '^Neomake: skip_job: ', '', '') + call neomake#log#debug(printf('%s: skipping job: %s.', + \ maker.name, msg), options) + continue + catch /^Neomake: / + let error = substitute(v:exception, '^Neomake: ', '', '').'.' + call neomake#log#error(error, options) + continue + endtry + if !empty(maker) + let options.maker = maker + let r += [options] + endif + endfor + return r +endfunction + +function! neomake#core#instantiate_maker(maker, options, check_exe) abort + let maker = a:maker + let options = a:options + let ft = get(options, 'ft', '') + let bufnr = get(options, 'bufnr', '') + + " Call InitForJob function in maker object, if any. + let l:Init = neomake#utils#GetSetting('InitForJob', maker, g:neomake#config#undefined, ft, bufnr) + if empty(Init) + " Deprecated: should use InitForJob instead. + if has_key(maker, 'fn') + unlet Init " vim73 + let l:Init = maker.fn + call neomake#log#warn_once(printf("Please use 'InitForJob' instead of 'fn' for maker %s.", maker.name), + \ printf('deprecated-fn-%s', maker.name)) + endif + endif + if !empty(Init) + let returned_maker = call(Init, [options], maker) + if returned_maker isnot# 0 + " This conditional assignment allows to both return a copy + " (factory), while also can be used as a init method. + let maker = returned_maker + endif + endif + + if has_key(maker, '_bind_args') + call maker._bind_args() + if type(maker.exe) != type('') + let error = printf('Non-string given for executable of maker %s: type %s', + \ maker.name, type(maker.exe)) + if !get(maker, 'auto_enabled', 0) + throw 'Neomake: '.error + endif + call neomake#log#debug(error.'.', options) + return {} + endif + if a:check_exe && !executable(maker.exe) + if get(maker, 'auto_enabled', 0) + call neomake#log#debug(printf( + \ 'Exe (%s) of auto-configured maker %s is not executable, skipping.', maker.exe, maker.name), options) + else + let error = printf('Exe (%s) of maker %s is not executable', maker.exe, maker.name) + throw 'Neomake: '.error + endif + return {} + endif + endif + return maker +endfunction + +" Base class for command makers. +let g:neomake#core#command_maker_base = {} + +function! g:neomake#core#command_maker_base._get_fname_for_args(jobinfo) abort dict + " Append file? (defaults to jobinfo.file_mode, project/global makers should set it to 0) + let append_file = neomake#utils#GetSetting('append_file', self, a:jobinfo.file_mode, a:jobinfo.ft, a:jobinfo.bufnr) + " Use/generate a filename? (defaults to 1 if tempfile_name is set) + let uses_filename = append_file || neomake#utils#GetSetting('uses_filename', self, has_key(self, 'tempfile_name'), a:jobinfo.ft, a:jobinfo.bufnr) + if append_file || uses_filename + let filename = self._get_fname_for_buffer(a:jobinfo) + if append_file + return filename + endif + endif + return '' +endfunction + +function! g:neomake#core#command_maker_base._get_argv(_jobinfo) abort dict + return neomake#compat#get_argv(self.exe, self.args, type(self.args) == type([])) +endfunction + +" Get tabnr and winnr for a given make ID. +function! neomake#core#get_tabwin_for_makeid(make_id) abort + let curtab = tabpagenr() + for t in [curtab] + range(1, curtab-1) + range(curtab+1, tabpagenr('$')) + for w in range(1, tabpagewinnr(t, '$')) + if index(neomake#compat#gettabwinvar(t, w, 'neomake_make_ids', []), a:make_id) != -1 + return [t, w] + endif + endfor + endfor + return [-1, -1] +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/debug.vim b/.vim/autoload/neomake/debug.vim new file mode 100644 index 0000000..66abcaf --- /dev/null +++ b/.vim/autoload/neomake/debug.vim @@ -0,0 +1,273 @@ +" Debug/feedback helpers. + +function! neomake#debug#pprint(d, ...) abort + return call('s:pprint', [a:d] + a:000) +endfunction + +function! s:pprint(v, ...) abort + let indent = a:0 ? a:1 : '' + if type(a:v) ==# type({}) + if empty(a:v) + return '{}' + endif + let r = "{\n" + for [k, l:V] in items(a:v) + let r .= printf("%s %s: %s,\n", + \ indent, + \ string(k), + \ s:pprint(neomake#utils#fix_self_ref(V), indent . ' ')) + unlet V " old-vim + endfor + let r .= indent.'}' + return r + elseif type(a:v) ==# type([]) + if empty(a:v) + return '[]' + endif + let r = '['."\n".join(map(copy(a:v), 'indent." ".s:pprint(v:val, indent." ")'), ",\n").",\n".indent.']' + return r + endif + return string(a:v) +endfunction + +function! neomake#debug#validate_maker(maker) abort + let issues = {'errors': [], 'warnings': []} + + if has_key(a:maker, 'process_json') && has_key(a:maker, 'process_output') + let issues.warnings += ['maker has process_json and process_output, but only process_json will be used.'] + let check_process = ['process_json'] + else + let check_process = ['process_json', 'process_output'] + endif + + for f in check_process + if has_key(a:maker, f) + if has_key(a:maker, 'mapexpr') + let issues.warnings += [printf( + \ 'maker has mapexpr, but only %s will be used.', + \ f)] + endif + if has_key(a:maker, 'postprocess') + let issues.warnings += [printf( + \ 'maker has postprocess, but only %s will be used.', + \ f)] + endif + if has_key(a:maker, 'errorformat') + let issues.warnings += [printf( + \ 'maker has errorformat, but only %s will be used.', + \ f)] + endif + endif + endfor + + try + let maker = neomake#core#instantiate_maker(a:maker, {}, 0) + if !executable(maker.exe) + let t = get(maker, 'auto_enabled', 0) ? 'warnings' : 'errors' + let issues[t] += [printf("maker's exe (%s) is not executable.", maker.exe)] + endif + catch /^Neomake: / + let issues.errors += [substitute(v:exception, '^Neomake: ', '', '').'.'] + endtry + + if has_key(a:maker, 'name') + if a:maker.name !~# g:neomake#core#valid_maker_name_pattern + call add(issues['errors'], printf( + \ 'Invalid maker name: %s (should match %s)', + \ string(a:maker.name), + \ string(g:neomake#core#valid_maker_name_pattern))) + endif + endif + + return issues +endfunction + +" Optional arg: ft +function! s:get_makers_info(...) abort + let maker_names = call('neomake#GetEnabledMakers', a:000) + if empty(maker_names) + return ['None.'] + endif + let maker_defaults = g:neomake#config#_defaults['maker_defaults'] + let r = [] + for maker_name in maker_names + let maker = call('neomake#GetMaker', [maker_name] + a:000) + let r += [' - '.maker.name] + let r += map(s:get_maker_info(maker, maker_defaults), "' '.v:val") + endfor + return r +endfunction + +function! s:get_maker_info(maker, ...) abort + let maker_defaults = a:0 ? a:1 : {} + let maker = a:maker + let r = [] + for [k, l:V] in sort(copy(items(maker))) + if k !=# 'name' && k !=# 'ft' && k !~# '^_' + if !has_key(maker_defaults, k) + \ || type(V) != type(maker_defaults[k]) + \ || V !=# maker_defaults[k] + let r += [' - '.k.': '.string(V)] + endif + endif + unlet V " vim73 + endfor + + let issues = neomake#debug#validate_maker(maker) + if !empty(issues) + for type in sort(copy(keys(issues))) + let items = issues[type] + if !empty(items) + let r += [' - '.toupper(type) . ':'] + for issue in items + let r += [' - ' . issue] + endfor + endif + endfor + endif + + if type(maker.exe) == type('') && executable(maker.exe) + let version_arg = get(maker, 'version_arg', '--version') + let exe = exists('*exepath') ? exepath(maker.exe) : maker.exe + let version_output = neomake#compat#systemlist([exe, version_arg]) + if empty(version_output) + let version_output = [printf( + \ 'failed to get version information (%s)', + \ v:shell_error)] + endif + let r += [printf(' - version information (%s %s): %s', + \ exe, + \ version_arg, + \ join(version_output, "\n "))] + endif + return r +endfunction + +function! s:get_fts_with_makers() abort + return neomake#compat#uniq(sort(map(split(globpath(escape(&runtimepath, ' '), + \ 'autoload/neomake/makers/ft/*.vim'), "\n"), + \ 'fnamemodify(v:val, ":t:r")'))) +endfunction + +function! neomake#debug#get_maker_info(maker_name) abort + let source = '' + let maker = neomake#get_maker_by_name(a:maker_name, &filetype) + if empty(maker) + let maker = neomake#get_maker_by_name(a:maker_name) + if empty(maker) + let fts = filter(s:get_fts_with_makers(), 'v:val != &filetype') + for ft in fts + let maker = neomake#get_maker_by_name(a:maker_name, ft) + if !empty(maker) + let source = 'filetype '.ft + break + endif + endfor + else + let source = 'project maker' + endif + endif + if empty(maker) + call neomake#log#error(printf('Maker not found: %s.', a:maker_name)) + return [] + endif + let maker = neomake#create_maker_object(maker, &filetype) + return [maker.name . (empty(source) ? '' : ' ('.source.')')] + \ + s:get_maker_info(maker) +endfunction + +function! neomake#debug#display_info(...) abort + let bang = a:0 ? a:1 : 0 + if a:0 > 1 + let maker_name = a:2 + let lines = neomake#debug#get_maker_info(maker_name) + else + let lines = neomake#debug#_get_info_lines() + endif + if bang + try + call setreg('+', join(lines, "\n"), 'l') + catch + call neomake#log#error(printf( + \ 'Could not set clipboard: %s.', v:exception)) + return + endtry + echom 'Copied Neomake info to clipboard ("+).' + else + echon join(lines, "\n") + endif +endfunction + +function! s:trim(s) abort + return substitute(a:s, '\v^[ \t\r\n]+|[ \t\r\n]+$', '', 'g') +endfunction + +function! neomake#debug#_get_info_lines() abort + let r = [] + let ft = &filetype + + let r += ['#### Neomake debug information'] + let r += [''] + let r += ['Async support: '.neomake#has_async_support()] + let r += ['Current filetype: '.ft] + let r += ['Windows: '.neomake#utils#IsRunningWindows()] + let r += ['[shell, shellcmdflag, shellslash]: '.string([&shell, &shellcmdflag, &shellslash])] + let r += [join(map(split(neomake#utils#redir('verb set makeprg?'), '\n'), 's:trim(v:val)'), ', ')] + + let r += [''] + let r += ['##### Enabled makers'] + let r += [''] + let r += ['For the current filetype ("'.ft.'", used with :Neomake):'] + let r += s:get_makers_info(ft) + if empty(ft) + let r += ['NOTE: the current buffer does not have a filetype.'] + else + let conf_ft = neomake#utils#get_ft_confname(ft) + let r += ['NOTE: you can define g:neomake_'.conf_ft.'_enabled_makers' + \ .' to configure it (or b:neomake_'.conf_ft.'_enabled_makers).'] + endif + let r += [''] + let r += ['For the project (used with :Neomake!):'] + let r += s:get_makers_info() + let r += ['NOTE: you can define g:neomake_enabled_makers to configure it.'] + let r += [''] + let r += ['Default maker settings:'] + for [k, v] in items(neomake#config#get('maker_defaults')) + let r += [' - '.k.': '.string(v)] + unlet! v " Fix variable type mismatch with Vim 7.3. + endfor + let r += [''] + let r += ['##### Settings'] + let r += [''] + let r += ['###### New-style (dict, overrides old-style)'] + let r += [''] + let r += ['```'] + + let r += ['g:neomake: '.(exists('g:neomake') ? s:pprint(g:neomake) : 'unset')] + let r += ['b:neomake: '.(exists('b:neomake') ? s:pprint(b:neomake) : 'unset')] + let r += ['```'] + let r += [''] + let r += ['###### Old-style'] + let r += [''] + let r += ['```'] + for [k, V] in sort(items(filter(copy(g:), "v:key =~# '^neomake_'"))) + let r += ['g:'.k.' = '.string(V)] + unlet! V " Fix variable type mismatch with Vim 7.3. + endfor + let r += [''] + let r += ['```'] + let r += ["\n"] + let r += ['#### :version'] + let r += [''] + let r += ['```'] + let r += split(neomake#utils#redir('version'), '\n') + let r += ['```'] + let r += [''] + let r += ['#### :messages'] + let r += [''] + let r += ['```'] + let r += split(neomake#utils#redir('messages'), '\n') + let r += ['```'] + return r +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/highlights.vim b/.vim/autoload/neomake/highlights.vim new file mode 100644 index 0000000..cdc416a --- /dev/null +++ b/.vim/autoload/neomake/highlights.vim @@ -0,0 +1,155 @@ +" vim: ts=4 sw=4 et + +let s:highlights = {'file': {}, 'project': {}} +let s:highlight_types = { + \ 'E': 'NeomakeError', + \ 'W': 'NeomakeWarning', + \ 'I': 'NeomakeInfo', + \ 'M': 'NeomakeMessage' + \ } + +let s:nvim_api = exists('*nvim_buf_add_highlight') + +" Used in tests. +function! neomake#highlights#_get() abort + return s:highlights +endfunction + +if s:nvim_api + function! s:InitBufHighlights(type, buf) abort + if !bufexists(a:buf) + " The buffer might be wiped by now: prevent 'Invalid buffer id'. + return + endif + if has_key(s:highlights[a:type], a:buf) + call nvim_buf_clear_highlight(a:buf, s:highlights[a:type][a:buf], 0, -1) + else + let s:highlights[a:type][a:buf] = nvim_buf_add_highlight(a:buf, 0, '', 0, 0, -1) + endif + endfunction + + function! s:reset(type, buf) abort + if has_key(s:highlights[a:type], a:buf) + call nvim_buf_clear_highlight(a:buf, s:highlights[a:type][a:buf], 0, -1) + unlet s:highlights[a:type][a:buf] + endif + endfunction +else + function! s:InitBufHighlights(type, buf) abort + let s:highlights[a:type][a:buf] = { + \ 'NeomakeError': [], + \ 'NeomakeWarning': [], + \ 'NeomakeInfo': [], + \ 'NeomakeMessage': [] + \ } + endfunction + + function! s:reset(type, buf) abort + if has_key(s:highlights[a:type], a:buf) + unlet s:highlights[a:type][a:buf] + call neomake#highlights#ShowHighlights() + endif + endfunction +endif + +function! neomake#highlights#ResetFile(buf) abort + call s:reset('file', a:buf) +endfunction +function! neomake#highlights#ResetProject(...) abort + if a:0 " deprecated a:buf + call neomake#log#warn_once('neomake#highlights#ResetProject does not use a:buf anymore.', + \ 'deprecated-highlight-resetproject') + endif + for buf in keys(s:highlights['project']) + call s:reset('project', +buf) + endfor +endfunction + +function! neomake#highlights#AddHighlight(entry, type) abort + " Some makers use line 0 for file warnings (which cannot be highlighted, + " e.g. cpplint with "no copyright" warnings). + if a:entry.lnum == 0 + return + endif + + if !has_key(s:highlights[a:type], a:entry.bufnr) + call s:InitBufHighlights(a:type, a:entry.bufnr) + endif + let hi = get(s:highlight_types, toupper(a:entry.type), 'NeomakeError') + + if a:entry.col > 0 && get(g:, 'neomake_highlight_columns', 1) + let length = get(a:entry, 'length', 1) + if s:nvim_api + call nvim_buf_add_highlight(a:entry.bufnr, s:highlights[a:type][a:entry.bufnr], hi, a:entry.lnum - 1, a:entry.col - 1, a:entry.col + length - 1) + else + call add(s:highlights[a:type][a:entry.bufnr][hi], [a:entry.lnum, a:entry.col, length]) + endif + elseif get(g:, 'neomake_highlight_lines', 0) + if s:nvim_api + call nvim_buf_add_highlight(a:entry.bufnr, s:highlights[a:type][a:entry.bufnr], hi, a:entry.lnum - 1, 0, -1) + else + call add(s:highlights[a:type][a:entry.bufnr][hi], a:entry.lnum) + endif + endif +endfunction + +if s:nvim_api + function! neomake#highlights#ShowHighlights() abort + endfunction +else + function! neomake#highlights#ShowHighlights() abort + if exists('w:neomake_highlights') + for highlight in w:neomake_highlights + try + call matchdelete(highlight) + catch /^Vim\%((\a\+)\)\=:E803/ + endtry + endfor + endif + let w:neomake_highlights = [] + + let buf = bufnr('%') + for type in ['file', 'project'] + for [hi, locs] in items(filter(copy(get(s:highlights[type], buf, {})), '!empty(v:val)')) + if exists('*matchaddpos') + call add(w:neomake_highlights, matchaddpos(hi, locs)) + else + for loc in locs + if len(loc) == 1 + call add(w:neomake_highlights, matchadd(hi, '\%' . loc[0] . 'l')) + else + call add(w:neomake_highlights, matchadd(hi, '\%' . loc[0] . 'l\%' . loc[1] . 'c.\{' . loc[2] . '}')) + endif + endfor + endif + endfor + endfor + endfunction +endif + +function! neomake#highlights#DefineHighlights() abort + for [group, link] in items({ + \ 'NeomakeError': 'SpellBad', + \ 'NeomakeWarning': 'SpellCap', + \ 'NeomakeInfo': 'NeomakeWarning', + \ 'NeomakeMessage': 'NeomakeWarning' + \ }) + if !neomake#utils#highlight_is_defined(group) + exe 'highlight link '.group.' '.link + endif + endfor +endfunction + +function! s:wipe_highlights(bufnr) abort + for type in ['file', 'project'] + if has_key(s:highlights[type], a:bufnr) + unlet s:highlights[type][a:bufnr] + endif + endfor +endfunction +augroup neomake_highlights + au! + autocmd BufWipeout * call s:wipe_highlights(expand('<abuf>')) +augroup END + +call neomake#highlights#DefineHighlights() diff --git a/.vim/autoload/neomake/jobinfo.vim b/.vim/autoload/neomake/jobinfo.vim new file mode 100644 index 0000000..278a3f5 --- /dev/null +++ b/.vim/autoload/neomake/jobinfo.vim @@ -0,0 +1,87 @@ +let s:jobinfo_base = { + \ 'cd_back_cmd': '', + \ 'pending_output': [], + \ } +function! s:jobinfo_base.get_pid() abort + if has_key(self, 'vim_job') + let info = job_info(self.vim_job) + if info.status ==# 'run' + return info.process + endif + return -1 + endif + try + return jobpid(self.nvim_job) + catch /^Vim(return):E900:/ + return -1 + endtry +endfunction + +function! s:jobinfo_base.as_string() abort + let extra = [] + for k in ['canceled', 'finished'] + if get(self, k, 0) + let extra += [k] + endif + endfor + return printf('Job %d: %s%s', self.id, self.name, + \ empty(extra) ? '' : ' ['.join(extra, ', ').']') +endfunction + +function! s:jobinfo_base.cd_back() abort + if !empty(self.cd_back_cmd) + exe self.cd_back_cmd + let self.cd_back_cmd = '' + endif +endfunction + +function! s:jobinfo_base.cd(...) abort + if a:0 + if has_key(self, 'cd_from_setting') + call neomake#log#debug(printf( + \ 'jobinfo.cd(): keeping cwd from setting: %s.', + \ string(self.cd_from_setting)), self) + return '' + endif + let dir = a:1 + else + let maker = self.maker + let dir = neomake#utils#GetSetting('cwd', maker, '', self.ft, self.bufnr, 1) + if !empty(dir) + let self.cd_from_setting = dir + endif + endif + + if dir !=# '' + if dir[0:1] ==# '%:' + let dir = neomake#utils#fnamemodify(self.bufnr, dir[1:]) + else + let dir = expand(dir, 1) + endif + let dir = fnamemodify(dir, ':p') + " NOTE: need to keep trailing backslash with "/" and "X:\" on Windows. + if dir !=# '/' && dir[-1:] ==# neomake#utils#Slash() && dir[-2] !=# ':' + let dir = dir[:-2] + endif + else + let dir = get(self, 'cwd', $HOME) + endif + + let cur_wd = getcwd() + if dir !=# cur_wd + let [cd_error, cd_back_cmd] = neomake#utils#temp_cd(dir, cur_wd) + if !empty(cd_error) + call neomake#log#debug(printf('jobinfo.cd(): error when trying to change cwd to %s: %s.', + \ dir, cd_error)) + return cd_error + endif + let self.cwd = dir + let self.cd_back_cmd = cd_back_cmd + else + let self.cwd = cur_wd + endif + return '' +endfunction + +let g:neomake#jobinfo#base = s:jobinfo_base +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/list.vim b/.vim/autoload/neomake/list.vim new file mode 100644 index 0000000..120b665 --- /dev/null +++ b/.vim/autoload/neomake/list.vim @@ -0,0 +1,1020 @@ +scriptencoding utf-8 +" Create a List object from a quickfix/location list. +" TODO: (optionally?) add entries sorted? (errors first, grouped by makers (?) etc) + +let s:can_set_qf_title = has('patch-7.4.2200') +let s:can_set_qf_context = has('patch-8.0.0590') +let s:can_set_qf_items = has('patch-8.0.0657') +let s:has_support_for_qfid = has('patch-8.0.1023') +let s:use_efm_parsing = has('patch-8.0.1040') " 'efm' in setqflist/getqflist + +" Do we need to replace (instead of append) the location/quickfix list, for +" :lwindow to not open it with only invalid entries?! +" Without patch-7.4.379 this does not work though, and a new list needs to +" be created (which is not done). +" @vimlint(EVL108, 1) +let s:needs_to_replace_qf_for_lwindow = has('patch-7.4.379') + \ && (!has('patch-7.4.1752') || (has('nvim') && !has('nvim-0.2.0'))) +" @vimlint(EVL108, 0) +let s:needs_to_init_qf_for_lwindow = !has('patch-8.1.0622') + +function! neomake#list#ListForMake(make_info) abort + let type = a:make_info.options.file_mode ? 'loclist' : 'quickfix' + let list = neomake#list#List(type) + let list.make_info = a:make_info + if type ==# 'loclist' + let info = get(w:, '_neomake_info', {}) + let info['loclist'] = list + let w:_neomake_info = info + else + let info = get(g:, '_neomake_info', {}) + let info['qflist'] = list + let g:_neomake_info = info + endif + return list +endfunction + +" a:type: "loclist" or "quickfix" +function! neomake#list#List(type) abort + let list = deepcopy(s:base_list) + let list.type = a:type + " Display debug messages about changed entries. + let list.debug = get(g:, 'neomake_debug_list', + \ exists('g:neomake_test_messages') + \ || !empty(get(g:, 'neomake_logfile')) + \ || neomake#utils#get_verbosity() >= 3) + return list +endfunction + +" Internal base list implementation. +let s:base_list = { + \ 'need_init': 1, + \ 'entries': [], + \ } +" Info about contained jobs. +let s:base_list.job_entries = {} +let s:base_list.maker_info_by_jobid = {} + +function! s:base_list.sort_by_location() dict abort + let entries = get(self, '_sorted_entries_by_location', copy(self.entries)) + let self._sorted_entries_by_location = sort(entries, 's:cmp_listitem_loc') + return self._sorted_entries_by_location +endfunction + +" a:1: optional jobinfo +function! s:base_list.add_entries(entries, ...) dict abort + let idx = len(self.entries) + if a:0 && !has_key(self.job_entries, a:1.id) + let self.job_entries[a:1.id] = [] + let self.maker_info_by_jobid[a:1.id] = a:1.maker + endif + for entry in a:entries + let idx += 1 + let e = extend(copy(entry), {'nmqfidx': idx}) + if a:0 + call add(self.job_entries[a:1.id], e) + let e.job_id = a:1.id + endif + call add(self.entries, e) + endfor + if self.debug + let indexes = map(copy(self.entries), 'v:val.nmqfidx') + if len(neomake#compat#uniq(sort(copy(indexes)))) != len(indexes) + call neomake#log#error(printf('Duplicate qf indexes in list entries: %s.', + \ string(indexes))) + endif + endif + " Sort if it was sorted before. + if has_key(self, '_sorted_entries_by_location') + call extend(self._sorted_entries_by_location, a:entries) + call self.sort_by_location() + endif +endfunction + +" Add entries for a job (non-efm method). +function! s:base_list.add_entries_for_job(entries, jobinfo) dict abort + let tempfiles = get(self.make_info, 'tempfiles', []) + if !empty(tempfiles) + let mapped = 0 + for e in a:entries + if has_key(e, 'filename') && get(e, 'bufnr', 0) == 0 + if index(tempfiles, e.filename) != -1 + unlet e.filename + let e.bufnr = a:jobinfo.bufnr + let mapped += 1 + endif + endif + endfor + if mapped + call neomake#log#debug(printf('Mapped %d bufnrs from temporary files.', mapped), a:jobinfo) + endif + endif + return self._appendlist(a:entries, a:jobinfo) +endfunction + +function! neomake#list#get_title(prefix, bufnr, maker_info) abort + let prefix = 'Neomake' + if !empty(a:prefix) + let prefix .= '['.a:prefix.']' + endif + if a:bufnr + let bufname = bufname(a:bufnr) + if empty(bufname) + let bufname = 'buf:'.a:bufnr + else + let bufname = pathshorten(bufname) + endif + let maker_info = bufname + if empty(a:maker_info) + let maker_info = bufname + else + let maker_info = bufname.' ('.a:maker_info.')' + endif + else + let maker_info = a:maker_info + endif + let title = prefix + if !empty(maker_info) + let title = prefix.': '.maker_info + endif + return title +endfunction + +function! s:base_list._get_title() abort + let maker_info = [] + for job in self.make_info.finished_jobs + let info = job.maker.name + let ok = 1 + if get(job, 'aborted', 0) + let info .= '!' + let ok = 0 + endif + if has_key(self.job_entries, job.id) + let c = len(self.job_entries[job.id]) + let info .= '('.c.')' + let ok = 0 + endif + if ok + let info .= '✓' + endif + call add(maker_info, info) + endfor + for job in self.make_info.active_jobs + let info = job.maker.name + let info .= '...' + if has_key(self.job_entries, job.id) + let c = len(self.job_entries[job.id]) + let info .= '('.c.')' + endif + call add(maker_info, info) + endfor + for job in self.make_info.jobs_queue + let info = job.maker.name + let info .= '?' + call add(maker_info, info) + endfor + for job in get(self.make_info, 'aborted_jobs', []) + let info = job.maker.name + let info .= '-' + call add(maker_info, info) + endfor + let maker_info_str = join(maker_info, ', ') + if self.type ==# 'loclist' + let bufnr = self.make_info.options.bufnr + else + let bufnr = 0 + endif + if get(self.make_info.options, 'automake') + let prefix = 'auto' + elseif self.make_info.options.file_mode + let prefix = 'file' + else + let prefix = 'project' + endif + return neomake#list#get_title(prefix, bufnr, maker_info_str) +endfunction + +function! s:base_list.finish_for_make() abort + if self.need_init + if self.type ==# 'loclist' + call neomake#log#debug('Cleaning location list.', self.make_info) + else + call neomake#log#debug('Cleaning quickfix list.', self.make_info) + endif + call self._call_qf_fn('set', [], ' ') + else + " Set title, but only if list window is still valid. + if s:has_support_for_qfid + let valid = self._has_valid_qf() + elseif self.type ==# 'loclist' + let valid = self._get_loclist_win(1) != -1 + else + let valid = 1 + endif + if !valid + call neomake#log#debug('list: finish: list is not valid anymore.', self.make_info) + return + endif + call self.set_title() + endif +endfunction + +function! s:base_list._call_qf_fn(action, ...) abort + let fns_args = call(self._get_fn_args, [a:action] + a:000, self) + + if a:action ==# 'get' + let [fn, args] = fns_args[0] + if s:has_support_for_qfid + let args[-1].items = 1 + if self.debug + call neomake#log#debug(printf('list: call: "get", returning items: %s.', string(fns_args))) + endif + return call(fn, args).items + endif + if self.debug + call neomake#log#debug(printf('list: call: "get": %s.', string(fns_args))) + endif + return call(fn, args) + endif + + for fns in fns_args + let [fn, args] = fns + + if self.debug + if a:action ==# 'set' + let log_args = deepcopy(args) + " Only display 5 items. + if self.type ==# 'loclist' + let log_args[1] = neomake#utils#shorten_list_for_log(log_args[1], 5) + else + let log_args[0] = neomake#utils#shorten_list_for_log(log_args[0], 5) + endif + " Massage options dict. + if type(log_args[-1]) == type({}) + let neomake_context = get(get(log_args[-1], 'context', {}), 'neomake', {}) + if !empty(neomake_context) + for [k, v] in items(neomake_context) + if k ==# 'make_info' + " Fixes self-ref, and makes it much shorter. + let neomake_context[k] = 'make_id='.v.make_id + endif + endfor + endif + " Only display 5 items. + if has_key(log_args[-1], 'items') + let log_args[-1].items = neomake#utils#shorten_list_for_log(log_args[-1].items, 5) + endif + endif + call neomake#log#debug(printf('list: call: set: %s.', string(log_args))) + else + call neomake#log#debug(printf('list: call: "%s": %s.', a:action, string(args))) + endif + endif + + call call(fn, args, self) + endfor + + " Get qfid. + if self.need_init + if a:action ==# 'set' && s:has_support_for_qfid + if self.type ==# 'loclist' + let loclist_win = self._get_loclist_win() + let self.qfid = getloclist(loclist_win, {'id': 0}).id + else + let self.qfid = getqflist({'id': 0}).id + endif + if self.debug + call neomake#log#debug(printf('list: got qfid (action=%s): %s.', a:action, self.qfid)) + endif + endif + let self.need_init = 0 + endif +endfunction + +function! s:base_list.set_title() abort + if s:can_set_qf_title + call self._call_qf_fn('title', self._get_title()) + endif +endfunction + +" Check if quickfix list is still valid, which might not be the case anymore +" if more than 10 new lists have been opened etc. +" Returns -1 without suffort for quickfix ids. +function! s:base_list._has_valid_qf() abort + if !s:has_support_for_qfid + return -1 + endif + + if self.type ==# 'loclist' + let loclist_win = self._get_loclist_win(1) + if loclist_win is -1 + return 0 + endif + if !get(getloclist(loclist_win, {'id': self.qfid}), 'id') + return 0 + endif + else + if !get(getqflist({'id': self.qfid}), 'id') + return 0 + endif + endif + return 1 +endfunction + +" Get winnr/winid to be used with loclist functions. +" a:1: return -1 instead of throwing when no window could be found? +function! s:base_list._get_loclist_win(...) abort + if !has_key(self, 'make_info') + throw 'cannot handle type=loclist without make_info' + endif + let loclist_win = 0 + let make_id = self.make_info.make_id + " NOTE: prefers using 0 for when winid is not supported with + " setloclist() yet (vim74-xenial). + if index(get(w:, 'neomake_make_ids', []), make_id) == -1 + if has_key(self.make_info.options, 'winid') + let loclist_win = self.make_info.options.winid + else + let [t, w] = neomake#core#get_tabwin_for_makeid(make_id) + if [t, w] == [-1, -1] + if a:0 && a:1 + return -1 + endif + throw printf('Neomake: could not find location list for make_id %d.', make_id) + endif + if t != tabpagenr() + if a:0 && a:1 + return -1 + endif + throw printf('Neomake: trying to use location list from another tab (current=%d != target=%d).', tabpagenr(), t) + endif + let loclist_win = w + endif + endif + return loclist_win +endfunction + +" Return a list of commands to be called. +" action: "get", "set", "init", "title" +" a:000: optional args (for set/init/title) +function! s:base_list._get_fn_args(action, ...) abort + if self.type ==# 'loclist' + if a:action ==# 'get' + let fn = 'getloclist' + else + let fn = 'setloclist' + endif + else + if a:action ==# 'get' + let fn = 'getqflist' + else + let fn = 'setqflist' + endif + endif + + if self.type ==# 'loclist' + let args = [self._get_loclist_win()] + else + let args = [] + endif + + let options = {} + if !self.need_init + let valid = self._has_valid_qf() + if valid == 1 + let options.id = self.qfid + elseif valid == 0 + if self.type ==# 'loclist' + let loclist_win = args[0] + throw printf('Neomake: qfid %d for location list (%d) has become invalid.', self.qfid, loclist_win) + else + throw printf('Neomake: qfid %d for quickfix list has become invalid.', self.qfid) + endif + endif + endif + + if a:action ==# 'title' + call extend(args, [[], 'a']) + if exists('*vader#assert#true') + call vader#assert#true(s:can_set_qf_title) + endif + let options.title = a:1 + else + call extend(args, a:000) + if a:action ==# 'set' + if exists('*vader#assert#equal') + call vader#assert#equal(len(a:000), 2) + endif + if s:can_set_qf_items + let options.items = a:1 + let args[-2] = [] + endif + endif + endif + if !empty(options) + call add(args, options) + endif + + let r = [] + if a:action ==# 'set' + if self.need_init && get(self, 'reset_existing_qflist') + if self.type ==# 'loclist' + let args[2] = 'r' " action + else + let args[1] = 'r' " action + endif + if self.type ==# 'loclist' + let msg = 'Reusing location list for entries.' + else + let msg = 'Reusing quickfix list for entries.' + endif + call neomake#log#debug(msg, self.make_info) + endif + + " Experimental: set make_info into context. + " This is used to access make info from the qf window itself. + if self.need_init && s:can_set_qf_context + let options.context = {'neomake': {'make_info': self.make_info}} + endif + + " Handle setting title, which gets done initially and when maker + " names are updated. This has to be done in a separate call + " without patch-8.0.0657. + if s:can_set_qf_title + let title = self._get_title() + if s:can_set_qf_items + if type(args[-1]) != type({}) + call add(args, {'title': title, 'items': args[1]}) + else + let args[-1].title = title + endif + else + " Update title after actual call. + call add(r, [fn, args]) + + if self.type ==# 'loclist' + let args = [args[0], [], 'a', {'title': title}] + else + let args = [[], 'a', {'title': title}] + endif + endif + endif + endif + call add(r, [fn, args]) + return r +endfunction + +function! s:mark_entry_with_nmcfg(entry, maker_info) abort + let maker_name = a:maker_info.name + let config = { + \ 'name': maker_name, + \ 'short': get(a:maker_info, 'short_name', maker_name[:3]), + \ } + let marker_entry = copy(a:entry) + let marker_entry.text .= printf(' nmcfg:%s', string(config)) + return marker_entry +endfunction + +function! s:base_list._replace_qflist_entries(entries) abort + let set_entries = a:entries + + " Handle nmcfg markers when setting all entries without jobinfo. + if neomake#quickfix#is_enabled() + let set_entries = copy(set_entries) + let prev_job_id = 0 + + " Handle re-setting all entries. This is meant to be used later + " for replacing the whole list. + let i = 0 + for e in set_entries + if e.job_id != prev_job_id + let maker_info = self.maker_info_by_jobid[e.job_id] + let set_entries[i] = s:mark_entry_with_nmcfg(e, maker_info) + let prev_job_id = e.job_id + endif + let i += 1 + endfor + endif + + call self._set_qflist_entries(set_entries, 'r') +endfunction + +function! s:base_list._set_qflist_entries(entries, action) abort + let action = a:action + if self.need_init && !get(self, 'reset_existing_qflist') + if self.type ==# 'loclist' + let msg = 'Creating location list for entries.' + else + let msg = 'Creating quickfix list for entries.' + endif + call neomake#log#debug(msg, self.make_info) + + if s:needs_to_init_qf_for_lwindow + " Clean list without autocommands (customqf etc) to avoid + " flicker. This is only to work around a Vim bug anyway. + noautocmd call self._call_qf_fn('set', [], ' ') + else + let action = ' ' + endif + endif + call self._call_qf_fn('set', a:entries, action) +endfunction + +function! s:base_list._get_qflist_entries() abort + return self._call_qf_fn('get') +endfunction + +" Append entries to location/quickfix list. +function! s:base_list._appendlist(entries, jobinfo) abort + call neomake#log#debug(printf('Adding %d list entries.', len(a:entries)), self.make_info) + + let set_entries = a:entries + let action = 'a' + if !self.need_init + let action = 'a' + if s:needs_to_replace_qf_for_lwindow || neomake#quickfix#is_enabled() + " Need to replace whole list with customqf to trigger FileType + " autocmd (which is not done for action='a'). + " This should be enhanced to only format new entries instead + " later, but needs support for changing non-current buffer lines. + let action = 'r' + if self.type ==# 'loclist' + let set_entries = self._get_qflist_entries() + set_entries + else + let set_entries = getqflist() + set_entries + endif + endif + endif + + " Add marker for custom quickfix to the first (new) entry. + let needs_custom_qf_marker = neomake#quickfix#is_enabled() + if needs_custom_qf_marker + if action ==# 'a' + let prev_idx = 0 + else + let prev_idx = len(self.entries) + endif + let set_entries = copy(set_entries) + let set_entries[prev_idx] = s:mark_entry_with_nmcfg(set_entries[prev_idx], a:jobinfo.maker) + endif + + " NOTE: need to fetch (or pre-parse with new patch) to get updated bufnr etc. + call self._set_qflist_entries(set_entries, action) + let added = self._get_qflist_entries()[len(self.entries) :] + + if needs_custom_qf_marker + " Remove marker that should only be in the quickfix list. + let added[0].text = substitute(added[0].text, ' nmcfg:{.\{-}}$', '', '') + endif + + if self.debug && added != a:entries + let diff = neomake#list#_diff_new_entries(a:entries, added) + if !empty(diff) + for [k, v] in items(diff) + " TODO: handle valid=1 being added? + call neomake#log#debug(printf( + \ 'Entry %d differs after adding: %s.', + \ k+1, + \ string(v)), + \ a:jobinfo) + endfor + endif + endif + + let parsed_entries = copy(a:entries) + let idx = 0 + for e in added + if parsed_entries[idx].bufnr != e.bufnr + call neomake#log#debug(printf( + \ 'Updating entry bufnr: %s => %s.', + \ a:entries[idx].bufnr, e.bufnr)) + let parsed_entries[idx].bufnr = e.bufnr + endif + let idx += 1 + endfor + + call self.add_entries(parsed_entries, a:jobinfo) + return parsed_entries +endfunction + +function! neomake#list#_diff_new_entries(orig, new) abort + if a:orig == a:new + return {} + endif + let i = 0 + let r = {} + for new in a:new + let orig = copy(get(a:orig, i, {})) + for [k, v] in items({'pattern': '', 'module': '', 'valid': 1}) + if has_key(new, k) + let orig[k] = v + endif + endfor + if new != orig + " 'removed': {'length': 4, 'filename': 'from.rs', + " 'maker_name': 'cargo'}} + let new = copy(new) + for k in ['length', 'maker_name'] + if has_key(orig, k) + let new[k] = orig[k] + endif + endfor + let diff = neomake#utils#diff_dict(orig, new) + if !empty(diff) + let r[i] = diff + endif + endif + let i += 1 + endfor + return r +endfunction + +" Add raw lines using errorformat. +" This either pre-parses them with newer versions, or uses +" :laddexpr/:caddexpr. +function! s:base_list.add_lines_with_efm(lines, jobinfo) dict abort + let maker = a:jobinfo.maker + let file_mode = self.type ==# 'loclist' + + if s:use_efm_parsing + let efm = a:jobinfo.maker.errorformat + let parsed_entries = get(getqflist({'lines': a:lines, 'efm': efm}), 'items', -1) + if parsed_entries is -1 + call neomake#log#error(printf('Failed to get items via efm-parsing. Invalid errorformat? (%s)', efm), a:jobinfo) + let parsed_entries = getqflist({'lines': a:lines, 'efm': &errorformat}).items + endif + if empty(parsed_entries) + return [] + endif + else + if self.need_init + if self.type ==# 'loclist' + let msg = 'Creating location list.' + else + let msg = 'Creating quickfix list.' + endif + call neomake#log#debug(msg, self.make_info) + call self._call_qf_fn('set', [], ' ') + endif + let olderrformat = &errorformat + try + let &errorformat = maker.errorformat + catch + call neomake#log#error(printf('Failed to set errorformat (%s): %s.', string(maker.errorformat), v:exception), a:jobinfo) + endtry + try + if file_mode + let cmd = 'laddexpr' + else + let cmd = 'caddexpr' + endif + let a:jobinfo._delayed_qf_autocmd = 'QuickfixCmdPost '.cmd + let cmd = 'noautocmd '.cmd.' a:lines' + if self.debug + call neomake#log#debug(printf('list: exe: %s (with %d lines).', cmd, len(a:lines)), a:jobinfo) + endif + exe cmd + finally + let &errorformat = olderrformat + call a:jobinfo.cd_back() + endtry + + let new_list = self._get_qflist_entries() + let parsed_entries = new_list[len(self.entries) :] + if empty(parsed_entries) + return [] + endif + endif + + let l:Postprocess = neomake#utils#GetSetting('postprocess', maker, [], a:jobinfo.ft, a:jobinfo.bufnr) + if type(Postprocess) != type([]) + let postprocessors = [Postprocess] + else + let postprocessors = Postprocess + endif + + let default_type = 'unset' + + let entries = [] + let changed_entries = {} + let removed_entries = [] + let different_bufnrs = {} + let bufnr_from_temp = {} + let bufnr_from_stdin = {} + let tempfile_bufnrs = has_key(self.make_info, 'tempfiles') ? map(copy(self.make_info.tempfiles), 'bufnr(v:val)') : [] + let uses_stdin = get(a:jobinfo, 'uses_stdin', 0) + + let entry_idx = -1 + for entry in parsed_entries + let entry_idx += 1 + let before = copy(entry) + " Handle unlisted buffers via tempfiles and uses_stdin. + if entry.bufnr && entry.bufnr != a:jobinfo.bufnr + \ && (!empty(tempfile_bufnrs) || uses_stdin) + let map_bufnr = index(tempfile_bufnrs, entry.bufnr) + if map_bufnr != -1 + let entry.bufnr = a:jobinfo.bufnr + let map_bufnr = tempfile_bufnrs[map_bufnr] + if !has_key(bufnr_from_temp, map_bufnr) + let bufnr_from_temp[map_bufnr] = [] + endif + let bufnr_from_temp[map_bufnr] += [entry_idx+1] + elseif uses_stdin + if !buflisted(entry.bufnr) && bufexists(entry.bufnr) + if !has_key(bufnr_from_stdin, entry.bufnr) + let bufnr_from_stdin[entry.bufnr] = [] + endif + let bufnr_from_stdin[entry.bufnr] += [entry_idx+1] + let entry.bufnr = a:jobinfo.bufnr + endif + endif + endif + if self.debug && entry.bufnr && entry.bufnr != a:jobinfo.bufnr + if !has_key(different_bufnrs, entry.bufnr) + let different_bufnrs[entry.bufnr] = 1 + else + let different_bufnrs[entry.bufnr] += 1 + endif + endif + if !empty(postprocessors) + let g:neomake_postprocess_context = {'jobinfo': a:jobinfo} + try + for l:F in postprocessors + if type(F) == type({}) + call call(F.fn, [entry], F) + else + call call(F, [entry], maker) + endif + unlet! F " vim73 + endfor + finally + unlet! g:neomake_postprocess_context " Might be unset already with sleep in postprocess. + endtry + endif + if entry != before + let changed_entries[entry_idx] = entry + if self.debug + " Ignore bufnr changes for tempfiles/stdin (logged together + " later). + let diff = neomake#utils#diff_dict(before, entry) + let changed_bufnr = get(get(diff, 'changed', {}), 'bufnr', []) + if !empty(changed_bufnr) && ( + \ has_key(bufnr_from_temp, changed_bufnr[0]) + \ || has_key(bufnr_from_stdin, changed_bufnr[0])) + unlet diff.changed.bufnr + if empty(diff.changed) + unlet diff.changed + endif + endif + if !empty(diff) + call neomake#log#debug(printf( + \ 'Modified list entry %d (postprocess): %s.', + \ entry_idx + 1, + \ substitute(string(diff), '\n', '\\n', 'g')), + \ a:jobinfo) + endif + endif + endif + + if entry.valid <= 0 + if entry.valid < 0 || maker.remove_invalid_entries + call insert(removed_entries, entry_idx) + let entry_copy = copy(entry) + call neomake#log#debug(printf( + \ 'Removing invalid entry: %s (%s).', + \ remove(entry_copy, 'text'), + \ string(entry_copy)), a:jobinfo) + continue + endif + endif + + if empty(entry.type) && entry.valid + if default_type ==# 'unset' + let default_type = neomake#utils#GetSetting('default_entry_type', maker, 'W', a:jobinfo.ft, a:jobinfo.bufnr) + endif + if !empty(default_type) + let entry.type = default_type + let changed_entries[entry_idx] = entry + endif + endif + call add(entries, entry) + endfor + + if !s:use_efm_parsing + let new_index = len(self.entries) + " Add marker for custom quickfix to the first (new) entry. + if neomake#quickfix#is_enabled() + let changed_entries[0] = s:mark_entry_with_nmcfg(entries[0], maker) + endif + + if !empty(changed_entries) || !empty(removed_entries) + " Need to update/replace current list. + let list = self._get_qflist_entries() + if !empty(changed_entries) + for k in keys(changed_entries) + let list[new_index + k] = changed_entries[k] + endfor + endif + if !empty(removed_entries) + for k in removed_entries + call remove(list, new_index + k) + endfor + endif + call self._set_qflist_entries(list, 'r') + endif + endif + + if !empty(bufnr_from_temp) || !empty(bufnr_from_stdin) + if !has_key(self.make_info, '_wipe_unlisted_buffers') + let self.make_info._wipe_unlisted_buffers = [] + endif + let self.make_info._wipe_unlisted_buffers += keys(bufnr_from_stdin) + keys(bufnr_from_stdin) + if !empty(bufnr_from_temp) + for [tempbuf, entries_idx] in items(bufnr_from_temp) + let log_entries_idx = join(neomake#utils#shorten_list_for_log(entries_idx, 50), ', ') + call neomake#log#debug(printf( + \ 'Used bufnr from temporary buffer %d (%s) for %d entries: %s.', + \ tempbuf, + \ bufname(+tempbuf), + \ len(entries_idx), + \ log_entries_idx), a:jobinfo) + endfor + endif + if !empty(bufnr_from_stdin) + for [tempbuf, entries_idx] in items(bufnr_from_stdin) + let log_entries_idx = join(neomake#utils#shorten_list_for_log(entries_idx, 50), ', ') + call neomake#log#debug(printf( + \ 'Used bufnr from stdin buffer %d (%s) for %d entries: %s.', + \ tempbuf, + \ bufname(+tempbuf), + \ len(entries_idx), + \ log_entries_idx), a:jobinfo) + endfor + endif + endif + if !empty(different_bufnrs) + call neomake#log#debug(printf('WARN: seen entries with bufnr different from jobinfo.bufnr (%d): %s, current bufnr: %d.', a:jobinfo.bufnr, string(different_bufnrs), bufnr('%'))) + endif + + if empty(entries) + return [] + endif + + if s:use_efm_parsing + call self._appendlist(entries, a:jobinfo) + else + call self.add_entries(entries, a:jobinfo) + endif + return entries +endfunction + +" Get the current location or quickfix list. +function! neomake#list#get() abort + let winnr = winnr() + let win_info = neomake#compat#getwinvar(winnr, '_neomake_info', {}) + if has_key(win_info, 'loclist') + return win_info['loclist'] + endif + let info = get(g:, '_neomake_info', {}) + if has_key(info, 'qflist') + return info['qflist'] + endif + return {} +endfunction + +function! neomake#list#get_loclist(...) abort + let winnr = a:0 ? a:1 : winnr() + let info = neomake#compat#getwinvar(winnr, '_neomake_info', {}) + if !has_key(info, 'loclist') + " Create a new list, not bound to a job. + call neomake#log#debug('Creating new List object.') + let list = neomake#list#List('loclist') + call list.add_entries(getloclist(winnr)) + let info['loclist'] = list + call setwinvar(winnr, '_neomake_info', info) + endif + return info['loclist'] +endfunction + +" TODO: save project-maker quickfix list. +function! neomake#list#get_qflist() abort + let info = get(g:, '_neomake_info', {}) + if !has_key(info, 'qflist') + " Create a new list, not bound to a job. + call neomake#log#debug('Creating new List object.') + let list = neomake#list#List('quickfix') + call list.add_entries(getqflist()) + let info['qflist'] = list + let g:_neomake_info = info + endif + return info['qflist'] +endfunction + +function! s:get_list(file_mode) abort + if a:file_mode + let list = neomake#list#get_loclist() + let g:unimpaired_prevnext = ['NeomakePrevLoclist', 'NeomakeNextLoclist'] + else + let list = neomake#list#get_qflist() + let g:unimpaired_prevnext = ['NeomakePrevQuickfix', 'NeomakeNextQuickfix'] + endif + return list +endfunction + +function! neomake#list#next(c, ...) abort + let file_mode = a:0 ? a:1 : 1 + let list = s:get_list(file_mode) + call s:goto_nearest(list, a:c == 0 ? 1 : a:c) +endfunction + +function! neomake#list#prev(c, ...) abort + let file_mode = a:0 ? a:1 : 1 + let list = s:get_list(file_mode) + call s:goto_nearest(list, a:c == 0 ? -1 : -a:c) +endfunction + +" TODO: global / already used somewhere else? / config +let g:neomake#list#type_prio = { + \ 'E': 0, + \ 'W': 1, + \ 'I': 2, + \ } + +" TODO: allow to customize via own callback(s)? +function! s:cmp_listitem_loc(a, b) abort + let buf_diff = a:a.bufnr - a:b.bufnr + if buf_diff + return buf_diff + endif + + if exists('*vader#assert#not_equal') + call vader#assert#not_equal(a:a.bufnr, -1) + call vader#assert#not_equal(a:b.bufnr, -1) + endif + + let lnum_diff = a:a.lnum - a:b.lnum + if lnum_diff + return lnum_diff + endif + + let col_diff = a:a.col - a:b.col + if col_diff + return col_diff + endif + + let prio = g:neomake#list#type_prio + return get(prio, a:a.type, 99) - get(prio, a:b.type, 99) +endfunction + +function! s:goto_nearest(list, offset) abort + let [lnum, col] = getpos('.')[1:2] + if a:offset == 0 + throw 'a:offset must not be 0' + endif + + if !has_key(a:list, '_sorted_entries_by_location') + call a:list.sort_by_location() + endif + let entries = a:list._sorted_entries_by_location + if a:offset < 0 + call reverse(entries) + endif + + let c = a:offset + let step = a:offset > 0 ? 1 : -1 + let found = 0 + for item in entries + if (a:offset > 0 && (item.lnum > lnum || (item.lnum == lnum && item.col > col))) + \ || (a:offset < 0 && (item.lnum < lnum || (item.lnum == lnum && item.col < col))) + let c -= step + let found = item.nmqfidx + if c == 0 + break + endif + endif + endfor + + if found + if a:list.type ==# 'loclist' + if exists('*vader#assert#equal') + " @vimlint(EVL102, 1, l:ll_item) + let ll_item = getloclist(0)[found-1] + call vader#assert#equal([ll_item.bufnr, ll_item.lnum], [item.bufnr, item.lnum]) + endif + execute 'll '.found + else + if exists('*vader#assert#equal') + " @vimlint(EVL102, 1, l:cc_item) + let cc_item = getqflist()[found-1] + call vader#assert#equal([cc_item.bufnr, cc_item.lnum], [item.bufnr, item.lnum]) + endif + execute 'cc '.found + endif + elseif c > 0 + call neomake#log#error('No more next items.') + elseif c < 0 + call neomake#log#error('No more previous items.') + endif +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/log.vim b/.vim/autoload/neomake/log.vim new file mode 100644 index 0000000..4e8e6bf --- /dev/null +++ b/.vim/autoload/neomake/log.vim @@ -0,0 +1,171 @@ +let s:level_to_name = {0: 'error ', 1: 'warning', 2: 'verbose', 3: 'debug '} +let s:name_to_level = {'error': 0, 'warning': 1, 'verbose': 2, 'debug': 3} +let s:short_level_to_name = {0: 'E', 1: 'W', 2: 'V', 3: 'D'} +let s:is_testing = exists('g:neomake_test_messages') +let s:pid = getpid() + +let s:last_msg_ts = neomake#compat#reltimefloat() + +function! s:reltime_lastmsg() abort + let cur = neomake#compat#reltimefloat() + let diff = (cur - s:last_msg_ts) + let s:last_msg_ts = neomake#compat#reltimefloat() + + if diff < 0.01 + return ' ' + elseif diff < 10 + let format = '+%.2f' + elseif diff < 100 + let format = '+%.1f' + elseif diff < 100 + let format = ' +%.0f' + elseif diff < 1000 + let format = ' +%.0f' + else + let format = '+%.0f' + endif + return printf(format, diff) +endfunction + +function! s:log(level, msg, ...) abort + let context = a:0 ? a:1 : {} + let verbosity = neomake#utils#get_verbosity(context) + let logfile = get(g:, 'neomake_logfile', '') + + if !s:is_testing && verbosity < a:level && empty(logfile) + return + endif + + if a:0 + if has_key(a:1, 'options') + let context = copy(a:1.options) + let context.make_id = a:1.make_id + else + let context = copy(a:1) + endif + let msg = printf('[%s.%s:%s:%d] %s', + \ get(context, 'make_id', '-'), + \ get(context, 'id', '-'), + \ get(context, 'bufnr', get(context, 'file_mode', 0) ? '?' : '-'), + \ get(context, 'winnr', winnr()), + \ a:msg) + else + let msg = a:msg + endif + + " Use Vader's log for messages during tests. + " @vimlint(EVL104, 1, l:timediff) + if s:is_testing && (verbosity >= a:level || get(g:, 'neomake_test_log_all_messages', 0)) + let timediff = s:reltime_lastmsg() + if timediff !=# ' ' + let test_msg = '['.s:short_level_to_name[a:level].' '.timediff.']: '.msg + else + let test_msg = '['.s:level_to_name[a:level].']: '.msg + endif + + if exists('*vader#log') + " Might not exist with rpcrequest-based nvim test, or throw errors + " if called too early. + call vader#log(test_msg) + endif + " Only keep context entries that are relevant for / used in the message. + let context = a:0 + \ ? extend(filter(copy(context), "index(['id', 'make_id', 'bufnr', 'winnr'], v:key) != -1"), {'winnr': winnr()}, 'keep') + \ : {} + call add(g:neomake_test_messages, [a:level, a:msg, context]) + if index(['.', '!', ')', ']'], a:msg[-1:-1]) == -1 + let g:neomake_test_errors += ['Log msg does not end with punctuation: "'.a:msg.'".'] + endif + elseif verbosity >= a:level + redraw + if verbosity > 2 + echom 'Neomake: '.msg + else + if a:level ==# 0 + echohl ErrorMsg + else + echohl WarningMsg + endif + " Use message without context for non-debug msgs. + echom 'Neomake: '.a:msg + echohl None + endif + endif + if !empty(logfile) + if !exists('s:logfile_writefile_opts') + " Use 'append' with writefile, but only if it is available. Otherwise, just + " overwrite the file. 'S' is used to disable fsync in Neovim + " (https://github.com/neovim/neovim/pull/6427). + if has('patch-7.4.503') + let s:logfile_writefile_opts = 'aS' + else + let s:logfile_writefile_opts = '' + redraw + echohl WarningMsg + echom 'Neomake: appending to the logfile is not supported in your Vim version.' + echohl NONE + endif + endif + + let time = strftime('%H:%M:%S') + if !exists('timediff') + let timediff = s:reltime_lastmsg() + endif + try + call writefile([printf('%s %s [%s %s] %s', + \ time, s:pid, s:short_level_to_name[a:level], timediff, msg)], + \ logfile, s:logfile_writefile_opts) + catch + unlet g:neomake_logfile + call neomake#log#error(printf('Error when trying to write to logfile %s: %s. Unsetting g:neomake_logfile.', logfile, v:exception)) + endtry + endif + " @vimlint(EVL104, 0, l:timediff) +endfunction + +function! neomake#log#error(...) abort + call call('s:log', [0] + a:000) +endfunction + +function! neomake#log#warning(...) abort + call call('s:log', [1] + a:000) +endfunction + +function! neomake#log#info(...) abort + call call('s:log', [2] + a:000) +endfunction + +function! neomake#log#debug(...) abort + call call('s:log', [3] + a:000) +endfunction + +function! neomake#log#debug_obj(msg, obj) abort + if s:is_testing || neomake#utils#get_verbosity() >= 3 || !empty(get(g:, 'neomake_logfile', '')) + call neomake#log#debug(a:msg.': '.neomake#utils#Stringify(a:obj).'.') + endif +endfunction + +function! neomake#log#exception(error, ...) abort + let log_context = a:0 ? a:1 : {'bufnr': bufnr('%')} + redraw + echom printf('Neomake error in: %s', v:throwpoint) + call neomake#log#error(a:error, log_context) + call neomake#log#debug(printf('(in %s)', v:throwpoint), log_context) +endfunction + +let s:warned = {} +function! neomake#log#warn_once(msg, key) abort + if !has_key(s:warned, a:key) + let s:warned[a:key] = 1 + echohl WarningMsg + redraw | echom 'Neomake: ' . a:msg + echohl None + let v:warningmsg = 'Neomake: '.a:msg + call neomake#log#debug('Neomake warning: '.a:msg) + endif +endfunction + +function! neomake#log#reset_warnings() abort + let s:warned = {} +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/cabal.vim b/.vim/autoload/neomake/makers/cabal.vim new file mode 100644 index 0000000..070b2a5 --- /dev/null +++ b/.vim/autoload/neomake/makers/cabal.vim @@ -0,0 +1,15 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#cabal#cabal() abort + let errorformat = join([ + \ '%A%f:%l:%c:', + \ '%A%f:%l:%c: %m', + \ '%+C %m', + \ '%-Z%[%^ ]', + \ ], ',') + return { + \ 'exe': 'cabal', + \ 'args': ['build'], + \ 'errorformat': errorformat + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/clippy.vim b/.vim/autoload/neomake/makers/clippy.vim new file mode 100644 index 0000000..6f2a8a3 --- /dev/null +++ b/.vim/autoload/neomake/makers/clippy.vim @@ -0,0 +1,39 @@ +" vim: ts=4 sw=4 et + +" Yet to be determined +let s:rustup_has_nightly = get(g:, 'neomake_clippy_rustup_has_nightly', -1) + +function! neomake#makers#clippy#clippy() abort + " When rustup and a nightly toolchain is installed, that is used. + " Otherwise, the default cargo exectuable is used. If this is not part + " of a nightly rust, this will fail. + if s:rustup_has_nightly == -1 + if !executable('rustup') + let s:rustup_has_nightly = 0 + call system('rustc --version | grep -q "\-nightly"') + if v:shell_error + call neomake#log#warning('Clippy requires a nightly rust installation.') + endif + else + call system('rustup show | grep -q "^nightly-"') + let s:rustup_has_nightly = !v:shell_error + endif + endif + + let cargo_maker = neomake#makers#ft#rust#cargo() + let json_args = ['--message-format=json', '--quiet'] + + if s:rustup_has_nightly + return { + \ 'exe': 'rustup', + \ 'args': ['run', 'nightly', 'cargo', 'clippy'] + json_args, + \ 'process_output': cargo_maker.process_output, + \ } + else + return { + \ 'exe': 'cargo', + \ 'args': ['clippy'] + json_args, + \ 'process_output': cargo_maker.process_output, + \ } + endif +endfunction diff --git a/.vim/autoload/neomake/makers/ft/ada.vim b/.vim/autoload/neomake/makers/ft/ada.vim new file mode 100644 index 0000000..822da3c --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/ada.vim @@ -0,0 +1,14 @@ +function! neomake#makers#ft#ada#EnabledMakers() abort + return ['gcc'] +endfunction + +function! neomake#makers#ft#ada#gcc() abort + return { + \ 'args': ['-c', '-x', 'ada', '-gnatc'], + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%f:%l:%c: %m,' . + \ '%f:%l: %m' + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/angular.vim b/.vim/autoload/neomake/makers/ft/angular.vim new file mode 100644 index 0000000..8c2f2d9 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/angular.vim @@ -0,0 +1,9 @@ +function! neomake#makers#ft#angular#SupersetOf() abort + return 'javascript' +endfunction + +function! neomake#makers#ft#angular#EnabledMakers() abort + return ['jshint', 'eslint', 'jscs'] +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/ansible.vim b/.vim/autoload/neomake/makers/ft/ansible.vim new file mode 100644 index 0000000..a1a001f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/ansible.vim @@ -0,0 +1,17 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#ansible#EnabledMakers() abort + return ['ansiblelint', 'yamllint'] +endfunction + +function! neomake#makers#ft#ansible#yamllint() abort + return neomake#makers#ft#yaml#yamllint() +endfunction + +function! neomake#makers#ft#ansible#ansiblelint() abort + return { + \ 'exe': 'ansible-lint', + \ 'args': ['-p', '--nocolor'], + \ 'errorformat': '%f:%l: [%tANSIBLE%n] %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/apiblueprint.vim b/.vim/autoload/neomake/makers/ft/apiblueprint.vim new file mode 100644 index 0000000..2e91b42 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/apiblueprint.vim @@ -0,0 +1,16 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#apiblueprint#EnabledMakers() abort + return executable('drafter') ? ['drafter'] : [] +endfunction + +function! neomake#makers#ft#apiblueprint#drafter() abort + " Drafter only operates on a single file at a time, and therefore doesn't + " bother to print out a file name with each error. We need to attach this + " so that the quickfix list can function properly. + return { + \ 'args': ['-l', '-u'], + \ 'errorformat': '%f: %t%[%^:]\\+: (%n) %m; line %l\, column %c%.%#', + \ 'mapexpr': 'neomake_bufname . ": " . v:val' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/applescript.vim b/.vim/autoload/neomake/makers/ft/applescript.vim new file mode 100644 index 0000000..71a00f1 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/applescript.vim @@ -0,0 +1,11 @@ +function! neomake#makers#ft#applescript#EnabledMakers() abort + return ['osacompile'] +endfunction + +function! neomake#makers#ft#applescript#osacompile() abort + return { + \ 'args': ['-o', g:neomake#compat#dev_null], + \ 'errorformat': '%f:%l: %trror: %m', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/asciidoc.vim b/.vim/autoload/neomake/makers/ft/asciidoc.vim new file mode 100644 index 0000000..4d53751 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/asciidoc.vim @@ -0,0 +1,28 @@ +function! neomake#makers#ft#asciidoc#SupersetOf() abort + return 'text' +endfunction + +function! neomake#makers#ft#asciidoc#EnabledMakers() abort + let makers = executable('asciidoctor') ? ['asciidoctor'] : ['asciidoc'] + return makers + neomake#makers#ft#text#EnabledMakers() +endfunction + +function! neomake#makers#ft#asciidoc#asciidoc() abort + return { + \ 'errorformat': + \ '%E%\w%\+: %tRROR: %f: line %l: %m,' . + \ '%E%\w%\+: %tRROR: %f: %m,' . + \ '%E%\w%\+: FAILED: %f: line %l: %m,' . + \ '%E%\w%\+: FAILED: %f: %m,' . + \ '%W%\w%\+: %tARNING: %f: line %l: %m,' . + \ '%W%\w%\+: %tARNING: %f: %m,' . + \ '%W%\w%\+: DEPRECATED: %f: line %l: %m,' . + \ '%W%\w%\+: DEPRECATED: %f: %m', + \ 'args': ['-o', g:neomake#compat#dev_null], + \ } +endfunction + +function! neomake#makers#ft#asciidoc#asciidoctor() abort + return neomake#makers#ft#asciidoc#asciidoc() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/beancount.vim b/.vim/autoload/neomake/makers/ft/beancount.vim new file mode 100644 index 0000000..95eb31a --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/beancount.vim @@ -0,0 +1,12 @@ +function! neomake#makers#ft#beancount#EnabledMakers() abort + return ['bean_check'] +endfunction + +function! neomake#makers#ft#beancount#bean_check() abort + return { + \ 'exe': 'bean-check', + \ 'errorformat': '%E%f:%l:%m', + \ 'postprocess': function('neomake#postprocess#compress_whitespace'), + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/bib.vim b/.vim/autoload/neomake/makers/ft/bib.vim new file mode 100644 index 0000000..e3a9602 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/bib.vim @@ -0,0 +1,16 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#bib#EnabledMakers() abort + return [] +endfunction + +function! neomake#makers#ft#bib#bibtex() abort + return { + \ 'exe': 'bibtex', + \ 'args': ['-terse', '%:r'], + \ 'append_file': 0, + \ 'uses_filename': 0, + \ 'errorformat': '%E%m---line %l of file %f', + \ 'cwd': '%:p:h' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/c.vim b/.vim/autoload/neomake/makers/ft/c.vim new file mode 100644 index 0000000..1d0cda8 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/c.vim @@ -0,0 +1,110 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#c#EnabledMakers() abort + let makers = executable('clang') ? ['clang', 'clangtidy', 'clangcheck'] : ['gcc'] + call add(makers, 'checkpatch') + call add(makers, 'cppcheck') + return makers +endfunction + +let g:neomake#makers#ft#c#project_root_files = ['configure', 'CMakeLists.txt'] + +function! neomake#makers#ft#c#clang() abort + " as a single-file maker, include the current directory in the default + " search path + return { + \ 'args': ['-fsyntax-only', '-Wall', '-Wextra', '-I./'], + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%I%f:%l:%c: note: %m,' . + \ '%f:%l:%c: %m,'. + \ '%f:%l: %trror: %m,'. + \ '%f:%l: %tarning: %m,'. + \ '%I%f:%l: note: %m,'. + \ '%f:%l: %m' + \ } +endfunction + +function! neomake#makers#ft#c#clangcheck() abort + return { + \ 'exe': 'clang-check', + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%I%f:%l:%c: note: %m,' . + \ '%f:%l:%c: %m,'. + \ '%f:%l: %trror: %m,'. + \ '%f:%l: %tarning: %m,'. + \ '%I%f:%l: note: %m,'. + \ '%f:%l: %m', + \ } +endfunction + +function! neomake#makers#ft#c#gcc() abort + " as a single-file maker, include the current directory in the default + " search path + return { + \ 'args': ['-fsyntax-only', '-Wall', '-Wextra', '-I./'], + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%-G%f:%l: %#error: %#(Each undeclared identifier is reported only%.%#,' . + \ '%-G%f:%l: %#error: %#for each function it appears%.%#,' . + \ '%-GIn file included%.%#,' . + \ '%-G %#from %f:%l\,,' . + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%I%f:%l:%c: note: %m,' . + \ '%f:%l:%c: %m,' . + \ '%f:%l: %trror: %m,' . + \ '%f:%l: %tarning: %m,'. + \ '%I%f:%l: note: %m,'. + \ '%f:%l: %m', + \ } +endfunction + +" The -p option followed by the path to the build directory should be set in +" the maker's arguments. That directory should contain the compile command +" database (compile_commands.json). +function! neomake#makers#ft#c#clangtidy() abort + return { + \ 'exe': 'clang-tidy', + \ 'errorformat': + \ '%E%f:%l:%c: fatal error: %m,' . + \ '%E%f:%l:%c: error: %m,' . + \ '%W%f:%l:%c: warning: %m,' . + \ '%-G%\m%\%%(LLVM ERROR:%\|No compilation database found%\)%\@!%.%#,' . + \ '%E%m', + \ 'short_name': 'ctdy', + \ } +endfunction + +function! neomake#makers#ft#c#checkpatch() abort + return { + \ 'exe': 'checkpatch.pl', + \ 'args': ['--no-summary', '--no-tree', '--terse', '--file'], + \ 'errorformat': + \ '%f:%l: %tARNING: %m,' . + \ '%f:%l: %tRROR: %m', + \ } +endfunction + +function! neomake#makers#ft#c#cppcheck() abort + " Uses --force to avoid: + " nofile:0:0:information:Too many #ifdef configurations - cppcheck only checks 12 configurations. + " NOTE: '--language=c' should be the first args, it gets replaced in + " neomake#makers#ft#cpp#cppcheck. + return { + \ 'args': ['--language=c', '--quiet', '--enable=warning', '--force', + \ '--template="{file}:{line}:{column}:{severity}:{message}"'], + \ 'errorformat': + \ 'nofile:0:0:%trror:%m,' . + \ '%f:%l:%c:%trror:%m,' . + \ 'nofile:0:0:%tarning:%m,'. + \ '%f:%l:%c:%tarning:%m,'. + \ 'nofile:0:0:%tnformation:%m,'. + \ '%f:%l:%c:%tnformation:%m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/cf3.vim b/.vim/autoload/neomake/makers/ft/cf3.vim new file mode 100644 index 0000000..7826fc6 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/cf3.vim @@ -0,0 +1,14 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#cf3#EnabledMakers() abort + return ['cfpromises'] +endfunction + +function! neomake#makers#ft#cf3#cfpromises() abort + return { + \ 'exe': 'cf-promises', + \ 'args': ['-cf'], + \ 'errorformat': + \ '%E%f:%l:%c: error: %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/chef.vim b/.vim/autoload/neomake/makers/ft/chef.vim new file mode 100644 index 0000000..805a070 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/chef.vim @@ -0,0 +1,23 @@ +function! neomake#makers#ft#chef#SupersetOf() abort + return 'ruby' +endfunction + +function! neomake#makers#ft#chef#EnabledMakers() abort + let ruby_makers = neomake#makers#ft#ruby#EnabledMakers() + return ruby_makers + ['foodcritic', 'cookstyle'] +endfunction + +function! neomake#makers#ft#chef#foodcritic() abort + return { + \ 'errorformat': '%WFC%n: %m: %f:%l', + \ } +endfunction + +function! neomake#makers#ft#chef#cookstyle() abort + return { + \ 'args': ['-f', 'emacs'], + \ 'errorformat': '%f:%l:%c: %t: %m', + \ 'postprocess': function('neomake#makers#ft#ruby#RubocopEntryProcess'), + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/coffee.vim b/.vim/autoload/neomake/makers/ft/coffee.vim new file mode 100644 index 0000000..67c6cc3 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/coffee.vim @@ -0,0 +1,15 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#coffee#EnabledMakers() abort + return ['coffeelint'] +endfunction + +function! neomake#makers#ft#coffee#coffeelint() abort + return { + \ 'args': ['--reporter=csv'], + \ 'errorformat': '%f\,%l\,%\d%#\,%trror\,%m,' . + \ '%f\,%l\,%trror\,%m,' . + \ '%f\,%l\,%\d%#\,%tarn\,%m,' . + \ '%f\,%l\,%tarn\,%m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/cpp.vim b/.vim/autoload/neomake/makers/ft/cpp.vim new file mode 100644 index 0000000..0cfa877 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/cpp.vim @@ -0,0 +1,50 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#cpp#EnabledMakers() abort + let makers = executable('clang++') ? ['clang', 'clangtidy', 'clangcheck'] : ['gcc'] + call add(makers, 'cppcheck') + return makers +endfunction + +function! neomake#makers#ft#cpp#clang() abort + let maker = neomake#makers#ft#c#clang() + let maker.exe = 'clang++' + let maker.args += ['-std=c++1z'] + return maker +endfunction + +function! neomake#makers#ft#cpp#gcc() abort + let maker = neomake#makers#ft#c#gcc() + let maker.exe = 'g++' + let maker.args += ['-std=c++1z'] + return maker +endfunction + +function! neomake#makers#ft#cpp#clangtidy() abort + return neomake#makers#ft#c#clangtidy() +endfunction + +function! neomake#makers#ft#cpp#clangcheck() abort + return neomake#makers#ft#c#clangcheck() +endfunction + +function! neomake#makers#ft#cpp#cppcheck() abort + let maker = neomake#makers#ft#c#cppcheck() + let maker.args[0] = '--language=c++' + return maker +endfunction + +function! neomake#makers#ft#cpp#cpplint() abort + return { + \ 'exe': executable('cpplint') ? 'cpplint' : 'cpplint.py', + \ 'args': ['--verbose=3'], + \ 'errorformat': + \ '%A%f:%l: %m [%t],' . + \ '%-G%.%#', + \ 'postprocess': function('neomake#makers#ft#cpp#CpplintEntryProcess') + \ } +endfunction + +function! neomake#makers#ft#cpp#CpplintEntryProcess(entry) abort + let a:entry.type = str2nr(a:entry.type) < 5 ? 'W' : 'E' +endfunction diff --git a/.vim/autoload/neomake/makers/ft/crystal.vim b/.vim/autoload/neomake/makers/ft/crystal.vim new file mode 100644 index 0000000..b570c74 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/crystal.vim @@ -0,0 +1,25 @@ +function! neomake#makers#ft#crystal#EnabledMakers() abort + return ['crystal', 'ameba'] +endfunction + +function! neomake#makers#ft#crystal#crystal() abort + " from vim-crystal + return { + \ 'args': ['run', '--no-color', '--no-codegen'], + \ 'errorformat': + \ '%ESyntax error in line %l: %m,'. + \ '%ESyntax error in %f:%l: %m,'. + \ '%EError in %f:%l: %m,'. + \ '%C%p^,'. + \ '%-C%.%#' + \ } +endfunction + +function! neomake#makers#ft#crystal#ameba() abort + " from vim-crystal + return { + \ 'args': ['--format', 'flycheck'], + \ 'errorformat': '%f:%l:%c: %t: %m' + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/cs.vim b/.vim/autoload/neomake/makers/ft/cs.vim new file mode 100644 index 0000000..6457cff --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/cs.vim @@ -0,0 +1,22 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#cs#EnabledMakers() abort + return ['mcs'] +endfunction + +function! neomake#makers#ft#cs#mcs() abort + return { + \ 'args': ['--parse', '--unsafe'], + \ 'errorformat': '%f(%l\,%c): %trror %m', + \ } +endfunction + +function! neomake#makers#ft#cs#msbuild() abort + return { + \ 'exe': 'msbuild', + \ 'args': ['-nologo', '-v:q', '-property:GenerateFullPaths=true', neomake#utils#FindGlobFile('*.sln')], + \ 'errorformat': '%E%f(%l\,%c): error CS%n: %m [%.%#],'. + \ '%W%f(%l\,%c): warning CS%n: %m [%.%#]', + \ 'append_file' : 0, + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/css.vim b/.vim/autoload/neomake/makers/ft/css.vim new file mode 100644 index 0000000..3afbccd --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/css.vim @@ -0,0 +1,35 @@ +scriptencoding utf8 + +function! neomake#makers#ft#css#EnabledMakers() abort + return ['csslint', 'stylelint'] +endfunction + +function! neomake#makers#ft#css#csslint() abort + return { + \ 'args': ['--format=compact'], + \ 'errorformat': + \ '%-G,'. + \ '%-G%f: lint free!,'. + \ '%f: line %l\, col %c\, %trror - %m,'. + \ '%f: line %l\, col %c\, %tarning - %m,'. + \ '%f: line %l\, col %c\, %m,'. + \ '%f: %tarning - %m' + \ } +endfunction + +function! neomake#makers#ft#css#stylelint() abort + let maker = { + \ 'errorformat': + \ '%-P%f,'. + \ '%W%*\s%l:%c%*\s✖ %m,'. + \ '%-Q,'. + \ '%+EError: No configuration provided for %f,%-C %.%#' + \ } + + function! maker.postprocess(entry) abort + let a:entry.text = substitute(a:entry.text, '\v\s\s+(.{-})\s*$', ' [\1]', 'g') + endfunction + + return maker +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/cuda.vim b/.vim/autoload/neomake/makers/ft/cuda.vim new file mode 100644 index 0000000..0fbf6c9 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/cuda.vim @@ -0,0 +1,15 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#cuda#EnabledMakers() abort + return ['nvcc'] +endfunction + +function! neomake#makers#ft#cuda#nvcc() abort + return { + \ 'exe': 'nvcc', + \ 'errorformat': + \ '%f\(%l\): %trror: %m,'. + \ '%f\(%l\): %tarning: %m,'. + \ '%f\(%l\): %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/d.vim b/.vim/autoload/neomake/makers/ft/d.vim new file mode 100644 index 0000000..5206a8d --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/d.vim @@ -0,0 +1,92 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#d#EnabledMakers() abort + " dmd, ldmd, and gdmd all share a common CLI. + " Ordered in efficiency of compiler + for m in ['dmd', 'ldmd', 'gdmd'] + if executable(m) + return [m] + endif + endfor + return [] +endfunction + +function! s:findDubRoot() abort + "Look upwards for a dub.json or dub.sdl to find the root + "I did it like this because it's the only cross platform way I know of + let tmp_file = findfile('dub.json', '.;') + if empty(tmp_file) + let tmp_file = findfile('dub.sdl', '.;') + endif + return tmp_file +endfunction + +function! s:UpdateDub() abort + "Add dub directories + let s:dubImports = [] + let tmp_file = s:findDubRoot() + if executable('dub') && !empty(tmp_file) + let tmp_dir = fnamemodify(tmp_file,':p:h') + let dubCmd = 'dub describe --data=import-paths --annotate ' + \ .'--skip-registry=all --vquiet --data-list --root=' + let output = system(dubCmd . tmp_dir) + if(v:shell_error == 0 && !empty(output)) + " Is \n portable? + let s:dubImports = split(output, '\n') + call map(s:dubImports, "'-I' . v:val") + endif + endif +endfunction + +"GDMD does not adhere to dmd's flags or output, but to GCC's. +"This is for LDMD and dmd only. +function! s:DmdStyleMaker(args) abort + "Updating dub paths each make might be slow? + call s:UpdateDub() + let args = ['-w', '-wi', '-c', '-o-', '-vcolumns'] + a:args + s:dubImports + return { + \ 'args': args, + \ 'errorformat': + \ '%f(%l\,%c): %trror: %m,' . + \ '%f(%l): %trror: %m,' . + \ '%f(%l\,%c): %tarning: %m,' . + \ '%f(%l): %tarning: %m,' . + \ '%f(%l\,%c): Deprecation: %m,' . + \ '%f(%l): Deprecation: %m,', + \ } +endfunction + +function! neomake#makers#ft#d#dmd() abort + let args = [] + if exists('g:neomake_d_dmd_args_conf') + call add(args, '-conf=' . expand(g:neomake_d_dmd_args_conf)) + endif + return s:DmdStyleMaker(args) +endfunction + +function! neomake#makers#ft#d#ldmd() abort + let args = [] + if exists('g:neomake_d_ldmd_args_conf') + call add(args, '-conf=' . expand(g:neomake_d_ldmd_args_conf)) + endif + return s:DmdStyleMaker(args) +endfunction + +function! neomake#makers#ft#d#gdmd() abort + let args = ['-c', '-o-', '-fsyntax-only', s:UpdateDub()] + return { + \ 'args': args, + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%-G%f:%l: %#error: %#(Each undeclared identifier is reported only%.%#,' . + \ '%-G%f:%l: %#error: %#for each function it appears%.%#,' . + \ '%-GIn file included%.%#,' . + \ '%-G %#from %f:%l\,,' . + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%f:%l:%c: %m,' . + \ '%f:%l: %trror: %m,' . + \ '%f:%l: %tarning: %m,'. + \ '%f:%l: %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/docbk.vim b/.vim/autoload/neomake/makers/ft/docbk.vim new file mode 100644 index 0000000..dceffac --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/docbk.vim @@ -0,0 +1,8 @@ +function! neomake#makers#ft#docbk#EnabledMakers() abort + return ['xmllint'] +endfunction + +function! neomake#makers#ft#docbk#xmllint() abort + return neomake#makers#ft#xml#xmllint() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/dockerfile.vim b/.vim/autoload/neomake/makers/ft/dockerfile.vim new file mode 100644 index 0000000..a6d767f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/dockerfile.vim @@ -0,0 +1,13 @@ +function! neomake#makers#ft#dockerfile#EnabledMakers() abort + return ['hadolint'] +endfunction + +function! neomake#makers#ft#dockerfile#hadolint() abort + return { + \ 'output_stream': 'stdout', + \ 'uses_stdin': 1, + \ 'args': ['--format', 'tty'], + \ 'errorformat': '%f:%l %m', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/elixir.vim b/.vim/autoload/neomake/makers/ft/elixir.vim new file mode 100644 index 0000000..4de652e --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/elixir.vim @@ -0,0 +1,72 @@ +" vim: ts=4 sw=4 et + +" Credo error types. +" F -> Refactoring opportunities +" W -> Warnings +" C -> Convention violation +" D -> Software design suggestions +" R -> Readability suggestions +" Map structure {CredoError: NeomakeType, ...} +let s:neomake_elixir_credo_config_typemap = { + \ 'F': 'W', + \ 'C': 'W', + \ 'D': 'I', + \ 'R': 'I'} + +function! neomake#makers#ft#elixir#PostprocessEnforceMaxBufferLine(entry) abort + let buffer_lines = str2nr(line('$')) + if (buffer_lines < a:entry.lnum) + let a:entry.lnum = buffer_lines + endif +endfunction + +function! neomake#makers#ft#elixir#PostprocessCredo(entry) abort + let type = toupper(a:entry.type) + let type_map = extend(s:neomake_elixir_credo_config_typemap, + \ get(g:, 'neomake_elixir_credo_config_typemap', {})) + if has_key(type_map, type) + let a:entry.type = type_map[type] + endif +endfunction + +function! neomake#makers#ft#elixir#EnabledMakers() abort + return ['mix'] +endfunction + +function! neomake#makers#ft#elixir#elixir() abort + return { + \ 'errorformat': + \ '%E** %s %f:%l: %m,'. + \ '%W%f:%l: warning: %m' + \ } +endfunction + +function! neomake#makers#ft#elixir#credo() abort + return { + \ 'exe': 'mix', + \ 'args': ['credo', 'list', '--format=oneline'], + \ 'postprocess': function('neomake#makers#ft#elixir#PostprocessCredo'), + \ 'errorformat': + \'[%t] %. %f:%l:%c %m,' . + \'[%t] %. %f:%l %m' + \ } +endfunction + +function! neomake#makers#ft#elixir#mix() abort + return { + \ 'exe' : 'mix', + \ 'args': ['compile', '--warnings-as-errors'], + \ 'postprocess': function('neomake#makers#ft#elixir#PostprocessEnforceMaxBufferLine'), + \ 'errorformat': + \ '** %s %f:%l: %m,'. + \ '%Ewarning: %m,%C %f:%l,%Z' + \ } +endfunction + +function! neomake#makers#ft#elixir#dogma() abort + return { + \ 'exe': 'mix', + \ 'args': ['dogma', '--format=flycheck'], + \ 'errorformat': '%E%f:%l:%c: %.: %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/elm.vim b/.vim/autoload/neomake/makers/ft/elm.vim new file mode 100644 index 0000000..fe1d2f6 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/elm.vim @@ -0,0 +1,53 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#elm#EnabledMakers() abort + return ['elmMake'] +endfunction + +function! neomake#makers#ft#elm#elmMake() abort + return { + \ 'exe': 'elm-make', + \ 'args': ['--report=json', '--output=' . g:neomake#compat#dev_null], + \ 'process_output': function('neomake#makers#ft#elm#ElmMakeProcessOutput') + \ } +endfunction + +function! neomake#makers#ft#elm#ElmMakeProcessOutput(context) abort + let errors = [] + " output will be a List, containing either: + " 1) A success message + " 2) A string holding a JSON array for both warnings and errors + + for line in a:context.output + if line[0] ==# '[' + let decoded = neomake#compat#json_decode(line) + for item in decoded + if get(item, 'type', '') ==# 'warning' + let code = 'W' + else + let code = 'E' + endif + + let compiler_error = item['tag'] + let message = item['overview'] + let filename = item['file'] + let region_start = item['region']['start'] + let region_end = item['region']['end'] + let row = region_start['line'] + let col = region_start['column'] + let length = region_end['column'] - region_start['column'] + + let error = { + \ 'text': compiler_error . ' : ' . message, + \ 'type': code, + \ 'lnum': row, + \ 'col': col, + \ 'length': length, + \ 'filename': filename, + \ } + call add(errors, error) + endfor + endif + endfor + return errors +endfunction diff --git a/.vim/autoload/neomake/makers/ft/erlang.vim b/.vim/autoload/neomake/makers/ft/erlang.vim new file mode 100644 index 0000000..a554098 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/erlang.vim @@ -0,0 +1,72 @@ + +function! neomake#makers#ft#erlang#EnabledMakers() abort + return ['erlc'] +endfunction + +function! neomake#makers#ft#erlang#erlc() abort + let maker = { + \ 'errorformat': + \ '%W%f:%l: Warning: %m,' . + \ '%E%f:%l: %m' + \ } + function! maker.InitForJob(_jobinfo) abort + let self.args = neomake#makers#ft#erlang#GlobPaths() + endfunction + return maker +endfunction + +if !exists('g:neomake_erlang_erlc_target_dir') + let g:neomake_erlang_erlc_target_dir = tempname() +endif + +function! neomake#makers#ft#erlang#GlobPaths() abort + " Find project root directory. + let rebar_config = neomake#utils#FindGlobFile('rebar.config') + if !empty(rebar_config) + let root = fnamemodify(rebar_config, ':h') + else + " At least try with CWD + let root = getcwd() + endif + let root = fnamemodify(root, ':p') + let build_dir = root . '_build' + let ebins = [] + if isdirectory(build_dir) + " Pick the rebar3 profile to use + let default_profile = expand('%') =~# '_SUITE.erl$' ? 'test' : 'default' + let profile = get(b:, 'neomake_erlang_erlc_rebar3_profile', default_profile) + let ebins += neomake#compat#glob_list(build_dir . '/' . profile . '/lib/*/ebin') + let target_dir = build_dir . '/neomake' + else + let target_dir = get(b:, 'neomake_erlang_erlc_target_dir', + \ get(g:, 'neomake_erlang_erlc_target_dir')) + endif + " If <root>/_build doesn't exist it might be a rebar2/erlang.mk project + if isdirectory(root . 'deps') + let ebins += neomake#compat#glob_list(root . 'deps/*/ebin') + endif + " Set g:neomake_erlang_erlc_extra_deps in a project-local .vimrc, e.g.: + " let g:neomake_erlang_erlc_extra_deps = ['deps.local'] + " Or just b:neomake_erlang_erlc_extra_deps in a specific buffer. + let extra_deps_dirs = get(b:, 'neomake_erlang_erlc_extra_deps', + \ get(g:, 'neomake_erlang_erlc_extra_deps')) + if !empty(extra_deps_dirs) + for extra_deps in extra_deps_dirs + if extra_deps[-1] !=# '/' + let extra_deps .= '/' + endif + let ebins += neomake#compat#glob_list(extra_deps . '*/ebin') + endfor + endif + let args = ['-pa', 'ebin', '-I', 'include', '-I', 'src'] + for ebin in ebins + let args += [ '-pa', ebin, + \ '-I', substitute(ebin, 'ebin$', 'include', '') ] + endfor + if !isdirectory(target_dir) + call mkdir(target_dir, 'p') + endif + let args += ['-o', target_dir] + return args +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/fish.vim b/.vim/autoload/neomake/makers/ft/fish.vim new file mode 100644 index 0000000..429afcc --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/fish.vim @@ -0,0 +1,16 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#fish#EnabledMakers() abort + return ['fish'] +endfunction + +function! neomake#makers#ft#fish#fish() abort + return { + \ 'args': ['-n'], + \ 'errorformat': + \ '%C%f (line %l): %s,'. + \ '%-Gfish: %.%#,'. + \ '%Z%p^,'. + \ '%E%m' + \} +endfunction diff --git a/.vim/autoload/neomake/makers/ft/fortran.vim b/.vim/autoload/neomake/makers/ft/fortran.vim new file mode 100644 index 0000000..828bba9 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/fortran.vim @@ -0,0 +1,32 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#fortran#EnabledMakers() abort + return ['gfortran'] +endfunction + +" Using the errorformat from syntastic +function! neomake#makers#ft#fortran#ifort() abort + return { + \ 'args': ['-syntax-only', '-warn'], + \ 'errorformat': + \ '%E%f(%l): error #%n: %m,'. + \ '%W%f(%l): warning #%n: %m,'. + \ '%W%f(%l): remark #%n: %m,'. + \ '%-Z%p^,'. + \ '%-G%.%#', + \ } +endfunction + +" Using the errorformat from syntastic +function! neomake#makers#ft#fortran#gfortran() abort + return { + \ 'args': ['-fsyntax-only', '-Wall', '-Wextra'], + \ 'errorformat': + \ '%-C %#,'. + \ '%-C %#%.%#,'. + \ '%A%f:%l%[.:]%c:,'. + \ '%Z%\m%\%%(Fatal %\)%\?%trror: %m,'. + \ '%Z%tarning: %m,'. + \ '%-G%.%#', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/go.vim b/.vim/autoload/neomake/makers/ft/go.vim new file mode 100644 index 0000000..ac53730 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/go.vim @@ -0,0 +1,84 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#go#EnabledMakers() abort + let makers = ['go'] + if executable('golangci-lint') + call add(makers, 'golangci_lint') + elseif executable('gometalinter') + call add(makers, 'gometalinter') + else + call extend(makers, ['golint', 'govet']) + endif + return makers +endfunction + +function! neomake#makers#ft#go#go() abort + return { + \ 'args': [ + \ 'test', '-c', + \ '-o', g:neomake#compat#dev_null, + \ ], + \ 'append_file': 0, + \ 'cwd': '%:h', + \ 'serialize': 1, + \ 'serialize_abort_on_error': 1, + \ 'errorformat': + \ '%W%f:%l: warning: %m,' . + \ '%E%f:%l:%c:%m,' . + \ '%E%f:%l:%m,' . + \ '%C%\s%\+%m,' . + \ '%-G%.%#\\\[no test files],' . + \ '%-G#%.%#', + \ 'postprocess': function('neomake#postprocess#compress_whitespace'), + \ 'version_arg': 'version', + \ } +endfunction + +function! neomake#makers#ft#go#golint() abort + " golint's issues are informational, as they're stylistic (not bugs) + return { + \ 'errorformat': + \ '%I%f:%l:%c: %m,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#go#govet() abort + return { + \ 'exe': 'go', + \ 'args': ['vet'], + \ 'append_file': 0, + \ 'cwd': '%:h', + \ 'errorformat': + \ '%Evet: %.%\+: %f:%l:%c: %m,' . + \ '%W%f:%l: %m,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#go#gometalinter() abort + " Only run a subset of gometalinter for speed, users can override with: + " let g:neomake_go_gometalinter_args = ['--disable-all', '--enable=X', ...] + " + " All linters are only warnings, the go compiler will report errors + return { + \ 'args': ['--disable-all', '--enable=errcheck', '--enable=megacheck', '--vendor'], + \ 'append_file': 0, + \ 'cwd': '%:h', + \ 'errorformat': + \ '%f:%l:%c:%t%*[^:]: %m,' . + \ '%f:%l::%t%*[^:]: %m' + \ } +endfunction + +function! neomake#makers#ft#go#golangci_lint() abort + return { + \ 'exe': 'golangci-lint', + \ 'args': ['run', '--out-format=line-number', '--print-issued-lines=false'], + \ 'output_stream': 'stdout', + \ 'append_file': 0, + \ 'cwd': '%:h', + \ 'errorformat': + \ '%f:%l:%c: %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/haml.vim b/.vim/autoload/neomake/makers/ft/haml.vim new file mode 100644 index 0000000..df79b38 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/haml.vim @@ -0,0 +1,13 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#haml#EnabledMakers() abort + return ['hamllint'] +endfunction + +function! neomake#makers#ft#haml#hamllint() abort + return { + \ 'exe': 'haml-lint', + \ 'args': ['--no-color'], + \ 'errorformat': '%f:%l [%t] %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/haskell.vim b/.vim/autoload/neomake/makers/ft/haskell.vim new file mode 100644 index 0000000..64a5227 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/haskell.vim @@ -0,0 +1,169 @@ +unlet! s:makers +unlet! s:uses_cabal + +function! neomake#makers#ft#haskell#EnabledMakers() abort + if !exists('s:makers') + " cache whether each maker is available, to avoid lots of (UI blocking) + " system calls + " TODO: figure out how to do all this configuration async instead of + " caching it--that would allow the user to change directories from + " within vim and recalculate maker availability without restarting vim + let commands = ['ghc-mod', 'hdevtools', 'hlint', 'liquid'] + let s:makers = [] + let s:jobs = [] + for command in commands + " stack may be able to find a maker binary that's not on the normal + " path so check for that first + if executable('stack') + " run the maker command using stack to see whether stack can + " find it use the help flag to run the maker command without + " doing anything + let stack_command = [ + \ 'stack' + \ , 'exec' + \ , '--' + \ , command + \ , '--help' + \ ] + if has('nvim') + let job_id = jobstart( + \ stack_command, + \ { 'command': command + \ , 'on_exit': function('s:CheckStackMakerAsync') + \ }) + if job_id > 0 + call add(s:jobs, job_id) + endif + else + call extend(stack_command, ['> /dev/null 2>&1;', 'echo $?']) + if system(join(stack_command, ' ')) == 0 + call add(s:makers, substitute(command, '-', '', 'g')) + endif + endif + elseif executable(command) " no stack bin so check for maker bin + call add(s:makers, substitute(command, '-', '', 'g')) + endif + endfor + if has('nvim') + call jobwait(s:jobs) + endif + endif + return s:makers +endfunction + +function! neomake#makers#ft#haskell#hdevtools() abort + let params = { + \ 'exe': 'hdevtools', + \ 'args': ['check', '-g-Wall'], + \ 'mapexpr': s:CleanUpSpaceAndBackticks(), + \ 'errorformat': + \ '%-Z %#,'. + \ '%W%f:%l:%v: Warning: %m,'. + \ '%W%f:%l:%v: Warning:,'. + \ '%E%f:%l:%v: %m,'. + \ '%E%>%f:%l:%v:,'. + \ '%+C %#%m,'. + \ '%W%>%f:%l:%v:,'. + \ '%+C %#%tarning: %m,' + \ } + " hdevtools needs the GHC-PACKAGE-PATH environment variable to exist + " when running on a project WITHOUT a cabal file, but it needs the + " GHC-PACKAGE-PATH to NOT exist when running on a with a project WITH + " a cabal file + if !exists('s:uses_cabal') + let s:uses_cabal = 0 + if executable('stack') + let output = neomake#compat#systemlist(['stack', '--verbosity', 'silent', 'path', '--project-root']) + if !empty(output) + let rootdir = output[0] + if !empty(glob(rootdir . '/*.cabal')) + let s:uses_cabal = 1 + endif + endif + endif + endif + if s:uses_cabal + let params['stackexecargs'] = ['--no-ghc-package-path'] + endif + return s:TryStack(params) +endfunction + +function! neomake#makers#ft#haskell#ghcmod() abort + " This filters out newlines, which is what neovim gives us instead of the + " null bytes that ghc-mod sometimes spits out. + let mapexpr = 'substitute(v:val, "\n", "", "g")' + return s:TryStack({ + \ 'exe': 'ghc-mod', + \ 'args': ['check'], + \ 'mapexpr': mapexpr, + \ 'errorformat': + \ '%-G%\s%#,' . + \ '%f:%l:%c:%trror: %m,' . + \ '%f:%l:%c:%tarning: %m,'. + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%E%f:%l:%c:%m,' . + \ '%E%f:%l:%c:,' . + \ '%Z%m' + \ }) +endfunction + +function! neomake#makers#ft#haskell#HlintEntryProcess(entry) abort + " Postprocess hlint output to make it more readable as a single line + let a:entry.text = substitute(a:entry.text, '\v(Found:)\s*\n', ' | \1', 'g') + let a:entry.text = substitute(a:entry.text, '\v(Why not:)\s*\n', ' | \1', 'g') + let a:entry.text = substitute(a:entry.text, '^No hints$', '', 'g') + call neomake#postprocess#compress_whitespace(a:entry) +endfunction + +function! neomake#makers#ft#haskell#hlint() abort + return s:TryStack({ + \ 'exe': 'hlint', + \ 'postprocess': function('neomake#makers#ft#haskell#HlintEntryProcess'), + \ 'args': [], + \ 'errorformat': + \ '%E%f:%l:%v: Error: %m,' . + \ '%W%f:%l:%v: Warning: %m,' . + \ '%I%f:%l:%v: Suggestion: %m,' . + \ '%C%m' + \ }) +endfunction + +function! neomake#makers#ft#haskell#liquid() abort + return s:TryStack({ + \ 'exe': 'liquid', + \ 'args': [], + \ 'mapexpr': s:CleanUpSpaceAndBackticks(), + \ 'errorformat': + \ '%E %f:%l:%c-%.%#Error: %m,' . + \ '%C%.%#|%.%#,' . + \ '%C %#^%#,' . + \ '%C%m,' + \ }) +endfunction + +function! s:CheckStackMakerAsync(_job_id, data, _event) dict abort + if a:data == 0 + call add(s:makers, substitute(self.command, '-', '', 'g')) + endif +endfunction + +function! s:TryStack(maker) abort + if executable('stack') + if !has_key(a:maker, 'stackexecargs') + let a:maker['stackexecargs'] = [] + endif + let a:maker['args'] = + \ ['--verbosity', 'silent', 'exec'] + \ + a:maker['stackexecargs'] + \ + ['--', a:maker['exe']] + \ + a:maker['args'] + let a:maker['exe'] = 'stack' + endif + return a:maker +endfunction + +function! s:CleanUpSpaceAndBackticks() abort + return 'substitute(substitute(v:val, " \\{2,\\}", " ", "g"), "`", "''", "g")' +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/haxe.vim b/.vim/autoload/neomake/makers/ft/haxe.vim new file mode 100644 index 0000000..9fd07ec --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/haxe.vim @@ -0,0 +1,11 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#haxe#EnabledMakers() abort + return ['haxe'] +endfunction + +function! neomake#makers#ft#haxe#haxe() abort + return { + \ 'errorformat': '%E%f:%l: characters %c-%n : %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/help.vim b/.vim/autoload/neomake/makers/ft/help.vim new file mode 100644 index 0000000..c573cef --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/help.vim @@ -0,0 +1,40 @@ +let s:makers = ['writegood'] + +let s:slash = neomake#utils#Slash() +let s:vimhelplint_exe = '' +if executable('vimhelplint') + let s:vimhelplint_exe = 'vimhelplint' +else + let s:neomake_root = expand('<sfile>:p:h:h:h:h:h', 1) + if !empty(glob(join([s:neomake_root, 'build', 'vimhelplint'], s:slash))) + let s:vimhelplint_exe = join([s:neomake_root, 'contrib', 'vimhelplint'], s:slash) + endif +endif +if !empty(s:vimhelplint_exe) + let s:makers += ['vimhelplint'] +endif + +function! neomake#makers#ft#help#EnabledMakers() abort + return s:makers +endfunction + +function! neomake#makers#ft#help#vimhelplint() abort + " NOTE: does not support/uses arg from wrapper script (i.e. no support for + " tempfiles). It will use the arg only to expand/glob `*.txt` + " (which does not include the hidden tempfile). + return { + \ 'exe': s:vimhelplint_exe, + \ 'errorformat': '%f:%l:%c:%trror:%n:%m,%f:%l:%c:%tarning:%n:%m', + \ 'postprocess': function('neomake#postprocess#generic_length'), + \ 'output_stream': 'stdout', + \ } +endfunction + +function! neomake#makers#ft#help#proselint() abort + return neomake#makers#ft#text#proselint() +endfunction + +function! neomake#makers#ft#help#writegood() abort + return neomake#makers#ft#text#writegood() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/html.vim b/.vim/autoload/neomake/makers/ft/html.vim new file mode 100644 index 0000000..6100175 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/html.vim @@ -0,0 +1,20 @@ +function! neomake#makers#ft#html#tidy() abort + " NOTE: could also have info items, but those are skipped with -e/-q, e.g. + " 'line 7 column 1 - Info: value for attribute "id" missing quote marks'. + return { + \ 'args': ['-e', '-q', '--gnu-emacs', 'true'], + \ 'errorformat': '%W%f:%l:%c: Warning: %m', + \ } +endfunction + +function! neomake#makers#ft#html#htmlhint() abort + return { + \ 'args': ['--format', 'unix', '--nocolor'], + \ 'errorformat': '%f:%l:%c: %m,%-G,%-G%*\d problems', + \ } +endfunction + +function! neomake#makers#ft#html#EnabledMakers() abort + return ['tidy', 'htmlhint'] +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/idris.vim b/.vim/autoload/neomake/makers/ft/idris.vim new file mode 100644 index 0000000..5d95edb --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/idris.vim @@ -0,0 +1,25 @@ +function! neomake#makers#ft#idris#EnabledMakers() abort + return ['idris'] +endfunction + +function! neomake#makers#ft#idris#Postprocess(entry) abort + call neomake#postprocess#compress_whitespace(a:entry) + " Extract length from the beginning of the entry ('-4:When checking left hand side of xor:'). + if a:entry.text =~# '\v^\d+:' + let end = 0 + a:entry.text " cast to int + let a:entry.length = end - a:entry.col + let a:entry.text = substitute(a:entry.text, '\v^([^:]+:){2} ', '', '') + endif +endfunction + +function! neomake#makers#ft#idris#idris() abort + return { + \ 'exe': 'idris', + \ 'args': ['--check', '--warn', '--total', '--warnpartial', '--warnreach'], + \ 'errorformat': + \ '%E%f:%l:%c:%.%#,%-C %#%m,%-C%.%#,'. + \ '%E%f:%l:%c-%m,%-C %#%m,%-C%.%#', + \ 'postprocess': function('neomake#makers#ft#idris#Postprocess'), + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/jade.vim b/.vim/autoload/neomake/makers/ft/jade.vim new file mode 100644 index 0000000..c747950 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/jade.vim @@ -0,0 +1,13 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#jade#EnabledMakers() abort + return ['jadelint'] +endfunction + +function! neomake#makers#ft#jade#jadelint() abort + return { + \ 'exe': 'jade-lint', + \ 'args': ['--reporter', 'inline'], + \ 'errorformat': '%f:%l:%c %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/jasmine.vim b/.vim/autoload/neomake/makers/ft/jasmine.vim new file mode 100644 index 0000000..56e0a4f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/jasmine.vim @@ -0,0 +1,9 @@ +function! neomake#makers#ft#jasmine#SupersetOf() abort + return 'javascript' +endfunction + +function! neomake#makers#ft#jasmine#EnabledMakers() abort + return ['jshint', 'eslint', 'jscs'] +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/java.vim b/.vim/autoload/neomake/makers/ft/java.vim new file mode 100644 index 0000000..1c09bda --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/java.vim @@ -0,0 +1,396 @@ +"============================================================================ +"File: java.vim +"Description: Syntax checking plugin for neomake +"Maintainer: Wang Shidong <wsdjeg at outlook dot com> +"License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +"============================================================================ + +let s:save_cpo = &cpoptions +set cpoptions&vim + +if exists('g:loaded_neomake_java_javac_maker') + finish +endif +let g:loaded_neomake_java_javac_maker = 1 + +let g:neomake_java_javac_maven_pom_tags = ['build', 'properties'] +let g:neomake_java_javac_maven_pom_properties = {} +let s:is_windows = has('win32') || has('win64') || has('win16') || has('dos32') || has('dos16') +if s:is_windows + let s:fsep = ';' + let s:psep = '\' +else + let s:fsep = ':' + let s:psep = '/' +endif +let g:neomake_java_checker_home = fnamemodify(expand('<sfile>'), ':p:h:gs?\\?/?') + +" custom options +let g:neomake_java_javac_executable = + \ get(g:, 'neomake_java_javac_executable', 'javac') + +let g:neomake_java_maven_executable = + \ get(g:, 'neomake_java_maven_executable', 'mvn') + +let g:neomake_java_gradle_executable = + \ get(g:, 'neomake_java_gradle_executable', s:is_windows? '.\gradlew.bat' : './gradlew') + +let g:neomake_java_ant_executable = + \ get(g:, 'neomake_java_ant_executable', 'ant') + +let g:neomake_java_checkstyle_executable = + \ get(g:, 'neomake_java_checkstyle_executable', 'checkstyle') + +let g:neomake_java_javac_options = + \ get(g:, 'neomake_java_javac_options', ['-Xlint']) + +let g:neomake_java_maven_options = + \ get(g:, 'neomake_java_maven_options', '') + +let g:neomake_java_javac_classpath = + \ get(g:, 'neomake_java_javac_classpath', '') + +let g:neomake_java_javac_outputdir = + \ get(g:, 'neomake_java_javac_outputdir', '') + +let g:neomake_java_checkstyle_xml = + \ get(g:, 'neomake_java_checkstyle_xml', '/usr/share/checkstyle/google_checks.xml') + +let g:neomake_java_javac_delete_output = + \ get(g:, 'neomake_java_javac_delete_output', 1) + +let g:neomake_java_javac_autoload_maven_classpath = + \ get(g:, 'neomake_java_javac_autoload_maven_classpath', 1) + +let g:neomake_java_javac_autoload_gradle_classpath = + \ get(g:, 'neomake_java_javac_autoload_gradle_classpath', 1) + +let g:neomake_java_javac_autoload_ant_classpath = + \ get(g:, 'neomake_java_javac_autoload_ant_classpath', 1) + +let g:neomake_java_javac_autoload_eclipse_classpath = + \ get(g:, 'neomake_java_javac_autoload_eclipse_classpath', 1) + +let g:neomake_java_javac_maven_pom_ftime = + \ get(g:, 'neomake_java_javac_maven_pom_ftime', {}) + +let g:neomake_java_javac_maven_pom_classpath = + \ get(g:, 'neomake_java_javac_maven_pom_classpath', {}) + +let g:neomake_java_javac_gradle_ftime = + \ get(g:, 'neomake_java_javac_gradle_ftime', {}) + +let g:neomake_java_javac_gradle_classpath = + \ get(g:, 'neomake_java_javac_gradle_classpath', {}) + +let g:neomake_java_javac_ant_ftime = + \ get(g:, 'neomake_java_javac_ant_ftime', {}) + +let g:neomake_java_javac_ant_classpath = + \ get(g:, 'neomake_java_javac_ant_classpath', {}) + + +let s:has_maven = executable(expand(g:neomake_java_maven_executable, 1)) +let s:has_gradle = executable(expand(g:neomake_java_gradle_executable, 1)) +let s:has_ant = executable(expand(g:neomake_java_ant_executable, 1)) + +function! s:tmpdir() abort + let tempdir = tempname() + call mkdir(tempdir, 'p', 0700) + return tempdir +endfunction + +function! s:ClassSep() abort + return (s:is_windows || has('win32unix')) ? ';' : ':' +endfunction + +function! s:shescape(string) abort + return neomake#utils#shellescape(a:string) +endfunction + +function! s:AddToClasspath(classpath, path) abort + if a:path ==# '' + return a:classpath + endif + return (a:classpath !=# '') ? a:classpath . s:ClassSep() . a:path : a:path +endfunction + +" @vimlint(EVL103, 1, a:classpathFile) +function! s:ReadClassPathFile(classpathFile) abort + let cp = '' + let file = g:neomake_java_checker_home. s:psep. 'java'. s:psep. 'classpath.py' + if has('python3') + execute 'py3file' file + py3 import vim + py3 vim.command("let cp = '%s'" % os.pathsep.join(ReadClasspathFile(vim.eval('a:classpathFile'))).replace('\\', '/')) + elseif has('python') + execute 'pyfile' file + py import vim + py vim.command("let cp = '%s'" % os.pathsep.join(ReadClasspathFile(vim.eval('a:classpathFile'))).replace('\\', '/')) + endif + return cp +endfunction +" @vimlint(EVL103, 0, a:classpathFile) + +function! neomake#makers#ft#java#EnabledMakers() abort + let makers = [] + if executable(expand(g:neomake_java_javac_executable, 1)) + call add(makers, g:neomake_java_javac_executable) + endif + if executable(expand(g:neomake_java_checkstyle_executable, 1)) + call add(makers, g:neomake_java_checkstyle_executable) + endif + return makers +endfunction + +function! neomake#makers#ft#java#javac() abort + let javac_opts = extend([], g:neomake_java_javac_options) + + let output_dir = '' + if g:neomake_java_javac_delete_output + let output_dir = s:tmpdir() + let javac_opts = extend(javac_opts, ['-d', s:shescape(output_dir)]) + endif + + let javac_classpath = get(g:, 'neomake_java_javac_classpath', '') + + if s:has_maven && g:neomake_java_javac_autoload_maven_classpath && empty(javac_classpath) + if !g:neomake_java_javac_delete_output + let javac_opts = extend(javac_opts, ['-d', s:shescape(s:MavenOutputDirectory())]) + endif + let javac_classpath = s:AddToClasspath(javac_classpath, s:GetMavenClasspath()) + endif + + if s:has_gradle && g:neomake_java_javac_autoload_gradle_classpath && empty(javac_classpath) + if !g:neomake_java_javac_delete_output + let javac_opts = extend(javac_opts, ['-d', s:shescape(s:GradleOutputDirectory())]) + endif + let javac_classpath = s:AddToClasspath(javac_classpath, s:GetGradleClasspath()) + endif + + if s:has_ant && g:neomake_java_javac_autoload_ant_classpath && empty(javac_classpath) + let javac_classpath = s:AddToClasspath(javac_classpath, s:GetAntClasspath()) + endif + + if (has('python') || has('python3')) && empty(javac_classpath) + let classpathFile = fnamemodify(findfile('.classpath', escape(expand('.'), '*[]?{}, ') . ';'), ':p') + if !empty(classpathFile) && filereadable(classpathFile) + let javac_classpath = s:ReadClassPathFile(classpathFile) + endif + endif + + if javac_classpath !=# '' + let javac_opts = extend(javac_opts, ['-cp', javac_classpath]) + endif + + return { + \ 'args': javac_opts, + \ 'exe': g:neomake_java_javac_executable, + \ 'errorformat': + \ '%E%f:%l: error: %m,'. + \ '%W%f:%l: warning: %m,'. + \ '%E%f:%l: %m,'. + \ '%Z%p^,'. + \ '%-G%.%#', + \ 'version_arg': '-version' + \ } +endfunction + +function! neomake#makers#ft#java#checkstyle() abort + return { + \ 'args': ['-c', g:neomake_java_checkstyle_xml], + \ 'exe': g:neomake_java_checkstyle_executable, + \ 'errorformat': + \ '%-GStarting audit...,'. + \ '%-GAudit done.,'. + \ '%-GPicked up _JAVA_OPTIONS:%.%#,'. + \ '[%t%*[^]]] %f:%l:%c: %m [%s],'. + \ '[%t%*[^]]] %f:%l: %m [%s]', + \ 'version_arg': '-v' + \ } +endfunction + +function! s:findFileInParent(what, where) abort " {{{2 + let old_suffixesadd = &suffixesadd + let &suffixesadd = '' + let file = findfile(a:what, escape(a:where, ' ') . ';') + let &suffixesadd = old_suffixesadd + return file +endfunction " }}}2 + +function! s:GetMavenProperties() abort " {{{2 + let mvn_properties = {} + let pom = s:findFileInParent('pom.xml', expand('%:p:h', 1)) + if s:has_maven && filereadable(pom) + if !has_key(g:neomake_java_javac_maven_pom_properties, pom) + let mvn_cmd = s:shescape(expand(g:neomake_java_maven_executable, 1)) . + \ ' -f ' . s:shescape(pom) . + \ ' ' . g:neomake_java_maven_options + let mvn_is_managed_tag = 1 + let mvn_settings_output = split(system(mvn_cmd . ' help:effective-pom'), "\n") + let current_path = 'project' + for line in mvn_settings_output + let matches = matchlist(line, '\m^\s*<\([a-zA-Z0-9\-\.]\+\)>\s*$') + if mvn_is_managed_tag && !empty(matches) + let mvn_is_managed_tag = index(g:neomake_java_javac_maven_pom_tags, matches[1]) >= 0 + let current_path .= '.' . matches[1] + else + let matches = matchlist(line, '\m^\s*</\([a-zA-Z0-9\-\.]\+\)>\s*$') + if !empty(matches) + let mvn_is_managed_tag = index(g:neomake_java_javac_maven_pom_tags, matches[1]) < 0 + let current_path = substitute(current_path, '\m\.' . matches[1] . '$', '', '') + else + let matches = matchlist(line, '\m^\s*<\([a-zA-Z0-9\-\.]\+\)>\(.\+\)</[a-zA-Z0-9\-\.]\+>\s*$') + if mvn_is_managed_tag && !empty(matches) + let mvn_properties[current_path . '.' . matches[1]] = matches[2] + endif + endif + endif + endfor + let g:neomake_java_javac_maven_pom_properties[pom] = mvn_properties + endif + return g:neomake_java_javac_maven_pom_properties[pom] + endif + return mvn_properties +endfunction " }}}2 + +function! s:GetMavenClasspath() abort " {{{2 + let pom = s:findFileInParent('pom.xml', expand('%:p:h', 1)) + if s:has_maven && filereadable(pom) + if !has_key(g:neomake_java_javac_maven_pom_ftime, pom) || g:neomake_java_javac_maven_pom_ftime[pom] != getftime(pom) + let mvn_cmd = s:shescape(expand(g:neomake_java_maven_executable, 1)) . + \ ' -f ' . s:shescape(pom) . + \ ' ' . g:neomake_java_maven_options + let mvn_classpath_output = split(system(mvn_cmd . ' dependency:build-classpath -DincludeScope=test'), "\n") + let mvn_classpath = '' + let class_path_next = 0 + + for line in mvn_classpath_output + if class_path_next == 1 + let mvn_classpath = substitute(line, "\r", '', 'g') + break + endif + if stridx(line, 'Dependencies classpath:') >= 0 + let class_path_next = 1 + endif + endfor + + let mvn_properties = s:GetMavenProperties() + + let output_dir = get(mvn_properties, 'project.build.outputDirectory', join(['target', 'classes'], s:psep)) + let mvn_classpath = s:AddToClasspath(mvn_classpath, output_dir) + + let test_output_dir = get(mvn_properties, 'project.build.testOutputDirectory', join(['target', 'test-classes'], s:psep)) + let mvn_classpath = s:AddToClasspath(mvn_classpath, test_output_dir) + + let g:neomake_java_javac_maven_pom_ftime[pom] = getftime(pom) + let g:neomake_java_javac_maven_pom_classpath[pom] = mvn_classpath + endif + return g:neomake_java_javac_maven_pom_classpath[pom] + endif + return '' +endfunction " }}}2 + +function! s:MavenOutputDirectory() abort " {{{2 + let pom = s:findFileInParent('pom.xml', expand('%:p:h', 1)) + if s:has_maven && filereadable(pom) + let mvn_properties = s:GetMavenProperties() + let output_dir = get(mvn_properties, 'project.properties.build.dir', getcwd()) + + let src_main_dir = get(mvn_properties, 'project.build.sourceDirectory', join(['src', 'main', 'java'], s:psep)) + let src_test_dir = get(mvn_properties, 'project.build.testsourceDirectory', join(['src', 'test', 'java'], s:psep)) + if stridx(expand('%:p:h', 1), src_main_dir) >= 0 + let output_dir = get(mvn_properties, 'project.build.outputDirectory', join ([output_dir, 'target', 'classes'], s:psep)) + endif + if stridx(expand('%:p:h', 1), src_test_dir) >= 0 + let output_dir = get(mvn_properties, 'project.build.testOutputDirectory', join([output_dir, 'target', 'test-classes'], s:psep)) + endif + + if has('win32unix') + let output_dir = substitute(system('cygpath -m ' . s:shescape(output_dir)), "\n", '', 'g') + endif + return output_dir + endif + return '.' +endfunction " }}}2 + +function! s:GradleOutputDirectory() abort + let gradle_build = s:findFileInParent('build.gradle', expand('%:p:h', 1)) + let items = split(gradle_build, s:psep) + if len(items)==1 + return join(['build', 'intermediates', 'classes', 'debug'], s:psep) + endif + let outputdir = '' + for i in items + if i !=# 'build.gradle' + let outputdir .= i . s:psep + endif + endfor + return outputdir . join(['build', 'intermediates', 'classes', 'debug'], s:psep) +endf + +function! s:GetGradleClasspath() abort + let gradle = s:findFileInParent('build.gradle', expand('%:p:h', 1)) + if s:has_gradle && filereadable(gradle) + if !has_key(g:neomake_java_javac_gradle_ftime, gradle) || g:neomake_java_javac_gradle_ftime[gradle] != getftime(gradle) + try + let f = tempname() + if s:is_windows + let gradle_cmd = '.\gradlew.bat' + else + let gradle_cmd = './gradlew' + endif + call writefile(["allprojects{apply from: '" . g:neomake_java_checker_home . s:psep. 'java'. s:psep. "classpath.gradle'}"], f) + let ret = system(gradle_cmd . ' -q -I ' . shellescape(f) . ' classpath' ) + if v:shell_error == 0 + let cp = filter(split(ret, "\n"), "v:val =~# '^CLASSPATH:'")[0][10:] + if filereadable(getcwd() . s:psep . 'build.gradle') + let out_putdir = neomake#compat#globpath_list(getcwd(), join( + \ ['**', 'build', 'intermediates', 'classes', 'debug'], + \ s:psep), 0) + for classes in out_putdir + let cp .= s:ClassSep() . classes + endfor + endif + else + let cp = '' + endif + catch + finally + call delete(f) + endtry + let g:neomake_java_javac_gradle_ftime[gradle] = getftime(gradle) + let g:neomake_java_javac_gradle_classpath[gradle] = cp + endif + return g:neomake_java_javac_gradle_classpath[gradle] + endif + return '' +endf + +function! s:GetAntClasspath() abort + let ant = s:findFileInParent('build.xml', expand('%:p:h', 1)) + if s:has_ant && filereadable(ant) + if !has_key(g:neomake_java_javac_ant_ftime, ant) || g:neomake_java_javac_ant_ftime[ant] != getftime(ant) + try + let ant_cmd = 'ant classpath -f build.xml -S -q' + let cp = system(ant_cmd) + if v:shell_error != 0 + let cp = '' + endif + catch + endtry + let g:neomake_java_javac_ant_ftime[ant] = getftime(ant) + let g:neomake_java_javac_ant_classpath[ant] = cp + endif + return g:neomake_java_javac_ant_classpath[ant] + endif + return '' +endf + +let &cpoptions = s:save_cpo +unlet s:save_cpo +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/java/classpath.gradle b/.vim/autoload/neomake/makers/ft/java/classpath.gradle new file mode 100644 index 0000000..f548c0d --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/java/classpath.gradle @@ -0,0 +1,46 @@ +task classpath << { + + String finalFileContents = "" + HashSet<String> classpathFiles = new HashSet<String>() + for (proj in allprojects) { + + def exploded = proj.getBuildDir().absolutePath + File.separator + "intermediates" + File.separator + "exploded-aar" + def listFiles = new File(exploded) + if (listFiles.exists()) { + listFiles.eachFileRecurse(){ file -> + if (file.name.endsWith(".jar")){ + classpathFiles += file + } + } + } + + def rjava = proj.getBuildDir().absolutePath + File.separator + "intermediates" + File.separator + "classes" + File.separator + "debug" + def rFiles = new File(rjava) + if (rFiles.exists()) { + classpathFiles += rFiles + } + + for (conf in proj.configurations) { + for (dependency in conf) { + if (dependency.name.endsWith("aar")){ + } else { + classpathFiles += dependency + } + } + } + if (proj.hasProperty("android")){ + classpathFiles += proj.android.bootClasspath + } + + if (proj.hasProperty("sourceSets")) { + + for (srcSet in proj.sourceSets) { + for (dir in srcSet.java.srcDirs) { + classpathFiles += dir.absolutePath + } + } + } + } + def paths = classpathFiles.join(File.pathSeparator) + println "CLASSPATH:" + paths +} diff --git a/.vim/autoload/neomake/makers/ft/java/classpath.py b/.vim/autoload/neomake/makers/ft/java/classpath.py new file mode 100644 index 0000000..5a7ea8d --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/java/classpath.py @@ -0,0 +1,15 @@ +import os +from xml.etree.ElementTree import * + + +def ReadClasspathFile(fn): + cp = [] + for a in parse(fn).findall('classpathentry'): + kind = a.get('kind') + if kind == 'src' and 'output' in a.keys(): + cp.append(os.path.abspath(a.get('output'))) + elif kind == 'lib' and 'path' in a.keys(): + cp.append(os.path.abspath(a.get('path'))) + elif kind == 'output' and 'path' in a.keys(): + cp.append(os.path.abspath(a.get('path'))) + return cp diff --git a/.vim/autoload/neomake/makers/ft/javascript.vim b/.vim/autoload/neomake/makers/ft/javascript.vim new file mode 100644 index 0000000..7bb379f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/javascript.vim @@ -0,0 +1,119 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#javascript#EnabledMakers() abort + return ['jshint', 'jscs', + \ executable('eslint_d') ? 'eslint_d' : 'eslint', + \] +endfunction + +function! neomake#makers#ft#javascript#tsc() abort + return neomake#makers#ft#typescript#tsc() +endfunction + +function! neomake#makers#ft#javascript#gjslint() abort + return { + \ 'args': ['--nodebug_indentation', '--nosummary', '--unix_mode', '--nobeep'], + \ 'errorformat': '%f:%l:(New Error -%\\?\%n) %m,' . + \ '%f:%l:(-%\\?%n) %m,' . + \ '%-G1 files checked,' . + \ ' no errors found.,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#javascript#jshint() abort + return { + \ 'args': ['--verbose'], + \ 'errorformat': '%A%f: line %l\, col %v\, %m \(%t%*\d\),%-G,%-G%\\d%\\+ errors', + \ 'postprocess': function('neomake#postprocess#generic_length'), + \ } +endfunction + +function! neomake#makers#ft#javascript#jscs() abort + return { + \ 'args': ['--no-colors', '--reporter', 'inline'], + \ 'errorformat': '%E%f: line %l\, col %c\, %m', + \ } +endfunction + +function! neomake#makers#ft#javascript#eslint() abort + let maker = { + \ 'args': ['--format=compact'], + \ 'errorformat': '%E%f: line %l\, col %c\, Error - %m,' . + \ '%W%f: line %l\, col %c\, Warning - %m,%-G,%-G%*\d problems%#', + \ 'cwd': '%:p:h', + \ 'output_stream': 'stdout', + \ } + + function! maker.supports_stdin(_jobinfo) abort + let self.args += ['--stdin', '--stdin-filename=%:p'] + let self.tempfile_name = '' + return 1 + endfunction + + return maker +endfunction + +function! neomake#makers#ft#javascript#eslint_d() abort + return neomake#makers#ft#javascript#eslint() +endfunction + +function! neomake#makers#ft#javascript#standard() abort + return { + \ 'args': ['-v'], + \ 'errorformat': '%W %f:%l:%c: %m,%-Gstandard: %.%#' + \ } +endfunction + +function! neomake#makers#ft#javascript#semistandard() abort + return { + \ 'errorformat': '%W %f:%l:%c: %m' + \ } +endfunction + +function! neomake#makers#ft#javascript#rjsx() abort + return { + \ 'exe': 'emacs', + \ 'args': ['%t','--quick','--batch','--eval=' + \ .'(progn(setq package-load-list ''((js2-mode t)(rjsx-mode t)))(package-initialize)(require ''rjsx-mode)' + \ .' (setq js2-include-node-externs t js2-include-rhino-externs t js2-include-browser-externs t js2-strict-missing-semi-warning nil)' + \ .' (rjsx-mode)(js2-reparse)(js2-display-error-list)' + \ .' (princ(replace-regexp-in-string "^" (concat buffer-file-name " ")' + \ .' (with-current-buffer "*js-lint*" (buffer-substring-no-properties(point-min)(point-max)))))(terpri))'], + \ 'errorformat': '%f line %l: %m,%-G%.%#', + \ 'append_file': 0, + \ } +endfunction + +function! neomake#makers#ft#javascript#flow() abort + return { + \ 'args': ['--from=vim', '--show-all-errors'], + \ 'errorformat': + \ '%-GNo errors!,' + \ .'%EFile "%f"\, line %l\, characters %c-%m,' + \ .'%trror: File "%f"\, line %l\, characters %c-%m,' + \ .'%C%m,%Z', + \ 'postprocess': function('neomake#makers#ft#javascript#FlowProcess') + \ } +endfunction + +function! neomake#makers#ft#javascript#FlowProcess(entry) abort + let lines = split(a:entry.text, '\n') + if !empty(lines) + let a:entry.text = join(lines[1:]) + let a:entry.length = lines[0] - a:entry.col + 1 + endif +endfunction + +function! neomake#makers#ft#javascript#xo() abort + return { + \ 'args': ['--compact'], + \ 'errorformat': '%E%f: line %l\, col %c\, Error - %m,' . + \ '%W%f: line %l\, col %c\, Warning - %m', + \ } +endfunction + +function! neomake#makers#ft#javascript#stylelint() abort + return neomake#makers#ft#css#stylelint() +endfunction + diff --git a/.vim/autoload/neomake/makers/ft/json.vim b/.vim/autoload/neomake/makers/ft/json.vim new file mode 100644 index 0000000..89a38e0 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/json.vim @@ -0,0 +1,38 @@ +function! neomake#makers#ft#json#EnabledMakers() abort + return ['jsonlint'] +endfunction + +function! neomake#makers#ft#json#jsonlintpy() abort + return { + \ 'exe': 'jsonlint-py', + \ 'args': ['--strict'], + \ 'errorformat': + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,', + \ } +endfunction + +function! neomake#makers#ft#json#jsonlint() abort + return { + \ 'args': ['--compact'], + \ 'errorformat': + \ '%ELine %l:%c,'. + \ '%Z\\s%#Reason: %m,'. + \ '%C%.%#,'. + \ '%f: line %l\, col %c\, %m,'. + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#json#eslint() abort + let maker = neomake#makers#ft#javascript#eslint() + let maker.args += ['--plugin', 'json'] + return maker +endfunction + +function! neomake#makers#ft#json#eslint_d() abort + let maker = neomake#makers#ft#javascript#eslint_d() + let maker.args += ['--plugin', 'json'] + return maker +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/jsx.vim b/.vim/autoload/neomake/makers/ft/jsx.vim new file mode 100644 index 0000000..38d3cc3 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/jsx.vim @@ -0,0 +1,17 @@ +function! neomake#makers#ft#jsx#SupersetOf() abort + return 'javascript' +endfunction + +function! neomake#makers#ft#jsx#EnabledMakers() abort + return ['jshint', executable('eslint_d') ? 'eslint_d' : 'eslint'] +endfunction + +function! neomake#makers#ft#jsx#jsxhint() abort + return neomake#makers#ft#javascript#jshint() +endfunction + +function! neomake#makers#ft#jsx#stylelint() abort + return neomake#makers#ft#css#stylelint() +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/julia.vim b/.vim/autoload/neomake/makers/ft/julia.vim new file mode 100644 index 0000000..a6fed9f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/julia.vim @@ -0,0 +1,24 @@ +function! neomake#makers#ft#julia#EnabledMakers() abort + return ['lint'] +endfunction + +function! neomake#makers#ft#julia#lint() abort + return { +\ 'errorformat': '%f:%l %t%*[^ ] %m', +\ 'exe': 'julia', +\ 'args': ['-e', ' +\ try +\ using Lint +\ catch +\ println("$(basename(ARGS[1])):1 E999 Install Lint.jl: Pkg.add(""Lint"")"); +\ exit(1) +\ end; +\ r = lintfile(ARGS[1]); +\ if !isempty(r) +\ display(r); +\ exit(1) +\ end +\ '] +\ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/kotlin.vim b/.vim/autoload/neomake/makers/ft/kotlin.vim new file mode 100644 index 0000000..d7273e3 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/kotlin.vim @@ -0,0 +1,12 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#kotlin#EnabledMakers() abort + return ['ktlint'] +endfunction + +function! neomake#makers#ft#kotlin#ktlint() abort + return { + \ 'errorformat': '%E%f:%l:%c: %m', + \ } +endfunction + diff --git a/.vim/autoload/neomake/makers/ft/less.vim b/.vim/autoload/neomake/makers/ft/less.vim new file mode 100644 index 0000000..51ba941 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/less.vim @@ -0,0 +1,19 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#less#EnabledMakers() abort + return executable('stylelint') ? ['stylelint'] : ['lessc'] +endfunction + +function! neomake#makers#ft#less#lessc() abort + return { + \ 'args': ['--lint', '--no-color'], + \ 'errorformat': + \ '%m in %f on line %l\, column %c:,' . + \ '%m in %f:%l:%c,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#less#stylelint() abort + return neomake#makers#ft#css#stylelint() +endfunction diff --git a/.vim/autoload/neomake/makers/ft/lex.vim b/.vim/autoload/neomake/makers/ft/lex.vim new file mode 100644 index 0000000..7dafebf --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/lex.vim @@ -0,0 +1,11 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#lex#EnabledMakers() abort + return ['flex'] +endfunction + +function! neomake#makers#ft#lex#flex() abort + return { + \ 'errorformat': '%f:%l: %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/lua.vim b/.vim/autoload/neomake/makers/ft/lua.vim new file mode 100644 index 0000000..c0e6bce --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/lua.vim @@ -0,0 +1,33 @@ +function! neomake#makers#ft#lua#EnabledMakers() abort + return executable('luacheck') ? ['luacheck'] : ['luac'] +endfunction + +" luacheck: postprocess: use pattern (%s) for end column. +function! neomake#makers#ft#lua#PostprocessLuacheck(entry) abort + let end_col = matchstr(a:entry.pattern, '\v\d+') + if !empty(end_col) + let a:entry.length = end_col - a:entry.col + 1 + else + echom 'luacheck: no end_col: '.string(a:entry) + endif + let a:entry.pattern = '' +endfunction + +function! neomake#makers#ft#lua#luacheck() abort + " cwd: luacheck looks for .luacheckrc upwards from there. + return { + \ 'args': ['--no-color', '--formatter=plain', '--ranges', '--codes', '--filename', '%:p'], + \ 'cwd': '%:p:h', + \ 'errorformat': '%E%f:%l:%c-%s: \(%t%n\) %m', + \ 'postprocess': function('neomake#makers#ft#lua#PostprocessLuacheck'), + \ 'supports_stdin': 1, + \ } +endfunction + +function! neomake#makers#ft#lua#luac() abort + return { + \ 'args': ['-p'], + \ 'errorformat': '%*\f: %#%f:%l: %m', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/mail.vim b/.vim/autoload/neomake/makers/ft/mail.vim new file mode 100644 index 0000000..54cd09e --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/mail.vim @@ -0,0 +1,8 @@ +function! neomake#makers#ft#mail#EnabledMakers() abort + return ['proselint'] +endfunction + +function! neomake#makers#ft#mail#proselint() abort + return neomake#makers#ft#text#proselint() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/markdown.vim b/.vim/autoload/neomake/makers/ft/markdown.vim new file mode 100644 index 0000000..1146488 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/markdown.vim @@ -0,0 +1,97 @@ +function! neomake#makers#ft#markdown#SupersetOf() abort + return 'text' +endfunction + +function! neomake#makers#ft#markdown#EnabledMakers() abort + let makers = executable('mdl') ? ['mdl'] : ['markdownlint'] + if executable('vale') | let makers += ['vale'] | endif + return makers + neomake#makers#ft#text#EnabledMakers() +endfunction + +function! neomake#makers#ft#markdown#mdl() abort + let maker = { + \ + \ 'errorformat': + \ '%W%f:%l: %m,%-G%.%#', + \ 'output_stream': 'stdout', + \ } + function! maker.postprocess(entry) abort + if a:entry.text[0:1] ==# 'MD' + let [code, text] = split(a:entry.text, '\v^MD\d+\zs ') + let a:entry.nr = str2nr(code[2:]) + let a:entry.text = printf('%s (%s)', text, code) + endif + return a:entry + endfunction + return maker +endfunction + +function! neomake#makers#ft#markdown#markdownlint() abort + return { + \ 'errorformat': '%f: %l: %m' + \ } +endfunction + +let s:alex_supports_stdin = {} +function! neomake#makers#ft#markdown#alex() abort + let maker = { + \ 'errorformat': + \ '%P%f,' + \ .'%-Q,' + \ .'%*[ ]%l:%c-%*\d:%n%*[ ]%tarning%*[ ]%m,' + \ .'%-G%.%#' + \ } + + function! maker.supports_stdin(_jobinfo) abort + let exe = exists('*exepath') ? exepath(self.exe) : self.exe + let support = get(s:alex_supports_stdin, exe, -1) + if support == -1 + let ver = neomake#compat#systemlist(['alex', '--version']) + let ver_split = split(ver[0], '\.') + if len(ver_split) > 1 && (ver_split[0] > 0 || +ver_split[1] >= 6) + let support = 1 + else + let support = 0 + endif + let s:alex_supports_stdin[exe] = support + call neomake#log#debug('alex: stdin support: '.support.'.') + endif + if support + let self.args += ['--stdin'] + let self.tempfile_name = '' + endif + return support + endfunction + + return maker +endfunction + +function! neomake#makers#ft#markdown#ProcessVale(context) abort + let entries = [] + for [filename, items] in items(a:context['json']) + for data in items + let entry = { + \ 'maker_name': 'vale', + \ 'filename': filename, + \ 'text': data.Message, + \ 'lnum': data.Line, + \ 'col': data.Span[0], + \ 'length': data.Span[1] - data.Span[0] + 1, + \ 'type': toupper(data.Severity[0]) + \ } + call add(entries, entry) + endfor + endfor + return entries +endfunction + +function! neomake#makers#ft#markdown#vale() abort + return { + \ 'args': [ + \ '--no-wrap', + \ '--output', 'JSON' + \ ], + \ 'process_json': function('neomake#makers#ft#markdown#ProcessVale') + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/matlab.vim b/.vim/autoload/neomake/makers/ft/matlab.vim new file mode 100644 index 0000000..f208be6 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/matlab.vim @@ -0,0 +1,15 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#matlab#EnabledMakers() abort + return ['mlint'] +endfunction + +function! neomake#makers#ft#matlab#mlint() abort + return { + \ 'args': ['-id'], + \ 'mapexpr': "neomake_bufname.':'.v:val", + \ 'errorformat': + \ '%f:L %l (C %c): %m,'. + \ '%f:L %l (C %c-%*[0-9]): %m,', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/moon.vim b/.vim/autoload/neomake/makers/ft/moon.vim new file mode 100644 index 0000000..486bea7 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/moon.vim @@ -0,0 +1,15 @@ +function! neomake#makers#ft#moon#EnabledMakers() abort + return ['moonc'] +endfunction + +function! neomake#makers#ft#moon#moonc() abort + return { + \ 'args': ['-l'], + \ 'errorformat': + \ '%-G,' . + \ '%-G>%#,' . + \ '%+P%f,'. + \ 'line\ %l:\ %m' + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/neomake_tests.vim b/.vim/autoload/neomake/makers/ft/neomake_tests.vim new file mode 100644 index 0000000..4d06e7a --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/neomake_tests.vim @@ -0,0 +1,58 @@ +if !exists('g:neomake_test_messages') + " Only use it during tests. + finish +endif + +function! neomake#makers#ft#neomake_tests#EnabledMakers() abort + return get(b:, 'neomake_test_enabledmakers', + \ get(g:, 'neomake_test_enabledmakers', + \ ['maker_without_exe', 'nonexisting'])) +endfunction + +function! neomake#makers#ft#neomake_tests#maker_without_exe() abort + return {} +endfunction + +function! neomake#makers#ft#neomake_tests#maker_with_nonstring_exe() abort + return {'exe': function('tr')} +endfunction + +function! neomake#makers#ft#neomake_tests#echo_maker() abort + return { + \ 'exe': 'printf', + \ 'args': 'neomake_tests_echo_maker', + \ 'errorformat': '%m', + \ 'append_file': 0, + \ } +endfunction + +function! neomake#makers#ft#neomake_tests#echo_args() abort + return { + \ 'exe': 'echo', + \ 'errorformat': '%m', + \ } +endfunction + +function! neomake#makers#ft#neomake_tests#true() abort + return {} +endfunction + +function! neomake#makers#ft#neomake_tests#error_maker() abort + return { + \ 'exe': 'printf', + \ 'args': ['%s:1:error_msg_1'], + \ 'errorformat': '%E%f:%l:%m', + \ 'append_file': 1, + \ 'short_name': 'errmkr', + \ } +endfunction + +function! neomake#makers#ft#neomake_tests#process_output_error() abort + let maker = {'exe': 'echo', 'args': 'output', 'append_file': 0} + + function! maker.process_output(...) abort + return [{'valid': 1, 'text': 'error', 'lnum': 1, 'bufnr': bufnr('%')}] + endfunction + return maker +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/nim.vim b/.vim/autoload/neomake/makers/ft/nim.vim new file mode 100644 index 0000000..68b72a3 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/nim.vim @@ -0,0 +1,16 @@ +function! neomake#makers#ft#nim#EnabledMakers() abort + return ['nim'] +endfunction + +function! neomake#makers#ft#nim#nim() abort + return { + \ 'exe': 'nim', + \ 'args': ['--listFullPaths', '--verbosity:0', '--colors:off', + \ '-c', 'check'], + \ 'errorformat': + \ '%I%f(%l\, %c) Hint: %m,' . + \ '%W%f(%l\, %c) Warning: %m,' . + \ '%E%f(%l\, %c) Error: %m' + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/nix.vim b/.vim/autoload/neomake/makers/ft/nix.vim new file mode 100644 index 0000000..f239789 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/nix.vim @@ -0,0 +1,14 @@ +" vim: ts=4 sw=4 et +" +function! neomake#makers#ft#nix#EnabledMakers() abort + return ['nix_instantiate'] +endfunction + +function! neomake#makers#ft#nix#nix_instantiate() abort + return { + \ 'exe': 'nix-instantiate', + \ 'args': ['--parse-only'], + \ 'errorformat': 'error: %m at %f:%l:%c' + \ } +endfunction + diff --git a/.vim/autoload/neomake/makers/ft/node.vim b/.vim/autoload/neomake/makers/ft/node.vim new file mode 100644 index 0000000..a6cd321 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/node.vim @@ -0,0 +1,9 @@ +function! neomake#makers#ft#node#SupersetOf() abort + return 'javascript' +endfunction + +function! neomake#makers#ft#node#EnabledMakers() abort + return ['jshint', 'eslint', 'jscs'] +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/objc.vim b/.vim/autoload/neomake/makers/ft/objc.vim new file mode 100644 index 0000000..5b093f4 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/objc.vim @@ -0,0 +1,55 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#objc#EnabledMakers() abort + let makers = ['clang', 'clangtidy', 'clangcheck'] + return makers +endfunction + +function! neomake#makers#ft#objc#clang() abort + " We will enable ARC and disable warnings about unused parameters because + " it is quite common in Cocoa not to use every method parameter. + return { + \ 'args': ['-fsyntax-only', '-fobjc-arc', '-Wall', '-Wextra', '-Wno-unused-parameter'], + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%I%f:%l:%c: note: %m,' . + \ '%f:%l:%c: %m,'. + \ '%f:%l: %trror: %m,'. + \ '%f:%l: %tarning: %m,'. + \ '%I%f:%l: note: %m,'. + \ '%f:%l: %m' + \ } +endfunction + +" The -p option followed by the path to the build directory should be set in +" the maker's arguments. That directory should contain the compile command +" database (compile_commands.json). +function! neomake#makers#ft#objc#clangtidy() abort + return { + \ 'exe': 'clang-tidy', + \ 'errorformat': + \ '%E%f:%l:%c: fatal error: %m,' . + \ '%E%f:%l:%c: error: %m,' . + \ '%W%f:%l:%c: warning: %m,' . + \ '%-G%\m%\%%(LLVM ERROR:%\|No compilation database found%\)%\@!%.%#,' . + \ '%E%m', + \ } +endfunction + +function! neomake#makers#ft#objc#clangcheck() abort + return { + \ 'exe': 'clang-check', + \ 'errorformat': + \ '%-G%f:%s:,' . + \ '%f:%l:%c: %trror: %m,' . + \ '%f:%l:%c: %tarning: %m,' . + \ '%I%f:%l:%c: note: %m,' . + \ '%f:%l:%c: %m,'. + \ '%f:%l: %trror: %m,'. + \ '%f:%l: %tarning: %m,'. + \ '%I%f:%l: note: %m,'. + \ '%f:%l: %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/pandoc.vim b/.vim/autoload/neomake/makers/ft/pandoc.vim new file mode 100644 index 0000000..ae56b04 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/pandoc.vim @@ -0,0 +1,8 @@ +function! neomake#makers#ft#pandoc#SupersetOf() abort + return 'markdown' +endfunction + +function! neomake#makers#ft#pandoc#EnabledMakers() abort + return neomake#makers#ft#markdown#EnabledMakers() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/perl.vim b/.vim/autoload/neomake/makers/ft/perl.vim new file mode 100644 index 0000000..da07694 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/perl.vim @@ -0,0 +1,34 @@ +" vim: ts=4 sw=4 et +function! neomake#makers#ft#perl#EnabledMakers() abort + return ['perl', 'perlcritic'] +endfunction + +function! neomake#makers#ft#perl#perlcritic() abort + return { + \ 'args' : ['--quiet', '--nocolor', '--verbose', + \ '\\%f:\\%l:\\%c:(\\%s) \\%m (\\%e)\\n'], + \ 'errorformat': '%f:%l:%c:%m,' + \} +endfunction + +function! neomake#makers#ft#perl#perl() abort + return { + \ 'args' : ['-c', '-X', '-Mwarnings'], + \ 'errorformat': '%-G%.%#had too many errors.,' + \ . '%-G%.%#had compilation errors.,' + \ . '%-G%.%#syntax OK,' + \ . '%m at %f line %l.,' + \ . '%+E%.%# at %f line %l\,%.%#,' + \ . '%+C%.%#', + \ 'postprocess': function('neomake#makers#ft#perl#PerlEntryProcess'), + \} +endfunction + +function! neomake#makers#ft#perl#PerlEntryProcess(entry) abort + let extramsg = substitute(a:entry.pattern, '\^\\V', '', '') + let extramsg = substitute(extramsg, '\\\$', '', '') + + if !empty(extramsg) + let a:entry.text .= ' ' . extramsg + endif +endfunction diff --git a/.vim/autoload/neomake/makers/ft/php.vim b/.vim/autoload/neomake/makers/ft/php.vim new file mode 100644 index 0000000..7edefa3 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/php.vim @@ -0,0 +1,72 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#php#EnabledMakers() abort + return ['php', 'phpmd', 'phpcs', 'phpstan'] +endfunction + +function! neomake#makers#ft#php#php() abort + return { + \ 'args': ['-l', '-d', 'display_errors=1', '-d', 'log_errors=0', + \ '-d', 'xdebug.cli_color=0'], + \ 'errorformat': + \ '%-GNo syntax errors detected in%.%#,'. + \ '%EParse error: %#syntax error\, %m in %f on line %l,'. + \ '%EParse error: %m in %f on line %l,'. + \ '%EFatal error: %m in %f on line %l,'. + \ '%-G\s%#,'. + \ '%-GErrors parsing %.%#', + \ 'output_stream': 'stdout', + \ } +endfunction + +function! neomake#makers#ft#php#phpcs() abort + let args = ['--report=csv', '-q'] + + "Add standard argument if one is set. + if exists('g:neomake_php_phpcs_args_standard') + call add(args, '--standard=' . expand(g:neomake_php_phpcs_args_standard)) + endif + + return { + \ 'args': args, + \ 'errorformat': + \ '%-GFile\,Line\,Column\,Type\,Message\,Source\,Severity%.%#,'. + \ '"%f"\,%l\,%c\,%t%*[a-zA-Z]\,"%m"\,%*[a-zA-Z0-9_.-]\,%*[0-9]%.%#', + \ } +endfunction + +function! neomake#makers#ft#php#phpmd() abort + return { + \ 'args': ['%t', 'text', 'codesize,design,unusedcode,naming'], + \ 'append_file': 0, + \ 'errorformat': '%W%f:%l%\s%\s%#%m' + \ } +endfunction + +function! neomake#makers#ft#php#phpstan() abort + " PHPStan normally considers 0 to be the default level, so that is used here as the default: + let maker = { + \ 'args': ['analyse', '--error-format', 'raw', '--no-progress', '--level', get(g:, 'neomake_phpstan_level', 0)], + \ 'errorformat': '%E%f:%l:%m', + \ } + " Check for the existence of a default PHPStan project configuration file. + " Technically PHPStan does not have a concept of a default filename for a + " project configuration file, but phpstan.neon is the filename shown in the + " example in the PHPStan documentation, so this is the default name expected + " by Neomake. + let phpStanConfigFilePath = neomake#utils#FindGlobFile('phpstan.neon') + if !empty(phpStanConfigFilePath) + call extend(maker.args, ['-c', phpStanConfigFilePath]) + endif + return maker +endfunction + +function! neomake#makers#ft#php#psalm() abort + let maker = { + \ 'args': [ + \ '--output-format=pylint' + \ ], + \ 'errorformat': '%A%f:%l:%\s[%t%n]%\s%m', + \ } + return maker +endfunction diff --git a/.vim/autoload/neomake/makers/ft/proto.vim b/.vim/autoload/neomake/makers/ft/proto.vim new file mode 100644 index 0000000..fcff577 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/proto.vim @@ -0,0 +1,12 @@ +function! neomake#makers#ft#proto#EnabledMakers() abort + return ['prototool'] +endfunction + +function! neomake#makers#ft#proto#prototool() abort + return { + \ 'exe': 'prototool', + \ 'args': ['lint'], + \ 'errorformat': '%f:%l:%c:%m', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/pug.vim b/.vim/autoload/neomake/makers/ft/pug.vim new file mode 100644 index 0000000..53f2214 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/pug.vim @@ -0,0 +1,13 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#pug#EnabledMakers() abort + return ['puglint'] +endfunction + +function! neomake#makers#ft#pug#puglint() abort + return { + \ 'exe': 'pug-lint', + \ 'args': ['--reporter', 'inline'], + \ 'errorformat': '%f:%l:%c %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/puppet.vim b/.vim/autoload/neomake/makers/ft/puppet.vim new file mode 100644 index 0000000..c7a467d --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/puppet.vim @@ -0,0 +1,29 @@ +function! neomake#makers#ft#puppet#EnabledMakers() abort + return ['puppet', 'puppetlint'] +endfunction + +function! neomake#makers#ft#puppet#puppetlint() abort + return { + \ 'exe': 'puppet-lint', + \ 'args': ['--log-format', '%%{path}:%%{line}:%%{column}:%%{kind}:[%%{check}] %%{message}'], + \ 'errorformat': '%f:%l:%c:%t%*[a-zA-Z]:%m', + \ 'short_name': 'pupl', + \ 'output_stream': 'stdout', + \ } +endfunction + +function! neomake#makers#ft#puppet#puppet() abort + return { + \ 'args': ['parser', 'validate', '--color=false'], + \ 'errorformat': + \ '%-Gerr: Try ''puppet help parser validate'' for usage,' . + \ '%-GError: Try ''puppet help parser validate'' for usage,' . + \ '%t%*[a-zA-Z]: %m at %f:%l:%c,' . + \ '%t%*[a-zA-Z]: %m at %f:%l,'. + \ '%t%*[a-zA-Z]: Could not parse for environment production: %m (file: %f\, line: %l\, column: %c),' . + \ '%t%*[a-zA-Z]: Could not parse for environment production: %m (file: %f)', + \ 'short_name': 'pupp', + \ 'output_stream': 'stderr', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/purescript.vim b/.vim/autoload/neomake/makers/ft/purescript.vim new file mode 100644 index 0000000..a26a40f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/purescript.vim @@ -0,0 +1,63 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#purescript#EnabledMakers() abort + return ['pulp'] +endfunction + +function! neomake#makers#ft#purescript#pulp() abort + " command is `pulp build --no-psa -- --json-errors` + " as indicated in https://github.com/nwolverson/atom-ide-purescript/issues/136 + let maker = { + \ 'args': ['build', '--no-psa', '--', '--json-errors'], + \ 'append_file': 0, + \ 'process_output': function('neomake#makers#ft#purescript#PSProcessOutput'), + \ } + + " Find project root, since files are reported relative to it. + let bower_file = neomake#utils#FindGlobFile('bower.json') + if !empty(bower_file) + let maker.cwd = fnamemodify(bower_file, ':h') + endif + + return maker +endfunction + +function! neomake#makers#ft#purescript#PSProcessOutput(context) abort + let errors = [] + for line in a:context.output + if line[0] !=# '{' + continue + endif + let decoded = neomake#compat#json_decode(line) + for [key, values] in items(decoded) + let code = key ==# 'warnings' ? 'W' : 'E' + for item in values + let compiler_error = item['errorCode'] + let message = item['message'] + let position = item['position'] + let filename = item['filename'] + if position is g:neomake#compat#json_null + let row = 1 + let col = 1 + let end_col = 1 + let length = 1 + else + let row = position['startLine'] + let col = position['startColumn'] + let end_col = position['endColumn'] + let length = end_col - col + endif + + call add(errors, { + \ 'text': compiler_error . ' : ' . message, + \ 'type': code, + \ 'lnum': row, + \ 'col': col, + \ 'length': length, + \ 'filename': filename, + \ }) + endfor + endfor + endfor + return errors +endfunction diff --git a/.vim/autoload/neomake/makers/ft/python.vim b/.vim/autoload/neomake/makers/ft/python.vim new file mode 100644 index 0000000..d8c8369 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/python.vim @@ -0,0 +1,419 @@ +" vim: ts=4 sw=4 et + +if !exists('s:compile_script') + let s:slash = neomake#utils#Slash() + let s:compile_script = expand('<sfile>:p:h', 1).s:slash.'python'.s:slash.'compile.py' +endif + +function! neomake#makers#ft#python#EnabledMakers() abort + let makers = ['python', 'frosted'] + if executable('pylama') + call add(makers, 'pylama') + else + if executable('flake8') + call add(makers, 'flake8') + else + call extend(makers, ['pyflakes', 'pycodestyle', 'pydocstyle']) + endif + call add(makers, 'pylint') " Last because it is the slowest + endif + return makers +endfunction + +let neomake#makers#ft#python#project_root_files = ['setup.cfg', 'tox.ini'] + +function! neomake#makers#ft#python#DetectPythonVersion() abort + let output = neomake#compat#systemlist('python -V 2>&1') + if v:shell_error + call neomake#log#error(printf( + \ 'Failed to detect Python version: %s.', + \ join(output))) + let s:python_version = [-1, -1, -1] + else + let s:python_version = split(split(output[0])[1], '\.') + endif +endfunction + +let s:ignore_python_warnings = [ + \ '\v[\/]inspect.py:\d+: Warning:', + \ '\v^.{-}:\d+: FutureWarning:', + \ ] + +" Filter Python warnings (the warning and the following line). +" To be used as a funcref with filter(). +function! s:filter_py_warning(v) abort + if s:filter_next_py_warning + let s:filter_next_py_warning = 0 + " Only keep (expected) lines starting with two spaces. + return a:v[0:1] !=# ' ' + endif + for pattern in s:ignore_python_warnings + if a:v =~# pattern + let s:filter_next_py_warning = 1 + return 0 + endif + endfor + return 1 +endfunction + +function! neomake#makers#ft#python#FilterPythonWarnings(lines, context) abort + if a:context.source ==# 'stderr' + let s:filter_next_py_warning = 0 + call filter(a:lines, 's:filter_py_warning(v:val)') + endif +endfunction + +function! neomake#makers#ft#python#pylint() abort + let maker = { + \ 'args': [ + \ '--output-format=text', + \ '--msg-template="{path}:{line}:{column}:{C}: [{symbol}] {msg} [{msg_id}]"', + \ '--reports=no' + \ ], + \ 'errorformat': + \ '%A%f:%l:%c:%t: %m,' . + \ '%A%f:%l: %m,' . + \ '%A%f:(%l): %m,' . + \ '%-Z%p^%.%#,' . + \ '%-G%.%#', + \ 'output_stream': 'stdout', + \ 'postprocess': [ + \ function('neomake#postprocess#generic_length'), + \ function('neomake#makers#ft#python#PylintEntryProcess'), + \ ]} + function! maker.filter_output(lines, context) abort + if a:context.source ==# 'stderr' + call filter(a:lines, "v:val !=# 'No config file found, using default configuration' && v:val !~# '^Using config file '") + endif + call neomake#makers#ft#python#FilterPythonWarnings(a:lines, a:context) + endfunction + return maker +endfunction + +function! neomake#makers#ft#python#PylintEntryProcess(entry) abort + if a:entry.type ==# 'F' " Fatal error which prevented further processing + let type = 'E' + elseif a:entry.type ==# 'E' " Error for important programming issues + let type = 'E' + elseif a:entry.type ==# 'W' " Warning for stylistic or minor programming issues + let type = 'W' + elseif a:entry.type ==# 'R' " Refactor suggestion + let type = 'W' + elseif a:entry.type ==# 'C' " Convention violation + let type = 'W' + elseif a:entry.type ==# 'I' " Informations + let type = 'I' + else + let type = '' + endif + let a:entry.type = type + " Pylint uses 0-indexed columns, vim uses 1-indexed columns + let a:entry.col += 1 +endfunction + +function! neomake#makers#ft#python#flake8() abort + let maker = { + \ 'args': ['--format=default'], + \ 'errorformat': + \ '%E%f:%l: could not compile,%-Z%p^,' . + \ '%A%f:%l:%c: %t%n %m,' . + \ '%A%f:%l: %t%n %m,' . + \ '%-G%.%#', + \ 'postprocess': function('neomake#makers#ft#python#Flake8EntryProcess'), + \ 'short_name': 'fl8', + \ 'output_stream': 'stdout', + \ 'filter_output': function('neomake#makers#ft#python#FilterPythonWarnings'), + \ } + + function! maker.supports_stdin(jobinfo) abort + let self.args += ['--stdin-display-name', '%:p'] + + let bufpath = bufname(a:jobinfo.bufnr) + if !empty(bufpath) + let bufdir = fnamemodify(bufpath, ':p:h') + if stridx(bufdir, getcwd()) != 0 + " The buffer is not below the current dir, so let's cd for lookup + " of config files etc. + " This avoids running into issues with flake8's per-file-ignores, + " which is handled not relative to the config file currently + " (https://gitlab.com/pycqa/flake8/issues/517). + call a:jobinfo.cd(bufdir) + endif + endif + return 1 + endfunction + return maker +endfunction + +function! neomake#makers#ft#python#Flake8EntryProcess(entry) abort + if a:entry.type ==# 'F' " pyflakes + " Ref: http://flake8.pycqa.org/en/latest/user/error-codes.html + if a:entry.nr > 400 && a:entry.nr < 500 + if a:entry.nr == 407 + let type = 'E' " 'an undefined __future__ feature name was imported' + else + let type = 'W' + endif + elseif a:entry.nr == 841 + let type = 'W' + else + let type = 'E' + endif + elseif a:entry.type ==# 'E' && a:entry.nr >= 900 " PEP8 runtime errors (E901, E902) + let type = 'E' + elseif a:entry.type ==# 'E' || a:entry.type ==# 'W' " PEP8 errors & warnings + let type = 'W' + elseif a:entry.type ==# 'N' || a:entry.type ==# 'D' " Naming (PEP8) & docstring (PEP257) conventions + let type = 'W' + elseif a:entry.type ==# 'C' || a:entry.type ==# 'T' " McCabe complexity & todo notes + let type = 'I' + elseif a:entry.type ==# 'I' " keep at least 'I' from isort (I1), could get style subtype?! + let type = a:entry.type + else + let type = '' + endif + + let token_pattern = '\v''\zs[^'']+\ze' + if a:entry.type ==# 'F' && (a:entry.nr == 401 || a:entry.nr == 811) + " Special handling for F401 (``module`` imported but unused) and + " F811 (redefinition of unused ``name`` from line ``N``). + " The unused column is incorrect for import errors and redefinition + " errors. + let token = matchstr(a:entry.text, token_pattern) + if !empty(token) + let view = winsaveview() + call cursor(a:entry.lnum, a:entry.col) + " The number of lines to give up searching afterwards + let search_lines = 5 + + if searchpos('\<from\>', 'cnW', a:entry.lnum)[1] == a:entry.col + " for 'from xxx.yyy import zzz' the token looks like + " xxx.yyy.zzz, but only the zzz part should be highlighted. So + " this discards the module part + let token = split(token, '\.')[-1] + + " Also the search should be started at the import keyword. + " Otherwise for 'from os import os' the first os will be + " found. This moves the cursor there. + call search('\<import\>', 'cW', a:entry.lnum + search_lines) + endif + + " Search for the first occurrence of the token and highlight in + " the next couple of lines and change the lnum and col to that + " position. + " Don't match entries surrounded by dots, even though + " it ends a word, we want to find a full identifier. It also + " matches all seperators such as spaces and newlines with + " backslashes until it knows for sure the previous real character + " was not a dot. + let ident_pos = searchpos('\(\.\(\_s\|\\\)*\)\@<!\<' . + \ token . '\>\(\(\_s\|\\\)*\.\)\@!', + \ 'cnW', + \ a:entry.lnum + search_lines) + if ident_pos[1] > 0 + let a:entry.lnum = ident_pos[0] + let a:entry.col = ident_pos[1] + endif + + call winrestview(view) + + let a:entry.length = strlen(token) + endif + else + call neomake#postprocess#generic_length_with_pattern(a:entry, token_pattern) + + " Special processing for F821 (undefined name) in f-strings. + if !has_key(a:entry, 'length') && a:entry.type ==# 'F' && a:entry.nr == 821 + let token = matchstr(a:entry.text, token_pattern) + if !empty(token) + " Search for '{token}' in reported and following lines. + " It seems like for the first line it is correct already (i.e. + " flake8 reports the column therein), but we still test there + " to be sure. + " https://gitlab.com/pycqa/flake8/issues/407 + let line = get(getbufline(a:entry.bufnr, a:entry.lnum), 0, '') + " NOTE: uses byte offset, starting at col means to start after + " the opening quote. + let pattern = '\V\C{\.\{-}\zs'.escape(token, '\').'\>' + let pos = match(line, pattern, a:entry.col) + if pos == -1 + let line_offset = 0 + while line_offset < 10 + let line_offset += 1 + let line = get(getbufline(a:entry.bufnr, a:entry.lnum + line_offset), 0, '') + let pos = match(line, pattern) + if pos != -1 + let a:entry.lnum = a:entry.lnum + line_offset + break + endif + endwhile + endif + if pos > 0 + let a:entry.col = pos + 1 + let a:entry.length = strlen(token) + endif + endif + endif + endif + + let a:entry.text = a:entry.type . a:entry.nr . ' ' . a:entry.text + let a:entry.type = type + " Reset "nr" to Avoid redundancy with neomake#GetCurrentErrorMsg. + " TODO: This is rather bad, since "nr" itself can be useful. + " This should rather use the entry via Neomake's list, and then a + " new property like "current_error_text" could be used. + " Or with the maker being available a callback could be used. + let a:entry.nr = -1 +endfunction + +function! neomake#makers#ft#python#pyflakes() abort + return { + \ 'errorformat': + \ '%E%f:%l: could not compile,' . + \ '%-Z%p^,'. + \ '%E%f:%l:%c: %m,' . + \ '%E%f:%l: %m,' . + \ '%-G%.%#', + \ } +endfunction + +function! neomake#makers#ft#python#pycodestyle() abort + if !exists('s:_pycodestyle_exe') + " Use the preferred exe to avoid deprecation warnings. + let s:_pycodestyle_exe = executable('pycodestyle') ? 'pycodestyle' : 'pep8' + endif + return { + \ 'exe': s:_pycodestyle_exe, + \ 'errorformat': '%f:%l:%c: %m', + \ 'postprocess': function('neomake#makers#ft#python#Pep8EntryProcess') + \ } +endfunction + +" Note: pep8 has been renamed to pycodestyle, but is kept also as alias. +function! neomake#makers#ft#python#pep8() abort + return neomake#makers#ft#python#pycodestyle() +endfunction + +function! neomake#makers#ft#python#Pep8EntryProcess(entry) abort + if a:entry.text =~# '^E9' " PEP8 runtime errors (E901, E902) + let a:entry.type = 'E' + elseif a:entry.text =~# '^E113' " unexpected indentation (IndentationError) + let a:entry.type = 'E' + else " Everything else is a warning + let a:entry.type = 'W' + endif +endfunction + +function! neomake#makers#ft#python#pydocstyle() abort + if !exists('s:_pydocstyle_exe') + " Use the preferred exe to avoid deprecation warnings. + let s:_pydocstyle_exe = executable('pydocstyle') ? 'pydocstyle' : 'pep257' + endif + return { + \ 'exe': s:_pydocstyle_exe, + \ 'errorformat': + \ '%W%f:%l %.%#:,' . + \ '%+C %m', + \ 'postprocess': function('neomake#postprocess#compress_whitespace'), + \ } +endfunction + +" Note: pep257 has been renamed to pydocstyle, but is kept also as alias. +function! neomake#makers#ft#python#pep257() abort + return neomake#makers#ft#python#pydocstyle() +endfunction + +function! neomake#makers#ft#python#PylamaEntryProcess(entry) abort + if a:entry.nr == -1 + " Get number from the beginning of text. + let nr = matchstr(a:entry.text, '\v^\u\zs\d+') + if !empty(nr) + let a:entry.nr = nr + 0 + endif + endif + if a:entry.type ==# 'C' && a:entry.text =~# '\v\[%(pycodestyle|pep8)\]$' + call neomake#makers#ft#python#Pep8EntryProcess(a:entry) + elseif a:entry.type ==# 'D' " pydocstyle/pep257 + let a:entry.type = 'W' + elseif a:entry.type ==# 'C' && a:entry.nr == 901 " mccabe + let a:entry.type = 'I' + elseif a:entry.type ==# 'R' " Radon + let a:entry.type = 'W' + endif +endfunction + +function! neomake#makers#ft#python#pylama() abort + let maker = { + \ 'args': ['--format', 'parsable'], + \ 'errorformat': '%f:%l:%c: [%t] %m', + \ 'postprocess': function('neomake#makers#ft#python#PylamaEntryProcess'), + \ 'output_stream': 'stdout', + \ } + " Pylama looks for the config only in the current directory. + " Therefore we change to where the config likely is. + " --options could be used to pass a config file, but we cannot be sure + " which one really gets used. + let ini_file = neomake#utils#FindGlobFile('{pylama.ini,setup.cfg,tox.ini,pytest.ini}') + if !empty(ini_file) + let maker.cwd = fnamemodify(ini_file, ':h') + endif + return maker +endfunction + +function! neomake#makers#ft#python#python() abort + return { + \ 'args': [s:compile_script], + \ 'errorformat': '%E%f:%l:%c: %m', + \ 'serialize': 1, + \ 'serialize_abort_on_error': 1, + \ 'output_stream': 'stdout', + \ 'short_name': 'py', + \ } +endfunction + +function! neomake#makers#ft#python#frosted() abort + return { + \ 'args': [ + \ '-vb' + \ ], + \ 'errorformat': + \ '%f:%l:%c:%m,' . + \ '%E%f:%l: %m,' . + \ '%-Z%p^,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#python#vulture() abort + return { + \ 'errorformat': '%f:%l: %m', + \ } +endfunction + +" --fast-parser: adds experimental support for async/await syntax +" --silent-imports: replaced by --ignore-missing-imports +function! neomake#makers#ft#python#mypy() abort + let args = ['--check-untyped-defs', '--ignore-missing-imports'] + + " Append '--py2' to args with Python 2 for Python 2 mode. + if !exists('s:python_version') + call neomake#makers#ft#python#DetectPythonVersion() + endif + if s:python_version[0] ==# '2' + call add(args, '--py2') + endif + + return { + \ 'args': args, + \ 'errorformat': + \ '%E%f:%l: error: %m,' . + \ '%W%f:%l: warning: %m,' . + \ '%I%f:%l: note: %m', + \ } +endfunction + +function! neomake#makers#ft#python#py3kwarn() abort + return { + \ 'errorformat': '%W%f:%l:%c: %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/python/compile.py b/.vim/autoload/neomake/makers/ft/python/compile.py new file mode 100755 index 0000000..d211673 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/python/compile.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +from __future__ import print_function +from sys import argv, exit + + +if len(argv) != 2: + exit(64) + +try: + compile(open(argv[1]).read(), argv[1], 'exec', 0, 1) +except SyntaxError as err: + print('%s:%s:%s: %s' % (err.filename, err.lineno, err.offset, err.msg)) + exit(1) diff --git a/.vim/autoload/neomake/makers/ft/r.vim b/.vim/autoload/neomake/makers/ft/r.vim new file mode 100644 index 0000000..59f488a --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/r.vim @@ -0,0 +1,17 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#r#EnabledMakers() abort + return ['lintr'] +endfunction + +function! neomake#makers#ft#r#lintr() abort + return { + \ 'exe': 'R', + \ 'args': ['--slave', '--no-restore', '--no-save', '-e lintr::lint("%t")'], + \ 'append_file': 0, + \ 'errorformat': + \ '%W%f:%l:%c: style: %m,' . + \ '%W%f:%l:%c: warning: %m,' . + \ '%E%f:%l:%c: error: %m,' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/racket.vim b/.vim/autoload/neomake/makers/ft/racket.vim new file mode 100644 index 0000000..fc7145a --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/racket.vim @@ -0,0 +1,32 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#racket#EnabledMakers() abort + return ['raco'] +endfunction + +" This is the same form of syntax-checking used by DrRacket as well. The +" downside is that it will only catch the first error, but none of the +" subsequent ones. This is due to how evaluation in Racket works. +" +" About the error format: raco will print the first line as +" <file>:<line>:<column> <message> +" Every successive line will be indented by two spaces: +" in: <keyword> +" context...: +" <file>:<line>:<column>: <keyword> +" The last pattern will be repeated as often as necessary. Example: +" foo.rkt:4:1: dfine: unbound identifier in modulemessage +" in: dfine +" context...: +" /usr/local/Cellar/racket/6.5/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt:34:15: loop +" /usr/local/Cellar/racket/6.5/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt:10:2: show-program +" /usr/local/Cellar/racket/6.5/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt: [running body] +" /usr/local/Cellar/minimal-racket/6.6/share/racket/collects/raco/raco.rkt: [running body] +" /usr/local/Cellar/minimal-racket/6.6/share/racket/collects/raco/main.rkt: [running body] +function! neomake#makers#ft#racket#raco() abort + return { + \ 'exe': 'raco', + \ 'args': ['expand'], + \ 'errorformat': '%-G %.%#,%E%f:%l:%c: %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/rst.vim b/.vim/autoload/neomake/makers/ft/rst.vim new file mode 100644 index 0000000..a7874ec --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/rst.vim @@ -0,0 +1,89 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#rst#SupersetOf() abort + return 'text' +endfunction + +" Get Sphinx source dir for the current buffer (determined by looking for +" conf.py, typically in docs/ or doc/). +" Caches the value in a buffer-local setting. +function! s:get_sphinx_srcdir() abort + let srcdir = neomake#config#get('sphinx.source_dir') + if srcdir isnot# g:neomake#config#undefined + return srcdir + endif + + let r = '' + let project_root = neomake#utils#get_project_root() + let bufname = bufname('%') + if empty(bufname) + call neomake#log#debug('sphinx: skipping setting of source_dir for empty bufname.', {'bufnr': bufnr('%')}) + return '' + endif + let f = findfile('conf.py', printf('%s;%s', fnamemodify(bufname, ':p:h'), project_root)) + if !empty(f) + let r = fnamemodify(f, ':p:h') + endif + call neomake#log#debug(printf('sphinx: setting b:neomake.sphinx.source_dir=%s.', string(r)), {'bufnr': bufnr('%')}) + call neomake#config#set('b:sphinx.source_dir', r) + return r +endfunction + +function! neomake#makers#ft#rst#EnabledMakers() abort + if executable('sphinx-build') && !empty(s:get_sphinx_srcdir()) + return ['sphinx'] + endif + return ['rstlint', 'rstcheck'] +endfunction + +function! neomake#makers#ft#rst#rstlint() abort + return { + \ 'exe': 'rst-lint', + \ 'errorformat': + \ '%ESEVERE %f:%l %m,'. + \ '%EERROR %f:%l %m,'. + \ '%WWARNING %f:%l %m,'. + \ '%IINFO %f:%l %m,'. + \ '%C%m', + \ 'postprocess': function('neomake#postprocess#compress_whitespace'), + \ 'output_stream': 'stdout', + \ } +endfunction + +function! neomake#makers#ft#rst#rstcheck() abort + return { + \ 'errorformat': + \ '%I%f:%l: (INFO/1) %m,'. + \ '%W%f:%l: (WARNING/2) %m,'. + \ '%E%f:%l: (ERROR/3) %m,'. + \ '%E%f:%l: (SEVERE/4) %m', + \ } +endfunction + +function! neomake#makers#ft#rst#sphinx() abort + " TODO: + " - project mode (after cleanup branch) + let srcdir = s:get_sphinx_srcdir() + if empty(srcdir) + throw 'Neomake: sphinx: could not find conf.py (you can configure sphinx.source_dir)' + endif + if !exists('s:sphinx_cache') + let s:sphinx_cache = tempname() + endif + " NOTE: uses '%Z%m,%-G%.%#' instead of '%C%m,%-G' to include next line in + " multiline errors (fixed in 7.4.203). + return { + \ 'exe': 'sphinx-build', + \ 'args': ['-n', '-E', '-q', '-N', '-b', 'dummy', srcdir, s:sphinx_cache], + \ 'append_file': 0, + \ 'errorformat': + \ '%f:%l: %tARNING: %m,' . + \ '%EWARNING: %f:%l: (SEVER%t/4) %m,' . + \ '%EWARNING: %f:%l: (%tRROR/3) %m,' . + \ '%EWARNING: %f:%l: (%tARNING/2) %m,' . + \ '%Z%m,' . + \ '%-G%.%#', + \ 'output_stream': 'stderr', + \ 'postprocess': function('neomake#postprocess#compress_whitespace'), + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/ruby.vim b/.vim/autoload/neomake/makers/ft/ruby.vim new file mode 100644 index 0000000..ceb6a46 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/ruby.vim @@ -0,0 +1,90 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#ruby#EnabledMakers() abort + return ['flog', 'mri', 'rubocop', 'reek', 'rubylint'] +endfunction + +function! neomake#makers#ft#ruby#rubocop() abort + return { + \ 'args': ['--format', 'emacs', '--force-exclusion', '--display-cop-names'], + \ 'errorformat': '%f:%l:%c: %t: %m,%E%f:%l: %m', + \ 'postprocess': function('neomake#makers#ft#ruby#RubocopEntryProcess'), + \ 'output_stream': 'stdout', + \ } +endfunction + +function! neomake#makers#ft#ruby#RubocopEntryProcess(entry) abort + if a:entry.type ==# 'F' " Fatal error which prevented further processing + let a:entry.type = 'E' + elseif a:entry.type ==# 'E' " Error for important programming issues + let a:entry.type = 'E' + elseif a:entry.type ==# 'W' " Warning for stylistic or minor programming issues + let a:entry.type = 'W' + elseif a:entry.type ==# 'R' " Refactor suggestion + let a:entry.type = 'W' + elseif a:entry.type ==# 'C' " Convention violation + let a:entry.type = 'I' + endif +endfunction + +function! neomake#makers#ft#ruby#rubylint() abort + return { + \ 'exe': 'ruby-lint', + \ 'args': ['--presenter', 'syntastic'], + \ 'errorformat': '%f:%t:%l:%c: %m', + \ } +endfunction + +function! neomake#makers#ft#ruby#mri() abort + let errorformat = '%-G%\m%.%#warning: %\%%(possibly %\)%\?useless use of == in void context,' + let errorformat .= '%-G%\%.%\%.%\%.%.%#,' + let errorformat .= + \ '%-GSyntax OK,'. + \ '%E%f:%l: syntax error\, %m,'. + \ '%Z%p^,'. + \ '%W%f:%l: warning: %m,'. + \ '%Z%p^,'. + \ '%W%f:%l: %m,'. + \ '%-C%.%#' + + return { + \ 'exe': 'ruby', + \ 'args': ['-c', '-T1', '-w'], + \ 'errorformat': errorformat, + \ 'output_stream': 'both', + \ } +endfunction + +function! neomake#makers#ft#ruby#jruby() abort + let errorformat = + \ '%-GSyntax OK for %f,'. + \ '%ESyntaxError in %f:%l: syntax error\, %m,'. + \ '%Z%p^,'. + \ '%W%f:%l: warning: %m,'. + \ '%Z%p^,'. + \ '%W%f:%l: %m,'. + \ '%-C%.%#' + + return { + \ 'exe': 'jruby', + \ 'args': ['-c', '-T1', '-w'], + \ 'errorformat': errorformat + \ } +endfunction + +function! neomake#makers#ft#ruby#reek() abort + return { + \ 'args': ['--format', 'text', '--single-line'], + \ 'errorformat': '%W%f:%l: %m', + \ } +endfunction + +function! neomake#makers#ft#ruby#flog() abort + return { + \ 'errorformat': + \ '%W%m %f:%l-%c,' . + \ '%-G\s%#,' . + \ '%-G%.%#: flog total,' . + \ '%-G%.%#: flog/method average,' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/rust.vim b/.vim/autoload/neomake/makers/ft/rust.vim new file mode 100644 index 0000000..71ddec1 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/rust.vim @@ -0,0 +1,233 @@ +function! neomake#makers#ft#rust#EnabledMakers() abort + return ['cargo'] +endfunction + +function! neomake#makers#ft#rust#rustc() abort + return { + \ 'errorformat': + \ '%-Gerror: aborting due to previous error,'. + \ '%-Gerror: aborting due to %\\d%\\+ previous errors,'. + \ '%-Gerror: Could not compile `%s`.,'. + \ '%Eerror[E%n]: %m,'. + \ '%Eerror: %m,'. + \ '%Wwarning: %m,'. + \ '%Inote: %m,'. + \ '%-Z\ %#-->\ %f:%l:%c,'. + \ '%G\ %#\= %*[^:]: %m,'. + \ '%G\ %#|\ %#%\\^%\\+ %m,'. + \ '%I%>help:\ %#%m,'. + \ '%Z\ %#%m,'. + \ '%-G%.%#', + \ } +endfunction + +function! s:get_cargo_workspace_root() abort + if !exists('b:_neomake_cargo_workspace') + let cmd = 'cargo metadata --no-deps --format-version 1' + let [cd_error, cd_back_cmd] = neomake#utils#temp_cd(expand('%:h')) + if !empty(cd_error) + call neomake#log#debug(printf( + \ 's:get_cargo_workspace_root: failed to cd to buffer directory: %s.', + \ cd_error)) + endif + let output = system(cmd) + if !empty(cd_back_cmd) + exe cd_back_cmd + endif + if v:shell_error + call neomake#log#debug(printf( + \ 'Failed to get cargo metadata for workspace using %s.', + \ string(cmd))) + let b:_neomake_cargo_workspace = '' + else + let json = neomake#compat#json_decode(output) + let b:_neomake_cargo_workspace = json['workspace_root'] + endif + endif + return b:_neomake_cargo_workspace +endfunction + +function! s:get_cargo_maker_cwd(default) abort + let cargo_workspace_root = s:get_cargo_workspace_root() + if !empty(cargo_workspace_root) + return cargo_workspace_root + endif + + let cargo_toml = neomake#utils#FindGlobFile('Cargo.toml') + if !empty(cargo_toml) + return fnamemodify(cargo_toml, ':h') + endif + + return a:default +endfunction + +function! neomake#makers#ft#rust#cargotest() abort + " NOTE: duplicates are removed due to https://github.com/rust-lang/cargo/issues/5128. + let maker = { + \ 'exe': 'cargo', + \ 'args': ['test', '%:t:r', '--quiet'], + \ 'append_file': 0, + \ 'uses_filename': 0, + \ 'postprocess': copy(g:neomake#postprocess#remove_duplicates), + \ 'errorformat': + \ '%-G,' . + \ '%-Gtest %s,' . + \ '%-Grunning %\\d%# test%s,' . + \ '%-Gfailures:%s,' . + \ '%-G----%s,' . + \ '%-G%.%#--verbose%s,' . + \ '%-G%.%#--explain%s,' . + \ '%-Gerror: aborting due to previous error,' . + \ '%-G%\ %#error: aborting due to %\\d%#%\ %#previous errors,' . + \ '%E%\ %#error[E%n]:\ %m,' . + \ '%E%\ %#error:\ %m,' . + \ '%I%\ %#note:\ %m,'. + \ '%W%\ %#warning:\ %m,' . + \ '%-Z%\ %#-->\ %f:%l:%c,' . + \ '%-G%\\d%# %#|\ %s,' . + \ '%-G%\\d%# %#|,' . + \ '%-G\ %#\= %*[^:]:\ %m,'. + \ '%E%\ %#%m,' . + \ '%G%\ %#%s%\\,,' . + \ '%Z%\ %#%s%\\,%\\s%f:%l:%c' + \ } + + function! maker.InitForJob(_jobinfo) abort + if !has_key(self, 'cwd') + let self.cwd = s:get_cargo_maker_cwd('%:p:h') + return self + endif + endfunction + return maker +endfunction + +function! neomake#makers#ft#rust#cargo() abort + let maker_command = get(b:, 'neomake_rust_cargo_command', + \ get(g:, 'neomake_rust_cargo_command', ['check'])) + let maker = { + \ 'args': maker_command + ['--message-format=json', '--quiet'], + \ 'append_file': 0, + \ 'process_output': function('neomake#makers#ft#rust#CargoProcessOutput'), + \ } + + function! maker.InitForJob(_jobinfo) abort + if !has_key(self, 'cwd') + let self.cwd = s:get_cargo_maker_cwd('%:p:h') + return self + endif + endfunction + return maker +endfunction + +" NOTE: does not use process_json, since cargo outputs multiple JSON root +" elements per line. +function! neomake#makers#ft#rust#CargoProcessOutput(context) abort + let errors = [] + for line in a:context['output'] + if line[0] !=# '{' + continue + endif + + let decoded = neomake#compat#json_decode(line) + let data = get(decoded, 'message', -1) + if type(data) != type({}) || empty(data['spans']) + continue + endif + + let error = {'maker_name': 'cargo'} + let code_dict = get(data, 'code', -1) + if code_dict is g:neomake#compat#json_null + if get(data, 'level', '') ==# 'warning' + let error.type = 'W' + else + let error.type = 'E' + endif + else + let error.type = code_dict['code'][0] + let error.nr = code_dict['code'][1:] + endif + + let span = data.spans[0] + for candidate_span in data.spans + if candidate_span.is_primary + let span = candidate_span + break + endif + endfor + + let expanded = 0 + let has_expansion = type(span.expansion) == type({}) + \ && type(span.expansion.span) == type({}) + \ && type(span.expansion.def_site_span) == type({}) + + if span.file_name =~# '^<.*>$' && has_expansion + let expanded = 1 + call neomake#makers#ft#rust#FillErrorFromSpan(error, + \ span.expansion.span) + else + call neomake#makers#ft#rust#FillErrorFromSpan(error, span) + endif + + let error.text = data.message + let detail = span.label + let children = data.children + if type(detail) == type('') && !empty(detail) + let error.text = error.text . ': ' . detail + elseif !empty(children) && has_key(children[0], 'message') + let error.text = error.text . '. ' . children[0].message + endif + + call add(errors, error) + + if has_expansion && !expanded + let error = copy(error) + call neomake#makers#ft#rust#FillErrorFromSpan(error, + \ span.expansion.span) + call add(errors, error) + endif + + for child in children[1:] + if !has_key(child, 'message') + continue + endif + + let info = deepcopy(error) + let info.type = 'I' + let info.text = child.message + call neomake#postprocess#compress_whitespace(info) + if has_key(child, 'rendered') + \ && !(child.rendered is g:neomake#compat#json_null) + let info.text = info.text . ': ' . child.rendered + endif + + if len(child.spans) + let span = child.spans[0] + if span.file_name =~# '^<.*>$' + \ && type(span.expansion) == type({}) + \ && type(span.expansion.span) == type({}) + \ && type(span.expansion.def_site_span) == type({}) + call neomake#makers#ft#rust#FillErrorFromSpan(info, + \ span.expansion.span) + else + call neomake#makers#ft#rust#FillErrorFromSpan(info, span) + endif + let detail = span.label + if type(detail) == type('') && len(detail) + let info.text = info.text . ': ' . detail + endif + endif + + call add(errors, info) + endfor + endfor + return errors +endfunction + +function! neomake#makers#ft#rust#FillErrorFromSpan(error, span) abort + let a:error.filename = a:span.file_name + let a:error.col = a:span.column_start + let a:error.lnum = a:span.line_start + let a:error.length = a:span.byte_end - a:span.byte_start +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/scala.vim b/.vim/autoload/neomake/makers/ft/scala.vim new file mode 100644 index 0000000..0899881 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/scala.vim @@ -0,0 +1,40 @@ +" vim: ts=4 sw=4 et +function! neomake#makers#ft#scala#EnabledMakers() abort + " use let g:neomake_scala_enabled_makers = ['fsc','scalastyle'] for fsc + let makers = ['scalac', 'scalastyle'] + return makers +endfunction + +function! neomake#makers#ft#scala#fsc() abort + return { + \ 'args': [ + \ '-Ystop-after:parser' + \ ], + \ 'errorformat': + \ '%E%f:%l: %trror: %m,' . + \ '%Z%p^,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#scala#scalac() abort + return { + \ 'args': [ + \ '-Ystop-after:parser' + \ ], + \ 'errorformat': + \ '%E%f:%l: %trror: %m,' . + \ '%Z%p^,' . + \ '%-G%.%#' + \ } +endfunction + +function! neomake#makers#ft#scala#scalastyle() abort + return { + \ 'errorformat': + \ '%trror file=%f message=%m line=%l column=%c,' . + \ '%trror file=%f message=%m line=%l,' . + \ '%tarning file=%f message=%m line=%l column=%c,' . + \ '%tarning file=%f message=%m line=%l' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/scss.vim b/.vim/autoload/neomake/makers/ft/scss.vim new file mode 100644 index 0000000..e33ea6f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/scss.vim @@ -0,0 +1,25 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#scss#EnabledMakers() abort + return executable('stylelint') ? ['stylelint'] : executable('sass-lint') ? ['sasslint'] : ['scsslint'] +endfunction + +function! neomake#makers#ft#scss#sasslint() abort + return { + \ 'exe': 'sass-lint', + \ 'args': ['--no-exit', '--verbose', '--format', 'compact'], + \ 'errorformat': neomake#makers#ft#javascript#eslint()['errorformat'] + \ } +endfunction + +function! neomake#makers#ft#scss#scsslint() abort + return { + \ 'exe': 'scss-lint', + \ 'errorformat': '%A%f:%l:%v [%t] %m,' . + \ '%A%f:%l [%t] %m' + \ } +endfunction + +function! neomake#makers#ft#scss#stylelint() abort + return neomake#makers#ft#css#stylelint() +endfunction diff --git a/.vim/autoload/neomake/makers/ft/serpent.vim b/.vim/autoload/neomake/makers/ft/serpent.vim new file mode 100644 index 0000000..eff20ba --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/serpent.vim @@ -0,0 +1,13 @@ +function! neomake#makers#ft#serpent#EnabledMakers() abort + return ['serplint'] +endfunction + +function! neomake#makers#ft#serpent#serplint() abort + return { + \ 'exe': 'serplint', + \ 'args': [], + \ 'errorformat': + \ '%f:%l:%c %t%n %m', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/sh.vim b/.vim/autoload/neomake/makers/ft/sh.vim new file mode 100644 index 0000000..00889b9 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/sh.vim @@ -0,0 +1,86 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#sh#EnabledMakers() abort + return ['sh', 'shellcheck'] +endfunction + +let s:shellcheck = { + \ 'args': ['-fgcc', '-x'], + \ 'errorformat': + \ '%f:%l:%c: %trror: %m [SC%n],' . + \ '%f:%l:%c: %tarning: %m [SC%n],' . + \ '%I%f:%l:%c: Note: %m [SC%n]', + \ 'output_stream': 'stdout', + \ 'short_name': 'SC', + \ 'cwd': '%:h', + \ } + +function! neomake#makers#ft#sh#shellcheck() abort + let maker = deepcopy(s:shellcheck) + + let line1 = getline(1) + if match(line1, '\v^#!.*<%(sh|dash|bash|ksh)') < 0 + \ && match(line1, '\v^#\s*shellcheck\s+shell\=') < 0 + " shellcheck does not read the shebang by itself. + let ext = expand('%:e') + if ext ==# 'ksh' + let maker.args += ['-s', 'ksh'] + elseif ext ==# 'sh' + if exists('g:is_sh') + let maker.args += ['-s', 'sh'] + elseif exists('g:is_posix') || exists('g:is_kornshell') + let maker.args += ['-s', 'ksh'] + else + let maker.args += ['-s', 'bash'] + endif + else + let maker.args += ['-s', 'bash'] + endif + endif + return maker +endfunction + +function! neomake#makers#ft#sh#checkbashisms() abort + return { + \ 'args': ['-fx'], + \ 'errorformat': + \ '%-Gscript %f is already a bash script; skipping,' . + \ '%Eerror: %f: %m\, opened in line %l,' . + \ '%Eerror: %f: %m,' . + \ '%Ecannot open script %f for reading: %m,' . + \ '%Wscript %f %m,%C%.# lines,' . + \ '%Wpossible bashism in %f line %l (%m):,%C%.%#,%Z.%#,' . + \ '%-G%.%#', + \ 'output_stream': 'stderr', + \ } +endfunction + +function! neomake#makers#ft#sh#sh() abort + let shebang = matchstr(getline(1), '^#!\s*\zs.*$') + if !empty(shebang) + let l = split(shebang) + let exe = l[0] + let args = l[1:] + ['-n'] + else + let exe = '/usr/bin/env' + let args = ['sh', '-n'] + endif + + " NOTE: the format without "line" is used by dash. + return { + \ 'exe': exe, + \ 'args': args, + \ 'errorformat': + \ '%E%f: line %l: %m,' . + \ '%E%f: %l: %m', + \ 'output_stream': 'stderr', + \} +endfunction + +function! neomake#makers#ft#sh#dash() abort + return { + \ 'args': ['-n'], + \ 'errorformat': '%E%f: %l: %m', + \ 'output_stream': 'stderr', + \} +endfunction diff --git a/.vim/autoload/neomake/makers/ft/slim.vim b/.vim/autoload/neomake/makers/ft/slim.vim new file mode 100644 index 0000000..931f57f --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/slim.vim @@ -0,0 +1,13 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#slim#EnabledMakers() abort + return ['slimlint'] +endfunction + +function! neomake#makers#ft#slim#slimlint() abort + return { + \ 'exe': 'slim-lint', + \ 'args': ['--no-color'], + \ 'errorformat': '%f:%l [%t] %m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/sml.vim b/.vim/autoload/neomake/makers/ft/sml.vim new file mode 100644 index 0000000..46e0bd0 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/sml.vim @@ -0,0 +1,19 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#sml#EnabledMakers() abort + return ['smlnj'] +endfunction + +" This comes straight out of syntastic. +function! neomake#makers#ft#sml#smlnj() abort + return { + \ 'exe': 'sml', + \ 'errorformat': + \ '%E%f:%l%\%.%c %trror: %m,' . + \ '%E%f:%l%\%.%c-%\d%\+%\%.%\d%\+ %trror: %m,' . + \ '%W%f:%l%\%.%c %tarning: %m,' . + \ '%W%f:%l%\%.%c-%\d%\+%\%.%\d%\+ %tarning: %m,' . + \ '%C%\s%\+%m,' . + \ '%-G%.%#' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/solidity.vim b/.vim/autoload/neomake/makers/ft/solidity.vim new file mode 100644 index 0000000..200e910 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/solidity.vim @@ -0,0 +1,16 @@ +function! neomake#makers#ft#solidity#EnabledMakers() abort + return ['solium', 'solhint'] +endfunction + +function! neomake#makers#ft#solidity#solium() abort + return { + \ 'args': ['--reporter', 'gcc', '--file'], + \ 'errorformat': + \ '%f:%l:%c: %t%s: %m', + \ } +endfunction + +function! neomake#makers#ft#solidity#solhint() abort + return neomake#makers#ft#javascript#eslint() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/spar.vim b/.vim/autoload/neomake/makers/ft/spar.vim new file mode 100644 index 0000000..9efe7a1 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/spar.vim @@ -0,0 +1,13 @@ +function! neomake#makers#ft#spar#EnabledMakers() abort + return ['spar'] +endfunction + +function! neomake#makers#ft#spar#spar() abort + return { + \ 'args': ['-g', '-c'], + \ 'errorformat': + \ '%f:%l:%c: %m', + \ 'nvim_job_opts': {'pty': 1} + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/spec.vim b/.vim/autoload/neomake/makers/ft/spec.vim new file mode 100644 index 0000000..2723340 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/spec.vim @@ -0,0 +1,16 @@ +function! neomake#makers#ft#spec#EnabledMakers() abort + return ['rpmlint'] +endfunction + +function! neomake#makers#ft#spec#rpmlint() abort + return { + \ 'errorformat': + \ '%E%f:%l: E: %m,' . + \ '%E%f: E: %m,' . + \ '%W%f:%l: W: %m,' . + \ '%W%f: W: %m,' . + \ '%-G%.%#' + \ } +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/sql.vim b/.vim/autoload/neomake/makers/ft/sql.vim new file mode 100644 index 0000000..bdbfdfa --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/sql.vim @@ -0,0 +1,13 @@ +function! neomake#makers#ft#sql#EnabledMakers() abort + return ['sqlint'] +endfunction + +function! neomake#makers#ft#sql#sqlint() abort + return { + \ 'errorformat': + \ '%E%f:%l:%c:ERROR %m,' . + \ '%W%f:%l:%c:WARNING %m,' . + \ '%C %m' + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/stylus.vim b/.vim/autoload/neomake/makers/ft/stylus.vim new file mode 100644 index 0000000..113a194 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/stylus.vim @@ -0,0 +1,16 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#stylus#EnabledMakers() abort + return ['stylint'] +endfunction + +function! neomake#makers#ft#stylus#stylint() abort + return { + \ 'errorformat': + \ '%WWarning: %m,' . + \ '%EError: %m,' . + \ '%-Csee file: %f for the original selector,' . + \ '%CFile: %f,' . + \ '%ZLine: %l:%.%#' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/swift.vim b/.vim/autoload/neomake/makers/ft/swift.vim new file mode 100644 index 0000000..76bb440 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/swift.vim @@ -0,0 +1,54 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#swift#EnabledMakers() abort + if !empty(s:get_swiftpm_config()) + return ['swiftpm'] + endif + return ['swiftc'] +endfunction + +function! s:get_swiftpm_config() abort + return neomake#utils#FindGlobFile('Package.swift') +endfunction + +function! s:get_swiftpm_base_maker() abort + let maker = { + \ 'exe': 'swift', + \ 'append_file': 0, + \ 'errorformat': + \ '%E%f:%l:%c: error: %m,' . + \ '%E%f:%l: error: %m,' . + \ '%W%f:%l:%c: warning: %m,' . + \ '%Z%\s%#^~%#,' . + \ '%-G%.%#', + \ } + let config = s:get_swiftpm_config() + if !empty(config) + let maker.cwd = fnamemodify(config, ':h') + endif + return maker +endfunction + +function! neomake#makers#ft#swift#swiftpm() abort + let maker = s:get_swiftpm_base_maker() + let maker.args = ['build', '--build-tests'] + return maker +endfunction + +function! neomake#makers#ft#swift#swiftpmtest() abort + let maker = s:get_swiftpm_base_maker() + let maker.args = ['test'] + return maker +endfunction + +function! neomake#makers#ft#swift#swiftc() abort + " `export SDKROOT="$(xcodebuild -version -sdk macosx Path)"` + return { + \ 'args': ['-parse'], + \ 'errorformat': + \ '%E%f:%l:%c: error: %m,' . + \ '%W%f:%l:%c: warning: %m,' . + \ '%Z%\s%#^~%#,' . + \ '%-G%.%#', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/tcl.vim b/.vim/autoload/neomake/makers/ft/tcl.vim new file mode 100644 index 0000000..76c5af4 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/tcl.vim @@ -0,0 +1,15 @@ +function! neomake#makers#ft#tcl#EnabledMakers() abort + return ['nagelfar'] +endfunction + +function! neomake#makers#ft#tcl#nagelfar() abort + return { + \ 'exe': 'nagelfar', + \ 'args': ['-H'], + \ 'errorformat': + \ '%I%f: %l: N %m,' . + \ '%f: %l: %t %m,' . + \ '%-GChecking file %f' + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/tex.vim b/.vim/autoload/neomake/makers/ft/tex.vim new file mode 100644 index 0000000..9fca53b --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/tex.vim @@ -0,0 +1,69 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#tex#EnabledMakers() abort + return ['chktex', 'lacheck', 'rubberinfo', 'proselint'] +endfunction + +function! neomake#makers#ft#tex#chktex() abort + let maker = { + \ 'args': [], + \ 'errorformat': + \ '%EError %n in %f line %l: %m,' . + \ '%WWarning %n in %f line %l: %m,' . + \ '%WMessage %n in %f line %l: %m,' . + \ '%Z%p^,' . + \ '%-G%.%#' + \ } + let rcfile = neomake#utils#FindGlobFile('.chktexrc') + if !empty(rcfile) + let maker.args += ['-l', fnamemodify(rcfile, ':h')] + endif + return maker +endfunction + +function! neomake#makers#ft#tex#lacheck() abort + return { + \ 'errorformat': + \ '%-G** %f:,' . + \ '%E"%f"\, line %l: %m' + \ } +endfunction + +function! neomake#makers#ft#tex#rubber() abort + return { + \ 'args': ['--pdf', '-f', '--warn=all'], + \ 'errorformat': + \ '%f:%l: %m,' . + \ '%f: %m' + \ } +endfunction + +function! neomake#makers#ft#tex#rubberinfo() abort + return { + \ 'exe': 'rubber-info', + \ 'errorformat': + \ '%f:%l: %m,' . + \ '%f:%l-%\d%\+: %m,' . + \ '%f: %m' + \ } +endfunction + +function! neomake#makers#ft#tex#latexrun() abort + return { + \ 'args': ['--color', 'never'], + \ 'errorformat': + \ '%f:%l: %m' + \ } +endfunction + +function! neomake#makers#ft#tex#pdflatex() abort + return { + \ 'exe': 'pdflatex', + \ 'args': ['-shell-escape', '-file-line-error', '-interaction', 'nonstopmode'], + \ 'errorformat': '%E%f:%l: %m' + \ } +endfunction + +function! neomake#makers#ft#tex#proselint() abort + return neomake#makers#ft#text#proselint() +endfunction diff --git a/.vim/autoload/neomake/makers/ft/text.vim b/.vim/autoload/neomake/makers/ft/text.vim new file mode 100644 index 0000000..a1ebe0a --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/text.vim @@ -0,0 +1,30 @@ +function! neomake#makers#ft#text#EnabledMakers() abort + " No makers enabled by default, since text is used as fallback often. + return [] +endfunction + +function! neomake#makers#ft#text#proselint() abort + return { + \ 'errorformat': '%W%f:%l:%c: %m', + \ 'postprocess': function('neomake#postprocess#generic_length'), + \ } +endfunction + +function! neomake#makers#ft#text#PostprocessWritegood(entry) abort + let a:entry.col += 1 + if a:entry.text[0] ==# '"' + let matchend = match(a:entry.text, '\v^[^"]+\zs"', 1) + if matchend != -1 + let a:entry.length = matchend - 1 + endif + endif +endfunction + +function! neomake#makers#ft#text#writegood() abort + return { + \ 'args': ['--parse'], + \ 'errorformat': '%W%f:%l:%c:%m,%C%m,%-G', + \ 'postprocess': function('neomake#makers#ft#text#PostprocessWritegood'), + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/toml.vim b/.vim/autoload/neomake/makers/ft/toml.vim new file mode 100644 index 0000000..d314911 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/toml.vim @@ -0,0 +1,15 @@ +function! neomake#makers#ft#toml#EnabledMakers() abort + return ['tomlcheck'] +endfunction + +function! neomake#makers#ft#toml#tomlcheck() abort + return { + \ 'args': ['-f'], + \ 'errorformat': + \ '%E%f:%l:%c:,' . + \ '%E%m' + \ } +endfunction + +" vim: et sw=4 ts=4 +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/tsx.vim b/.vim/autoload/neomake/makers/ft/tsx.vim new file mode 100644 index 0000000..2a31b4d --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/tsx.vim @@ -0,0 +1,15 @@ +function! neomake#makers#ft#tsx#SupersetOf() abort + return 'typescript' +endfunction + +function! neomake#makers#ft#tsx#EnabledMakers() abort + return ['tsc', 'tslint'] +endfunction + +function! neomake#makers#ft#tsx#tsc() abort + let config = neomake#makers#ft#typescript#tsc() + let config.args = config.args + ['--jsx', 'preserve'] + return config +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/typescript.vim b/.vim/autoload/neomake/makers/ft/typescript.vim new file mode 100644 index 0000000..4d011b7 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/typescript.vim @@ -0,0 +1,45 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#typescript#EnabledMakers() abort + return ['tsc', 'tslint'] +endfunction + +function! neomake#makers#ft#typescript#tsc() abort + " tsc should not be passed a single file. + let maker = { + \ 'args': ['--noEmit', '--watch', 'false', '--pretty', 'false'], + \ 'append_file': 0, + \ 'errorformat': + \ '%E%f %#(%l\,%c): error %m,' . + \ '%E%f %#(%l\,%c): %m,' . + \ '%Eerror %m,' . + \ '%C%\s%\+%m' + \ } + let config = neomake#utils#FindGlobFile('tsconfig.json') + if !empty(config) + let maker.args += ['--project', config] + endif + return maker +endfunction + +function! neomake#makers#ft#typescript#tslint() abort + " NOTE: output format changed in tslint 5.12.0. + let maker = { + \ 'args': ['-t', 'prose'], + \ 'errorformat': '%-G,' + \ .'%EERROR: %f:%l:%c - %m,' + \ .'%WWARNING: %f:%l:%c - %m,' + \ .'%EERROR: %f[%l\, %c]: %m,' + \ .'%WWARNING: %f[%l\, %c]: %m', + \ } + let config = neomake#utils#FindGlobFile('tsconfig.json') + if !empty(config) + let maker.args += ['--project', config] + let maker.cwd = fnamemodify(config, ':h') + endif + return maker +endfunction + +function! neomake#makers#ft#typescript#eslint() abort + return neomake#makers#ft#javascript#eslint() +endfunction diff --git a/.vim/autoload/neomake/makers/ft/verilog.vim b/.vim/autoload/neomake/makers/ft/verilog.vim new file mode 100644 index 0000000..78d9189 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/verilog.vim @@ -0,0 +1,16 @@ +function! neomake#makers#ft#verilog#EnabledMakers() abort + return ['iverilog'] +endfunction + +function! neomake#makers#ft#verilog#iverilog() abort + return { + \ 'args' : ['-tnull', '-Wall', '-y./'], + \ 'cwd' : '%:h', + \ 'errorformat' : '%f:%l: %trror: %m,' . + \ '%f:%l: %tarning: %m,' . + \ '%E%f:%l: : %m,' . + \ '%W%f:%l: : %m,' . + \ '%f:%l: %m', + \ } +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/vhdl.vim b/.vim/autoload/neomake/makers/ft/vhdl.vim new file mode 100644 index 0000000..dffa813 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/vhdl.vim @@ -0,0 +1,12 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#vhdl#EnabledMakers() abort + return ['ghdl'] +endfunction + +function! neomake#makers#ft#vhdl#ghdl() abort + return { + \ 'args' : ['-s'], + \ 'errorformat' : '%E%f:%l:%c: %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/vim.vim b/.vim/autoload/neomake/makers/ft/vim.vim new file mode 100644 index 0000000..8cd1318 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/vim.vim @@ -0,0 +1,87 @@ +function! neomake#makers#ft#vim#EnabledMakers() abort + return ['vint'] +endfunction + +let s:slash = neomake#utils#Slash() +let s:neomake_root = expand('<sfile>:p:h:h:h:h:h', 1) + +let s:vint_supports_stdin = {} + +function! neomake#makers#ft#vim#neomake_checks() abort + let maker = { + \ 'exe': join([s:neomake_root, 'contrib', 'vim-checks'], s:slash), + \ 'errorformat': '%f:%l: %m', + \ } + + return maker +endfunction + +function! neomake#makers#ft#vim#vint() abort + let args = ['--style-problem', '--no-color', + \ '-f', '{file_path}:{line_number}:{column_number}:{severity}:{description} ({policy_name})'] + + if has('nvim') + call add(args, '--enable-neovim') + endif + + let maker = { + \ 'args': args, + \ 'errorformat': '%I%f:%l:%c:style_problem:%m,' + \ .'%f:%l:%c:%t%*[^:]:E%n: %m,' + \ .'%f:%l:%c:%t%*[^:]:%m', + \ 'output_stream': 'stdout', + \ 'postprocess': { + \ 'fn': function('neomake#postprocess#generic_length'), + \ 'pattern': '\v%(^:|%([^:]+: ))\zs(\S+)', + \ }} + + function! maker.supports_stdin(_jobinfo) abort + let exe = exists('*exepath') ? exepath(self.exe) : self.exe + let support = get(s:vint_supports_stdin, exe, -1) + if support == -1 + let ver = neomake#compat#systemlist(['vint', '--version']) + let ver_split = split(ver[0], '\.') + if len(ver_split) > 1 && (ver_split[0] > 0 || +ver_split[1] >= 4) + let support = 1 + else + let support = 0 + endif + let s:vint_supports_stdin[exe] = support + call neomake#log#debug('vint: stdin support: '.support.'.') + endif + if support + let self.args += ['--stdin-display-name', '%:.'] + endif + return support + endfunction + return maker +endfunction + +function! neomake#makers#ft#vim#vimlint() abort + return { + \ 'args': ['-u'], + \ 'errorformat': '%f:%l:%c:%trror: EVL%n: %m,' + \ . '%f:%l:%c:%tarning: EVL%n: %m,' + \ . '%f:%l:%c:%t%*[^:]: EVP_%#E%#%n: %m', + \ 'postprocess': function('neomake#makers#ft#vim#PostprocessVimlint'), + \ 'output_stream': 'stdout', + \ } +endfunction + +function! neomake#makers#ft#vim#PostprocessVimlint(entry) abort + let m = matchlist(a:entry.text, '\v`\zs[^`]{-}\ze`') + if empty(m) + return + endif + + " Ensure that the text is there. + let l = len(m[0]) + let line = getline(a:entry.lnum) + if line[a:entry.col-1 : a:entry.col-2+l] == m[0] + let a:entry.length = l + elseif m[0][0:1] ==# 'l:' && line[a:entry.col-1 : a:entry.col-4+l] == m[0][2:] + " Ignore implicit 'l:' prefix. + let a:entry.length = l - 2 + endif +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/vue.vim b/.vim/autoload/neomake/makers/ft/vue.vim new file mode 100644 index 0000000..d9f5303 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/vue.vim @@ -0,0 +1,28 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#vue#EnabledMakers() abort + return ['eslint', 'standard'] +endfunction + +function! neomake#makers#ft#vue#eslint() abort + let maker = neomake#makers#ft#javascript#eslint() + call extend(get(maker, 'args', []), ['--plugin', 'html']) + return maker +endfunction + +function! neomake#makers#ft#vue#eslint_d() abort + return neomake#makers#ft#vue#eslint() +endfunction + +function! neomake#makers#ft#vue#standard() abort + let maker = neomake#makers#ft#javascript#standard() + call extend(get(maker, 'args', []), ['--plugin', 'html']) + return maker +endfunction + +function! neomake#makers#ft#vue#semistandard() abort + let maker = neomake#makers#ft#javascript#semistandard() + call extend(get(maker, 'args', []), ['--plugin', 'html']) + return maker +endfunction + diff --git a/.vim/autoload/neomake/makers/ft/xml.vim b/.vim/autoload/neomake/makers/ft/xml.vim new file mode 100644 index 0000000..75b6996 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/xml.vim @@ -0,0 +1,25 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#xml#EnabledMakers() abort + return ['xmllint'] +endfunction + +function! neomake#makers#ft#xml#xmllint() abort + let args = ['--xinclude', '--postvalid', '--noout'] + + return { + \ 'args': args, + \ 'supports_stdin': 1, + \ 'errorformat': + \ '%E%f:%l: error : %m,' . + \ '%-G%f:%l: validity error : Validation failed: no DTD found %m,' . + \ '%W%f:%l: warning : %m,' . + \ '%W%f:%l: validity warning : %m,' . + \ '%E%f:%l: validity error : %m,' . + \ '%E%f:%l: parser error : %m,' . + \ '%E%f:%l: %m,' . + \ '%-Z%p^,' . + \ '%-C%.%#,' . + \ '%-G%.%#', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/xslt.vim b/.vim/autoload/neomake/makers/ft/xslt.vim new file mode 100644 index 0000000..61bcf02 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/xslt.vim @@ -0,0 +1,8 @@ +function! neomake#makers#ft#xslt#EnabledMakers() abort + return ['xmllint'] +endfunction + +function! neomake#makers#ft#xslt#xmllint() abort + return neomake#makers#ft#xml#xmllint() +endfunction +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/makers/ft/yacc.vim b/.vim/autoload/neomake/makers/ft/yacc.vim new file mode 100644 index 0000000..8a2edd5 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/yacc.vim @@ -0,0 +1,17 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#yacc#EnabledMakers() abort + return ['bison'] +endfunction + +function! neomake#makers#ft#yacc#bison() abort + return { + \ 'errorformat': + \ '%E%f:%l%.%v-%.%\{-}: %trror: %m,' . + \ '%E%f:%l%.%v: %trror: %m,' . + \ '%W%f:%l%.%v-%.%\{-}: %tarning: %m,' . + \ '%W%f:%l%.%v: %tarning: %m,' . + \ '%I%f:%l%.%v-%.%\{-}: %\s%\+%m,' . + \ '%I%f:%l%.%v: %\s%\+%m' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/yaml.vim b/.vim/autoload/neomake/makers/ft/yaml.vim new file mode 100644 index 0000000..338ca8c --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/yaml.vim @@ -0,0 +1,12 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#yaml#EnabledMakers() abort + return ['yamllint'] +endfunction + +function! neomake#makers#ft#yaml#yamllint() abort + return { + \ 'args': ['-f', 'parsable'], + \ 'errorformat': '%E%f:%l:%c: [error] %m,%W%f:%l:%c: [warning] %m', + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/ft/zsh.vim b/.vim/autoload/neomake/makers/ft/zsh.vim new file mode 100644 index 0000000..a63e365 --- /dev/null +++ b/.vim/autoload/neomake/makers/ft/zsh.vim @@ -0,0 +1,19 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#ft#zsh#EnabledMakers() abort + return ['zsh'] +endfunction + +" Note: newer versions of shellcheck do not support zsh. +function! neomake#makers#ft#zsh#shellcheck() abort + let maker = neomake#makers#ft#sh#shellcheck() + let maker.args += ['--shell', 'zsh'] + return maker +endfunction + +function! neomake#makers#ft#zsh#zsh() abort + return { + \ 'args': ['-n'], + \ 'errorformat': '%E%f:%l: %m' + \} +endfunction diff --git a/.vim/autoload/neomake/makers/gradle.vim b/.vim/autoload/neomake/makers/gradle.vim new file mode 100644 index 0000000..de892a7 --- /dev/null +++ b/.vim/autoload/neomake/makers/gradle.vim @@ -0,0 +1,28 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#gradle#gradle() abort + let g:gradleBin = filereadable('./gradlew') ? './gradlew' : 'gradle' + + return { + \ 'exe': g:gradleBin, + \ 'append_file': 0, + \ 'args': ['assemble', '--daemon'], + \ 'errorformat': '\%+ATask\ %.%#\ not\ found\ %.%#.,'. + \'%EExecution\ failed\ for\ task\ %m,'. + \'findbugs:\ %tarning\ %f:%l:%c\ %m,'. + \'pmd:\ %tarning\ %f:%l:%c\ %m,'. + \'checkstyle:\ %tarning\ %f:%l:%c\ %m,'. + \'lint:\ %tarning\ %f:%l:%c\ %m,'. + \'%A>\ %f:%l:%c:\ %trror:\ %m,'. + \'%A>\ %f:%l:%c:\ %tarning:\ %m,'. + \'%A%f:%l:\ %trror:\ %m,'. + \'%A%f:%l:\ %tarning:\ %m,'. + \'%A%f:%l:\ %trror\ -\ %m,'. + \'%A%f:%l:\ %tarning\ -\ %m,'. + \'%E%f:%l\ :\ %m,'. + \'%C>\ %m,'. + \'%-G%p^,'. + \'%+G\ \ %.%#,'. + \'%-G%.%#' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/mvn.vim b/.vim/autoload/neomake/makers/mvn.vim new file mode 100644 index 0000000..cac2a80 --- /dev/null +++ b/.vim/autoload/neomake/makers/mvn.vim @@ -0,0 +1,9 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#mvn#mvn() abort + return { + \ 'exe': 'mvn', + \ 'args': ['install'], + \ 'errorformat': '[%tRROR]\ %f:[%l]\ %m,%-G%.%#' + \ } +endfunction diff --git a/.vim/autoload/neomake/makers/sbt.vim b/.vim/autoload/neomake/makers/sbt.vim new file mode 100644 index 0000000..93e233b --- /dev/null +++ b/.vim/autoload/neomake/makers/sbt.vim @@ -0,0 +1,13 @@ +" vim: ts=4 sw=4 et + +function! neomake#makers#sbt#sbt() abort + return { + \ 'exe': 'sbt', + \ 'args': ['-Dsbt.log.noformat=true', 'compile'], + \ 'errorformat': + \ '%E[%trror]\ %f:%l:%c:\ %m,' . + \ '%-Z[error]\ %p^,' . + \ '%-C%.%#,' . + \ '%-G%.%#' + \ } +endfunction diff --git a/.vim/autoload/neomake/postprocess.vim b/.vim/autoload/neomake/postprocess.vim new file mode 100644 index 0000000..d92a897 --- /dev/null +++ b/.vim/autoload/neomake/postprocess.vim @@ -0,0 +1,77 @@ +" Generic postprocessor to add `length` to `a:entry`. +" The pattern can be overridden on `self` and should adhere to this: +" - the matched word should be returned as the whole match (you can use \zs +" and \ze). +" - enclosing patterns should be returned as \1 and \2, where \1 is used as +" offset when the first entry did not match. +" See tests/postprocess.vader for tests/examples. +" See neomake#postprocess#generic_length_with_pattern for a non-dict variant. +function! neomake#postprocess#generic_length(entry) abort dict + if a:entry.lnum > 0 && a:entry.col + let pattern = get(self, 'pattern', '\v(["''`])\zs[^\1]{-}\ze(\1)') + let start = 0 + let best = 0 + while 1 + let m = matchlist(a:entry.text, pattern, start) + if empty(m) + break + endif + let l = len(m[0]) + if l > best + " Ensure that the text is there. + let line = get(getbufline(a:entry.bufnr, a:entry.lnum), 0, '') + if line[a:entry.col-1 : a:entry.col-2+l] == m[0] + let best = l + endif + endif + if exists('*matchstrpos') " vim73 + let pos = matchstrpos(a:entry.text, pattern, start) + if pos[1] == -1 + break + endif + let start += pos[2] + len(m[2]) + else + break + endif + endwhile + if best + let a:entry.length = best + endif + endif +endfunction + +" Wrapper to call neomake#process#generic_length (a dict function). +function! neomake#postprocess#generic_length_with_pattern(entry, pattern) abort + let this = {'pattern': a:pattern} + return call('neomake#postprocess#generic_length', [a:entry], this) +endfunction + +" Deprecated: renamed to neomake#postprocess#generic_length. +function! neomake#postprocess#GenericLengthPostprocess(entry) abort dict + return neomake#postprocess#generic_length(a:entry) +endfunction + +function! neomake#postprocess#compress_whitespace(entry) abort + let text = a:entry.text + let text = substitute(text, "\001", '', 'g') + let text = substitute(text, '\r\?\n', ' ', 'g') + let text = substitute(text, '\m\s\{2,}', ' ', 'g') + let text = substitute(text, '\m^\s\+', '', '') + let text = substitute(text, '\m\s\+$', '', '') + let a:entry.text = text +endfunction + +let g:neomake#postprocess#remove_duplicates = {} +function! g:neomake#postprocess#remove_duplicates.fn(entry) abort + if exists('self._seen_entries') + if index(self._seen_entries, a:entry) != -1 + let a:entry.valid = -1 + else + call add(self._seen_entries, a:entry) + endif + else + let self._seen_entries = [a:entry] + endif +endfunction +lockvar g:neomake#postprocess#remove_duplicates " Needs to be copied. +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/quickfix.vim b/.vim/autoload/neomake/quickfix.vim new file mode 100644 index 0000000..8e22836 --- /dev/null +++ b/.vim/autoload/neomake/quickfix.vim @@ -0,0 +1,363 @@ +" vim: ts=4 sw=4 et +scriptencoding utf-8 + +let s:is_enabled = 0 + +let s:match_base_priority = 10 + +" args: a:1: force enabling? (used in tests and for VimEnter callback) +function! neomake#quickfix#enable(...) abort + if has('vim_starting') && !(a:0 && a:1) + " Delay enabling for our FileType autocommand to happen as late as + " possible, since placing signs triggers a redraw, and together with + " vim-qf_resize this causes flicker. + " https://github.com/vim/vim/issues/2763 + augroup neomake_qf + autocmd! + autocmd VimEnter * call neomake#quickfix#enable(1) + augroup END + return + endif + call neomake#log#debug('enabling custom quickfix list handling.') + let s:is_enabled = 1 + augroup neomake_qf + autocmd! + autocmd FileType qf call neomake#quickfix#FormatQuickfix() + augroup END + if &filetype ==# 'qf' + call neomake#quickfix#FormatQuickfix() + endif +endfunction + +function! neomake#quickfix#disable() abort + call neomake#log#debug('disabling custom quickfix list handling.') + let s:is_enabled = 0 + if &filetype ==# 'qf' + call neomake#quickfix#FormatQuickfix() + endif + if exists('#neomake_qf') + autocmd! neomake_qf + augroup! neomake_qf + endif +endfunction + +function! neomake#quickfix#is_enabled() abort + return s:is_enabled +endfunction + +function! s:cursor_moved() abort + if b:neomake_start_col + if col('.') <= b:neomake_start_col + 1 + call cursor(line('.'), b:neomake_start_col + 2) + endif + + if exists('w:_neomake_cursor_match_id') + silent! call matchdelete(w:_neomake_cursor_match_id) + endif + if exists('*matchaddpos') + let w:_neomake_cursor_match_id = matchaddpos('neomakeCursorListNr', + \ [[line('.'), (b:neomake_start_col - b:neomake_number_len) + 2, b:neomake_number_len]], + \ s:match_base_priority+3) + else + let w:_neomake_cursor_match_id = matchadd('neomakeCursorListNr', + \ '\%' . line('.') . 'c' + \. '\%' . ((b:neomake_start_col - b:neomake_number_len) + 2) . 'c' + \. '.\{' . b:neomake_number_len . '}', + \ s:match_base_priority+3) + endif + endif +endfunction + +function! s:set_qf_lines(lines) abort + let ul = &l:undolevels + setlocal modifiable nonumber undolevels=-1 + + call setline(1, a:lines) + + let &l:undolevels = ul + setlocal nomodifiable nomodified +endfunction + +function! s:clean_qf_annotations() abort + call neomake#log#debug('cleaning qf annotations.', {'bufnr': bufnr('%')}) + if exists('b:_neomake_qf_orig_lines') + call s:set_qf_lines(b:_neomake_qf_orig_lines) + unlet b:_neomake_qf_orig_lines + endif + unlet b:neomake_qf + augroup neomake_qf + autocmd! * <buffer> + augroup END + + call s:clean_matches() +endfunction + +function! s:clean_matches() abort + if exists('w:_neomake_maker_match_id') + silent! call matchdelete(w:_neomake_maker_match_id) + endif + if exists('w:_neomake_gutter_match_id') + silent! call matchdelete(w:_neomake_gutter_match_id) + endif + if exists('w:_neomake_bufname_match_id') + silent! call matchdelete(w:_neomake_bufname_match_id) + endif + if exists('w:_neomake_cursor_match_id') + silent! call matchdelete(w:_neomake_cursor_match_id) + endif + call neomake#signs#ResetFile(bufnr('%')) +endfunction + +function! neomake#quickfix#FormatQuickfix() abort + let buf = bufnr('%') + if !s:is_enabled || &filetype !=# 'qf' + if exists('b:neomake_qf') + call s:clean_qf_annotations() + endif + return + endif + + let src_buf = 0 + if has('patch-7.4.2215') + let is_loclist = getwininfo(win_getid())[0].loclist + if is_loclist + let qflist = getloclist(0) + else + let qflist = getqflist() + endif + else + let is_loclist = 1 + let qflist = getloclist(0) + if empty(qflist) + let is_loclist = 0 + let qflist = getqflist() + endif + endif + + if empty(qflist) || qflist[0].text !~# ' nmcfg:{.\{-}}$' + if exists('b:neomake_qf') + call neomake#log#debug('Resetting custom qf for non-Neomake change.') + call s:clean_qf_annotations() + endif + return + endif + + if is_loclist + let b:neomake_qf = 'file' + let src_buf = qflist[0].bufnr + else + let b:neomake_qf = 'project' + endif + + let lines = [] + let signs = [] + let i = 0 + let lnum_width = 0 + let col_width = 0 + let maker_width = 0 + let nmcfg = {} + let makers = {} + + for item in qflist + " Look for marker at end of entry. + if item.text[-1:] ==# '}' + let idx = strridx(item.text, ' nmcfg:{') + if idx != -1 + let config = item.text[idx+7:] + try + let nmcfg = eval(config) + if !has_key(makers, nmcfg.name) + let makers[nmcfg.name] = 0 + endif + let item.text = idx == 0 ? '' : item.text[:(idx-1)] + catch + call neomake#log#exception(printf( + \ 'Error when evaluating nmcfg (%s): %s.', + \ config, v:exception)) + endtry + endif + endif + + " Count entries. + if !empty(nmcfg) + let makers[nmcfg.name] += 1 + endif + + let item.maker_name = get(nmcfg, 'short', '????') + let maker_width = max([len(item.maker_name), maker_width]) + + if item.lnum + let lnum_width = max([len(item.lnum), lnum_width]) + let col_width = max([len(item.col), col_width]) + endif + + let i += 1 + endfor + + let syntax = keys(makers) + if src_buf + for ft in split(neomake#compat#getbufvar(src_buf, '&filetype', ''), '\.') + if !empty(ft) && index(syntax, ft) == -1 + call add(syntax, ft) + endif + endfor + endif + if get(b:, '_neomake_cur_syntax', []) != syntax + runtime! syntax/neomake/qf.vim + for name in syntax + execute 'runtime! syntax/neomake/'.name.'.vim ' + \ . 'syntax/neomake/'.name.'/*.vim' + endfor + let b:_neomake_cur_syntax = syntax + endif + + if maker_width + lnum_width + col_width > 0 + let b:neomake_start_col = maker_width + lnum_width + col_width + 2 + let b:neomake_number_len = lnum_width + col_width + 2 + let blank_col = repeat(' ', lnum_width + col_width + 1) + else + let b:neomake_start_col = 0 + let b:neomake_number_len = 0 + let blank_col = '' + endif + + " Count number of different buffers and cache their names. + let buffers = neomake#compat#uniq(sort( + \ filter(map(copy(qflist), 'v:val.bufnr'), 'v:val != 0'))) + let buffer_names = {} + if len(buffers) > 1 + for b in buffers + let bufname = bufname(b) + if empty(bufname) + let bufname = 'buf:'.b + else + let bufname = fnamemodify(bufname, ':t') + if len(bufname) > 15 + let bufname = bufname[0:13].'…' + endif + endif + let buffer_names[b] = bufname + endfor + endif + + let i = 1 + let last_bufnr = -1 + for item in qflist + if item.lnum + call add(signs, {'lnum': i, 'bufnr': buf, 'type': item.type}) + endif + let i += 1 + + let text = item.text + if item.bufnr != 0 && !empty(buffer_names) + if last_bufnr != item.bufnr + let text = printf('[%s] %s', buffer_names[item.bufnr], text) + let last_bufnr = item.bufnr + endif + endif + + if !item.lnum + call add(lines, printf('%*s %s %s', + \ maker_width, item.maker_name, + \ blank_col, text)) + else + call add(lines, printf('%*s %*s:%*s %s', + \ maker_width, item.maker_name, + \ lnum_width, item.lnum, + \ col_width, item.col ? item.col : '-', + \ text)) + endif + endfor + + if !exists('b:_neomake_qf_orig_lines') + let b:_neomake_qf_orig_lines = getbufline('%', 1, '$') + endif + call s:set_qf_lines(lines) + + if exists('+breakindent') + " Keeps the text aligned with the fake gutter. + setlocal breakindent linebreak + let &breakindentopt = 'shift:'.(b:neomake_start_col + 1) + endif + + call neomake#signs#Reset(buf, 'file') + call neomake#signs#PlaceSigns(buf, signs, 'file') + + call s:add_window_matches(maker_width) + + augroup neomake_qf + autocmd! * <buffer> + autocmd CursorMoved <buffer> call s:cursor_moved() + + " Annotate in new window, e.g. with "tab sp". + " It keeps the syntax there, so should also have the rest. + " This happens on Neovim already through CursorMoved being invoked + " always then. + if exists('##WinNew') + exe 'autocmd WinNew <buffer> call s:add_window_matches('.maker_width.')' + endif + + " Clear matches when opening another buffer in the same window, with + " the original window/buffer still being visible (e.g. in another + " tab). + autocmd BufLeave <buffer> call s:on_bufleave() + augroup END + + " Set title. + " Fallback without patch-7.4.2200, fix for without 8.0.1831. + if !has('patch-7.4.2200') || !exists('w:quickfix_title') || w:quickfix_title[0] ==# ':' + let maker_info = [] + for [maker, c] in items(makers) + call add(maker_info, maker.'('.c.')') + endfor + let maker_info_str = join(maker_info, ', ') + if is_loclist + let prefix = 'file' + else + let prefix = 'project' + endif + let w:quickfix_title = neomake#list#get_title(prefix, src_buf, maker_info_str) + endif +endfunction + +function! s:on_bufleave() abort + let s:left_winnr = winnr() + augroup neomake_qf + autocmd BufEnter * call s:on_bufenter_after_bufleave() + augroup END +endfunction + +function! s:on_bufenter_after_bufleave() abort + if winnr() == s:left_winnr + call s:clean_matches() + endif + unlet s:left_winnr + augroup neomake_qf + autocmd! BufEnter + augroup END +endfunction + +function! s:add_window_matches(maker_width) abort + if !b:neomake_start_col + return + endif + if exists('w:_neomake_maker_match_id') + silent! call matchdelete(w:_neomake_maker_match_id) + endif + let w:_neomake_maker_match_id = matchadd('neomakeMakerName', + \ '.*\%<'.(a:maker_width + 1).'c', + \ s:match_base_priority+1) + if exists('w:_neomake_gutter_match_id') + silent! call matchdelete(w:_neomake_gutter_match_id) + endif + let w:_neomake_gutter_match_id = matchadd('neomakeListNr', + \ '\%>'.(a:maker_width).'c' + \ .'.*\%<'.(b:neomake_start_col + 2).'c', + \ s:match_base_priority+2) + if exists('w:_neomake_bufname_match_id') + silent! call matchdelete(w:_neomake_bufname_match_id) + endif + let w:_neomake_bufname_match_id = matchadd('neomakeBufferName', + \ '.*\%<'.(a:maker_width + 1).'c', + \ s:match_base_priority+3) +endfunction diff --git a/.vim/autoload/neomake/setup.vim b/.vim/autoload/neomake/setup.vim new file mode 100644 index 0000000..e0c5298 --- /dev/null +++ b/.vim/autoload/neomake/setup.vim @@ -0,0 +1,37 @@ +if has('signs') + let g:neomake_place_signs = get(g:, 'neomake_place_signs', 1) +else + let g:neomake_place_signs = 0 + lockvar g:neomake_place_signs +endif + +function! neomake#setup#define_highlights() abort + if g:neomake_place_signs + call neomake#signs#DefineHighlights() + endif + if get(g:, 'neomake_highlight_columns', 1) + \ || get(g:, 'neomake_highlight_lines', 0) + call neomake#highlights#DefineHighlights() + endif +endfunction + +function! neomake#setup#setup_autocmds() abort + augroup neomake + au! + if !exists('*nvim_buf_add_highlight') + autocmd BufEnter * call neomake#highlights#ShowHighlights() + endif + if has('timers') + autocmd CursorMoved * call neomake#CursorMovedDelayed() + " Force-redraw display of current error after resizing Vim, which appears + " to clear the previously echoed error. + autocmd VimResized * call timer_start(100, function('neomake#EchoCurrentError')) + else + autocmd CursorHold,CursorHoldI * call neomake#CursorMoved() + endif + autocmd VimLeave * call neomake#VimLeave() + autocmd ColorScheme * call neomake#setup#define_highlights() + augroup END +endfunction + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/signs.vim b/.vim/autoload/neomake/signs.vim new file mode 100644 index 0000000..fb96934 --- /dev/null +++ b/.vim/autoload/neomake/signs.vim @@ -0,0 +1,289 @@ +" vim: ts=4 sw=4 et +scriptencoding utf-8 + +if !has('signs') + call neomake#log#error('Trying to load signs.vim, without +signs.') + finish +endif + +let s:base_sign_id = 5000 +let s:placed_signs = {'project': {}, 'file': {}} +let s:last_placed_signs = {'project': {}, 'file': {}} + +exe 'sign define neomake_invisible' + +" Reset signs placed by a :Neomake! call +function! neomake#signs#ResetProject() abort + for buf in keys(s:placed_signs.project) + call neomake#signs#Reset(buf, 'project') + call neomake#signs#CleanOldSigns(buf, 'project') + endfor +endfunction + +" Reset signs placed by a :Neomake call in a buffer +function! neomake#signs#ResetFile(bufnr) abort + call neomake#signs#Reset(a:bufnr, 'file') + call neomake#signs#CleanOldSigns(a:bufnr, 'file') +endfunction + +function! neomake#signs#Reset(bufnr, type) abort + if has_key(s:placed_signs[a:type], a:bufnr) + " Clean any lingering, already retired signs. + call neomake#signs#CleanOldSigns(a:bufnr, a:type) + let s:last_placed_signs[a:type][a:bufnr] = s:placed_signs[a:type][a:bufnr] + unlet s:placed_signs[a:type][a:bufnr] + endif +endfunction + +let s:sign_order = {'neomake_file_err': 0, 'neomake_file_warn': 1, + \ 'neomake_file_info': 2, 'neomake_file_msg': 3, + \ 'neomake_project_err': 4, 'neomake_project_warn': 5, + \ 'neomake_project_info': 6, 'neomake_project_msg': 7} + +" Get the defined signs for a:bufnr. +" It returns a dictionary with line numbers as keys. +" If there are multiple entries for a line only the first (visible) entry is +" returned. +function! neomake#signs#by_lnum(bufnr) abort + let bufnr = a:bufnr + 0 + if !bufexists(bufnr) + return {} + endif + + let r = {} + if exists('*sign_getplaced') " patch-8.1.0614 + for sign in sign_getplaced(bufnr)[0].signs + if has_key(r, sign.lnum) + continue + endif + let r[sign.lnum] = [sign.id, sign.name] + endfor + return r + endif + + let signs_output = split(neomake#utils#redir('sign place buffer='.a:bufnr), '\n') + + " Originally via ALE. + " Matches output like : + " line=4 id=1 name=neomake_err + " строка=1 id=1000001 имя=neomake_err + " 行=1 識別子=1000001 名前=neomake_err + " línea=12 id=1000001 nombre=neomake_err + " riga=1 id=1000001, nome=neomake_err + for line in reverse(signs_output[2:]) + " XXX: does not really match "name=" + " (broken by patch-8.1.0614, but handled above) + let sign_type = line[strridx(line, '=')+1:] + if sign_type[0:7] ==# 'neomake_' + let lnum_idx = stridx(line, '=') + let lnum = line[lnum_idx+1:] + 0 + if lnum + let sign_id = line[stridx(line, '=', lnum_idx+1)+1:] + 0 + let r[lnum] = [sign_id, sign_type] + endif + endif + endfor + return r +endfunction + +let s:entry_to_sign_type = {'W': 'warn', 'I': 'info', 'M': 'msg'} + +" Place signs for list a:entries in a:bufnr for a:type ('file' or 'project'). +" List items in a:entries need to have a "type" and "lnum" (non-zero) property. +function! neomake#signs#PlaceSigns(bufnr, entries, type) abort + " Query the list of currently placed signs. + " This allows to cope with movements, e.g. when lines were added. + let placed_signs = neomake#signs#by_lnum(a:bufnr) + + let entries_by_linenr = {} + for entry in a:entries + let lnum = entry.lnum + let sign_type = printf('neomake_%s_%s', + \ a:type, + \ get(s:entry_to_sign_type, toupper(entry.type), 'err')) + if !exists('entries_by_linenr[lnum]') + \ || s:sign_order[entries_by_linenr[lnum]] + \ > s:sign_order[sign_type] + let entries_by_linenr[lnum] = sign_type + endif + endfor + + let place_new = [] + let log_context = {'bufnr': a:bufnr} + let count_reused = 0 + for [lnum, sign_type] in items(entries_by_linenr) + let existing_sign = get(placed_signs, lnum, []) + if empty(existing_sign) || existing_sign[1] !~# '^neomake_'.a:type.'_' + call add(place_new, [lnum, sign_type]) + continue + endif + + let sign_id = existing_sign[0] + if existing_sign[1] == sign_type + let count_reused += 1 + " call neomake#log#debug(printf( + " \ 'Reusing sign: id=%d, type=%s, lnum=%d.', + " \ sign_id, existing_sign[1], lnum), log_context) + else + let cmd = printf('sign place %s name=%s buffer=%d', + \ sign_id, sign_type, a:bufnr) + call neomake#log#debug('Upgrading sign for lnum='.lnum.': '.cmd.'.', log_context) + exe cmd + endif + + " Keep this sign from being cleaned. + if exists('s:last_placed_signs[a:type][a:bufnr][sign_id]') + unlet s:last_placed_signs[a:type][a:bufnr][sign_id] + endif + endfor + if count_reused + call neomake#log#debug(printf('Reused %d signs.', count_reused), log_context) + endif + + for [lnum, sign_type] in place_new + if !exists('next_sign_id') + if !empty(placed_signs) + let next_sign_id = max(map(values(copy(placed_signs)), 'v:val[0]')) + 1 + else + let next_sign_id = s:base_sign_id + endif + else + let next_sign_id += 1 + endif + let cmd = 'sign place '.next_sign_id.' line='.lnum. + \ ' name='.sign_type. + \ ' buffer='.a:bufnr + call neomake#log#debug('Placing sign: '.cmd.'.', log_context) + let placed_signs[lnum] = [next_sign_id, sign_type] + exe cmd + endfor + + let s:placed_signs[a:type][a:bufnr] = {} + for [lnum, sign_info] in items(placed_signs) + let s:placed_signs[a:type][a:bufnr][sign_info[0]] = sign_info[1] + endfor +endfunction + +function! neomake#signs#CleanAllOldSigns(type) abort + call neomake#log#debug_obj('Removing signs', s:last_placed_signs) + for buf in keys(s:last_placed_signs[a:type]) + call neomake#signs#CleanOldSigns(buf, a:type) + endfor +endfunction + +" type may be either 'file' or 'project' +function! neomake#signs#CleanOldSigns(bufnr, type) abort + if !has_key(s:last_placed_signs[a:type], a:bufnr) + return + endif + let placed_signs = s:last_placed_signs[a:type][a:bufnr] + unlet s:last_placed_signs[a:type][a:bufnr] + if bufexists(+a:bufnr) + call neomake#log#debug(printf('Cleaning %d old signs.', len(placed_signs)), {'bufnr': a:bufnr}) + for sign_id in keys(placed_signs) + exe 'sign unplace '.sign_id.' buffer='.a:bufnr + if has_key(s:placed_signs[a:type], a:bufnr) + if has_key(s:placed_signs[a:type][a:bufnr], sign_id) + unlet s:placed_signs[a:type][a:bufnr][sign_id] + endif + endif + endfor + else + call neomake#log#debug_obj('Skipped cleaning of old signs in non-existing buffer '.a:bufnr, placed_signs) + endif +endfunction + +function! neomake#signs#RedefineSign(name, opts) abort + let sign_define = 'sign define '.a:name + for attr in keys(a:opts) + let sign_define .= ' '.attr.'='.a:opts[attr] + endfor + call neomake#log#debug(printf('Defining sign: %s.', sign_define)) + exe sign_define +endfunction + +function! neomake#signs#RedefineErrorSign(...) abort + let default_opts = {'text': '✖', 'texthl': 'NeomakeErrorSign'} + let opts = {} + if a:0 + call extend(opts, a:1) + elseif exists('g:neomake_error_sign') + call extend(opts, g:neomake_error_sign) + endif + call extend(opts, default_opts, 'keep') + call neomake#signs#RedefineSign('neomake_file_err', opts) + call neomake#signs#RedefineSign('neomake_project_err', opts) +endfunction + +function! neomake#signs#RedefineWarningSign(...) abort + let default_opts = {'text': '‼', 'texthl': 'NeomakeWarningSign'} + let opts = {} + if a:0 + call extend(opts, a:1) + elseif exists('g:neomake_warning_sign') + call extend(opts, g:neomake_warning_sign) + endif + call extend(opts, default_opts, 'keep') + call neomake#signs#RedefineSign('neomake_file_warn', opts) + call neomake#signs#RedefineSign('neomake_project_warn', opts) +endfunction + +function! neomake#signs#RedefineMessageSign(...) abort + let default_opts = {'text': '➤', 'texthl': 'NeomakeMessageSign'} + let opts = {} + if a:0 + call extend(opts, a:1) + elseif exists('g:neomake_message_sign') + call extend(opts, g:neomake_message_sign) + endif + call extend(opts, default_opts, 'keep') + call neomake#signs#RedefineSign('neomake_file_msg', opts) + call neomake#signs#RedefineSign('neomake_project_msg', opts) +endfunction + +function! neomake#signs#RedefineInfoSign(...) abort + let default_opts = {'text': 'ℹ', 'texthl': 'NeomakeInfoSign'} + let opts = {} + if a:0 + call extend(opts, a:1) + elseif exists('g:neomake_info_sign') + call extend(opts, g:neomake_info_sign) + endif + call extend(opts, default_opts, 'keep') + call neomake#signs#RedefineSign('neomake_file_info', opts) + call neomake#signs#RedefineSign('neomake_project_info', opts) +endfunction + +function! neomake#signs#DefineHighlights() abort + " Use background from SignColumn. + let ctermbg = neomake#utils#GetHighlight('SignColumn', 'bg', 'Normal') + let guibg = neomake#utils#GetHighlight('SignColumn', 'bg#', 'Normal') + + " Define NeomakeErrorSign, NeomakeWarningSign etc. + call neomake#utils#define_derived_highlights('Neomake%sSign', [ctermbg, guibg]) +endfunction + +function! neomake#signs#DefineSigns() abort + call neomake#signs#RedefineErrorSign() + call neomake#signs#RedefineWarningSign() + call neomake#signs#RedefineInfoSign() + call neomake#signs#RedefineMessageSign() +endfunction + +function! s:wipe_signs(bufnr) abort + for type in ['file', 'project'] + if has_key(s:placed_signs[type], a:bufnr) + unlet s:placed_signs[type][a:bufnr] + endif + if has_key(s:last_placed_signs[type], a:bufnr) + unlet s:last_placed_signs[type][a:bufnr] + endif + endfor +endfunction +augroup neomake_signs + au! + autocmd BufWipeout * call s:wipe_signs(expand('<abuf>')) +augroup END + +call neomake#signs#DefineSigns() +call neomake#signs#DefineHighlights() diff --git a/.vim/autoload/neomake/statusline.vim b/.vim/autoload/neomake/statusline.vim new file mode 100644 index 0000000..14fb543 --- /dev/null +++ b/.vim/autoload/neomake/statusline.vim @@ -0,0 +1,423 @@ +scriptencoding utf-8 + +unlockvar s:unknown_counts +let s:unknown_counts = {} +lockvar s:unknown_counts + +let s:counts = {} + +" Key: bufnr, Value: dict with cache keys. +let s:cache = {} + +" For debugging. +let g:neomake#statusline#_s = s: + +function! s:clear_cache(bufnr) abort + if has_key(s:cache, a:bufnr) + unlet s:cache[a:bufnr] + endif +endfunction + +function! neomake#statusline#clear_cache() abort + let s:cache = {} +endfunction + +function! s:incCount(counts, item, buf) abort + if !empty(a:item.type) && (!a:buf || a:item.bufnr ==# a:buf) + let type = toupper(a:item.type) + let a:counts[type] = get(a:counts, type, 0) + 1 + if a:buf + call s:clear_cache(a:buf) + else + let s:cache = {} + endif + return 1 + endif + return 0 +endfunction + +function! neomake#statusline#make_finished(make_info) abort + if a:make_info.options.file_mode + let bufnr = a:make_info.options.bufnr + if !empty(a:make_info.finished_jobs) && !has_key(s:counts, bufnr) + let s:counts[bufnr] = {} + endif + call s:clear_cache(bufnr) + else + let s:cache = {} + if !empty(a:make_info.finished_jobs) && !has_key(s:counts, 'project') + let s:counts['project'] = {} + endif + endif + + " Trigger redraw of all statuslines. + " TODO: only do this if some relevant formats are used?! + redrawstatus! +endfunction + +function! neomake#statusline#ResetCountsForBuf(...) abort + let bufnr = a:0 ? +a:1 : bufnr('%') + call s:clear_cache(bufnr) + if has_key(s:counts, bufnr) + let r = s:counts[bufnr] != {} + unlet s:counts[bufnr] + if r + call neomake#utils#hook('NeomakeCountsChanged', { + \ 'reset': 1, 'file_mode': 1, 'bufnr': bufnr}) + endif + return r + endif + return 0 +endfunction + +function! neomake#statusline#ResetCountsForProject(...) abort + let s:cache = {} + if !has_key(s:counts, 'project') + return 0 + endif + let r = s:counts['project'] != {} + let bufnr = bufnr('%') + unlet s:counts['project'] + if r + call neomake#utils#hook('NeomakeCountsChanged', { + \ 'reset': 1, 'file_mode': 0, 'bufnr': bufnr}) + endif + return r +endfunction + +function! neomake#statusline#ResetCounts() abort + let r = neomake#statusline#ResetCountsForProject() + for bufnr in keys(s:counts) + let r = neomake#statusline#ResetCountsForBuf(bufnr) || r + endfor + let s:counts = {} + return r +endfunction + +function! neomake#statusline#AddLoclistCount(buf, item) abort + let s:counts[a:buf] = get(s:counts, a:buf, {}) + return s:incCount(s:counts[a:buf], a:item, a:buf) +endfunction + +function! neomake#statusline#AddQflistCount(item) abort + let s:counts['project'] = get(s:counts, 'project', {}) + return s:incCount(s:counts['project'], a:item, 0) +endfunction + +function! neomake#statusline#LoclistCounts(...) abort + let buf = a:0 ? a:1 : bufnr('%') + if buf is# 'all' + return s:counts + endif + return get(s:counts, buf, {}) +endfunction + +function! neomake#statusline#QflistCounts() abort + return get(s:counts, 'project', s:unknown_counts) +endfunction + +function! s:showErrWarning(counts, prefix) abort + let w = get(a:counts, 'W', 0) + let e = get(a:counts, 'E', 0) + if w || e + let result = a:prefix + if e + let result .= 'E:'.e + endif + if w + if e + let result .= ',' + endif + let result .= 'W:'.w + endif + return result + else + return '' + endif +endfunction + +function! neomake#statusline#LoclistStatus(...) abort + return s:showErrWarning(neomake#statusline#LoclistCounts(), a:0 ? a:1 : '') +endfunction + +function! neomake#statusline#QflistStatus(...) abort + return s:showErrWarning(neomake#statusline#QflistCounts(), a:0 ? a:1 : '') +endfunction + +" Get counts for a bufnr or 'project'. +" Returns all counts when used without arguments. +function! neomake#statusline#get_counts(...) abort + if a:0 + return get(s:counts, a:1, s:unknown_counts) + endif + return s:counts +endfunction + + +let s:formatter = { + \ 'args': {}, + \ } +function! s:formatter.running_job_names() abort + let jobs = get(self.args, 'running_jobs', s:running_jobs(self.args.bufnr)) + let sep = get(self.args, 'running_jobs_separator', ', ') + let format_running_job_file = get(self.args, 'format_running_job_file', '%s') + let format_running_job_project = get(self.args, 'format_running_job_project', '%s!') + let formatted = [] + for job in jobs + if job.file_mode + call add(formatted, printf(format_running_job_file, job.name)) + else + call add(formatted, printf(format_running_job_project, job.name)) + endif + endfor + return join(formatted, sep) +endfunction + +function! s:formatter._substitute(m) abort + if has_key(self.args, a:m) + return self.args[a:m] + endif + if !has_key(self, a:m) + let self.errors += [printf('Unknown statusline format: {{%s}}.', a:m)] + return '{{'.a:m.'}}' + endif + try + return call(self[a:m], [], self) + catch + call neomake#log#error(printf( + \ 'Error while formatting statusline: %s.', v:exception)) + endtry +endfunction + +function! s:formatter.format(f, args) abort + if empty(a:f) + return a:f + endif + let self.args = a:args + let self.errors = [] + let r = substitute(a:f, '{{\(.\{-}\)}}', '\=self._substitute(submatch(1))', 'g') + if !empty(self.errors) + call neomake#log#error(printf( + \ 'Error%s when formatting %s: %s', + \ len(self.errors) > 1 ? 's' : '', + \ string(a:f), join(self.errors, ', '))) + endif + return r +endfunction + + +function! s:running_jobs(bufnr) abort + return filter(copy(neomake#GetJobs()), + \ "v:val.bufnr == a:bufnr && !get(v:val, 'canceled', 0)") +endfunction + +function! s:format_running(format_running, options, bufnr, running_jobs) abort + let args = {'bufnr': a:bufnr, 'running_jobs': a:running_jobs} + for opt in ['running_jobs_separator', 'format_running_job_project', 'format_running_job_file'] + if has_key(a:options, opt) + let args[opt] = a:options[opt] + endif + endfor + return s:formatter.format(a:format_running, args) +endfunction + +function! neomake#statusline#get_status(bufnr, options) abort + let filemode_jobs = [] + let project_jobs = [] + let format_running = get(a:options, 'format_running', '… ({{running_job_names}})') + if format_running isnot 0 + let running_jobs = s:running_jobs(a:bufnr) + if !empty(running_jobs) + for j in running_jobs + if j.file_mode + let filemode_jobs += [j] + else + let project_jobs += [j] + endif + endfor + endif + endif + + let r_loclist = '' + let r_quickfix = '' + + let use_highlights_with_defaults = get(a:options, 'use_highlights_with_defaults', 1) + + " Location list counts. + let loclist_counts = get(s:counts, a:bufnr, s:unknown_counts) + if !empty(filemode_jobs) + let r_loclist = s:format_running(format_running, a:options, a:bufnr, filemode_jobs) + elseif empty(loclist_counts) + if loclist_counts is s:unknown_counts + let format_unknown = get(a:options, 'format_loclist_unknown', '?') + let r_loclist = s:formatter.format(format_unknown, {'bufnr': a:bufnr}) + else + let format_ok = get(a:options, 'format_loclist_ok', use_highlights_with_defaults ? '%#NeomakeStatusGood#✓%#NeomakeStatReset#' : '✓') + let r_loclist = s:formatter.format(format_ok, {'bufnr': a:bufnr}) + endif + else + let format_loclist = get(a:options, 'format_loclist_issues', + \ use_highlights_with_defaults ? '%s%%#NeomakeStatReset#' : '%s') + if !empty(format_loclist) + let loclist = '' + for [type, c] in items(loclist_counts) + if has_key(a:options, 'format_loclist_type_'.type) + let format = a:options['format_loclist_type_'.type] + elseif has_key(a:options, 'format_loclist_type_default') + let format = a:options['format_loclist_type_default'] + else + let hl = '' + if use_highlights_with_defaults + if hlexists('NeomakeStatColorType'.type) + let hl = '%#NeomakeStatColorType{{type}}#' + elseif hlexists('NeomakeStatColorDefault') + let hl = '%#NeomakeStatColorDefault#' + endif + endif + let format = hl.' {{type}}:{{count}} ' + endif + let loclist .= s:formatter.format(format, { + \ 'bufnr': a:bufnr, + \ 'count': c, + \ 'type': type}) + endfor + let r_loclist = printf(format_loclist, loclist) + endif + endif + + " Quickfix counts. + let qflist_counts = get(s:counts, 'project', s:unknown_counts) + if !empty(project_jobs) + let r_quickfix = s:format_running(format_running, a:options, a:bufnr, project_jobs) + elseif empty(qflist_counts) + let format_ok = get(a:options, 'format_quickfix_ok', '') + if !empty(format_ok) + let r_quickfix = s:formatter.format(format_ok, {'bufnr': a:bufnr}) + endif + else + let format_quickfix = get(a:options, 'format_quickfix_issues', + \ use_highlights_with_defaults ? '%s%%#NeomakeStatReset#' : '%s') + if !empty(format_quickfix) + let quickfix = '' + for [type, c] in items(qflist_counts) + if has_key(a:options, 'format_quickfix_type_'.type) + let format = a:options['format_quickfix_type_'.type] + elseif has_key(a:options, 'format_quickfix_type_default') + let format = a:options['format_quickfix_type_default'] + else + let hl = '' + if use_highlights_with_defaults + if hlexists('NeomakeStatColorQuickfixType'.type) + let hl = '%#NeomakeStatColorQuickfixType{{type}}#' + elseif hlexists('NeomakeStatColorQuickfixDefault') + let hl = '%#NeomakeStatColorQuickfixDefault#' + endif + endif + let format = hl.' Q{{type}}:{{count}} ' + endif + if !empty(format) + let quickfix .= s:formatter.format(format, { + \ 'bufnr': a:bufnr, + \ 'count': c, + \ 'type': type}) + endif + endfor + let r_quickfix = printf(format_quickfix, quickfix) + endif + endif + + let format_lists = get(a:options, 'format_lists', '{{loclist}}{{lists_sep}}{{quickfix}}') + if empty(r_loclist) || empty(r_quickfix) + let lists_sep = '' + else + let lists_sep = get(a:options, 'lists_sep', ' ') + endif + return s:formatter.format(format_lists, {'loclist': r_loclist, 'quickfix': r_quickfix, 'lists_sep': lists_sep}) +endfunction + +function! neomake#statusline#get(bufnr, ...) abort + let options = a:0 ? a:1 : {} + let cache_key = string(options) + if !exists('s:cache[a:bufnr][cache_key]') + if !has_key(s:cache, a:bufnr) + let s:cache[a:bufnr] = {} + endif + let bufnr = +a:bufnr + + " TODO: needs to go into cache key then! + if getbufvar(bufnr, '&filetype') ==# 'qf' + let s:cache[bufnr][cache_key] = '' + else + let [disabled, src] = neomake#config#get_with_source('disabled', -1, {'bufnr': bufnr, 'log_source': 'statusline#get'}) + if src ==# 'default' + let disabled_scope = '' + else + let disabled_scope = src[0] + endif + if disabled != -1 && disabled + " Automake Disabled + let format_disabled_info = get(options, 'format_disabled_info', '{{disabled_scope}}-') + let disabled_info = s:formatter.format(format_disabled_info, + \ {'disabled_scope': disabled_scope}) + " Defaults to showing the disabled information (i.e. scope) + let format_disabled = get(options, 'format_status_disabled', '{{disabled_info}} %s') + let outer_format = s:formatter.format(format_disabled, {'disabled_info': disabled_info}) + else + " Automake Enabled + " Defaults to showing only the status + let format_enabled = get(options, 'format_status_enabled', '%s') + let outer_format = s:formatter.format(format_enabled, {}) + endif + let format_status = get(options, 'format_status', '%s') + let status = neomake#statusline#get_status(bufnr, options) + + let r = printf(outer_format, printf(format_status, status)) + + let s:cache[bufnr][cache_key] = r + endif + endif + return s:cache[a:bufnr][cache_key] +endfunction + +" XXX: TODO: cleanup/doc?! +function! neomake#statusline#DefineHighlights() abort + for suffix in ['', 'NC'] + let hl = 'StatusLine'.suffix + + " Highlight used for resetting color (used after counts). + exe 'hi default link NeomakeStatReset'.suffix.' StatusLine'.suffix + + " Uses "green" for NeomakeStatusGood, but the default with + " NeomakeStatusGoodNC (since it might be underlined there, and should + " not stand out in general there). + exe 'hi default NeomakeStatusGood'.suffix + \ . ' ctermfg=' . (suffix ? neomake#utils#GetHighlight(hl, 'fg') : 'green') + \ . ' guifg=' . (suffix ? neomake#utils#GetHighlight(hl, 'fg#') : 'green') + \ . ' ctermbg='.neomake#utils#GetHighlight(hl, 'bg') + \ . ' guifg='.neomake#utils#GetHighlight(hl, 'bg#') + \ . (neomake#utils#GetHighlight(hl, 'underline') ? ' cterm=underline' : '') + \ . (neomake#utils#GetHighlight(hl, 'underline#') ? ' gui=underline' : '') + \ . (neomake#utils#GetHighlight(hl, 'reverse') ? ' cterm=reverse' : '') + \ . (neomake#utils#GetHighlight(hl, 'reverse#') ? ' gui=reverse' : '') + endfor + + " Default highlight for type counts. + exe 'hi NeomakeStatColorDefault cterm=NONE ctermfg=white ctermbg=blue' + hi link NeomakeStatColorQuickfixDefault NeomakeStatColorDefault + + " Specific highlights for types. Only used if defined. + exe 'hi NeomakeStatColorTypeE cterm=NONE ctermfg=white ctermbg=red' + hi link NeomakeStatColorQuickfixTypeE NeomakeStatColorTypeE + + exe 'hi NeomakeStatColorTypeW cterm=NONE ctermfg=white ctermbg=yellow' + hi link NeomakeStatColorQuickfixTypeW NeomakeStatColorTypeW +endfunction + +" Global augroup, gets configured always currently when autoloaded. +augroup neomake_statusline + autocmd! + autocmd BufWipeout * call s:clear_cache(expand('<abuf>')) + autocmd ColorScheme * call neomake#statusline#DefineHighlights() +augroup END +call neomake#statusline#DefineHighlights() +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/neomake/utils.vim b/.vim/autoload/neomake/utils.vim new file mode 100644 index 0000000..860fe41 --- /dev/null +++ b/.vim/autoload/neomake/utils.vim @@ -0,0 +1,795 @@ +" vim: ts=4 sw=4 et +scriptencoding utf-8 + +" Get verbosity, optionally based on jobinfo's make_id (a:1). +function! neomake#utils#get_verbosity(...) abort + if a:0 && has_key(a:1, 'make_id') + return neomake#GetMakeOptions(a:1.make_id).verbosity + endif + return get(g:, 'neomake_verbose', 1) + &verbose +endfunction + +function! neomake#utils#Stringify(obj) abort + if type(a:obj) == type([]) + let ls = map(copy(a:obj), 'neomake#utils#Stringify(v:val)') + return '['.join(ls, ', ').']' + elseif type(a:obj) == type({}) + let ls = [] + for [k, l:V] in items(neomake#utils#fix_self_ref(a:obj)) + if type(V) == type(function('tr')) + let fname = substitute(string(V), ', {\zs.*\ze})', '…', '') + call add(ls, k.': '.fname) + else + call add(ls, k.': '.neomake#utils#Stringify(V)) + endif + unlet V " vim73 + endfor + return '{'.join(ls, ', ').'}' + elseif type(a:obj) == type(function('tr')) + return string(a:obj) + else + return a:obj + endif +endfunction + +function! neomake#utils#truncate_width(string, width) abort + let pos = a:width + while pos >= 0 + let s = matchstr(a:string, '.\{,'.pos.'}', 0, 1) + let w = strwidth(s) + if w <= a:width + return s + endif + let pos -= max([(w-a:width)/2, 1]) + endwhile + return '' +endfunction + +" This comes straight out of syntastic. +"print as much of a:msg as possible without "Press Enter" prompt appearing +function! neomake#utils#WideMessage(msg) abort " {{{2 + let old_ruler = &ruler + let old_showcmd = &showcmd + + " Replace newlines (typically in the msg) with a single space. This + " might happen with writegood. + let msg = substitute(a:msg, '\r\?\n', ' ', 'g') + + "convert tabs to spaces so that the tabs count towards the window + "width as the proper amount of characters + let chunks = split(msg, "\t", 1) + let msg = join(map(chunks[:-2], "v:val . repeat(' ', &tabstop - strwidth(v:val) % &tabstop)"), '') . chunks[-1] + let msg = neomake#utils#truncate_width(msg, &columns-1) + + set noruler noshowcmd + redraw + + call neomake#log#debug('WideMessage: echo '.msg.'.') + echo msg + + let &ruler = old_ruler + let &showcmd = old_showcmd +endfunction " }}}2 + +" This comes straight out of syntastic. +function! neomake#utils#IsRunningWindows() abort + return has('win32') || has('win64') +endfunction + +" Get directory/path separator. +function! neomake#utils#Slash() abort + return (!exists('+shellslash') || &shellslash) ? '/' : '\' +endfunction + +function! neomake#utils#Exists(exe) abort + " DEPRECATED: just use executable() directly. + return executable(a:exe) +endfunction + +" Object used with neomake#utils#MakerFromCommand. +let s:maker_from_command = extend(copy(g:neomake#core#command_maker_base), { + \ 'remove_invalid_entries': 0, + \ }) +function! s:maker_from_command._get_argv(jobinfo) abort dict + let fname = self._get_fname_for_args(a:jobinfo) + let args = neomake#utils#ExpandArgs(self.args, a:jobinfo) + if !empty(fname) + if self.__command_is_string + let fname = neomake#utils#shellescape(fname) + let args[-1] .= ' '.fname + else + call add(args, fname) + endif + endif + return neomake#compat#get_argv(self.exe, args, 1) +endfunction + +" Create a maker object for a given command. +" Args: command (string or list). Gets wrapped in a shell in case it is a +" string. +function! neomake#utils#MakerFromCommand(command) abort + let maker = copy(s:maker_from_command) + if type(a:command) == type('') + let argv = split(&shell) + split(&shellcmdflag) + let maker.exe = argv[0] + let maker.args = argv[1:] + [a:command] + let maker.__command_is_string = 1 + else + let maker.exe = a:command[0] + let maker.args = a:command[1:] + let maker.__command_is_string = 0 + endif + return maker +endfunction + +let s:super_ft_cache = {} +function! neomake#utils#GetSupersetOf(ft) abort + if !has_key(s:super_ft_cache, a:ft) + call neomake#utils#load_ft_makers(a:ft) + let l:SupersetOf = 'neomake#makers#ft#'.a:ft.'#SupersetOf' + if exists('*'.SupersetOf) + let s:super_ft_cache[a:ft] = call(SupersetOf, []) + else + let s:super_ft_cache[a:ft] = '' + endif + endif + return s:super_ft_cache[a:ft] +endfunction + +let s:loaded_ft_maker_runtime = [] +function! neomake#utils#load_ft_makers(ft) abort + " Load ft maker, but only once (for performance reasons and to allow for + " monkeypatching it in tests). + if index(s:loaded_ft_maker_runtime, a:ft) == -1 + if !exists('*neomake#makers#ft#'.a:ft.'#EnabledMakers') + silent exe 'runtime! autoload/neomake/makers/ft/'.a:ft.'.vim' + endif + call add(s:loaded_ft_maker_runtime, a:ft) + endif +endfunction + +let s:loaded_global_maker_runtime = 0 +function! neomake#utils#load_global_makers() abort + " Load global makers, but only once (for performance reasons and to allow + " for monkeypatching it in tests). + if !s:loaded_global_maker_runtime + exe 'runtime! autoload/neomake/makers/*.vim' + let s:loaded_global_maker_runtime = 1 + endif +endfunction + +function! neomake#utils#get_ft_confname(ft, ...) abort + return substitute(a:ft, '\W', a:0 ? a:1 : '_', 'g') +endfunction + +" Resolve filetype a:ft into a list of filetypes suitable for config vars +" (i.e. 'foo.bar' => ['foo_bar', 'foo', 'bar']). +function! neomake#utils#get_config_fts(ft, ...) abort + let delim = a:0 ? a:1 : '_' + let cache_key = a:ft . delim + if !has_key(s:cache_config_fts, cache_key) + let r = [] + let fts = split(a:ft, '\.') + for ft in fts + call add(r, ft) + let super_ft = neomake#utils#GetSupersetOf(ft) + while !empty(super_ft) + if index(fts, super_ft) == -1 + call add(r, super_ft) + endif + let super_ft = neomake#utils#GetSupersetOf(super_ft) + endwhile + endfor + if len(fts) > 1 + call insert(r, a:ft, 0) + endif + let s:cache_config_fts[cache_key] = map(r, 'neomake#utils#get_ft_confname(v:val, delim)') + endif + return s:cache_config_fts[cache_key] +endfunction +let s:cache_config_fts = {} + +let s:unset = {} " Sentinel. + +" Get a setting by key, based on filetypes, from the buffer or global +" namespace, defaulting to default. +" Use an empty bufnr ('') to ignore buffer-local settings. +function! neomake#utils#GetSetting(key, maker, default, ft, bufnr, ...) abort + let maker_only = a:0 ? a:1 : 0 + + " Check new-style config. + if exists('g:neomake') || !empty(getbufvar(a:bufnr, 'neomake')) + let context = {'ft': a:ft, 'maker': a:maker, 'bufnr': a:bufnr, 'maker_only': maker_only} + let [l:Ret, source] = neomake#config#get_with_source(a:key, g:neomake#config#undefined, context) + " Check old-style setting when source is the maker. + if source ==# 'maker' && !maker_only + let tmpmaker = {} + if has_key(a:maker, 'name') + let tmpmaker.name = a:maker.name + endif + let l:RetOld = s:get_oldstyle_setting(a:key, tmpmaker, s:unset, a:ft, a:bufnr, 1) + if RetOld isnot# s:unset + return RetOld + endif + endif + if Ret isnot g:neomake#config#undefined + return Ret + endif + endif + + return s:get_oldstyle_setting(a:key, a:maker, a:default, a:ft, a:bufnr, maker_only) +endfunction + +function! s:get_oldstyle_setting(key, maker, default, ft, bufnr, maker_only) abort + let maker_name = get(a:maker, 'name', '') + if a:maker_only && empty(maker_name) + if has_key(a:maker, a:key) + return get(a:maker, a:key) + endif + return a:default + endif + + if !empty(a:ft) + let fts = neomake#utils#get_config_fts(a:ft) + [''] + else + let fts = [''] + endif + for ft in fts + let part = join(filter([ft, maker_name], '!empty(v:val)'), '_') + if empty(part) + break + endif + let config_var = 'neomake_'.part.'_'.a:key + if a:bufnr isnot# '' + let l:Bufcfgvar = neomake#compat#getbufvar(a:bufnr, config_var, s:unset) + if Bufcfgvar isnot s:unset + return copy(Bufcfgvar) + endif + endif + if has_key(g:, config_var) + return copy(get(g:, config_var)) + endif + unlet! Bufcfgvar " vim73 + endfor + + if has_key(a:maker, a:key) + return get(a:maker, a:key) + endif + + let key = a:key + if a:maker_only + let key = maker_name.'_'.key + endif + let key = a:maker_only ? maker_name.'_'.a:key : a:key + " Look for 'neomake_'.key in the buffer and global namespace. + let bufvar = neomake#compat#getbufvar(a:bufnr, 'neomake_'.key, s:unset) + if bufvar isnot s:unset + return bufvar + endif + if a:key !=# 'enabled_makers' && has_key(g:, 'neomake_'.key) + return get(g:, 'neomake_'.key) + endif + return a:default +endfunction + +" Helper function to define default highlight for a:group (e.g. +" "Neomake%sSign"), using fg from another highlight, abd given background. +function! neomake#utils#define_derived_highlights(group_format, bg) abort + for [type, fg_from] in items({ + \ 'Error': ['Error', 'bg'], + \ 'Warning': ['Todo', 'fg'], + \ 'Info': ['Question', 'fg'], + \ 'Message': ['ModeMsg', 'fg'] + \ }) + let group = printf(a:group_format, type) + call s:define_derived_highlight_group(group, fg_from, a:bg) + endfo +endfunction + +function! s:define_derived_highlight_group(group, fg_from, bg) abort + let [fg_group, fg_attr] = a:fg_from + let [ctermbg, guibg] = a:bg + let bg = 'ctermbg='.ctermbg.' guibg='.guibg + + " NOTE: fg falls back to "Normal" always, not bg (for e.g. "SignColumn") + " inbetween. + let ctermfg = neomake#utils#GetHighlight(fg_group, fg_attr, 'Normal') + let guifg = neomake#utils#GetHighlight(fg_group, fg_attr.'#', 'Normal') + + " Ensure that we're not using bg as fg (as with gotham + " colorscheme, issue https://github.com/neomake/neomake/pull/659). + if ctermfg !=# 'NONE' && ctermfg ==# ctermbg + let ctermfg = neomake#utils#GetHighlight(fg_group, neomake#utils#ReverseSynIDattr(fg_attr)) + endif + if guifg !=# 'NONE' && guifg ==# guibg + let guifg = neomake#utils#GetHighlight(fg_group, neomake#utils#ReverseSynIDattr(fg_attr).'#') + endif + exe 'hi '.a:group.'Default ctermfg='.ctermfg.' guifg='.guifg.' '.bg + if !neomake#utils#highlight_is_defined(a:group) + exe 'hi link '.a:group.' '.a:group.'Default' + endif +endfunction + +" Get property from highlighting group. +function! neomake#utils#GetHighlight(group, what, ...) abort + let fallback = a:0 ? a:1 : '' + let mode = a:what[-1:] ==# '#' ? 'gui' : 'cterm' + let reverse = synIDattr(synIDtrans(hlID(a:group)), 'reverse', mode) + let what = a:what + if reverse + let what = neomake#utils#ReverseSynIDattr(what) + endif + if what[-1:] ==# '#' + let val = synIDattr(synIDtrans(hlID(a:group)), what, mode) + else + let val = synIDattr(synIDtrans(hlID(a:group)), what, mode) + endif + if empty(val) || val == -1 + if !empty(fallback) + " NOTE: this might still be NONE also for "Normal", with + " e.g. `vim -u NONE`. + return neomake#utils#GetHighlight(fallback, a:what) + endif + return 'NONE' + endif + return val +endfunction + +function! neomake#utils#ReverseSynIDattr(attr) abort + if a:attr ==# 'fg' + return 'bg' + elseif a:attr ==# 'bg' + return 'fg' + elseif a:attr ==# 'fg#' + return 'bg#' + elseif a:attr ==# 'bg#' + return 'fg#' + endif + return a:attr +endfunction + +" Deprecated: moved to neomake#postprocess#compress_whitespace. +function! neomake#utils#CompressWhitespace(entry) abort + call neomake#postprocess#compress_whitespace(a:entry) +endfunction + +function! neomake#utils#redir(cmd) abort + " @vimlint(EVL108, 1) + if exists('*execute') && has('nvim-0.2.0') + " @vimlint(EVL108, 0) + " NOTE: require Neovim, since Vim has at least an issue when using + " this in a :command-completion function. + " Ref: https://github.com/neomake/neomake/issues/650. + " Neovim 0.1.7 also parses 'highlight' wrongly. + return execute(a:cmd) + endif + if type(a:cmd) == type([]) + let r = '' + for cmd in a:cmd + let r .= neomake#utils#redir(cmd) + endfor + return r + endif + try + redir => neomake_redir + silent exe a:cmd + catch /^Vim(redir):E121:/ + throw printf('Neomake: neomake#utils#redir: called with outer :redir (error: %s).', + \ v:exception) + finally + redir END + endtry + return neomake_redir +endfunction + +function! neomake#utils#ExpandArgs(args, jobinfo) abort + if has_key(a:jobinfo, 'tempfile') + let fname = a:jobinfo.tempfile + else + let fname = bufname(a:jobinfo.bufnr) + if !empty(fname) + let fname = fnamemodify(fname, ':p') + endif + endif + let ret = map(copy(a:args), "substitute(v:val, '%t', fname, 'g')") + + " Expand % in args similar to when using :! + " \% is ignored + " \\% is expanded to \\file.ext + " %% becomes % + " % must be followed with an expansion keyword + let ret = map(ret, + \ 'substitute(v:val, ' + \ . '''\(\%(\\\@<!\\\)\@<!%\%(%\|<\|\%(:[phtreS8.~]\)\+\|\ze\w\@!\)\)'', ' + \ . '''\=(submatch(1) == "%%" ? "%" : expand(substitute(submatch(1), "^%", "#'.a:jobinfo.bufnr.'", "")))'', ' + \ . '''g'')') + let ret = map(ret, 'substitute(v:val, ''\v^\~\ze%(/|$)'', expand(''~''), ''g'')') + return ret +endfunction + +if has('patch-7.3.1058') + function! s:function(name) abort + return function(a:name) + endfunction +else + " Older Vim does not handle s: function references across files. + function! s:function(name) abort + return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '.*\zs<SNR>\d\+_'),'')) + endfunction +endif + +function! s:handle_hook(jobinfo, event, context) abort + let context_str = string(map(copy(a:context), + \ "v:key ==# 'make_info' ? 'make_info #'.get(v:val, 'make_id')" + \ .": (v:key ==# 'options' && has_key(v:val, 'jobs') ? extend(copy(v:val), {'jobs': map(copy(v:val.jobs), 'v:val.maker.name')}, 'force')" + \ .": (v:key ==# 'jobinfo' ? v:val.as_string()" + \ .": (v:key ==# 'finished_jobs' ? map(copy(v:val), 'v:val.as_string()') : v:val)))")) + + if exists('g:neomake_hook_context') + call neomake#log#debug(printf('Queuing User autocmd %s for nested invocation (%s).', a:event, context_str), + \ a:jobinfo) + return neomake#action_queue#add( + \ ['Timer', 'BufEnter', 'WinEnter', 'InsertLeave', 'CursorHold', 'CursorHoldI'], + \ [s:function('s:handle_hook'), [a:jobinfo, a:event, a:context]]) + endif + + let log_args = [printf('Calling User autocmd %s with context: %s.', + \ a:event, context_str)] + if !empty(a:jobinfo) + let log_args += [a:jobinfo] + endif + call call('neomake#log#info', log_args) + + unlockvar g:neomake_hook_context + let g:neomake_hook_context = a:context + lockvar 1 g:neomake_hook_context + try + call neomake#compat#doautocmd('User '.a:event) + catch + let error = v:exception + if error[-1:] !=# '.' + let error .= '.' + endif + call neomake#log#exception(printf( + \ 'Error during User autocmd for %s: %s', + \ a:event, error), a:jobinfo) + finally + unlet g:neomake_hook_context + endtry + return g:neomake#action_queue#processed +endfunction + +function! neomake#utils#hook(event, context, ...) abort + if exists('#User#'.a:event) + let jobinfo = a:0 ? a:1 : ( + \ has_key(a:context, 'jobinfo') ? a:context.jobinfo : {}) + return s:handle_hook(jobinfo, a:event, a:context) + endif +endfunction + +function! neomake#utils#diff_dict(old, new) abort + let diff = {'removed': {}, 'added': {}, 'changed': {}} + + for k in keys(a:old) + if !has_key(a:new, k) + let diff['removed'][k] = a:old[k] + elseif type(a:old[k]) !=# type(a:new[k]) || a:old[k] !=# a:new[k] + let diff['changed'][k] = [a:old[k], a:new[k]] + endif + endfor + + for k in keys(a:new) + if !has_key(a:old, k) + let diff['added'][k] = a:new[k] + endif + endfor + + call filter(diff, '!empty(v:val)') + + return diff +endfunction + +" Sort quickfix/location list entries by distance to current cursor position's +" column, but preferring entries starting at or behind the cursor position. +function! neomake#utils#sort_by_col(a, b) abort + let col = getpos('.')[2] + if a:a.col > col + if a:b.col < col + return 1 + endif + elseif a:b.col > col + return -1 + endif + return abs(col - a:a.col) - abs(col - a:b.col) +endfunction + +function! neomake#utils#path_sep() abort + return neomake#utils#IsRunningWindows() ? ';' : ':' +endfunction + +" Find a file matching `a:glob` (using `globpath()`) by going up the +" directories from the start directory (a:1, defaults to `expand('%:p:h')`, +" i.e. the directory of the current buffer's file).) +function! neomake#utils#FindGlobFile(glob, ...) abort + let curDir = a:0 ? a:1 : expand('%:p:h') + let fileFound = [] + while 1 + let fileFound = neomake#compat#globpath_list(curDir, a:glob, 1) + if !empty(fileFound) + return fileFound[0] + endif + let lastFolder = curDir + let curDir = fnamemodify(curDir, ':h') + if curDir ==# lastFolder + break + endif + endwhile + return '' +endfunction + +function! neomake#utils#JSONdecode(json) abort + return neomake#compat#json_decode(a:json) +endfunction + +" Smarter shellescape, via vim-fugitive. +function! s:gsub(str,pat,rep) abort + return substitute(a:str,'\v\C'.a:pat,a:rep,'g') +endfunction + +function! neomake#utils#shellescape(arg) abort + if a:arg =~# '^[A-Za-z0-9_/.=-]\+$' + return a:arg + elseif &shell =~? 'cmd' || exists('+shellslash') && !&shellslash + return '"'.s:gsub(s:gsub(a:arg, '"', '""'), '\%', '"%"').'"' + endif + return shellescape(a:arg) +endfunction + +function! neomake#utils#get_buffer_lines(bufnr) abort + let buflines = getbufline(a:bufnr, 1, '$') + " Special case: empty buffer; do not write an empty line in this case. + if len(buflines) > 1 || buflines != [''] + if getbufvar(a:bufnr, '&endofline') + \ || (!getbufvar(a:bufnr, '&binary') + \ && (!exists('+fixendofline') || getbufvar(a:bufnr, '&fixendofline'))) + call add(buflines, '') + endif + endif + return buflines +endfunction + +function! neomake#utils#write_tempfile(bufnr, temp_file) abort + call writefile(neomake#utils#get_buffer_lines(a:bufnr), a:temp_file, 'b') + if exists('*setfperm') + let perms = getfperm(bufname(+a:bufnr)) + if empty(perms) + let perms = 'rw-------' + endif + call setfperm(a:temp_file, perms) + endif +endfunction + +" Wrapper around fnamemodify that handles special buffers (e.g. fugitive). +function! neomake#utils#fnamemodify(bufnr, modifier) abort + let bufnr = +a:bufnr + if empty(getbufvar(bufnr, 'fugitive_type')) + let path = bufname(bufnr) + else + if exists('*FugitivePath') + let path = FugitivePath(bufname(bufnr)) + else + let fug_buffer = fugitive#buffer(bufnr) + let path = fug_buffer.repo().translate(fug_buffer.path()) + endif + if empty(a:modifier) + let path = fnamemodify(path, ':.') + endif + endif + return empty(path) ? '' : fnamemodify(path, a:modifier) +endfunction + +function! neomake#utils#fix_self_ref(obj, ...) abort + if type(a:obj) != type({}) + if type(a:obj) == type([]) + return map(copy(a:obj), 'neomake#utils#fix_self_ref(v:val)') + endif + return a:obj + endif + let obj = copy(a:obj) + for k in keys(obj) + if a:0 + let self_ref = filter(copy(a:1), 'v:val[1][0] is obj[k]') + if !empty(self_ref) + let obj[k] = printf('<self-ref-%d: %s>', self_ref[0][0], self_ref[0][1][1]) + continue + endif + endif + if type(obj[k]) == type({}) + let obj[k] = neomake#utils#fix_self_ref(obj[k], a:0 ? a:1 + [[len(a:1)+1, [a:obj, k]]] : [[1, [a:obj, k]]]) + elseif has('nvim') + " Ensure that it can be used as a string. + " Ref: https://github.com/neovim/neovim/issues/7432 + try + call string(obj[k]) + catch /^Vim(call):E724:/ + let obj[k] = '<unrepresentable object, type='.type(obj).'>' + endtry + endif + endfor + return obj +endfunction + +function! neomake#utils#parse_highlight(group) abort + let output = neomake#utils#redir('highlight '.a:group) + return join(split(output)[2:]) +endfunction + +function! neomake#utils#highlight_is_defined(group) abort + if !hlexists(a:group) + return 0 + endif + return neomake#utils#parse_highlight(a:group) !=# 'cleared' +endfunction + +" Get the root directory of the current project. +" This is determined by looking for specific files (e.g. `.git` and +" `Makefile`), and `g:neomake#makers#ft#X#project_root_files` (if defined for +" filetype "X"). +" a:1 buffer number (defaults to current) +function! neomake#utils#get_project_root(...) abort + let bufnr = a:0 ? a:1 : bufnr('%') + let ft = getbufvar(bufnr, '&filetype') + call neomake#utils#load_ft_makers(ft) + + let project_root_files = ['.git', 'Makefile'] + + let ft_project_root_files = 'neomake#makers#ft#'.ft.'#project_root_files' + if has_key(g:, ft_project_root_files) + let project_root_files = get(g:, ft_project_root_files) + project_root_files + endif + + let buf_dir = expand('#'.bufnr.':p:h') + for fname in project_root_files + let project_root = neomake#utils#FindGlobFile(fname, buf_dir) + if !empty(project_root) + return fnamemodify(project_root, ':h') + endif + endfor + return '' +endfunction + +" Return the number of lines for a given buffer. +" This returns 0 for unloaded buffers. +if exists('*nvim_buf_line_count') + function! neomake#utils#get_buf_line_count(bufnr) abort + if !bufloaded(a:bufnr) + " https://github.com/neovim/neovim/issues/7688 + return 0 + endif + return nvim_buf_line_count(a:bufnr) + endfunction +else + function! neomake#utils#get_buf_line_count(bufnr) abort + if a:bufnr == bufnr('%') + return line('$') + endif + " TODO: this should get cached (based on b:changedtick), and cleaned + " in BufWipeOut. + return len(getbufline(a:bufnr, 1, '$')) + endfunction +endif + +" Returns: [error, cd_back_cmd] +function! neomake#utils#temp_cd(dir, ...) abort + if a:dir ==# '.' + return ['', ''] + endif + if a:0 + let cur_wd = a:1 + else + let cur_wd = getcwd() + if cur_wd ==# a:dir + " No need to change directory. + return ['', ''] + endif + endif + let cd = haslocaldir() ? 'lcd' : (exists(':tcd') == 2 && haslocaldir(-1, 0)) ? 'tcd' : 'cd' + try + exe cd.' '.fnameescape(a:dir) + catch + " Tests fail with E344, but in reality it is E472?! + " If uncaught, both are shown - let's just catch everything. + return [v:exception, ''] + endtry + return ['', cd.' '.fnameescape(cur_wd)] +endfunction + +if exists('*nvim_buf_get_lines') + function! neomake#utils#buf_get_lines(bufnr, start, end) abort + if a:start < 1 + throw 'neomake#utils#buf_get_lines: start is lower than 1' + endif + try + return nvim_buf_get_lines(a:bufnr, a:start-1, a:end-1, 1) + catch + throw 'neomake#utils#buf_get_lines: '.substitute(v:exception, '\v^[^:]+:', '', '') + endtry + endfunction +else + function! neomake#utils#buf_get_lines(bufnr, start, end) abort + if a:bufnr != bufnr('%') + throw 'Neomake: neomake#utils#buf_get_lines: used for non-current buffer' + endif + if a:start < 1 + throw 'neomake#utils#buf_get_lines: start is lower than 1' + endif + if a:end-1 > line('$') + throw 'neomake#utils#buf_get_lines: end is higher than number of lines' + endif + let r = [] + let i = a:start + while i < a:end + let r += [getline(i)] + let i += 1 + endwhile + return r + endfunction +endif + +if exists('*nvim_buf_set_lines') + function! neomake#utils#buf_set_lines(bufnr, start, end, replacement) abort + if a:start < 1 + return 'neomake#utils#buf_set_lines: start is lower than 1' + endif + try + call nvim_buf_set_lines(a:bufnr, a:start-1, a:end-1, 1, a:replacement) + catch + " call neomake#log#error('Fixing entry failed (out of bounds)') + return 'neomake#utils#buf_set_lines: '.substitute(v:exception, '\v^[^:]+:', '', '') + endtry + return '' + endfunction +else + function! neomake#utils#buf_set_lines(bufnr, start, end, replacement) abort + if a:bufnr != bufnr('%') + return 'neomake#utils#buf_set_lines: used for non-current buffer' + endif + + if a:start < 1 + return 'neomake#utils#buf_set_lines: start is lower than 1' + endif + if a:end > line('$')+1 + return 'neomake#utils#buf_set_lines: end is higher than number of lines' + endif + + if a:start == a:end + let lnum = a:start < 0 ? line('$') - a:start : a:start + if append(lnum-1, a:replacement) == 1 + call neomake#log#error(printf('Failed to append line(s): %d (%d).', a:start, lnum), {'bufnr': a:bufnr}) + endif + + else + let range = a:end - a:start + if range > len(a:replacement) + let end = min([a:end, line('$')]) + silent execute a:start.','.end.'d_' + call setline(a:start, a:replacement) + else + let i = 0 + let n = len(a:replacement) + while i < n + call setline(a:start + i, a:replacement[i]) + let i += 1 + endwhile + endif + endif + return '' + endfunction +endif + +function! neomake#utils#shorten_list_for_log(l, max) abort + if len(a:l) > a:max + return a:l[:a:max-1] + ['... ('.len(a:l).' total)'] + endif + return a:l +endfunction diff --git a/.vim/autoload/neomake/virtualtext.vim b/.vim/autoload/neomake/virtualtext.vim new file mode 100644 index 0000000..b97f2d7 --- /dev/null +++ b/.vim/autoload/neomake/virtualtext.vim @@ -0,0 +1,113 @@ +scriptencoding utf8 + +let s:highlight_types = { + \ 'E': 'NeomakeVirtualtextError', + \ 'W': 'NeomakeVirtualtextWarning', + \ 'I': 'NeomakeVirtualtextInfo', + \ 'M': 'NeomakeVirtualtextMessage' + \ } + +function! neomake#virtualtext#show(...) abort + let list = neomake#list#get() + if empty(list) + echom 'Neomake: no annotations to show (no list)' + return + endif + + let filter = a:0 ? a:1 : '' + if empty(filter) + let entries = list.entries + else + let entries = map(copy(list.entries), filter) + endif + + if empty(entries) + echom 'Neomake: no annotations to show (no errors)' + return + endif + + for entry in entries + let buf_info = getbufvar(entry.bufnr, '_neomake_info', {}) + + call neomake#virtualtext#add_entry(entry, s:all_ns) + + " Keep track of added entries, because stacking is not supported. + let set_buf_info = 0 + if !has_key(buf_info, 'virtual_text_entries') + let buf_info.virtual_text_entries = [] + endif + if index(buf_info.virtual_text_entries, entry.lnum) == -1 + " Do not add it, but define it still - could return here also later. + call add(buf_info.virtual_text_entries, entry.lnum) + let set_buf_info = 1 + endif + + if set_buf_info + call setbufvar(entry.bufnr, '_neomake_info', buf_info) + endif + endfor +endfunction + +function! neomake#virtualtext#add_entry(entry, src_id) abort + let hi = get(s:highlight_types, toupper(a:entry.type), 'NeomakeVirtualtextMessage') + let prefix = get(g:, 'neomake_virtualtext_prefix', '❯ ') + let text = prefix . a:entry.text + let used_src_id = nvim_buf_set_virtual_text(a:entry.bufnr, a:src_id, a:entry.lnum-1, [[text, hi]], {}) + return used_src_id +endfunction + +function! neomake#virtualtext#show_errors() abort + call neomake#virtualtext#show('v:val ==? "e"') +endfunction + +function! neomake#virtualtext#hide() abort + let bufnr = bufnr('%') + let buf_info = getbufvar(bufnr, '_neomake_info', {}) + call nvim_buf_clear_highlight(bufnr, s:all_ns, 0, -1) + if !empty(get(buf_info, 'virtual_text_entries', [])) + let buf_info.virtual_text_entries = [] + call setbufvar(bufnr, '_neomake_info', buf_info) + endif +endfunction + +if exists('*nvim_create_namespace') " Includes nvim_buf_set_virtual_text. + let s:current_ns = nvim_create_namespace('neomake-virtualtext-current') + let s:all_ns = nvim_create_namespace('neomake-virtualtext-all') + let s:cur_virtualtext = [] + + function! neomake#virtualtext#handle_current_error() abort + if !get(g:, 'neomake_virtualtext_current_error', 1) + return + endif + + if !empty(s:cur_virtualtext) + if bufexists(s:cur_virtualtext[0]) + call nvim_buf_clear_highlight(s:cur_virtualtext[0], s:cur_virtualtext[1], 0, -1) + endif + endif + let entry = neomake#get_nearest_error() + if empty(entry) + let s:cur_virtualtext = [] + else + " Only add it when there is none already (stacking is not + " supported). https://github.com/neovim/neovim/issues/9285 + let buf_info = getbufvar(entry.bufnr, '_neomake_info', {}) + if index(get(buf_info, 'virtual_text_entries', []), entry.lnum) == -1 + let src_id = neomake#virtualtext#add_entry(entry, s:current_ns) + let s:cur_virtualtext = [bufnr('%'), src_id] + endif + endif + endfunction +else + function! neomake#virtualtext#handle_current_error() abort + endfunction +endif + +function! neomake#virtualtext#DefineHighlights() abort + " NOTE: linking to SpellBad etc is bad/distracting (with undercurl). + call neomake#utils#define_derived_highlights('NeomakeVirtualtext%s', ['NONE', 'NONE']) +endfunction + +call neomake#virtualtext#DefineHighlights() + +" vim: ts=4 sw=4 et diff --git a/.vim/autoload/node.vim b/.vim/autoload/node.vim new file mode 100644 index 0000000..3954e4c --- /dev/null +++ b/.vim/autoload/node.vim @@ -0,0 +1,110 @@ +" Vim by default sets the filetype to JavaScript for the following suffices. +" And, yes, it has .jsx there. +let node#suffixesadd = [".js", ".json", ".es", ".jsx"] + +function! node#initialize(root) + let b:node_root = a:root + + command! -bar -bang -nargs=1 -buffer -complete=customlist,s:complete Nedit + \ exe s:nedit(<q-args>, bufname("%"), "edit<bang>") + command! -bar -bang -nargs=1 -buffer -complete=customlist,s:complete Nopen + \ exe s:nopen(<q-args>, bufname("%"), "edit<bang>") + + nnoremap <buffer><silent> <Plug>NodeGotoFile + \ :call <SID>edit(expand("<cfile>"), bufname("%"))<CR> + nnoremap <buffer><silent> <Plug>NodeSplitGotoFile + \ :call <SID>edit(expand("<cfile>"), bufname("%"), "split")<CR> + nnoremap <buffer><silent> <Plug>NodeVSplitGotoFile + \ :call <SID>edit(expand("<cfile>"), bufname("%"), "vsplit")<CR> + nnoremap <buffer><silent> <Plug>NodeTabGotoFile + \ :call <SID>edit(expand("<cfile>"), bufname("%"), "tab split")<CR> + + silent doautocmd User Node +endfunction + +function! node#javascript() + " This might be called multiple times if multiple filetypes match. + if exists("b:node_javascript") && b:node_javascript | return | endif + let b:node_javascript = 1 + + setlocal path-=/usr/include + let &l:suffixesadd .= "," . join(g:node#suffixesadd, ",") + let &l:include = '\<require(\(["'']\)\zs[^\1]\+\ze\1' + let &l:includeexpr = "node#lib#find(v:fname, bufname('%'))" + + " @ is used for scopes, but isn't a default filename character on + " non-Windows sytems. + setlocal isfname+=@-@ + + if !hasmapto("<Plug>NodeGotoFile") + " Split gotofiles don't take a count for the new window's width, but for + " opening the nth file. Though Node.vim doesn't support counts atm. + nmap <buffer> gf <Plug>NodeGotoFile + nmap <buffer> <C-w>f <Plug>NodeSplitGotoFile + nmap <buffer> <C-w><C-f> <Plug>NodeSplitGotoFile + nmap <buffer> <C-w>gf <Plug>NodeTabGotoFile + endif +endfunction + +function! s:edit(name, from, ...) + if empty(a:name) | return | endif + let dir = isdirectory(a:from) ? a:from : fnamemodify(a:from, ":h") + let command = a:0 == 1 ? a:1 : "edit" + + " If just a plain filename with no directory part, check if it exists: + if a:name !~# '^\v(/|\./|\.\./)' && filereadable(dir . "/" . a:name) + let path = dir . "/" . a:name + else + let path = node#lib#find(a:name, dir) + end + + if empty(path) + return s:error("E447: Can't find file \"" . a:name . "\" in path") + endif + + exe command . " " . fnameescape(path) +endfunction + +function! s:nedit(name, from, ...) + let command = a:0 == 1 ? a:1 : "edit" + call s:edit(a:name, b:node_root, command) +endfunction + +function! s:nopen(name, from, ...) + let command = a:0 == 1 ? a:1 : "edit" + call s:nedit(a:name, a:from, command) + if exists("b:node_root") | exe "lcd " . fnameescape(b:node_root) | endif +endfunction + +function! s:complete(arg, cmd, cursor) + let matches = node#lib#glob(s:dirname(a:arg)) + + " Show private modules (_*) only if explicitly asked: + if a:arg[0] != "_" | call filter(matches, "v:val[0] != '_'") | endif + + let filter = "stridx(v:val, a:arg) == 0" + let ignorecase = 0 + let ignorecase = ignorecase || exists("&fileignorecase") && &fileignorecase + let ignorecase = ignorecase || exists("&wildignorecase") && &wildignorecase + if ignorecase | let filter = "stridx(tolower(v:val),tolower(a:arg)) == 0" | en + + return filter(matches, filter) +endfunction + +function! s:dirname(path) + let dirname = fnamemodify(a:path, ":h") + if dirname == "." | return "" | endif + + " To not change the amount of final consecutive slashes, using this + " dirname/basename trick: + let basename = fnamemodify(a:path, ":t") + return a:path[0 : 0 - len(basename) - 1] +endfunction + +" Using the built-in :echoerr prints a stacktrace, which isn't that nice. +function! s:error(msg) + echohl ErrorMsg + echomsg a:msg + echohl NONE + let v:errmsg = a:msg +endfunction diff --git a/.vim/autoload/node/lib.vim b/.vim/autoload/node/lib.vim new file mode 100644 index 0000000..1c7a8c1 --- /dev/null +++ b/.vim/autoload/node/lib.vim @@ -0,0 +1,153 @@ +let s:ABSPATH = '^/' +let s:RELPATH = '\v^\.\.?(/|$)' +let s:MODULE = '\v^(/|\.\.?(/|$))@!' + +" Damn Netrw can't handle HTTPS at all. It's 2013! Insecure bastard! +let s:CORE_URL_PREFIX = "https://rawgit.com/nodejs/node" +let s:CORE_MODULES = ["_debugger", "_http_agent", "_http_client", + \ "_http_common", "_http_incoming", "_http_outgoing", "_http_server", + \ "_linklist", "_stream_duplex", "_stream_passthrough", "_stream_readable", + \ "_stream_transform", "_stream_writable", "_tls_legacy", "_tls_wrap", + \ "assert", "buffer", "child_process", "cluster", "console", "constants", + \ "crypto", "dgram", "dns", "domain", "events", "freelist", "fs", "http", + \ "https", "module", "net", "node", "os", "path", "punycode", "querystring", + \ "readline", "repl", "smalloc", "stream", "string_decoder", "sys", + \ "timers", "tls", "tty", "url", "util", "vm", "zlib"] + +function! node#lib#find(name, from) + if index(s:CORE_MODULES, a:name) != -1 + let l:version = node#lib#version() + let l:version = empty(l:version) ? "master" : "v" . l:version + let l:dir = a:name == "node" ? "src" : "lib" + let l:url = get(g:, "node_repository_url", s:CORE_URL_PREFIX) + return l:url ."/". l:version ."/". l:dir ."/". a:name .".js" + endif + + let l:path = s:resolve(s:absolutize(a:name, a:from)) + if !empty(path) | return fnamemodify(resolve(path), ":.") | endif +endfunction + +function! node#lib#version() + if exists("b:node_version") | return b:node_version | endif + if !executable("node") | let b:node_version = "" | return | endif + let b:node_version = matchstr(system("node --version"), '^v\?\zs[0-9.]\+') + return b:node_version +endfunction + +function! s:absolutize(name, from) + if a:name =~# s:ABSPATH + return a:name + elseif a:name =~# s:RELPATH + let dir = isdirectory(a:from) ? a:from : fnamemodify(a:from, ":h") + return dir . "/" . a:name + else + return b:node_root . "/node_modules/" . a:name + endif +endfunction + +function! s:resolve(path) + " Node checks for files *before* directories, so see if the path does not + " end with a slash or dots and try to match it as a file. + if a:path !~# '\v/(\.\.?/?)?$' + let path_with_suffix = s:resolveSuffix(a:path) + if !empty(path_with_suffix) | return path_with_suffix | endif + endif + + if isdirectory(a:path) | return s:resolveFromDirectory(a:path) | endif +endfunction + +function! s:resolveFromDirectory(path) + " Node.js checks for package.json in every directory, not just the + " module's parent. According to: + " http://nodejs.org/api/modules.html#modules_all_together + if filereadable(a:path . "/package.json") + " Turns out, even though Node says it does not support directories in + " main, it does. + " NOTE: If package.json's main is empty or refers to a non-existent file, + " ./index.js is still tried. + let main = s:mainFromPackage(a:path . "/package.json") + + if !empty(main) && main != "" + let path = s:resolve(a:path . "/" . main) + if !empty(path) | return path | endif + endif + endif + + " We need to check for ./index.js's existence here rather than leave it to + " the caller, because otherwise we can't distinguish if this ./index was + " from the directory defaulting to ./index.js or it was the package.json + " which referred to ./index, which in itself could mean both ./index.js and + " ./index/index.js. + return s:resolveSuffix(a:path . "/index") +endfunction + +function! s:mainFromPackage(path) + for line in readfile(a:path) + if line !~# '"main"\s*:' | continue | endif + return matchstr(line, '"main"\s*:\s*"\zs[^"]\+\ze"') + endfor +endfunction + +function! s:resolveSuffix(path) + for suffix in s:uniq([""] + g:node#suffixesadd + split(&l:suffixesadd, ",")) + let path = a:path . suffix + if filereadable(path) | return path | endif + endfor +endfunction + +let s:GLOB_WILDIGNORE = 1 + +function! node#lib#glob(name) + let matches = [] + + if empty(a:name) + let matches += s:CORE_MODULES + endif + + if empty(a:name) || a:name =~# s:MODULE + let root = b:node_root . "/node_modules" + let matches += s:glob(empty(a:name) ? root : root . "/" . a:name, root) + endif + + if a:name =~# s:ABSPATH + let matches += s:glob(a:name, 0) + endif + + if empty(a:name) || a:name =~# s:RELPATH + let root = b:node_root + let relatives = s:glob(empty(a:name) ? root : root . "/" . a:name, root) + + "call map(relatives, "substitute(v:val, '^\./\./', './', '')") + if empty(a:name) | call map(relatives, "'./' . v:val") | endif + call filter(relatives, "v:val !~# '^\\.//*node_modules/$'") + + let matches += relatives + endif + + return matches +endfunction + +function! s:glob(path, stripPrefix) + " Remove a single trailing slash because we're adding one with the glob. + let path = substitute(a:path, '/$', "", "") + " Glob() got the ability to return a list only in Vim 7.3.465. Using split + " for compatibility. + let list = split(glob(fnameescape(path)."/*", s:GLOB_WILDIGNORE), "\n") + + " Add slashes to directories, like /bin/ls. + call map(list, "v:val . (isdirectory(v:val) ? '/' : '')") + + if !empty(a:stripPrefix) + " Counting and removing bytes intentionally as there's no substr function + " that takes character count, only bytes. + let prefix_length = len(a:stripPrefix) + 1 + return map(list, "strpart(v:val, prefix_length)") + endif + + return list +endfunction + +function! s:uniq(list) + let list = reverse(copy(a:list)) + return reverse(filter(list, "index(list, v:val, v:key + 1) == -1")) +endfunction |