From 1d42b6301371a9f2e0c1c54ef7af50d4a9c7f91a Mon Sep 17 00:00:00 2001 From: Amir Salihefendic Date: Tue, 8 Jan 2019 11:11:54 +0100 Subject: [PATCH] Updated plugins --- .../ale/ale_linters/elm/make.vim | 70 +- .../ale/ale_linters/go/bingo.vim | 29 + .../ale/ale_linters/graphql/gqlint.vim | 8 +- .../ale/ale_linters/perl/perl.vim | 2 +- sources_non_forked/ale/autoload/ale/c.vim | 82 +- .../ale/autoload/ale/completion.vim | 6 + .../ale/autoload/ale/definition.vim | 2 +- sources_non_forked/ale/autoload/ale/fix.vim | 4 +- .../ale/autoload/ale/fixers/black.vim | 24 +- .../ale/autoload/ale/fixers/generic.vim | 4 +- .../autoload/ale/fixers/generic_python.vim | 4 +- .../ale/autoload/ale/fixers/help.vim | 2 +- .../ale/autoload/ale/fixers/standard.vim | 2 + sources_non_forked/ale/autoload/ale/job.vim | 15 +- .../ale/autoload/ale/references.vim | 1 + sources_non_forked/ale/autoload/ale/util.vim | 19 +- sources_non_forked/ale/doc/ale-go.txt | 18 +- sources_non_forked/ale/doc/ale-python.txt | 11 +- sources_non_forked/ale/doc/ale.txt | 74 +- sources_non_forked/ale/plugin/ale.vim | 9 +- .../vim-fugitive/autoload/fugitive.vim | 1257 ++++++++++++----- .../vim-fugitive/doc/fugitive.txt | 70 +- .../vim-fugitive/plugin/fugitive.vim | 14 +- .../vim-fugitive/syntax/fugitive.vim | 36 + sources_non_forked/vim-go/.dockerignore | 3 + sources_non_forked/vim-go/CHANGELOG.md | 15 + sources_non_forked/vim-go/autoload/go/cmd.vim | 43 +- .../vim-go/autoload/go/config.vim | 5 +- .../vim-go/autoload/go/coverage.vim | 4 +- .../vim-go/autoload/go/debug.vim | 40 +- .../vim-go/autoload/go/debug_test.vim | 58 +- sources_non_forked/vim-go/autoload/go/def.vim | 1 - .../vim-go/autoload/go/guru.vim | 4 +- sources_non_forked/vim-go/autoload/go/job.vim | 151 +- .../vim-go/autoload/go/lint.vim | 39 +- .../vim-go/autoload/go/list.vim | 1 + .../vim-go/autoload/go/rename.vim | 1 - .../vim-go/autoload/go/template.vim | 47 +- .../vim-go/autoload/go/template_test.vim | 62 + .../test-fixtures/debug/compilerror/main.go | 7 + .../{ => debug}/debugmain/debugmain.go | 0 .../vim-go/autoload/go/test.vim | 1 - .../vim-go/autoload/go/tool.vim | 4 +- sources_non_forked/vim-go/doc/vim-go.txt | 8 +- .../vim-go/ftdetect/gofiletype.vim | 4 +- sources_non_forked/vim-go/plugin/go.vim | 2 +- sources_non_forked/vim-go/scripts/runtest.vim | 2 +- sources_non_forked/vim-go/syntax/go.vim | 27 +- sources_non_forked/vim-isort | 1 + .../vim-markdown/ftdetect/markdown.vim | 9 +- .../vim-markdown/ftplugin/markdown.vim | 2 +- .../vim-markdown/syntax/markdown.vim | 18 +- .../UltiSnips/javascript.snippets | 15 +- .../vim-snippets/UltiSnips/rust.snippets | 2 +- .../vim-snippets/snippets/python.snippets | 5 + 55 files changed, 1669 insertions(+), 675 deletions(-) create mode 100644 sources_non_forked/ale/ale_linters/go/bingo.vim create mode 100644 sources_non_forked/vim-fugitive/syntax/fugitive.vim create mode 100644 sources_non_forked/vim-go/autoload/go/template_test.vim create mode 100644 sources_non_forked/vim-go/autoload/go/test-fixtures/debug/compilerror/main.go rename sources_non_forked/vim-go/autoload/go/test-fixtures/{ => debug}/debugmain/debugmain.go (100%) create mode 160000 sources_non_forked/vim-isort diff --git a/sources_non_forked/ale/ale_linters/elm/make.vim b/sources_non_forked/ale/ale_linters/elm/make.vim index ddea983f..76622028 100644 --- a/sources_non_forked/ale/ale_linters/elm/make.vim +++ b/sources_non_forked/ale/ale_linters/elm/make.vim @@ -137,9 +137,7 @@ function! ale_linters#elm#make#ParseMessageItem(item) abort endif endfunction -" Return the command to execute the linter in the projects directory. -" If it doesn't, then this will fail when imports are needed. -function! ale_linters#elm#make#GetCommand(buffer) abort +function! ale_linters#elm#make#GetPackageFile(buffer) abort let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json') if empty(l:elm_json) @@ -147,10 +145,55 @@ function! ale_linters#elm#make#GetCommand(buffer) abort let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm-package.json') endif + return l:elm_json +endfunction + +function! ale_linters#elm#make#IsVersionGte19(buffer) abort + let l:elm_json = ale_linters#elm#make#GetPackageFile(a:buffer) + + if l:elm_json =~# '-package' + return 0 + else + return 1 + endif +endfunction + +function! ale_linters#elm#make#GetRootDir(buffer) abort + let l:elm_json = ale_linters#elm#make#GetPackageFile(a:buffer) + if empty(l:elm_json) + return '' + else + return fnamemodify(l:elm_json, ':p:h') + endif +endfunction + +function! ale_linters#elm#make#IsTest(buffer) abort + let l:root_dir = ale_linters#elm#make#GetRootDir(a:buffer) + + if empty(l:root_dir) + return 0 + endif + + let l:tests_dir = join([l:root_dir, 'tests', ''], has('win32') ? '\' : '/') + + let l:buffer_path = fnamemodify(bufname(a:buffer), ':p') + + if stridx(l:buffer_path, l:tests_dir) == 0 + return 1 + else + return 0 + endif +endfunction + +" Return the command to execute the linter in the projects directory. +" If it doesn't, then this will fail when imports are needed. +function! ale_linters#elm#make#GetCommand(buffer) abort + let l:root_dir = ale_linters#elm#make#GetRootDir(a:buffer) + + if empty(l:root_dir) let l:dir_set_cmd = '' else - let l:root_dir = fnamemodify(l:elm_json, ':p:h') let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && ' endif @@ -161,11 +204,24 @@ function! ale_linters#elm#make#GetCommand(buffer) abort return l:dir_set_cmd . '%e make --report=json --output=/dev/null %t' endfunction +function! ale_linters#elm#make#GetExecutable(buffer) abort + let l:is_test = ale_linters#elm#make#IsTest(a:buffer) + let l:is_v19 = ale_linters#elm#make#IsVersionGte19(a:buffer) + + if l:is_test && l:is_v19 + return ale#node#FindExecutable( +\ a:buffer, +\ 'elm_make', +\ ['node_modules/.bin/elm-test', 'node_modules/.bin/elm'] +\ ) + else + return ale#node#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm']) + endif +endfunction + call ale#linter#Define('elm', { \ 'name': 'make', -\ 'executable_callback': ale#node#FindExecutableFunc('elm_make', [ -\ 'node_modules/.bin/elm', -\ ]), +\ 'executable_callback': 'ale_linters#elm#make#GetExecutable', \ 'output_stream': 'both', \ 'command_callback': 'ale_linters#elm#make#GetCommand', \ 'callback': 'ale_linters#elm#make#Handle' diff --git a/sources_non_forked/ale/ale_linters/go/bingo.vim b/sources_non_forked/ale/ale_linters/go/bingo.vim new file mode 100644 index 00000000..ba80fbe8 --- /dev/null +++ b/sources_non_forked/ale/ale_linters/go/bingo.vim @@ -0,0 +1,29 @@ +" Author: Jerko Steiner +" Description: https://github.com/saibing/bingo + +call ale#Set('go_bingo_executable', 'bingo') +call ale#Set('go_bingo_options', '--mode stdio') + +function! ale_linters#go#bingo#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'go_bingo_options')) +endfunction + +function! ale_linters#go#bingo#FindProjectRoot(buffer) abort + let l:project_root = ale#path#FindNearestFile(a:buffer, 'go.mod') + let l:mods = ':h' + + if empty(l:project_root) + let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git') + let l:mods = ':h:h' + endif + + return !empty(l:project_root) ? fnamemodify(l:project_root, l:mods) : '' +endfunction + +call ale#linter#Define('go', { +\ 'name': 'bingo', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('go_bingo_executable'), +\ 'command_callback': 'ale_linters#go#bingo#GetCommand', +\ 'project_root_callback': 'ale_linters#go#bingo#FindProjectRoot', +\}) diff --git a/sources_non_forked/ale/ale_linters/graphql/gqlint.vim b/sources_non_forked/ale/ale_linters/graphql/gqlint.vim index 882cc697..e45bf4c8 100644 --- a/sources_non_forked/ale/ale_linters/graphql/gqlint.vim +++ b/sources_non_forked/ale/ale_linters/graphql/gqlint.vim @@ -1,9 +1,15 @@ " Author: Michiel Westerbeek " Description: Linter for GraphQL Schemas +function! ale_linters#graphql#gqlint#GetCommand(buffer) abort + return ale#path#BufferCdString(a:buffer) + \ . 'gqlint' + \ . ' --reporter=simple %t' +endfunction + call ale#linter#Define('graphql', { \ 'name': 'gqlint', \ 'executable': 'gqlint', -\ 'command': 'gqlint --reporter=simple %t', +\ 'command_callback': 'ale_linters#graphql#gqlint#GetCommand', \ 'callback': 'ale#handlers#unix#HandleAsWarning', \}) diff --git a/sources_non_forked/ale/ale_linters/perl/perl.vim b/sources_non_forked/ale/ale_linters/perl/perl.vim index 1cb20fa7..4b954f0d 100644 --- a/sources_non_forked/ale/ale_linters/perl/perl.vim +++ b/sources_non_forked/ale/ale_linters/perl/perl.vim @@ -18,7 +18,7 @@ function! ale_linters#perl#perl#Handle(buffer, lines) abort return [] endif - let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)' + let l:pattern = '\(..\{-}\) at \(..\{-}\) line \(\d\+\)' let l:output = [] let l:basename = expand('#' . a:buffer . ':t') diff --git a/sources_non_forked/ale/autoload/ale/c.vim b/sources_non_forked/ale/autoload/ale/c.vim index ce5105b6..746d19b0 100644 --- a/sources_non_forked/ale/autoload/ale/c.vim +++ b/sources_non_forked/ale/autoload/ale/c.vim @@ -48,26 +48,38 @@ endfunction function! ale#c#ParseCFlags(path_prefix, cflag_line) abort let l:cflags_list = [] - let l:previous_options = [] + let l:previous_options = '' - let l:split_lines = split(a:cflag_line, '-') + let l:split_lines = split(a:cflag_line, ' ') let l:option_index = 0 while l:option_index < len(l:split_lines) - let l:option = l:split_lines[l:option_index] + let l:option = l:previous_options . l:split_lines[l:option_index] let l:option_index = l:option_index + 1 - call add(l:previous_options, l:option) - " Check if cflag contained a '-' and should not have been splitted - let l:option_list = split(l:option, '\zs') - if len(l:option_list) > 0 && l:option_list[-1] isnot# ' ' && l:option_index < len(l:split_lines) + " Check if cflag contained an unmatched characters and should not have been splitted + let l:option_special = substitute(l:option, '\\"', '', 'g') + let l:option_special = substitute(l:option_special, '[^"''()`]', '', 'g') + let l:option_special = substitute(l:option_special, '""', '', 'g') + let l:option_special = substitute(l:option_special, '''''', '', 'g') + let l:option_special = substitute(l:option_special, '``', '', 'g') + let l:option_special = substitute(l:option_special, '((', '(', 'g') + let l:option_special = substitute(l:option_special, '))', ')', 'g') + let l:option_special = substitute(l:option_special, '()', '', 'g') + + if len(l:option_special) > 0 && l:option_index < len(l:split_lines) + let l:previous_options = l:option . ' ' continue endif - let l:option = join(l:previous_options, '-') - let l:previous_options = [] + " Check if there was spaces after -D/-I and the flag should not have been splitted + if l:option is# '-D' || l:option is# '-I' + let l:previous_options = l:option + continue + endif + + let l:previous_options = '' - let l:option = '-' . substitute(l:option, '^\s*\(.\{-}\)\s*$', '\1', '') " Fix relative paths if needed if stridx(l:option, '-I') >= 0 && @@ -145,15 +157,17 @@ if !exists('s:compile_commands_cache') let s:compile_commands_cache = {} endif -function! s:GetListFromCompileCommandsFile(compile_commands_file) abort +function! s:GetLookupFromCompileCommandsFile(compile_commands_file) abort + let l:empty = [{}, {}] + if empty(a:compile_commands_file) - return [] + return l:empty endif let l:time = getftime(a:compile_commands_file) if l:time < 0 - return [] + return l:empty endif let l:key = a:compile_commands_file . ':' . l:time @@ -162,21 +176,36 @@ function! s:GetListFromCompileCommandsFile(compile_commands_file) abort return s:compile_commands_cache[l:key] endif - let l:data = [] - silent! let l:data = json_decode(join(readfile(a:compile_commands_file), '')) + let l:raw_data = [] + silent! let l:raw_data = json_decode(join(readfile(a:compile_commands_file), '')) - if !empty(l:data) - let s:compile_commands_cache[l:key] = l:data + let l:file_lookup = {} + let l:dir_lookup = {} - return l:data + for l:entry in l:raw_data + let l:basename = tolower(fnamemodify(l:entry.file, ':t')) + let l:file_lookup[l:basename] = get(l:file_lookup, l:basename, []) + [l:entry] + + let l:dirbasename = tolower(fnamemodify(l:entry.directory, ':p:h:t')) + let l:dir_lookup[l:dirbasename] = get(l:dir_lookup, l:basename, []) + [l:entry] + endfor + + if !empty(l:file_lookup) && !empty(l:dir_lookup) + let l:result = [l:file_lookup, l:dir_lookup] + let s:compile_commands_cache[l:key] = l:result + + return l:result endif - return [] + return l:empty endfunction -function! ale#c#ParseCompileCommandsFlags(buffer, dir, json_list) abort +function! ale#c#ParseCompileCommandsFlags(buffer, dir, file_lookup, dir_lookup) abort " Search for an exact file match first. - for l:item in a:json_list + let l:basename = tolower(expand('#' . a:buffer . ':t')) + let l:file_list = get(a:file_lookup, l:basename, []) + + for l:item in l:file_list if bufnr(l:item.file) is a:buffer return ale#c#ParseCFlags(a:dir, l:item.command) endif @@ -185,7 +214,10 @@ function! ale#c#ParseCompileCommandsFlags(buffer, dir, json_list) abort " Look for any file in the same directory if we can't find an exact match. let l:dir = ale#path#Simplify(expand('#' . a:buffer . ':p:h')) - for l:item in a:json_list + let l:dirbasename = tolower(expand('#' . a:buffer . ':p:h:t')) + let l:dir_list = get(a:dir_lookup, l:dirbasename, []) + + for l:item in l:dir_list if ale#path#Simplify(fnamemodify(l:item.file, ':h')) is? l:dir return ale#c#ParseCFlags(a:dir, l:item.command) endif @@ -196,9 +228,11 @@ endfunction function! ale#c#FlagsFromCompileCommands(buffer, compile_commands_file) abort let l:dir = ale#path#Dirname(a:compile_commands_file) - let l:json_list = s:GetListFromCompileCommandsFile(a:compile_commands_file) + let l:lookups = s:GetLookupFromCompileCommandsFile(a:compile_commands_file) + let l:file_lookup = l:lookups[0] + let l:dir_lookup = l:lookups[1] - return ale#c#ParseCompileCommandsFlags(a:buffer, l:dir, l:json_list) + return ale#c#ParseCompileCommandsFlags(a:buffer, l:dir, l:file_lookup, l:dir_lookup) endfunction function! ale#c#GetCFlags(buffer, output) abort diff --git a/sources_non_forked/ale/autoload/ale/completion.vim b/sources_non_forked/ale/autoload/ale/completion.vim index 9dd913f5..3bf29191 100644 --- a/sources_non_forked/ale/autoload/ale/completion.vim +++ b/sources_non_forked/ale/autoload/ale/completion.vim @@ -509,6 +509,12 @@ function! ale#completion#GetCompletions() abort return endif + call ale#completion#AlwaysGetCompletions() +endfunction + +" This function can be used to manually trigger autocomplete, even when +" g:ale_completion_enabled is set to false +function! ale#completion#AlwaysGetCompletions() abort let [l:line, l:column] = getcurpos()[1:2] let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column) diff --git a/sources_non_forked/ale/autoload/ale/definition.vim b/sources_non_forked/ale/autoload/ale/definition.vim index 984a4f9d..79d12596 100644 --- a/sources_non_forked/ale/autoload/ale/definition.vim +++ b/sources_non_forked/ale/autoload/ale/definition.vim @@ -86,7 +86,7 @@ function! s:OnReady(linter, lsp_details, line, column, options, ...) abort let l:request_id = ale#lsp#Send(l:id, l:message) let s:go_to_definition_map[l:request_id] = { - \ 'open_in_tab': get(a:options, 'open_in_tab', 0), + \ 'open_in': get(a:options, 'open_in', 'current-buffer'), \} endfunction diff --git a/sources_non_forked/ale/autoload/ale/fix.vim b/sources_non_forked/ale/autoload/ale/fix.vim index 03652ecf..423e85be 100644 --- a/sources_non_forked/ale/autoload/ale/fix.vim +++ b/sources_non_forked/ale/autoload/ale/fix.vim @@ -315,10 +315,10 @@ function! s:RunFixer(options) abort \ ? call(l:Function, [l:buffer, a:options.output]) \ : call(l:Function, [l:buffer, a:options.output, copy(l:input)]) else - " Chained commands accept (buffer, [input]) + " Chained commands accept (buffer, [done, input]) let l:result = ale#util#FunctionArgCount(l:Function) == 1 \ ? call(l:Function, [l:buffer]) - \ : call(l:Function, [l:buffer, copy(l:input)]) + \ : call(l:Function, [l:buffer, v:null, copy(l:input)]) endif if type(l:result) is v:t_number && l:result == 0 diff --git a/sources_non_forked/ale/autoload/ale/fixers/black.vim b/sources_non_forked/ale/autoload/ale/fixers/black.vim index 4169322a..27249c55 100644 --- a/sources_non_forked/ale/autoload/ale/fixers/black.vim +++ b/sources_non_forked/ale/autoload/ale/fixers/black.vim @@ -4,22 +4,28 @@ call ale#Set('python_black_executable', 'black') call ale#Set('python_black_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('python_black_options', '') +call ale#Set('python_black_auto_pipenv', 0) + +function! ale#fixers#black#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_black_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + + return ale#python#FindExecutable(a:buffer, 'python_black', ['black']) +endfunction function! ale#fixers#black#Fix(buffer) abort - let l:executable = ale#python#FindExecutable( - \ a:buffer, - \ 'python_black', - \ ['black'], - \) + let l:executable = ale#fixers#black#GetExecutable(a:buffer) - if !executable(l:executable) - return 0 - endif + let l:exec_args = l:executable =~? 'pipenv$' + \ ? ' run black' + \ : '' let l:options = ale#Var(a:buffer, 'python_black_options') return { - \ 'command': ale#Escape(l:executable) + \ 'command': ale#Escape(l:executable) . l:exec_args \ . (!empty(l:options) ? ' ' . l:options : '') \ . ' -', \} diff --git a/sources_non_forked/ale/autoload/ale/fixers/generic.vim b/sources_non_forked/ale/autoload/ale/fixers/generic.vim index cb8865b4..1d88553e 100644 --- a/sources_non_forked/ale/autoload/ale/fixers/generic.vim +++ b/sources_non_forked/ale/autoload/ale/fixers/generic.vim @@ -1,7 +1,7 @@ " Author: w0rp " Description: Generic functions for fixing files with. -function! ale#fixers#generic#RemoveTrailingBlankLines(buffer, lines) abort +function! ale#fixers#generic#RemoveTrailingBlankLines(buffer, done, lines) abort let l:end_index = len(a:lines) - 1 while l:end_index > 0 && empty(a:lines[l:end_index]) @@ -12,7 +12,7 @@ function! ale#fixers#generic#RemoveTrailingBlankLines(buffer, lines) abort endfunction " Remove all whitespaces at the end of lines -function! ale#fixers#generic#TrimWhitespace(buffer, lines) abort +function! ale#fixers#generic#TrimWhitespace(buffer, done, lines) abort let l:index = 0 let l:lines_new = range(len(a:lines)) diff --git a/sources_non_forked/ale/autoload/ale/fixers/generic_python.vim b/sources_non_forked/ale/autoload/ale/fixers/generic_python.vim index d55a23c3..9a929b96 100644 --- a/sources_non_forked/ale/autoload/ale/fixers/generic_python.vim +++ b/sources_non_forked/ale/autoload/ale/fixers/generic_python.vim @@ -2,7 +2,7 @@ " Description: Generic fixer functions for Python. " Add blank lines before control statements. -function! ale#fixers#generic_python#AddLinesBeforeControlStatements(buffer, lines) abort +function! ale#fixers#generic_python#AddLinesBeforeControlStatements(buffer, done, lines) abort let l:new_lines = [] let l:last_indent_size = 0 let l:last_line_is_blank = 0 @@ -41,7 +41,7 @@ endfunction " This function breaks up long lines so that autopep8 or other tools can " fix the badly-indented code which is produced as a result. -function! ale#fixers#generic_python#BreakUpLongLines(buffer, lines) abort +function! ale#fixers#generic_python#BreakUpLongLines(buffer, done, lines) abort " Default to a maximum line length of 79 let l:max_line_length = 79 let l:conf = ale#path#FindNearestFile(a:buffer, 'setup.cfg') diff --git a/sources_non_forked/ale/autoload/ale/fixers/help.vim b/sources_non_forked/ale/autoload/ale/fixers/help.vim index b20740fe..9fb0717b 100644 --- a/sources_non_forked/ale/autoload/ale/fixers/help.vim +++ b/sources_non_forked/ale/autoload/ale/fixers/help.vim @@ -1,7 +1,7 @@ " Author: w0rp " Description: Generic fixer functions for Vim help documents. -function! ale#fixers#help#AlignTags(buffer, lines) abort +function! ale#fixers#help#AlignTags(buffer, done, lines) abort let l:new_lines = [] for l:line in a:lines diff --git a/sources_non_forked/ale/autoload/ale/fixers/standard.vim b/sources_non_forked/ale/autoload/ale/fixers/standard.vim index 2b1f6f92..77712d40 100644 --- a/sources_non_forked/ale/autoload/ale/fixers/standard.vim +++ b/sources_non_forked/ale/autoload/ale/fixers/standard.vim @@ -14,9 +14,11 @@ endfunction function! ale#fixers#standard#Fix(buffer) abort let l:executable = ale#fixers#standard#GetExecutable(a:buffer) + let l:options = ale#Var(a:buffer, 'javascript_standard_options') return { \ 'command': ale#node#Executable(a:buffer, l:executable) + \ . (!empty(l:options) ? ' ' . l:options : '') \ . ' --fix %t', \ 'read_temporary_file': 1, \} diff --git a/sources_non_forked/ale/autoload/ale/job.vim b/sources_non_forked/ale/autoload/ale/job.vim index 0117c7dd..f9a917e1 100644 --- a/sources_non_forked/ale/autoload/ale/job.vim +++ b/sources_non_forked/ale/autoload/ale/job.vim @@ -173,10 +173,6 @@ endfunction function! ale#job#PrepareCommand(buffer, command) abort let l:wrapper = ale#Var(a:buffer, 'command_wrapper') - let l:command = !empty(l:wrapper) - \ ? s:PrepareWrappedCommand(l:wrapper, a:command) - \ : a:command - " The command will be executed in a subshell. This fixes a number of " issues, including reading the PATH variables correctly, %PATHEXT% " expansion on Windows, etc. @@ -184,6 +180,17 @@ function! ale#job#PrepareCommand(buffer, command) abort " NeoVim handles this issue automatically if the command is a String, " but we'll do this explicitly, so we use the same exact command for both " versions. + let l:command = !empty(l:wrapper) + \ ? s:PrepareWrappedCommand(l:wrapper, a:command) + \ : a:command + + " If a custom shell is specified, use that. + if exists('g:ale_shell') + let l:shell_arguments = get(g:, 'ale_shell_arguments', &shellcmdflag) + + return split(g:ale_shell) + split(l:shell_arguments) + [l:command] + endif + if has('win32') return 'cmd /s/c "' . l:command . '"' endif diff --git a/sources_non_forked/ale/autoload/ale/references.vim b/sources_non_forked/ale/autoload/ale/references.vim index d00a1fa9..24267bb4 100644 --- a/sources_non_forked/ale/autoload/ale/references.vim +++ b/sources_non_forked/ale/autoload/ale/references.vim @@ -27,6 +27,7 @@ function! ale#references#HandleTSServerResponse(conn_id, response) abort \ 'filename': l:response_item.file, \ 'line': l:response_item.start.line, \ 'column': l:response_item.start.offset, + \ 'match': substitute(l:response_item.lineText, '^\s*\(.\{-}\)\s*$', '\1', ''), \}) endfor diff --git a/sources_non_forked/ale/autoload/ale/util.vim b/sources_non_forked/ale/autoload/ale/util.vim index bb478957..ee9359f8 100644 --- a/sources_non_forked/ale/autoload/ale/util.vim +++ b/sources_non_forked/ale/autoload/ale/util.vim @@ -87,12 +87,25 @@ function! ale#util#GetFunction(string_or_ref) abort return a:string_or_ref endfunction +" Open the file (at the given line). +" options['open_in'] can be: +" current-buffer (default) +" tab +" vertical-split +" horizontal-split function! ale#util#Open(filename, line, column, options) abort - if get(a:options, 'open_in_tab', 0) - call ale#util#Execute('tabedit +' . a:line . ' ' . fnameescape(a:filename)) + let l:open_in = get(a:options, 'open_in', 'current-buffer') + let l:args_to_open = '+' . a:line . ' ' . fnameescape(a:filename) + + if l:open_in is# 'tab' + call ale#util#Execute('tabedit ' . l:args_to_open) + elseif l:open_in is# 'horizontal-split' + call ale#util#Execute('split ' . l:args_to_open) + elseif l:open_in is# 'vertical-split' + call ale#util#Execute('vsplit ' . l:args_to_open) elseif bufnr(a:filename) isnot bufnr('') " Open another file only if we need to. - call ale#util#Execute('edit +' . a:line . ' ' . fnameescape(a:filename)) + call ale#util#Execute('edit ' . l:args_to_open) else normal! m` endif diff --git a/sources_non_forked/ale/doc/ale-go.txt b/sources_non_forked/ale/doc/ale-go.txt index 43289bd5..3fbc6fb9 100644 --- a/sources_non_forked/ale/doc/ale-go.txt +++ b/sources_non_forked/ale/doc/ale-go.txt @@ -7,7 +7,7 @@ Integration Information The `gometalinter` linter is disabled by default. ALE enables `gofmt`, `golint` and `go vet` by default. It also supports `staticcheck`, `go -build`, `gosimple`, and `golangserver`. +build`, `gosimple`, `golangserver`. To enable `gometalinter`, update |g:ale_linters| as appropriate: > @@ -195,5 +195,21 @@ g:ale_go_golangci_lint_package *g:ale_go_golangci_lint_package* current file. +=============================================================================== +bingo *ale-go-bingo* + +g:ale_go_bingo_executable *g:ale_go_bingo_executable* + *b:ale_go_bingo_executable* + Type: |String| + Default: `'go-bingo'` + + Location of the go-bingo binary file. + +g:ale_go_bingo_options *g:ale_go_bingo_options* + *b:ale_go_bingo_options* + Type: |String| + Default: `''` + + =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/sources_non_forked/ale/doc/ale-python.txt b/sources_non_forked/ale/doc/ale-python.txt index f3f2801a..a1ad1500 100644 --- a/sources_non_forked/ale/doc/ale-python.txt +++ b/sources_non_forked/ale/doc/ale-python.txt @@ -75,7 +75,7 @@ g:ale_python_black_executable *g:ale_python_black_executable* See |ale-integrations-local-executables| -autopep8 + g:ale_python_black_options *g:ale_python_black_options* *b:ale_python_black_options* Type: |String| @@ -92,6 +92,15 @@ g:ale_python_black_use_global *g:ale_python_black_use_global* See |ale-integrations-local-executables| +g:ale_python_black_auto_pipenv *g:ale_python_black_auto_pipenv* + *b:ale_python_black_auto_pipenv* + Type: |Number| + Default: `0` + + Detect whether the file is inside a pipenv, and set the executable to `pipenv` + if true. This is overridden by a manually-set executable. + + =============================================================================== flake8 *ale-python-flake8* diff --git a/sources_non_forked/ale/doc/ale.txt b/sources_non_forked/ale/doc/ale.txt index 0b127725..6bedf755 100644 --- a/sources_non_forked/ale/doc/ale.txt +++ b/sources_non_forked/ale/doc/ale.txt @@ -118,6 +118,7 @@ CONTENTS *ale-contents* staticcheck.........................|ale-go-staticcheck| golangserver........................|ale-go-golangserver| golangci-lint.......................|ale-go-golangci-lint| + bingo...............................|ale-go-bingo| graphql...............................|ale-graphql-options| eslint..............................|ale-graphql-eslint| gqlint..............................|ale-graphql-gqlint| @@ -438,7 +439,7 @@ Notes: * FusionScript: `fusion-lint` * Git Commit Messages: `gitlint` * GLSL: glslang, `glslls` -* Go: `gofmt`, `goimports`, `go mod`!!, `go vet`!!, `golint`, `gotype`!!, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!!, `golangserver`, `golangci-lint`!! +* Go: `gofmt`, `goimports`, `go mod`!!, `go vet`!!, `golint`, `gotype`!!, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!!, `golangserver`, `golangci-lint`!!, `bingo` * GraphQL: `eslint`, `gqlint`, `prettier` * Hack: `hack`, `hackfmt`, `hhast` * Haml: `haml-lint` @@ -675,10 +676,14 @@ The values for `g:ale_fixers` can be a list of |String|, |Funcref|, or for a function set in the ALE fixer registry. Each function for fixing errors must accept either one argument `(buffer)` or -two arguments `(buffer, lines)`, representing the buffer being fixed and the -lines to fix. The functions must return either `0`, for changing nothing, a -|List| for new lines to set, or a |Dictionary| for describing a command to be -run in the background. +three arguments `(buffer, done, lines)`, representing the buffer being fixed, +a function to call with results, and the lines to fix. The functions must +return either `0`, for changing nothing, a |List| for new lines to set, a +|Dictionary| for describing a command to be run in the background, or `v:true` +for indicating that results will be provided asynchronously via the `done` +callback. + +NOTE: The `done` function has not been implemented yet. Functions receiving a variable number of arguments will not receive the second argument `lines`. Functions should name two arguments if the `lines` argument @@ -816,6 +821,9 @@ with |g:ale_completion_max_suggestions|. If you don't like some of the suggestions you see, you can filter them out with |g:ale_completion_excluded_words| or |b:ale_completion_excluded_words|. +The |ALEComplete| command can be used to show completion suggestions manually, +even when |g:ale_completion_enabled| is set to `0`. + *ale-completion-completopt-bug* ALE implements completion as you type by temporarily adjusting |completeopt| @@ -836,6 +844,8 @@ information returned by LSP servers. The following commands are supported: |ALEGoToDefinition| - Open the definition of the symbol under the cursor. |ALEGoToDefinitionInTab| - The same, but for opening the file in a new tab. +|ALEGoToDefinitionInSplit| - The same, but in a new split. +|ALEGoToDefinitionInVSplit| - The same, but in a new vertical split. ------------------------------------------------------------------------------- @@ -1787,6 +1797,33 @@ g:ale_set_signs *g:ale_set_signs* To limit the number of signs ALE will set, see |g:ale_max_signs|. +g:ale_shell *g:ale_shell* + + Type: |String| + Default: not set + + Override the shell used by ALE for executing commands. ALE uses 'shell' by + default, but falls back in `/bin/sh` if the default shell looks like `fish` + or `pwsh`, which are not compatible with all of the commands run by ALE. The + shell specified with this option will be used even if it might not work in + all cases. + + For Windows, ALE uses `cmd` when this option isn't set. Setting this option + will apply shell escaping to the command string, even on Windows. + + NOTE: Consider setting |g:ale_shell_arguments| if this option is defined. + + +g:ale_shell_arguments *g:ale_shell_arguments* + + Type: |String| + Default: not set + + This option specifies the arguments to use for executing a command with a + custom shell, per |g:ale_shell|. If this option is not set, 'shellcmdflag' + will be used instead. + + g:ale_sign_column_always *g:ale_sign_column_always* Type: |Number| @@ -2202,6 +2239,17 @@ ALE will use to search for Python executables. =============================================================================== 8. Commands/Keybinds *ale-commands* +ALEComplete *ALEComplete* + + Manually trigger LSP autocomplete and show the menu. Works only when called + from insert mode. > + + inoremap :AleComplete +< + A plug mapping `(ale_complete)` is defined for this command. > + + imap (ale_complete) +< ALEDocumentation *ALEDocumentation* Similar to the |ALEHover| command, retrieve documentation information for @@ -2262,6 +2310,22 @@ ALEGoToDefinitionInTab *ALEGoToDefinitionInTab* command. +ALEGoToDefinitionInSplit *ALEGoToDefinitionInSplit* + + The same as |ALEGoToDefinition|, but opens results in a new split. + + A plug mapping `(ale_go_to_definition_in_split)` is defined for this + command. + + +ALEGoToDefinitionInVSplit *ALEGoToDefinitionInVSplit* + + The same as |ALEGoToDefinition|, but opens results in a new vertical split. + + A plug mapping `(ale_go_to_definition_in_vsplit)` is defined for this + command. + + ALEHover *ALEHover* Print brief information about the symbol under the cursor, taken from any diff --git a/sources_non_forked/ale/plugin/ale.vim b/sources_non_forked/ale/plugin/ale.vim index 610ff142..4af59a91 100644 --- a/sources_non_forked/ale/plugin/ale.vim +++ b/sources_non_forked/ale/plugin/ale.vim @@ -188,7 +188,9 @@ command! -bar ALEFixSuggest :call ale#fix#registry#Suggest(&filetype) " Go to definition for tsserver and LSP command! -bar ALEGoToDefinition :call ale#definition#GoTo({}) -command! -bar ALEGoToDefinitionInTab :call ale#definition#GoTo({'open_in_tab': 1}) +command! -bar ALEGoToDefinitionInTab :call ale#definition#GoTo({'open_in': 'tab'}) +command! -bar ALEGoToDefinitionInSplit :call ale#definition#GoTo({'open_in': 'horizontal-split'}) +command! -bar ALEGoToDefinitionInVSplit :call ale#definition#GoTo({'open_in': 'vertical-split'}) " Find references for tsserver and LSP command! -bar ALEFindReferences :call ale#references#Find() @@ -202,6 +204,8 @@ command! -bar ALEDocumentation :call ale#hover#ShowDocumentationAtCursor() " Search for appearances of a symbol, such as a type name or function name. command! -nargs=1 ALESymbolSearch :call ale#symbol#Search() +command! -bar ALEComplete :call ale#completion#AlwaysGetCompletions() + " mappings for commands nnoremap (ale_previous) :ALEPrevious nnoremap (ale_previous_wrap) :ALEPreviousWrap @@ -222,9 +226,12 @@ nnoremap (ale_detail) :ALEDetail nnoremap (ale_fix) :ALEFix nnoremap (ale_go_to_definition) :ALEGoToDefinition nnoremap (ale_go_to_definition_in_tab) :ALEGoToDefinitionInTab +nnoremap (ale_go_to_definition_in_split) :ALEGoToDefinitionInSplit +nnoremap (ale_go_to_definition_in_vsplit) :ALEGoToDefinitionInVSplit nnoremap (ale_find_references) :ALEFindReferences nnoremap (ale_hover) :ALEHover nnoremap (ale_documentation) :ALEDocumentation +inoremap (ale_complete) :ALEComplete " Set up autocmd groups now. call ale#events#Init() diff --git a/sources_non_forked/vim-fugitive/autoload/fugitive.vim b/sources_non_forked/vim-fugitive/autoload/fugitive.vim index d8063a61..1a14c2b6 100644 --- a/sources_non_forked/vim-fugitive/autoload/fugitive.vim +++ b/sources_non_forked/vim-fugitive/autoload/fugitive.vim @@ -107,6 +107,19 @@ function! s:cpath(path, ...) abort return a:0 ? path ==# s:cpath(a:1) : path endfunction +function! s:Cd(...) abort + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : exists(':tcd') && haslocaldir(-1) ? 'tcd' : 'cd' + if !a:0 + return cd + endif + let cwd = getcwd() + if s:cpath(cwd, a:1) + return '' + endif + exe cd s:fnameescape(a:1) + return cd . ' ' . s:fnameescape(cwd) +endfunction + let s:executables = {} function! s:executable(binary) abort @@ -314,10 +327,54 @@ function! fugitive#RevParse(rev, ...) abort call s:throw('rev-parse '.a:rev.': '.hash) endfunction -function! fugitive#Config(name, ...) abort - let cmd = fugitive#Prepare(a:0 ? a:1 : get(b:, 'git_dir', ''), '--no-literal-pathspecs', 'config', '--get', '--', a:name) - let out = matchstr(system(cmd), "[^\n]*") - return v:shell_error ? '' : out +function! s:ConfigTimestamps(dir, dict) abort + let files = ['/etc/gitconfig', '~/.gitconfig', + \ len($XDG_CONFIG_HOME) ? $XDG_CONFIG_HOME . '/git/config' : '~/.config/git/config'] + if len(a:dir) + call add(files, fugitive#Find('.git/config', a:dir)) + endif + call extend(files, get(a:dict, 'include.path', [])) + return join(map(files, 'getftime(expand(v:val))'), ',') +endfunction + +let s:config = {} +function! fugitive#Config(...) abort + let dir = get(b:, 'git_dir', '') + let name = '' + if a:0 >= 2 && type(a:2) == type({}) + let name = substitute(a:1, '^[^.]\+\|[^.]\+$', '\L&', 'g') + return len(a:1) ? get(get(a:2, name, []), 0, '') : a:2 + elseif a:0 >= 2 + let dir = a:2 + let name = a:1 + elseif a:0 == 1 && type(a:1) == type({}) + return a:1 + elseif a:0 == 1 && a:1 =~# '^[[:alnum:]-]\+\.' + let name = a:1 + elseif a:0 == 1 + let dir = a:1 + endif + let name = substitute(name, '^[^.]\+\|[^.]\+$', '\L&', 'g') + let key = len(dir) ? dir : '_' + if has_key(s:config, key) && s:config[key][0] ==# s:ConfigTimestamps(dir, s:config[key][1]) + let dict = s:config[key][1] + else + let dict = {} + let lines = split(system(FugitivePrepare(['config', '--list', '-z'], dir)), "\1") + if v:shell_error + return {} + endif + for line in lines + let key = matchstr(line, "^[^\n]*") + if !has_key(dict, key) + let dict[key] = [] + endif + call add(dict[key], strpart(line, len(key) + 1)) + endfor + let s:config[dir] = [s:ConfigTimestamps(dir, dict), dict] + lockvar! dict + endif + return len(name) ? get(get(dict, name, []), 0, '') : dict endfunction function! s:Remote(dir) abort @@ -430,13 +487,11 @@ function! s:repo_git_chomp(...) dict abort endfunction function! s:repo_git_chomp_in_tree(...) dict abort - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let dir = getcwd() + let cdback = s:Cd(self.tree()) try - execute cd s:fnameescape(self.tree()) return call(self.git_chomp, a:000, self) finally - execute cd s:fnameescape(dir) + execute cdback endtry endfunction @@ -568,7 +623,7 @@ function! fugitive#Path(url, ...) abort let file = '/.git'.url[strlen(dir) : -1] elseif len(tree) && s:cpath(url[0 : len(tree)]) ==# s:cpath(tree . '/') let file = url[len(tree) : -1] - elseif s:cpath(url) ==# s:cpath(tree) || len(argdir) && empty(file) + elseif s:cpath(url) ==# s:cpath(tree) let file = '/' endif if empty(file) && a:1 =~# '^$\|^[.:]/$' @@ -1095,97 +1150,43 @@ let s:buffer_prototype = {} function! fugitive#buffer(...) abort let buffer = {'#': bufnr(a:0 ? a:1 : '%')} call extend(buffer, s:buffer_prototype, 'keep') - if buffer.getvar('git_dir') !=# '' - return buffer - endif - call s:throw('not a Fugitive buffer: ' . string(bufname(buffer['#']))) + return buffer endfunction function! s:buffer_getvar(var) dict abort - return getbufvar(self['#'],a:var) + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().getvar() which has been removed. Replace it with the local variable or getbufvar()" endfunction function! s:buffer_getline(lnum) dict abort - return get(getbufline(self['#'], a:lnum), 0, '') + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().getline() which has been removed. Replace it with getline() or getbufline()" endfunction function! s:buffer_repo() dict abort - return fugitive#repo(self.getvar('git_dir')) + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().repo() which has been removed. Replace it with fugitive#repo()" endfunction function! s:buffer_type(...) dict abort - if !empty(self.getvar('fugitive_type')) - let type = self.getvar('fugitive_type') - elseif fnamemodify(self.spec(),':p') =~# '\.git/refs/\|\.git/\w*HEAD$' - let type = 'head' - elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == '' - let type = 'tree' - elseif self.getline(1) =~ '^\d\{6\} \w\{4\} \x\{40\}\>\t' - let type = 'tree' - elseif self.getline(1) =~ '^\d\{6\} \x\{40\}\> \d\t' - let type = 'index' - elseif isdirectory(self.spec()) - let type = 'directory' - elseif self.spec() == '' - let type = 'null' - else - let type = 'file' - endif - if a:0 - return !empty(filter(copy(a:000),'v:val ==# type')) - else - return type - endif + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().type() which has been removed. Replace it with get(b:, 'fugitive_type', '')" endfunction -if has('win32') - - function! s:buffer_spec() dict abort - let bufname = bufname(self['#']) - let retval = '' - for i in split(bufname,'[^:]\zs\\') - let retval = fnamemodify((retval==''?'':retval.'\').i,':.') - endfor - return s:Slash(fnamemodify(retval,':p')) - endfunction - -else - - function! s:buffer_spec() dict abort - let bufname = bufname(self['#']) - return s:Slash(bufname == '' ? '' : fnamemodify(bufname,':p')) - endfunction - -endif +function! s:buffer_spec() dict abort + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().spec() which has been removed. Replace it with bufname(), expand('%:p'), etc" +endfunction function! s:buffer_name() dict abort - return self.spec() + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().name() which has been removed. Replace it with bufname(), expand('%:p'), etc" endfunction function! s:buffer_commit() dict abort - return matchstr(self.spec(),'^fugitive:\%(//\)\=.\{-\}\%(//\|::\)\zs\w*') + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().commit() which has been removed. Replace it with matchstr(FugitiveParse()[0], '^\x\+')" endfunction function! s:buffer_relative(...) dict abort - let rev = matchstr(self.spec(),'^fugitive:\%(//\)\=.\{-\}\%(//\|::\)\zs.*') - if rev != '' - let rev = s:sub(rev,'\w*','') - elseif s:cpath(self.spec()[0 : len(self.repo().dir())]) ==# - \ s:cpath(self.repo().dir() . '/') - let rev = '/.git'.self.spec()[strlen(self.repo().dir()) : -1] - elseif !self.repo().bare() && - \ s:cpath(self.spec()[0 : len(self.repo().tree())]) ==# - \ s:cpath(self.repo().tree() . '/') - let rev = self.spec()[strlen(self.repo().tree()) : -1] - endif - return s:sub(s:sub(rev,'.\zs/$',''),'^/',a:0 ? a:1 : '') + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().relative() which has been removed. Replace it with FugitivePath(@%, " . string(a:0 ? a:1 : '') . ")" endfunction function! s:buffer_path(...) dict abort - if a:0 - return self.relative(a:1) - endif - return self.relative() + throw "fugitive: A third-party plugin or vimrc is calling fugitive#buffer().path() which has been removed. Replace it with FugitivePath(@%, " . string(a:0 ? a:1 : '') . ")" endfunction call s:add_methods('buffer',['getvar','getline','repo','type','spec','name','commit','path','relative']) @@ -1291,15 +1292,17 @@ function! s:ReplaceCmd(cmd, ...) abort endif let temp = s:Resolve(temp) let fn = expand('%:p') - silent exe 'doau BufReadPre '.s:fnameescape(fn) silent exe 'keepalt file '.temp + let modelines = &modelines try + set modelines=0 if a:0 - silent noautocmd edit! + silent keepjumps noautocmd edit! else - silent edit! + silent keepjumps edit! endif finally + let &modelines = modelines try silent exe 'keepalt file '.s:fnameescape(fn) catch /^Vim\%((\a\+)\)\=:E302:/ @@ -1308,83 +1311,265 @@ function! s:ReplaceCmd(cmd, ...) abort if s:cpath(fnamemodify(bufname('$'), ':p'), temp) silent execute 'bwipeout '.bufnr('$') endif - silent exe 'doau BufReadPost '.s:fnameescape(fn) endtry endfunction +function! s:QueryLog(refspec) abort + let lines = split(system(FugitivePrepare('log', '-n', '256', '--format=%h%x09%s', a:refspec, '--')), "\n") + call map(lines, 'split(v:val, "\t")') + call map(lines, '{"type": "Log", "commit": v:val[0], "subject": v:val[-1]}') + return lines +endfunction + +function! s:FormatLog(dict) abort + return a:dict.commit . ' ' . a:dict.subject +endfunction + +function! s:FormatRebase(dict) abort + return a:dict.status . ' ' . a:dict.commit . ' ' . a:dict.subject +endfunction + +function! s:FormatFile(dict) abort + return a:dict.status . ' ' . a:dict.filename +endfunction + +function! s:Format(val) abort + if type(a:val) == type({}) + return s:Format{a:val.type}(a:val) + elseif type(a:val) == type([]) + return map(copy(a:val), 's:Format(v:val)') + else + return '' . a:val + endif +endfunction + +function! s:AddHeader(key, value) abort + if empty(a:value) + return + endif + let before = 1 + while !empty(getline(before)) + let before += 1 + endwhile + call append(before - 1, [a:key . ':' . (len(a:value) ? ' ' . a:value : '')]) + if before == 1 && line('$') == 2 + silent 2delete _ + endif +endfunction + +function! s:AddSection(label, lines, ...) abort + let note = a:0 ? a:1 : '' + if empty(a:lines) && empty(note) + return + endif + call append(line('$'), ['', a:label . (len(note) ? ': ' . note : ' (' . len(a:lines) . ')')] + s:Format(a:lines)) +endfunction + function! fugitive#BufReadStatus() abort let amatch = s:Slash(expand('%:p')) - if !exists('b:fugitive_display_format') - let b:fugitive_display_format = filereadable(expand('%').'.lock') - endif - let b:fugitive_display_format = b:fugitive_display_format % 2 let b:fugitive_type = 'index' try + silent doautocmd BufReadPre let cmd = [fnamemodify(amatch, ':h')] - setlocal noro ma nomodeline + setlocal noro ma nomodeline buftype=nowrite if s:cpath(fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : b:git_dir . '/index', ':p')) !=# s:cpath(amatch) let cmd += ['-c', 'GIT_INDEX_FILE=' . amatch] endif - if b:fugitive_display_format - let cmd += ['ls-files', '--stage'] - else - let cmd += [ - \ '-c', 'status.displayCommentPrefix=true', - \ '-c', 'color.status=false', - \ '-c', 'status.short=false', - \ 'status'] + let cmd += ['status', '--porcelain', '-bz'] + let output = split(system(fugitive#Prepare(cmd)), "\1") + if v:shell_error + throw 'fugitive: ' . join(output, ' ') endif - call s:ReplaceCmd(call('fugitive#Prepare', cmd), 1) - if b:fugitive_display_format - if &filetype !=# 'git' - set filetype=git - endif - set nospell + + let head = matchstr(output[0], '^## \zs\S\+\ze\%($\| \[\)') + let pull = '' + if head =~# '\.\.\.' + let [head, pull] = split(head, '\.\.\.') + let branch = head + elseif head ==# 'HEAD' || empty(head) + let head = FugitiveHead(11) + let branch = '' else - if &filetype !=# 'gitcommit' - set filetype=gitcommit - endif - set foldtext=fugitive#Foldtext() + let branch = head endif - setlocal readonly nomodifiable nomodified noswapfile + + let [staged, unstaged] = [[], []] + let i = 0 + while i < len(output) + let line = output[i] + let file = line[3:-1] + let files = file + let i += 1 + if line[0:1] =~# '[RC]' + let files = output[i] . ' -> ' . file + let i += 1 + endif + if line[0] !~# '[ ?!#]' + call add(staged, {'type': 'File', 'status': line[0], 'filename': (line[0] =~# '[RC]' ? files : file)}) + endif + if line[1] !~# '[ !#]' + call add(unstaged, {'type': 'File', 'status': line[1], 'filename': (line[1] =~# '[RC]' ? files : file)}) + endif + endwhile + + let config = fugitive#Config() + + let pull_type = 'Pull' + if len(pull) + let rebase = fugitive#Config('branch.' . branch . '.rebase', config) + if empty(rebase) + let rebase = fugitive#Config('pull.rebase', config) + endif + if rebase =~# '^\%(true\|yes\|on\|1\|interactive\)$' + let pull_type = 'Rebase' + elseif rebase =~# '^\%(false\|no|off\|0\|\)$' + let pull_type = 'Merge' + endif + endif + + let push_remote = fugitive#Config('branch.' . branch . '.pushRemote', config) + if empty(push_remote) + let push_remote = fugitive#Config('remote.pushDefault', config) + endif + let push = len(push_remote) && len(branch) ? push_remote . '/' . branch : '' + if empty(push) + let push = pull + endif + + if len(pull) + let unpulled = s:QueryLog(head . '..' . pull) + else + let unpulled = [] + endif + if len(push) + let unpushed = s:QueryLog(push . '..' . head) + else + let unpushed = [] + endif + + if isdirectory(fugitive#Find('.git/rebase-merge/')) + let rebasing_dir = fugitive#Find('.git/rebase-merge/') + elseif isdirectory(fugitive#Find('.git/rebase-apply/')) + let rebasing_dir = fugitive#Find('.git/rebase-apply/') + endif + + let rebasing = [] + let rebasing_head = 'detached HEAD' + if exists('rebasing_dir') && filereadable(rebasing_dir . 'git-rebase-todo') + let rebasing_head = substitute(readfile(rebasing_dir . 'head-name')[0], '\C^refs/heads/', '', '') + let len = 11 + let lines = readfile(rebasing_dir . 'git-rebase-todo') + for line in lines + let hash = matchstr(line, '^[^a-z].*\s\zs[0-9a-f]\{4,\}\ze\.\.') + if len(hash) + let len = len(hash) + break + endif + endfor + if getfsize(rebasing_dir . 'done') > 0 + let done = readfile(rebasing_dir . 'done') + call map(done, 'substitute(v:val, ''^\l\+\>'', "done", "")') + let done[-1] = substitute(done[-1], '^\l\+\>', 'stop', '') + let lines = done + lines + endif + call reverse(lines) + for line in lines + let match = matchlist(line, '^\(\l\+\)\s\+\(\x\{4,\}\)\s\+\(.*\)') + if len(match) && match[1] !~# 'exec\|merge\|label' + call add(rebasing, {'type': 'Rebase', 'status': get(s:rebase_abbrevs, match[1], match[1]), 'commit': strpart(match[2], 0, len), 'subject': match[3]}) + endif + endfor + endif + + let b:fugitive_diff = { + \ 'Staged': split(system(fugitive#Prepare('diff', '--no-ext-diff', '--no-prefix', '--cached')), "\n"), + \ 'Unstaged': split(system(fugitive#Prepare('diff', '--no-ext-diff', '--no-prefix')), "\n")} + let expanded = get(b:, 'fugitive_expanded', {'Staged': {}, 'Unstaged': {}}) + let b:fugitive_expanded = {'Staged': {}, 'Unstaged': {}} + + silent keepjumps %delete_ + + call s:AddHeader('Head', head) + call s:AddHeader(pull_type, pull) + if push !=# pull + call s:AddHeader('Push', push) + endif + call s:AddSection('Rebasing ' . rebasing_head, rebasing) + call s:AddSection('Unstaged', unstaged) + let unstaged_end = len(unstaged) ? line('$') : 0 + call s:AddSection('Staged', staged) + let staged_end = len(staged) ? line('$') : 0 + call s:AddSection('Unpushed to ' . push, unpushed) + call s:AddSection('Unpulled from ' . pull, unpulled) + + set nomodified readonly noswapfile + silent doautocmd BufReadPost + set foldtext=fugitive#Foldtext() + set filetype=fugitive + setlocal nomodifiable if &bufhidden ==# '' setlocal bufhidden=delete endif + let b:dispatch = ':Gfetch --all' call fugitive#MapJumps() let nowait = v:version >= 704 ? '' : '' nunmap P nunmap ~ nnoremap :execute StageNext(v:count1) nnoremap :execute StagePrevious(v:count1) - exe "nnoremap " nowait "- :silent execute StageToggle(line('.'),line('.')+v:count1-1)" - exe "xnoremap " nowait "- :silent execute StageToggle(line(\"'<\"),line(\"'>\"))" - nnoremap a :let b:fugitive_display_format += 1exe fugitive#BufReadStatus() - nnoremap i :let b:fugitive_display_format -= 1exe fugitive#BufReadStatus() + exe "nnoremap " nowait "- :execute StageToggle(line('.'),v:count)" + exe "xnoremap " nowait "- :execute StageToggle(line(\"'<\"),line(\"'>\")-line(\"'<\")+1)" + exe "nnoremap " nowait "s :execute StageToggleOnly('Unstaged',line('.'),v:count)" + exe "xnoremap " nowait "s :execute StageToggle(line(\"'<\"),line(\"'>\")-line(\"'<\")+1)" + exe "nnoremap " nowait "u :execute StageToggleOnly('Staged',line('.'),v:count)" + exe "xnoremap " nowait "u :execute StageToggle(line(\"'<\"),line(\"'>\")-line(\"'<\")+1)" nnoremap C :Gcommit:echohl WarningMsgecho ':Gstatus C is deprecated in favor of cc'echohl NONE - nnoremap cA :Gcommit --amend --reuse-message=HEAD:echohl WarningMsgecho ':Gstatus cA is deprecated in favor of ce'echohl NONE nnoremap ca :Gcommit --amend nnoremap cc :Gcommit nnoremap ce :Gcommit --amend --no-edit nnoremap cw :Gcommit --amend --only nnoremap cva :Gcommit -v --amend nnoremap cvc :Gcommit -v + nnoremap a :execute StageInline('toggle',line('.'),v:count) + nnoremap i :execute StageInline('toggle',line('.'),v:count) + exe 'nnoremap ' nowait "= :execute StageInline('toggle',line('.'),v:count)" + exe 'nnoremap ' nowait "< :execute StageInline('show', line('.'),v:count)" + exe 'nnoremap ' nowait "> :execute StageInline('hide', line('.'),v:count)" + exe 'xnoremap ' nowait "= :execute StageInline('toggle',line(\"'<\"),line(\"'>\")-line(\"'<\")+1)" + exe 'xnoremap ' nowait "< :execute StageInline('show', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)" + exe 'xnoremap ' nowait "> :execute StageInline('hide', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)" nnoremap D :execute StageDiff('Gdiff') nnoremap dd :execute StageDiff('Gdiff') nnoremap dh :execute StageDiff('Gsdiff') nnoremap ds :execute StageDiff('Gsdiff') nnoremap dp :execute StageDiffEdit() nnoremap dv :execute StageDiff('Gvdiff') - nnoremap p :execute StagePatch(line('.'),line('.')+v:count1-1) - xnoremap p :execute StagePatch(line("'<"),line("'>")) nnoremap P :execute StagePatch(line('.'),line('.')+v:count1-1) xnoremap P :execute StagePatch(line("'<"),line("'>")) nnoremap q :if bufnr('$') == 1quitelsebdeleteendif - nnoremap r :edit - nnoremap R :edit - nnoremap U :execute StageUndo() - nnoremap . : =fnameescape(StatusCfile()) + nnoremap r :exe ReloadStatus() + nnoremap R :exe ReloadStatus() + nnoremap U :echoerr 'Changed to X' + nnoremap g :execute StageDelete(line('.'),v:count) + xnoremap g :execute StageDelete(line("'<"),line("'>")-line("'<")+1) + nnoremap X :execute StageDelete(line('.'),v:count) + xnoremap X :execute StageDelete(line("'<"),line("'>")-line("'<")+1) + nnoremap . : =fnameescape(get(StatusCfile(),0,'')) + nnoremap q :bdelete nnoremap g? :help fugitive-:Gstatus nnoremap :help fugitive-:Gstatus + + for [lnum, section] in [[staged_end, 'Staged'], [unstaged_end, 'Unstaged']] + while len(getline(lnum)) + let filename = matchstr(getline(lnum), '^[A-Z?] \zs.*') + if has_key(expanded[section], filename) + call s:StageInline('show', lnum) + endif + let lnum -= 1 + endwhile + endfor + + return '' catch /^fugitive:/ return 'echoerr v:errmsg' endtry @@ -1460,7 +1645,7 @@ function! fugitive#BufReadCmd(...) abort unlet b:fugitive_type if rev =~# '^:\d:' let &readonly = !filewritable(dir . '/index') - return 'silent doautocmd BufNewFile '.s:fnameescape(amatch) + return 'silent doautocmd BufNewFile' else setlocal readonly nomodifiable return 'echo ' . string(error) @@ -1483,6 +1668,7 @@ function! fugitive#BufReadCmd(...) abort setlocal endofline try + silent doautocmd BufReadPre if b:fugitive_type ==# 'tree' let b:fugitive_display_format = b:fugitive_display_format % 2 if b:fugitive_display_format @@ -1523,20 +1709,16 @@ function! fugitive#BufReadCmd(...) abort call s:ReplaceCmd([dir, 'ls-files', '--stage']) elseif b:fugitive_type ==# 'blob' call s:ReplaceCmd([dir, 'cat-file', b:fugitive_type, rev]) - setlocal nomodeline endif finally keepjumps call setpos('.',pos) setlocal nomodified noswapfile - if rev !~# '^:.:' - setlocal nomodifiable - else - let &modifiable = b:fugitive_type !=# 'tree' - endif - let &readonly = !&modifiable || !filewritable(dir . '/index') + let modifiable = rev =~# '^:.:' && b:fugitive_type !=# 'tree' + let &readonly = !modifiable || !filewritable(dir . '/index') if &bufhidden ==# '' setlocal bufhidden=delete endif + let &l:modifiable = modifiable if b:fugitive_type !=# 'blob' setlocal filetype=git foldmethod=syntax nnoremap a :let b:fugitive_display_format += v:count1exe fugitive#BufReadCmd(@%) @@ -1546,7 +1728,9 @@ function! fugitive#BufReadCmd(...) abort endif endtry - return '' + setlocal modifiable + return 'silent doautocmd' . (v:version >= 704 ? ' ' : '') . + \ ' BufReadPost' . (modifiable ? '' : '|setl nomodifiable') catch /^fugitive:/ return 'echoerr v:errmsg' endtry @@ -1591,6 +1775,9 @@ function! s:SetupTemp(file) abort setlocal nomodifiable endif call FugitiveDetect(a:file) + if &filetype ==# 'git' + call fugitive#MapJumps() + endif endif return '' endfunction @@ -1630,7 +1817,7 @@ function! s:Git(bang, mods, args) abort else let cmd = "exe '!'.escape(" . string(git) . " . ' ' . s:ShellExpand(" . string(args) . "),'!#%')" if s:cpath(tree) !=# s:cpath(getcwd()) - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' + let cd = s:Cd() let cmd = 'try|' . cd . ' ' . tree . '|' . cmd . '|finally|' . cd . ' ' . s:fnameescape(getcwd()) . '|endtry' endif return cmd . after @@ -1691,27 +1878,116 @@ call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :exe " Section: :Gstatus call s:command("-bar -bang -range=-1 Gstatus :execute s:Status(0, , '')") +call s:command("-bar -bang -range=-1 G :execute s:Status(0, , '')") augroup fugitive_status autocmd! if !has('win32') autocmd FocusGained,ShellCmdPost * call fugitive#ReloadStatus() + autocmd QuickFixCmdPost c*file call fugitive#ReloadStatus() autocmd BufDelete term://* call fugitive#ReloadStatus() endif augroup END function! s:Status(bang, count, mods) abort try - exe (a:mods ==# '' ? '' : a:mods) 'Gpedit :' - wincmd P - setlocal foldmethod=syntax foldlevel=1 buftype=nowrite - nnoremap q :bdelete + let dir = b:git_dir + let mods = a:mods ==# '' || empty(a:mods) ? 'leftabove' : a:mods + let file = fugitive#Find(':') + for winnr in range(1, winnr('$')) + if s:cpath(file, fnamemodify(bufname(winbufnr(winnr)), ':p')) + exe winnr . 'wincmd w' + let w:fugitive_status = dir + return s:ReloadStatus() + endif + endfor + let wide = winwidth(0) >= 160 + if a:count ==# 0 + exe mods 'Gedit :' + elseif a:bang + exe mods (a:count ==# -1 && wide ? 'vert' : '') 'Gpedit :' + wincmd P + elseif a:count ==# -1 && wide + exe mods 'Gvsplit :' + else + exe mods a:count > 0 ? a:count : '' 'Gsplit :' + endif + let w:fugitive_status = dir + setlocal foldmethod=syntax foldlevel=1 catch /^fugitive:/ return 'echoerr v:errmsg' endtry return '' endfunction -function! fugitive#ReloadStatus() abort +function! s:StageSeek(info, fallback) abort + let info = a:info + if empty(info.section) + return a:fallback + endif + let line = search('^' . info.section, 'wn') + if !line + for section in get({'Staged': ['Unstaged'], 'Unstaged': ['Staged']}, info.section, []) + let line = search('^' . section, 'wn') + if line + return line + (info.index > 0 ? 1 : 0) + endif + endfor + return 1 + endif + let i = 0 + while len(getline(line)) + let filename = matchstr(getline(line), '^[A-Z?] \zs.*') + if len(filename) && + \ ((info.filename[-1:-1] ==# '/' && filename[0 : len(info.filename) - 1] ==# info.filename) || + \ (filename[-1:-1] ==# '/' && filename ==# info.filename[0 : len(filename) - 1]) || + \ filename ==# info.filename) + if info.offset < 0 + return line + else + if getline(line+1) !~# '^@' + exe s:StageInline('show', line) + endif + if getline(line+1) !~# '^@' + return line + endif + let type = info.sigil ==# '-' ? '-' : '+' + let offset = -1 + while offset < info.offset + let line += 1 + if getline(line) =~# '^@' + let offset = +matchstr(getline(line), type . '\zs\d\+') - 1 + elseif getline(line) =~# '^[ ' . type . ']' + let offset += 1 + elseif getline(line) !~# '^[ @\+-]' + return line - 1 + endif + endwhile + return line + endif + endif + let commit = matchstr(getline(line), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\+') + if len(commit) && commit ==# info.commit + return line + endif + if i ==# info.index + let backup = line + endif + let i += getline(line) !~# '^[ @\+-]' + let line += 1 + endwhile + return exists('backup') ? backup : line - 1 +endfunction + +function! s:ReloadStatus(...) abort + let original_lnum = a:0 ? a:1 : line('.') + let info = s:StageInfo(original_lnum) + call fugitive#BufReadStatus() + exe s:StageSeek(info, original_lnum) + normal! 0 + return '' +endfunction + +function! fugitive#ReloadStatus(...) abort if exists('s:reloading_status') return endif @@ -1728,10 +2004,11 @@ function! fugitive#ReloadStatus() abort endif try if !&modified - call fugitive#BufReadStatus() + exe s:ReloadStatus() endif finally if exists('restorewinnr') + unlet restorewinnr wincmd p endif execute 'tabnext '.mytab @@ -1744,40 +2021,61 @@ function! fugitive#ReloadStatus() abort endtry endfunction -function! fugitive#reload_status() abort - return fugitive#ReloadStatus() +function! s:StageInfo(...) abort + let lnum = a:0 ? a:1 : line('.') + let sigil = matchstr(getline('.'), '^[ @\+-]') + let offset = -1 + if getline(lnum) =~# '^[ @\+-]' + let type = sigil ==# '-' ? '-' : '+' + while lnum > 0 && getline(lnum) !~# '^@' + if getline(lnum) =~# '^[ '.type.']' + let offset += 1 + endif + let lnum -= 1 + endwhile + let offset += matchstr(getline(lnum), type.'\zs\d\+') + while getline(lnum) =~# '^[ @\+-]' + let lnum -= 1 + endwhile + endif + let slnum = lnum + 1 + let section = '' + let index = 0 + while len(getline(slnum - 1)) && empty(section) + let slnum -= 1 + let section = matchstr(getline(slnum), '^\u\l\+\ze.* (\d\+)$') + if empty(section) && getline(slnum) !~# '^[ @\+-]' + let index += 1 + endif + endwhile + return {'section': section, + \ 'heading': getline(slnum), + \ 'sigil': sigil, + \ 'offset': offset, + \ 'filename': matchstr(getline(lnum), '^[A-Z?] \zs.*'), + \ 'commit': matchstr(getline(lnum), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\{4,\}\ze '), + \ 'status': matchstr(getline(lnum), '^[A-Z?]\ze \|^\%(\x\x\x\)\@!\l\+\ze [0-9a-f]'), + \ 'index': index} endfunction -function! s:stage_info(lnum) abort - let filename = matchstr(getline(a:lnum),'^.\=\t\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$') - let lnum = a:lnum - if has('multi_byte_encoding') - let colon = '\%(:\|\%uff1a\)' - else - let colon = ':' - endif - while lnum && getline(lnum) !~# colon.'$' - let lnum -= 1 - endwhile - if !lnum - return ['', ''] - elseif (getline(lnum+1) =~# '^.\= .*\ line('w$') && line('.') > line('w0') + &scrolloff + execute "normal! \" + endwhile endif endfunction function! s:StageNext(count) abort for i in range(a:count) - call search('^.\=\t.*','W') + call search('^[A-Z?] .\|^[0-9a-f]\{4,\} \|^@','W') endfor + call s:StageReveal() return '.' endfunction @@ -1786,81 +2084,133 @@ function! s:StagePrevious(count) abort return 'CtrlP '.fnameescape(s:Tree()) else for i in range(a:count) - call search('^.\=\t.*','Wbe') + call search('^[A-Z?] .\|^[0-9a-f]\{4,\} \|^@','Wbe') endfor + call s:StageReveal() return '.' endif endfunction function! s:StageReloadSeek(target,lnum1,lnum2) abort - let jump = a:target - let f = matchstr(getline(a:lnum1-1),'^.\=\t\%([[:alpha:] ]\+: *\|.*\%uff1a *\)\=\zs.*') - if f !=# '' | let jump = f | endif - let f = matchstr(getline(a:lnum2+1),'^.\=\t\%([[:alpha:] ]\+: *\|.*\%uff1a *\)\=\zs.*') - if f !=# '' | let jump = f | endif - silent! edit! - 1 - redraw - call search('^.\=\t\%([[:alpha:] ]\+: *\|.*\%uff1a *\)\=\V'.jump.'\%( ([^()[:digit:]]\+)\)\=\$','W') + exe s:ReloadStatus(a:lnum1) + return '' endfunction -function! s:StageUndo() abort - let [filename, section] = s:stage_info(line('.')) - if empty(filename) - return '' - endif - let hash = s:TreeChomp('hash-object', '-w', './' . filename) - if !empty(hash) - if section ==# 'untracked' - call s:TreeChomp('clean', '-f', './' . filename) - elseif section ==# 'unmerged' - call s:TreeChomp('rm', './' . filename) - elseif section ==# 'unstaged' - call s:TreeChomp('checkout', './' . filename) - else - call s:TreeChomp('checkout', 'HEAD^{}', './' . filename) +function! s:StageInline(mode, ...) abort + let lnum1 = a:0 ? a:1 : line('.') + let lnum = lnum1 + 1 + if a:0 > 1 && a:2 == 0 + let info = s:StageInfo(lnum - 1) + if empty(info.filename) && len(info.section) + while len(getline(lnum)) + let lnum += 1 + endwhile endif - call s:StageReloadSeek(filename, line('.'), line('.')) - let @" = hash - return 'checktime|redraw|echomsg ' . - \ string('To restore, :Git cat-file blob '.hash[0:6].' > '.filename) + elseif a:0 > 1 + let lnum += a:2 - 1 endif + while lnum > lnum1 + let lnum -= 1 + while lnum > 0 && getline(lnum) =~# '^[ @\+-]' + let lnum -= 1 + endwhile + let info = s:StageInfo(lnum) + if !has_key(b:fugitive_diff, info.section) + continue + endif + if getline(lnum + 1) =~# '^[ @\+-]' + let lnum2 = lnum + 1 + while getline(lnum2 + 1) =~# '^[ @\+-]' + let lnum2 += 1 + endwhile + if a:mode !=# 'show' + setlocal modifiable noreadonly + exe 'silent keepjumps ' . (lnum + 1) . ',' . lnum2 . 'delete _' + call remove(b:fugitive_expanded[info.section], info.filename) + setlocal nomodifiable readonly nomodified + endif + continue + endif + if !has_key(b:fugitive_diff, info.section) || info.status !~# '^[ADM]$' || a:mode ==# 'hide' + continue + endif + let mode = '' + let diff = [] + let index = 0 + let start = -1 + for line in b:fugitive_diff[info.section] + if mode ==# 'await' && line[0] ==# '@' + let mode = 'capture' + endif + if mode !=# 'head' && line !~# '^[ @\+-]' + if len(diff) + break + endif + let start = index + let mode = 'head' + elseif mode ==# 'head' && line ==# '--- ' . info.filename + let mode = 'await' + elseif mode ==# 'head' && line ==# '+++ ' . info.filename + let mode = 'await' + elseif mode ==# 'capture' + call add(diff, line) + elseif line[0] ==# '@' + let mode = '' + endif + let index += 1 + endfor + if len(diff) + setlocal modifiable noreadonly + silent call append(lnum, diff) + let b:fugitive_expanded[info.section][info.filename] = [start, len(diff)] + setlocal nomodifiable readonly nomodified + endif + endwhile + return lnum endfunction function! s:StageDiff(diff) abort - let [filename, section] = s:stage_info(line('.')) - if filename ==# '' && section ==# 'staged' + let lnum = line('.') + let info = s:StageInfo(lnum) + let prefix = info.offset > 0 ? '+' . info.offset : '' + if empty(info.filename) && info.section ==# 'Staged' return 'Git! diff --no-ext-diff --cached' - elseif filename ==# '' + elseif empty(info.filename) return 'Git! diff --no-ext-diff' - elseif filename =~# ' -> ' - let [old, new] = split(filename,' -> ') - execute 'Gedit '.s:fnameescape(':0:'.new) + elseif info.filename =~# ' -> ' + let [old, new] = split(info.filename,' -> ') + execute 'Gedit' . prefix s:fnameescape(':0:'.new) return a:diff.' HEAD:'.s:fnameescape(old) - elseif section ==# 'staged' - execute 'Gedit '.s:fnameescape(':0:'.filename) - return a:diff.' -' + elseif info.section ==# 'Staged' && info.sigil ==# '-' + execute 'Gedit' prefix s:fnameescape('@:'.info.filename) + return a:diff.'! :0' + elseif info.section ==# 'Staged' + execute 'Gedit' prefix s:fnameescape(':0:'.info.filename) + return a:diff . (info.sigil ==# '+' ? '!' : '') . ' -' + elseif info.sigil ==# '-' + execute 'Gedit' prefix s:fnameescape(':0:'.info.filename) + return a:diff . '!' else - execute 'Gedit '.s:fnameescape('/'.filename) - return a:diff + execute 'Gedit' prefix s:fnameescape(':(top)'.info.filename) + return a:diff . (info.sigil ==# '+' ? '!' : '') endif endfunction function! s:StageDiffEdit() abort - let [filename, section] = s:stage_info(line('.')) - let arg = (filename ==# '' ? '.' : filename) - if section ==# 'staged' + let info = s:StageInfo(line('.')) + let arg = (empty(info.filename) ? '.' : info.filename) + if info.section ==# 'Staged' return 'Git! diff --no-ext-diff --cached '.s:shellesc(arg) - elseif section ==# 'untracked' + elseif info.status ==# '?' call s:TreeChomp('add', '--intent-to-add', './' . arg) if arg ==# '.' silent! edit! 1 - if !search('^.*:\n.*\n.\= .*"git checkout \|^\%(# \)=Changes not staged for commit:$','W') - call search(':$','W') + if !search('^Unstaged','W') + call search('^Staged','W') endif else - call s:StageReloadSeek(arg,line('.'),line('.')) + call s:StageReloadSeek([info.filename, 'Staged'], line('.'), line('.')) endif return '' else @@ -1868,67 +2218,166 @@ function! s:StageDiffEdit() abort endif endfunction -function! s:StageToggle(lnum1,lnum2) abort - if a:lnum1 == 1 && a:lnum2 == 1 +function! s:StageApply(info, lnum1, count, reverse, extra) abort + let cmd = ['apply', '-p0'] + a:extra + let info = a:info + let start = a:lnum1 + let end = start + if !a:count + while start > 0 && getline(start) !~# '^@@' + let start -= 1 + endwhile + while getline(end + 1) =~# '^[-+ ]' + let end += 1 + endwhile + else + let end = a:lnum1 + a:count - 1 + call add(cmd, '--recount') + endif + let lines = getline(start, end) + if empty(filter(copy(lines), 'v:val =~# "^[+-]"')) + return '' + endif + if len(filter(copy(lines), 'v:val !~# "^[ @\+-]"')) + return 'fugitive: cannot apply hunks across multiple files' + endif + while getline(end) =~# '^[-+ ]' + let end += 1 + if getline(end) =~# '^[' . (a:reverse ? '+' : '-') . ' ]' + call add(lines, ' ' . getline(end)[1:-1]) + endif + endwhile + while start > 0 && getline(start) !~# '^@' + let start -= 1 + if getline(start) =~# '^[' . (a:reverse ? '+' : '-') . ' ]' + call insert(lines, ' ' . getline(start)[1:-1]) + elseif getline(start) =~# '^@' + call insert(lines, getline(start)) + endif + endwhile + if start == 0 || getline(start) !~# '^@@ ' + return "fugitive: could not find hunk" + endif + let i = b:fugitive_expanded[info.section][info.filename][0] + let head = [] + while get(b:fugitive_diff[info.section], i, '@') !~# '^@' + call add(head, b:fugitive_diff[info.section][i]) + let i += 1 + endwhile + call extend(lines, head, 'keep') + let temp = tempname() + call writefile(lines, temp) + if a:reverse + call add(cmd, '--reverse') + endif + call extend(cmd, ['--', temp]) + let output = call('s:TreeChomp', cmd) + return v:shell_error ? output : '' +endfunction + +function! s:StageDelete(lnum, count) abort + let info = s:StageInfo(a:lnum) + if empty(info.filename) + return '' + endif + let hash = s:TreeChomp('hash-object', '-w', './' . info.filename) + if empty(hash) + return '' + elseif info.offset >= 0 + let output = s:StageApply(info, a:lnum, a:count, 1, info.section ==# 'Staged' ? ['--index'] : []) + if len(output) + return 'echoerr ' . string(output) + endif + elseif info.status ==# 'U' + call s:TreeChomp('rm', './' . info.filename) + elseif info.status ==# '?' + call s:TreeChomp('clean', '-f', './' . info.filename) + elseif info.section ==# 'Unstaged' + call s:TreeChomp('checkout', './' . info.filename) + else + call s:TreeChomp('checkout', 'HEAD^{}', './' . info.filename) + endif + exe s:ReloadStatus() + let @@ = hash + return 'checktime|redraw|echomsg ' . + \ string('To restore, :Git cat-file blob '.hash[0:6].' > '.info.filename) +endfunction + +function! s:StageToggle(lnum1, count) abort + if a:lnum1 == 1 && a:count == 0 return 'Gedit .git/|call search("^index$", "wc")' endif try - let output = '' - for lnum in range(a:lnum1,a:lnum2) - let [filename, section] = s:stage_info(lnum) - if getline('.') =~# ':$' - if section ==# 'staged' - call s:TreeChomp('reset','-q') - silent! edit! - 1 - if !search('^.*:\n.\= .*"git add .*\n#\n\|^\%(. \)\=Untracked files:$','W') - call search(':$','W') - endif - return '' - elseif section ==# 'unstaged' - call s:TreeChomp('add','-u') - silent! edit! - 1 - if !search('^.*:\n\.\= .*"git add .*\n#\n\|^\%( \)=Untracked files:$','W') - call search(':$','W') - endif - return '' - else - call s:TreeChomp('add', '.') - silent! edit! - 1 - call search(':$','W') - return '' + let info = s:StageInfo(a:lnum1) + if empty(info.filename) + if info.section ==# 'Staged' + call s:TreeChomp('reset','-q') + silent! edit! + 1 + call search('^Unstaged','W') + return '' + elseif info.section ==# 'Unstaged' + call s:TreeChomp('add','.') + silent! edit! + 1 + call search('^Staged','W') + return '' + elseif info.section ==# 'Unpushed' && len(info.commit) + let remote = matchstr(info.heading, 'to \zs[^/]\+\ze/') + if empty(remote) + let remote = '.' endif + let branch = matchstr(info.heading, 'to \%([^/]\+/\)\=\zs\S\+') + call feedkeys(':Gpush ' . remote . ' ' . info.commit . ':' . branch) + return '' + elseif info.section ==# 'Unpulled' + call feedkeys(':Grebase ' . info.commit) + return '' endif - if filename ==# '' + elseif info.offset >= 0 + let output = s:StageApply(info, a:lnum1, a:count, info.section ==# 'Staged', ['--cached']) + return len(output) ? 'redraw|echoerr ' . string(output) : s:ReloadStatus() + endif + let lnum2 = a:count ? a:lnum1 + a:count - 1 : a:lnum1 + for lnum in range(a:lnum1, lnum2) + let info = s:StageInfo(lnum) + let filename = info.filename + if empty(filename) || info.offset >= 0 continue endif execute lnum - if section ==# 'staged' + if info.section ==# 'Staged' let files_to_unstage = split(filename, ' -> ') let filename = files_to_unstage[-1] - let cmd = ['reset', '-q'] + map(copy(files_to_unstage), '"./" . v:val') - elseif getline(lnum) =~# '^.\=\tdeleted:' + let cmd = ['reset', '-q', '--'] + map(copy(files_to_unstage), 's:Tree() . "/" . v:val') + elseif getline(lnum) =~# '^D' let cmd = ['rm', './' . filename] - elseif getline(lnum) =~# '^.\=\tmodified:' + elseif getline(lnum) =~# '^M' let cmd = ['add', './' . filename] else let cmd = ['add','-A', './' . filename] endif - if !exists('first_filename') - let first_filename = filename + if !exists('target') + let target = [filename, info.section ==# 'Staged' ? '' : 'Staged'] endif - let output .= call('s:TreeChomp', cmd)."\n" + call call('s:TreeChomp', cmd) endfor - if exists('first_filename') - call s:StageReloadSeek(first_filename,a:lnum1,a:lnum2) + if exists('target') + exe s:ReloadStatus() endif - echo s:sub(s:gsub(output,'\n+','\n'),'\n$','') catch /^fugitive:/ return 'echoerr v:errmsg' endtry - return 'checktime' + return '' +endfunction + +function! s:StageToggleOnly(section, lnum1, count) abort + let info = s:StageInfo(a:lnum1) + if info.section ==# a:section + return s:StageToggle(a:lnum1, a:count) + else + return s:StageNext(a:count ? a:count : 1) + endif endfunction function! s:StagePatch(lnum1,lnum2) abort @@ -1936,26 +2385,21 @@ function! s:StagePatch(lnum1,lnum2) abort let reset = [] for lnum in range(a:lnum1,a:lnum2) - let [filename, section] = s:stage_info(lnum) - if getline('.') =~# ':$' && section ==# 'staged' + let info = s:StageInfo(lnum) + if empty(info.filename) && info.section ==# 'Staged' return 'Git reset --patch' - elseif getline('.') =~# ':$' && section ==# 'unstaged' + elseif empty(info.filename) && info.section ==# 'Unstaged' return 'Git add --patch' - elseif getline('.') =~# ':$' && section ==# 'untracked' - return 'Git add -N .' - elseif filename ==# '' + elseif info.filename ==# '' continue endif - if !exists('first_filename') - let first_filename = filename - endif execute lnum - if filename =~ ' -> ' - let reset += [split(filename,' -> ')[1]] - elseif section ==# 'staged' - let reset += [filename] - elseif getline(lnum) !~# '^.\=\tdeleted:' - let add += [filename] + if info.filename =~ ' -> ' + let reset += [split(info.filename,' -> ')[1]] + elseif info.section ==# 'Staged' + let reset += [info.filename] + elseif info.status !~# '^D' + let add += [info.filename] endif endfor try @@ -1965,16 +2409,10 @@ function! s:StagePatch(lnum1,lnum2) abort if !empty(reset) execute "Git reset --patch -- ".join(map(reset,'s:shellesc(v:val)')) endif - if exists('first_filename') - silent! edit! - 1 - redraw - call search('^.\=\t\%([[:alpha:] ]\+: *\)\=\V'.first_filename.'\%( ([^()[:digit:]]\+)\)\=\$','W') - endif catch /^fugitive:/ return 'echoerr v:errmsg' endtry - return 'checktime' + return s:ReloadStatus() endfunction " Section: :Gcommit @@ -1985,8 +2423,6 @@ function! s:Commit(mods, args, ...) abort let mods = s:gsub(a:mods ==# '' ? '' : a:mods, '', '-tab') let dir = a:0 ? a:1 : b:git_dir let tree = s:Tree(dir) - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let cwd = getcwd() let msgfile = dir . '/COMMIT_EDITMSG' let outfile = tempname() let errorfile = tempname() @@ -1996,7 +2432,7 @@ function! s:Commit(mods, args, ...) abort if &guioptions =~# '!' setglobal guioptions-=! endif - execute cd s:fnameescape(tree) + let cdback = s:Cd(tree) if s:winshell() let command = '' let old_editor = $GIT_EDITOR @@ -2015,7 +2451,7 @@ function! s:Commit(mods, args, ...) abort endif let error = v:shell_error finally - execute cd s:fnameescape(cwd) + execute cdback let &guioptions = guioptions endtry if !has('gui_running') @@ -2027,6 +2463,7 @@ function! s:Commit(mods, args, ...) abort echo line endfor endif + call fugitive#ReloadStatus() return '' else let errors = readfile(errorfile) @@ -2034,8 +2471,6 @@ function! s:Commit(mods, args, ...) abort if error =~# 'false''\=\.$' let args = s:gsub(args,'%(%(^| )-- )@' @@ -2045,10 +2480,6 @@ function! s:Commit(mods, args, ...) abort execute mods 'keepalt edit' s:fnameescape(msgfile) elseif a:args =~# '\%(^\| \)-\w*v' || mods =~# '\' execute mods 'keepalt -tabedit' s:fnameescape(msgfile) - elseif get(b:, 'fugitive_type', '') ==# 'index' - execute mods 'keepalt edit' s:fnameescape(msgfile) - execute (search('^#','n')+1).'wincmd+' - setlocal nopreviewwindow else execute mods 'keepalt split' s:fnameescape(msgfile) endif @@ -2056,7 +2487,8 @@ function! s:Commit(mods, args, ...) abort setlocal bufhidden=wipe filetype=gitcommit return '1' elseif error ==# '!' - return 'Gstatus' + echo get(readfile(outfile), -1, '') + return '' else call s:throw(empty(error)?join(errors, ' '):error) endif @@ -2069,7 +2501,6 @@ function! s:Commit(mods, args, ...) abort endif call delete(outfile) call delete(errorfile) - call fugitive#ReloadStatus() endtry endfunction @@ -2090,10 +2521,15 @@ function! s:CommitComplete(A,L,P) abort endfunction function! s:FinishCommit() abort - let args = getbufvar(+expand(''),'fugitive_commit_arguments') + let buf = +expand('') + let args = getbufvar(buf, 'fugitive_commit_arguments') if !empty(args) - call setbufvar(+expand(''),'fugitive_commit_arguments','') - return s:Commit('', args, getbufvar(+expand(''),'git_dir')) + call setbufvar(buf, 'fugitive_commit_arguments', '') + if getbufvar(buf, 'fugitive_commit_rebase') + call setbufvar(buf, 'fugitive_commit_rebase', 0) + let s:rebase_continue = getbufvar(buf, 'git_dir') + endif + return s:Commit('', args, getbufvar(buf, 'git_dir')) endif return '' endfunction @@ -2101,11 +2537,11 @@ endfunction " Section: :Gmerge, :Grebase, :Gpull call s:command("-nargs=? -bang -complete=custom,s:RevisionComplete Gmerge " . - \ "execute s:Merge('merge', 0, )") + \ "execute s:Merge('merge', 0, '', )") call s:command("-nargs=? -bang -complete=custom,s:RevisionComplete Grebase " . - \ "execute s:Merge('rebase', 0, )") + \ "execute s:Merge('rebase', 0, '', )") call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gpull " . - \ "execute s:Merge('pull --progress', 0, )") + \ "execute s:Merge('pull --progress', 0, '', )") function! s:RevisionComplete(A, L, P) abort return s:TreeChomp('rev-parse', '--symbolic', '--branches', '--tags', '--remotes') @@ -2124,6 +2560,19 @@ function! s:RemoteComplete(A, L, P) abort return join(matches, "\n") endfunction +function! s:RebaseSequenceAborter() abort + if !exists('s:rebase_sequence_aborter') + let temp = tempname() . '.sh' + call writefile( + \ ['#!/bin/sh', + \ 'echo exec false | cat - "$1" > "$1.fugitive"', + \ 'mv "$1.fugitive" "$1"'], + \ temp) + let s:rebase_sequence_aborter = temp + endif + return s:rebase_sequence_aborter +endfunction + function! fugitive#Cwindow() abort if &buftype == 'quickfix' cwindow @@ -2143,15 +2592,49 @@ let s:common_efm = '' \ . '%-G%.%#%\e[K%.%#,' \ . '%-G%.%#%\r%.%\+' -function! s:Merge(cmd, bang, args) abort - if a:cmd =~# '^rebase' && ' '.a:args =~# ' -i\| --interactive\| --edit-todo' - return 'echoerr "git rebase --interactive not supported"' +let s:rebase_abbrevs = { + \ 'p': 'pick', + \ 'r': 'reword', + \ 'e': 'edit', + \ 's': 'squash', + \ 'f': 'fixup', + \ 'x': 'exec', + \ 'd': 'drop', + \ 'l': 'label', + \ 't': 'reset', + \ 'm': 'merge', + \ 'b': 'break', + \ } + +function! s:RebaseEdit(cmd, dir) abort + return a:cmd . ' +setlocal\ bufhidden=wipe ' . s:fnameescape(a:dir . '/rebase-merge/git-rebase-todo') +endfunction + +function! s:Merge(cmd, bang, mods, args, ...) abort + let dir = a:0 ? a:1 : b:git_dir + let mods = substitute(a:mods, '\C', '', '') . ' ' + if a:cmd =~# '^rebase' && ' '.a:args =~# ' -i\| --interactive' + let cmd = fugitive#Prepare(dir, '-c', 'sequence.editor=sh ' . s:RebaseSequenceAborter(), 'rebase') . ' ' . a:args + let out = system(cmd)[0:-2] + for file in ['end', 'msgnum'] + let file = fugitive#Find('.git/rebase-merge/' . file, dir) + if !filereadable(file) + return 'echoerr ' . string("fugitive: " . out) + endif + call writefile([readfile(file)[0] - 1], file) + endfor + call writefile([], fugitive#Find('.git/rebase-merge/done', dir)) + if a:bang + return '' + endif + return s:RebaseEdit(mods . 'split', dir) + elseif a:cmd =~# '^rebase' && ' '.a:args =~# ' --edit-todo' && filereadable(dir . '/rebase-merge/git-rebase-todo') + return s:RebaseEdit(mods . 'split', dir) endif - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let cwd = getcwd() let [mp, efm] = [&l:mp, &l:efm] - let had_merge_msg = filereadable(b:git_dir . '/MERGE_MSG') + let had_merge_msg = filereadable(dir . '/MERGE_MSG') try + let cdback = s:Cd(s:Tree(dir)) let &l:errorformat = '' \ . '%-Gerror:%.%#false''.,' \ . '%-G%.%# ''git commit'' %.%#,' @@ -2161,6 +2644,7 @@ function! s:Merge(cmd, bang, args) abort \ . '%+ECannot %.%#: Your index contains uncommitted changes.,' \ . '%+EThere is no tracking information for the current branch.,' \ . '%+EYou are not currently on a branch. Please specify which,' + \ . '%+I %#git rebase --continue,' \ . 'CONFLICT (%m): %f deleted in %.%#,' \ . 'CONFLICT (%m): Merge conflict in %f,' \ . 'CONFLICT (%m): Rename \"%f\"->%.%#,' @@ -2173,21 +2657,27 @@ function! s:Merge(cmd, bang, args) abort \ . "%+E\u51b2\u7a81 %.%#," \ . 'U%\t%f' if a:cmd =~# '^merge' && empty(a:args) && - \ (had_merge_msg || isdirectory(b:git_dir . '/rebase-apply') || - \ !empty(s:TreeChomp('diff-files', '--diff-filter=U'))) + \ (had_merge_msg || isdirectory(dir . '/rebase-apply') || + \ !empty(s:TreeChomp(dir, 'diff-files', '--diff-filter=U'))) let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U' else let &l:makeprg = s:sub(s:UserCommand() . ' ' . a:cmd . - \ (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' || a:cmd =~# '^rebase' ? '' : ' --edit') . + \ (' ' . a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' || a:cmd =~# '^rebase' ? '' : ' --edit') . + \ (' ' . a:args =~# ' --autosquash\>' && a:cmd =~# '^rebase' ? ' --interactive' : '') . \ ' ' . a:args, ' *$', '') endif + if !empty($GIT_SEQUENCE_EDITOR) || has('win32') + let old_sequence_editor = $GIT_SEQUENCE_EDITOR + let $GIT_SEQUENCE_EDITOR = 'true' + else + let &l:makeprg = 'env GIT_SEQUENCE_EDITOR=true ' . &l:makeprg + endif if !empty($GIT_EDITOR) || has('win32') let old_editor = $GIT_EDITOR let $GIT_EDITOR = 'false' else - let &l:makeprg = 'env GIT_EDITOR=false ' . &l:makeprg + let &l:makeprg = 'env GIT_EDITOR=false ' . substitute(&l:makeprg, '^env ', '', '') endif - execute cd fnameescape(s:Tree()) silent noautocmd make! catch /^Vim\%((\a\+)\)\=:E211/ let err = v:exception @@ -2197,13 +2687,22 @@ function! s:Merge(cmd, bang, args) abort if exists('old_editor') let $GIT_EDITOR = old_editor endif - execute cd fnameescape(cwd) + if exists('old_sequence_editor') + let $GIT_SEQUENCE_EDITOR = old_editor + endif + execute cdback endtry call fugitive#ReloadStatus() - if empty(filter(getqflist(),'v:val.valid')) - if !had_merge_msg && filereadable(b:git_dir . '/MERGE_MSG') + if empty(filter(getqflist(),'v:val.valid && v:val.type !=# "I"')) + if a:cmd =~# '^rebase' && + \ filereadable(dir . '/rebase-merge/amend') && + \ filereadable(dir . '/rebase-merge/done') && + \ get(readfile(dir . '/rebase-merge/done'), -1, '') =~# '^[^e]' cclose - return 'Gcommit --no-status -n -t '.s:shellesc(b:git_dir . '/MERGE_MSG') + return 'exe ' . string(mods . 'Gcommit --amend -n -F ' . s:shellesc(dir . '/rebase-merge/message') . ' -e') . '|let b:fugitive_commit_rebase = 1' + elseif !had_merge_msg && filereadable(dir . '/MERGE_MSG') + cclose + return mods . 'Gcommit --no-status -n -t '.s:shellesc(dir . '/MERGE_MSG') endif endif let qflist = getqflist() @@ -2224,6 +2723,36 @@ function! s:Merge(cmd, bang, args) abort return exists('err') ? 'echoerr '.string(err) : '' endfunction +function! s:RebaseClean(file) abort + if !filereadable(a:file) + return '' + endif + let old = readfile(a:file) + let new = copy(old) + for i in range(len(new)) + let new[i] = substitute(new[i], '^\l\>', '\=get(s:rebase_abbrevs,submatch(0),submatch(0))', '') + endfor + if new !=# old + call writefile(new, a:file) + endif + return '' +endfunction + +augroup fugitive_merge + autocmd! + autocmd VimLeavePre,BufDelete git-rebase-todo + \ if getbufvar(+expand(''), '&bufhidden') ==# 'wipe' | + \ call s:RebaseClean(expand('')) | + \ if getfsize(FugitiveFind('.git/rebase-merge/done', +expand(''))) == 0 | + \ let s:rebase_continue = FugitiveGitDir(+expand('')) | + \ endif | + \ endif + autocmd BufEnter * nested + \ if exists('s:rebase_continue') | + \ exe s:Merge('rebase', 0, '', getfsize(fugitive#Find('.git/rebase-merge/git-rebase-todo', s:rebase_continue)) > 0 ? '--continue' : '--abort', remove(s:, 'rebase_continue')) | + \ endif +augroup END + " Section: :Ggrep, :Glog if !exists('g:fugitive_summary_format') @@ -2246,10 +2775,8 @@ call s:command("-bar -bang -nargs=* -range=-1 -complete=customlist,s:GrepComplet function! s:Grep(cmd,bang,arg) abort let grepprg = &grepprg let grepformat = &grepformat - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let dir = getcwd() try - execute cd s:fnameescape(s:Tree()) + let cdback = s:Cd(s:Tree()) let &grepprg = s:UserCommand() . ' --no-pager grep -n --no-color' let &grepformat = '%f:%l:%m,%m %f match%ts,%f' exe a:cmd.'! '.escape(s:ShellExpand(matchstr(a:arg, '\v\C.{-}%($|[''" ]\@=\|)@=')), '|#%') @@ -2278,7 +2805,7 @@ function! s:Grep(cmd,bang,arg) abort finally let &grepprg = grepprg let &grepformat = grepformat - execute cd s:fnameescape(dir) + execute cdback endtry endfunction @@ -2307,18 +2834,23 @@ function! s:Log(cmd, bang, line1, line2, ...) abort endif let grepformat = &grepformat let grepprg = &grepprg - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let dir = getcwd() try - execute cd s:fnameescape(s:Tree()) + let cdback = s:Cd(s:Tree()) + let format = before =~# ' -g\| --walk-reflogs' ? '%gD %gs' : g:fugitive_summary_format let &grepprg = escape(s:UserCommand() . ' --no-pager log --no-color ' . - \ s:shellesc('--pretty=format:fugitive://'.b:git_dir.'//%H'.path.'::'.g:fugitive_summary_format), '%#') + \ s:shellesc('--pretty=format:fugitive://'.b:git_dir.'//%H'.path.'::'.format), '%#') let &grepformat = '%Cdiff %.%#,%C--- %.%#,%C+++ %.%#,%Z@@ -%\d%\+\,%\d%\+ +%l\,%\d%\+ @@,%-G-%.%#,%-G+%.%#,%-G %.%#,%A%f::%m,%-G%.%#' exe a:cmd . (a:bang ? '! ' : ' ') . s:ShellExpand(before . after) + if len(path) && a:line2 == -1 + redraw + echohl WarningMsg + echo ':Glog will soon default to all files. Use :0Glog to target current file' + echohl NONE + endif finally let &grepformat = grepformat let &grepprg = grepprg - execute cd s:fnameescape(dir) + execute cdback endtry endfunction @@ -2326,6 +2858,8 @@ endfunction function! s:UsableWin(nr) abort return a:nr && !getwinvar(a:nr, '&previewwindow') && + \ empty(getwinvar(a:nr, 'fugitive_status')) && + \ index(['gitrebase', 'gitcommit'], getbufvar(winbufnr(a:nr), '&filetype')) < 0 && \ index(['nofile','help','quickfix'], getbufvar(winbufnr(a:nr), '&buftype')) < 0 endfunction @@ -2348,15 +2882,13 @@ function! s:EditParse(args) abort endfunction function! s:BlurStatus() abort - if &previewwindow && get(b:,'fugitive_type', '') ==# 'index' + if (&previewwindow || exists('w:fugitive_status')) && get(b:,'fugitive_type', '') ==# 'index' let winnrs = filter([winnr('#')] + range(1, winnr('$')), 's:UsableWin(v:val)') if len(winnrs) exe winnrs[0].'wincmd w' - elseif winnr('$') == 1 - let tabs = (&go =~# 'e' || !has('gui_running')) && &stal && (tabpagenr('$') >= &stal) - execute 'rightbelow' (&lines - &previewheight - &cmdheight - tabs - 1 - !!&laststatus).'new' else - rightbelow new + let wide = winwidth(0) >= 160 + exe 'rightbelow' (winwidth(0) >= 160 ? 'vert' : '') 'new' endif if &diff let mywinnr = winnr() @@ -2379,16 +2911,14 @@ function! s:Edit(cmd, bang, mods, args, ...) abort if a:bang let temp = tempname() - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let cwd = getcwd() try - execute cd s:fnameescape(s:Tree()) + let cdback = s:Cd(s:Tree()) let git = s:UserCommand() let args = s:ShellExpand(a:args) silent! execute '!' . escape(git . ' --no-pager ' . args, '!#%') . \ (&shell =~# 'csh' ? ' >& ' . temp : ' > ' . temp . ' 2>&1') finally - execute cd s:fnameescape(cwd) + execute cdback endtry let temp = s:Resolve(temp) let s:temp_files[s:cpath(temp)] = { 'dir': b:git_dir, 'filetype': 'git' } @@ -2427,15 +2957,13 @@ function! s:Read(count, line1, line2, range, bang, mods, args, ...) abort let delete = '' endif if a:bang - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let cwd = getcwd() try - execute cd s:fnameescape(s:Tree()) + let cdback = s:Cd(s:Tree()) let git = s:UserCommand() let args = s:ShellExpand(a:args) silent execute mods after.'read!' escape(git . ' --no-pager ' . args, '!#%') finally - execute cd s:fnameescape(cwd) + execute cdback endtry execute delete . 'diffupdate' call fugitive#ReloadStatus() @@ -2450,6 +2978,9 @@ function! s:Read(count, line1, line2, range, bang, mods, args, ...) abort if file =~# '^fugitive:' && after is# 0 return 'exe ' .string(mods . ' ' . fugitive#FileReadCmd(file, 0, pre)) . '|diffupdate' endif + if foldlevel(after) + exe after . 'foldopen!' + endif return mods . ' ' . after . 'read' . pre . ' ' . s:fnameescape(file) . '|' . delete . 'diffupdate' . (a:count < 0 ? '|' . line('.') : '') endfunction @@ -2639,13 +3170,11 @@ call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gpush execute call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gfetch execute s:Dispatch('', 'fetch '.)") function! s:Dispatch(bang, args) - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - let cwd = getcwd() let [mp, efm, cc] = [&l:mp, &l:efm, get(b:, 'current_compiler', '')] try + let cdback = s:Cd(s:Tree()) let b:current_compiler = 'git' let &l:errorformat = s:common_efm - execute cd fnameescape(s:Tree()) let &l:makeprg = substitute(s:UserCommand() . ' ' . a:args, '\s\+$', '', '') if exists(':Make') == 2 noautocmd Make @@ -2658,7 +3187,7 @@ function! s:Dispatch(bang, args) finally let [&l:mp, &l:efm, b:current_compiler] = [mp, efm, cc] if empty(cc) | unlet! b:current_compiler | endif - execute cd fnameescape(cwd) + execute cdback endtry endfunction @@ -3003,8 +3532,9 @@ function! s:Blame(bang, line1, line2, count, mods, args) abort let cmd += ['--', expand('%:p')] let basecmd = escape(fugitive#Prepare(cmd), '!#%') try - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' + let cd = s:Cd() let tree = s:Tree() + let cdback = s:Cd(tree) if len(tree) && s:cpath(tree) !=# s:cpath(getcwd()) let cwd = getcwd() execute cd s:fnameescape(tree) @@ -3480,6 +4010,14 @@ function! s:ContainingCommit() abort return empty(commit) ? 'HEAD' : commit endfunction +function! s:SquashArgument() abort + if &filetype == 'fugitive' + return matchstr(getline('.'), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\{4,\}\ze ') + else + return s:Owner(@%) + endif +endfunction + function! s:NavigateUp(count) abort let rev = substitute(s:DirRev(@%)[1], '^$', ':', 'g') let c = a:count @@ -3510,12 +4048,14 @@ function! fugitive#MapJumps(...) abort let nowait = v:version >= 704 ? '' : '' if get(b:, 'fugitive_type', '') ==# 'blob' nnoremap o :.,.+1Gblame - nnoremap S :vertical .,.+1Gblame + nnoremap S :echoerr 'Use gO' + nnoremap gO :vertical .,.+1Gblame nnoremap O :tab .,.+1Gblame nnoremap p :.,.+2Gblame else nnoremap o :exe GF("split") - nnoremap S :exe GF("vsplit") + nnoremap S :echoerr 'Use gO' + nnoremap gO :exe GF("vsplit") nnoremap O :exe GF("tabedit") nnoremap p :exe GF("pedit") endif @@ -3523,17 +4063,60 @@ function! fugitive#MapJumps(...) abort nnoremap P :exe 'Gedit ' . fnameescape(ContainingCommit().'^'.v:count1.Relative(':')) nnoremap ~ :exe 'Gedit ' . fnameescape(ContainingCommit().'~'.v:count1.Relative(':')) nnoremap C :exe 'Gedit ' . fnameescape(ContainingCommit()) - nnoremap cc :exe 'Gedit ' . fnameescape(ContainingCommit()) - nnoremap co :exe 'Gsplit ' . fnameescape(ContainingCommit()) - nnoremap cS :exe 'Gvsplit ' . fnameescape(ContainingCommit()) - nnoremap cO :exe 'Gtabedit ' . fnameescape(ContainingCommit()) - nnoremap cp :exe 'Gpedit ' . fnameescape(ContainingCommit()) + nnoremap cc :echoerr 'Use C' + nnoremap co :echoerr 'Use CTRL-W C' + nnoremap C :exe 'Gsplit ' . fnameescape(ContainingCommit()) + nnoremap cp :echoerr 'Use gC' + nnoremap gC :exe 'Gpedit ' . fnameescape(ContainingCommit()) + nnoremap gc :exe 'Gpedit ' . fnameescape(ContainingCommit()) + nnoremap cf :Gcommit --fixup==SquashArgument() + nnoremap cs :Gcommit --squash==SquashArgument() + nnoremap cA :Gcommit --edit --squash==SquashArgument() + nnoremap ri :Grebase --interactive=substitute(SquashArgument(),'.\+',' &^','') + nnoremap rf :Grebase --autosquash=substitute(SquashArgument(),'.\+',' &^','') + nnoremap ru :Grebase --interactive @{upstream} + nnoremap rp :Grebase --interactive @{push} + nnoremap rw :exe 'Grebase --interactive=substitute(SquashArgument(),'.\+',' &^','')'s/^pick/reword/e + nnoremap rm :exe 'Grebase --interactive=substitute(SquashArgument(),'.\+',' &^','')'s/^pick/edit/e + nnoremap rk :exe 'Grebase --interactive=substitute(SquashArgument(),'.\+',' &^','')'s/^pick/drop/e + nnoremap rr :Grebase --continue + nnoremap rs :Grebase --skip + nnoremap re :Grebase --edit-todo + nnoremap ra :Grebase --abort nmap . : endif endfunction function! s:StatusCfile(...) abort - let pre = '' + let tree = FugitiveTreeForGitDir(b:git_dir) + let lead = s:cpath(tree, getcwd()) ? './' : tree . '/' + let info = s:StageInfo() + let line = getline('.') + if len(info.sigil) && len(info.section) && len(info.filename) + if info.section ==# 'Unstaged' && info.sigil !=# '-' + return [lead . info.filename, info.offset, 'normal!zv'] + elseif info.section ==# 'Staged' && info.sigil ==# '-' + return ['@:' . info.filename, info.offset, 'normal!zv'] + else + return [':0:' . info.filename, info.offset, 'normal!zv'] + endif + elseif len(info.filename) + return [lead . info.filename] + elseif len(info.commit) + return [info.commit] + elseif line =~# '^\%(Head\|Merge\|Rebase\|Upstream\|Pull\|Push\): ' + return [matchstr(line, ' \zs.*')] + else + return [''] + endif +endfunction + +function! fugitive#StatusCfile() abort + let file = s:Generate(s:StatusCfile()[0]) + return empty(file) ? fugitive#Cfile() : s:fnameescape(file) +endfunction + +function! s:MessageCfile(...) abort let tree = FugitiveTreeForGitDir(b:git_dir) let lead = s:cpath(tree, getcwd()) ? './' : tree . '/' if getline('.') =~# '^.\=\trenamed:.* -> ' @@ -3555,8 +4138,8 @@ function! s:StatusCfile(...) abort endif endfunction -function! fugitive#StatusCfile() abort - let file = s:Generate(s:StatusCfile()) +function! fugitive#MessageCfile() abort + let file = s:Generate(s:MessageCfile()) return empty(file) ? fugitive#Cfile() : s:fnameescape(file) endfunction @@ -3716,7 +4299,7 @@ endfunction function! s:GF(mode) abort try - let results = &filetype ==# 'gitcommit' ? [s:StatusCfile()] : s:cfile() + let results = &filetype ==# 'fugitive' ? s:StatusCfile() : &filetype ==# 'gitcommit' ? [s:MessageCfile()] : s:cfile() catch /^fugitive:/ return 'echoerr v:errmsg' endtry @@ -3724,7 +4307,7 @@ function! s:GF(mode) abort return 'G' . a:mode . \ ' +' . escape(join(results[1:-1], '|'), '| ') . ' ' . \ s:fnameescape(results[0]) - elseif len(results) + elseif len(results) && len(results[0]) return 'G' . a:mode . ' ' . s:fnameescape(results[0]) else return '' diff --git a/sources_non_forked/vim-fugitive/doc/fugitive.txt b/sources_non_forked/vim-fugitive/doc/fugitive.txt index d3d99085..8e8ee8fe 100644 --- a/sources_non_forked/vim-fugitive/doc/fugitive.txt +++ b/sources_non_forked/vim-fugitive/doc/fugitive.txt @@ -29,9 +29,9 @@ that are part of Git repositories). *fugitive-:Glcd* :Glcd [directory] |:lcd| relative to the repository. - *fugitive-:Gstatus* -:Gstatus Bring up the output of git-status in the preview - window. The following maps, which work on the cursor + *fugitive-:Gstatus* *fugitive-:G* +:Gstatus Bring up a git-status inspired summary in the preview +:G window. The following maps, which work on the cursor line file where sensible, are provided: g? show this help @@ -40,42 +40,48 @@ that are part of Git repositories). |:Gedit| - |:Git| add - |:Git| reset (staged files) - a Show alternative format ca |:Gcommit| --amend cc |:Gcommit| ce |:Gcommit| --amend --no-edit cw |:Gcommit| --amend --only cva |:Gcommit| --verbose --amend cvc |:Gcommit| --verbose + cf |:Gcommit| --fixup= + cs |:Gcommit| --squash= + cA |:Gcommit| --edit --squash= + = toggle inline diff + < show inline diff + > hide inline diff D |:Gdiff| ds |:Gsdiff| dp |:Git!| diff (p for patch; use :Gw to apply) dp |:Git| add --intent-to-add (untracked files) dv |:Gvdiff| + gO |:Gvsplit| O |:Gtabedit| o |:Gsplit| P |:Git| add --patch P |:Git| reset --patch (staged files) + s |:Git| add + u |:Git| reset + X |:Git| checkout + X |:Git| checkout HEAD (staged files) + X |:Git| clean (untracked files) + X |:Git| rm (unmerged files) q close status - r reload status - S |:Gvsplit| - U |:Git| checkout - U |:Git| checkout HEAD (staged files) - U |:Git| clean (untracked files) - U |:Git| rm (unmerged files) + R reload status . enter |:| command line with file prepopulated *fugitive-:Gcommit* -:Gcommit [args] A wrapper around git-commit. If there is nothing - to commit, |:Gstatus| is called instead. Unless the - arguments given would skip the invocation of an editor - (e.g., -m), a split window will be used to obtain a - commit message, or a new tab if -v is given. Write - and close that window (:wq or |:Gwrite|) to finish the - commit. Unlike when running the actual git-commit - command, it is possible (but unadvisable) to alter the - index with commands like git-add and git-reset while a - commit message is pending. +:Gcommit [args] A wrapper around git-commit. Unless the arguments + given would skip the invocation of an editor (e.g., + -m), a split window will be used to obtain a commit + message, or a new tab if -v is given. Write and close + that window (:wq or |:Gwrite|) to finish the commit. + Unlike when running the actual git-commit command, it + is possible (but unadvisable) to alter the index with + commands like git-add and git-reset while a commit + message is pending. *fugitive-:Gmerge* :Gmerge [args] Calls git-merge and loads errors and conflicted files @@ -90,7 +96,7 @@ that are part of Git repositories). *fugitive-:Grebase* :Grebase [args] Like |:Gmerge|, but for git-rebase. Interactive - rebase not supported. + rebase is experimentally supported. *fugitive-:Gpush* :Gpush [args] Invoke git-push, load the results into the |quickfix| @@ -108,17 +114,18 @@ that are part of Git repositories). :Glgrep[!] [args] |:lgrep|[!] with git-grep as 'grepprg'. *fugitive-:Glog* -:Glog [args] Load all previous revisions of the current file into - the |quickfix| list. Additional git-log arguments can - be given (for example, --reverse). If "--" appears as - an argument, no file specific filtering is done, and - previous commits rather than previous file revisions - are loaded. +:Glog [args] Load the commit history into the |quickfix| list. + Additional git-log arguments can be given (for + example, --reverse). Provide "--" in the argument + list to target all commits. Otherwise, only commits + changing the current file will be targeted. This + special casing is slated to be removed. :{range}Glog [args] Use git-log -L to load previous revisions of the given range of the current file into the |quickfix| list. The cursor is positioned on the first line of the - first diff hunk for each commit. + first diff hunk for each commit. Use :0Glog to target + the entire file. *fugitive-:Gllog* :Gllog [args] Like |:Glog|, but use the location list instead of the @@ -284,8 +291,8 @@ These maps are available in committed Git objects. o Jump to the |fugitive-object| under the cursor in a new split. - *fugitive-S* -S Jump to the |fugitive-object| under the cursor in a + *fugitive-gO* +gO Jump to the |fugitive-object| under the cursor in a new vertical split. *fugitive-O* @@ -293,7 +300,8 @@ O Jump to the |fugitive-object| under the cursor in a new tab. *fugitive--* -- Go to the tree containing the current tree or blob. +- Go to the tree containing the current tree or blob + (i.e, the parent directory). *fugitive-~* ~ Go to the current file in the [count]th first diff --git a/sources_non_forked/vim-fugitive/plugin/fugitive.vim b/sources_non_forked/vim-fugitive/plugin/fugitive.vim index 06b14625..ca67b57b 100644 --- a/sources_non_forked/vim-fugitive/plugin/fugitive.vim +++ b/sources_non_forked/vim-fugitive/plugin/fugitive.vim @@ -72,8 +72,14 @@ function! FugitivePrepare(...) abort return call('fugitive#Prepare', a:000) endfunction -function! FugitiveConfig(key, ...) abort - return fugitive#Config(a:key, FugitiveGitDir(a:0 ? a:1 : -1)) +function! FugitiveConfig(...) abort + if a:0 == 2 && type(a:2) != type({}) + return fugitive#Config(a:1, FugitiveGitDir(a:2)) + elseif a:0 == 1 && a:1 !~# '^[[:alnum:]-]\+\.' + return fugitive#Config(FugitiveGitDir(a:1)) + else + return call('fugitive#Config', a:000) + endif endfunction function! FugitiveRemoteUrl(...) abort @@ -250,6 +256,10 @@ augroup fugitive \ call fugitive#MapCfile() | \ endif autocmd FileType gitcommit + \ if exists('b:git_dir') | + \ call fugitive#MapCfile('fugitive#MessageCfile()') | + \ endif + autocmd FileType fugitive \ if exists('b:git_dir') | \ call fugitive#MapCfile('fugitive#StatusCfile()') | \ endif diff --git a/sources_non_forked/vim-fugitive/syntax/fugitive.vim b/sources_non_forked/vim-fugitive/syntax/fugitive.vim new file mode 100644 index 00000000..e2389b5c --- /dev/null +++ b/sources_non_forked/vim-fugitive/syntax/fugitive.vim @@ -0,0 +1,36 @@ +if exists("b:current_syntax") + finish +endif + +syn sync fromstart +syn spell notoplevel + +syn include @fugitiveDiff syntax/diff.vim + +syn match fugitiveHeader /^[A-Z][a-z][^:]*:/ nextgroup=fugitiveHash,fugitiveSymbolicRef skipwhite + +syn region fugitiveSection start=/^\%(.*(\d\+)$\)\@=/ contains=fugitiveHeading end=/^$\@=/ +syn match fugitiveHeading /^[A-Z][a-z][^:]*\ze (\d\+)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite +syn match fugitiveCount /(\d\+)/hs=s+1,he=e-1 contained +syn match fugitivePreposition /\<\%([io]nto\|from\|to\|Rebasing\%( detached\)\=\)\>/ transparent contained nextgroup=fugitiveHash,fugitiveSymbolicRef skipwhite + +syn match fugitiveInstruction /^\l\l\+\>/ contained containedin=fugitiveSection nextgroup=fugitiveHash skipwhite +syn match fugitiveDone /^done\>/ contained containedin=fugitiveSection nextgroup=fugitiveHash skipwhite +syn match fugitiveStop /^stop\>/ contained containedin=fugitiveSection nextgroup=fugitiveHash skipwhite +syn match fugitiveModifier /^[MADRCU?]\{1,2} / contained containedin=fugitiveSection +syn match FugitiveSymbolicRef /\.\@!\%(\.\.\@!\|[^[:space:][:cntrl:]\:.]\)\+\.\@/ contained containedin=fugitiveSection +syn match fugitiveHash /\<\x\{4,\}\>/ contained + +syn region fugitiveHunk start=/^\%(@@ -\)\@=/ end=/^\%([A-Za-z?@]\|$\)\@=/ contains=@fugitiveDiff containedin=fugitiveSection fold + +hi def link fugitiveHeader Label +hi def link fugitiveHeading PreProc +hi def link fugitiveModifier Type +hi def link fugitiveInstruction Type +hi def link fugitiveStop Function +hi def link fugitiveHash Identifier +hi def link fugitiveSymbolicRef Function +hi def link fugitiveCount Number + +let b:current_syntax = "fugitive" diff --git a/sources_non_forked/vim-go/.dockerignore b/sources_non_forked/vim-go/.dockerignore index f12dac27..29f9b8b4 100644 --- a/sources_non_forked/vim-go/.dockerignore +++ b/sources_non_forked/vim-go/.dockerignore @@ -1,2 +1,5 @@ .local/ +.cache/ +.dlv/ .git/ +.viminfo diff --git a/sources_non_forked/vim-go/CHANGELOG.md b/sources_non_forked/vim-go/CHANGELOG.md index aa570e9d..3887569b 100644 --- a/sources_non_forked/vim-go/CHANGELOG.md +++ b/sources_non_forked/vim-go/CHANGELOG.md @@ -1,5 +1,9 @@ ## unplanned +BACKWARDS INCOMPATABILITIES: +* g:go_highlight_fuction_arguments is renamed to g:go_highlight_function_parameters + [[GH-2117]](https://github.com/fatih/vim-go/pull/2117) + IMPROVEMENTS: * Disable `g:go_gocode_propose_source` by default. [[GH-2050]](https://github.com/fatih/vim-go/pull/2050) @@ -15,6 +19,10 @@ IMPROVEMENTS: * Do not require `'autowrite'` or `'autowriteall'` to be set when using autocompletion in module mode. [[GH-2091]](https://github.com/fatih/vim-go/pull/2091) +* Fix use of g:go_metalinter_command _and_ apply it even when autosaving. + [[GH-2101]](https://github.com/fatih/vim-go/pull/2101) +* Report errors in quickfix when Delve fails to start (e.g. compiler errors). + [[GH-2111]](https://github.com/fatih/vim-go/pull/2111) BUG FIXES: * Fix opening of non-existent file from `:GoDeclsDir` when the current @@ -28,6 +36,13 @@ BUG FIXES: [[GH-2075]](https://github.com/fatih/vim-go/pull/2075) * Fix `:GoSameIdsToggle`. [[GH-2086]](https://github.com/fatih/vim-go/pull/2086) +* Do not set fileencoding or fileformat options or populate from template when + the buffer is not modifiable. + [[GH-2097]](https://github.com/fatih/vim-go/pull/2097) +* Do not clear buffer-local autocmds of other buffers. + [[GH-2109]](https://github.com/fatih/vim-go/pull/2109) +* Highlight return parameter types when g:go_highlight_function_arguments is set. + [[GH-2116]](https://github.com/fatih/vim-go/pull/2116) ## 1.19 - (November 4, 2018) diff --git a/sources_non_forked/vim-go/autoload/go/cmd.vim b/sources_non_forked/vim-go/autoload/go/cmd.vim index fa57f3fe..d3118edf 100644 --- a/sources_non_forked/vim-go/autoload/go/cmd.vim +++ b/sources_non_forked/vim-go/autoload/go/cmd.vim @@ -26,9 +26,7 @@ endfunction function! go#cmd#Build(bang, ...) abort " Create our command arguments. go build discards any results when it " compiles multiple packages. So we pass the `errors` package just as an - " placeholder with the current folder (indicated with '.'). We also pass -i - " that tries to install the dependencies, this has the side effect that it - " caches the build results, so every other build is faster. + " placeholder with the current folder (indicated with '.'). let l:args = \ ['build', '-tags', go#config#BuildTags()] + \ map(copy(a:000), "expand(v:val)") + @@ -63,6 +61,7 @@ function! go#cmd#Build(bang, ...) abort redraw! finally execute cd . fnameescape(dir) + let &makeprg = default_makeprg endtry let errors = go#list#Get(l:listtype) @@ -72,8 +71,6 @@ function! go#cmd#Build(bang, ...) abort else call go#util#EchoSuccess("[build] SUCCESS") endif - - let &makeprg = default_makeprg endif endfunction @@ -169,11 +166,15 @@ function! go#cmd#Run(bang, ...) abort let l:listtype = go#list#Type("GoRun") - if l:listtype == "locationlist" - exe 'lmake!' - else - exe 'make!' - endif + try + if l:listtype == "locationlist" + exe 'lmake!' + else + exe 'make!' + endif + finally + let &makeprg = default_makeprg + endtry let items = go#list#Get(l:listtype) let errors = go#tool#FilterValids(items) @@ -184,7 +185,6 @@ function! go#cmd#Run(bang, ...) abort call go#list#JumpToFirst(l:listtype) endif - let &makeprg = default_makeprg endfunction " Install installs the package by simple calling 'go install'. If any argument @@ -226,6 +226,7 @@ function! go#cmd#Install(bang, ...) abort redraw! finally execute cd . fnameescape(dir) + let &makeprg = default_makeprg endtry let errors = go#list#Get(l:listtype) @@ -235,8 +236,6 @@ function! go#cmd#Install(bang, ...) abort else call go#util#EchoSuccess("installed to ". go#path#Default()) endif - - let &makeprg = default_makeprg endfunction " Generate runs 'go generate' in similar fashion to go#cmd#Build() @@ -255,12 +254,17 @@ function! go#cmd#Generate(bang, ...) abort let l:listtype = go#list#Type("GoGenerate") echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None - if l:listtype == "locationlist" - silent! exe 'lmake!' - else - silent! exe 'make!' - endif - redraw! + + try + if l:listtype == "locationlist" + silent! exe 'lmake!' + else + silent! exe 'make!' + endif + finally + redraw! + let &makeprg = default_makeprg + endtry let errors = go#list#Get(l:listtype) call go#list#Window(l:listtype, len(errors)) @@ -272,7 +276,6 @@ function! go#cmd#Generate(bang, ...) abort redraws! | echon "vim-go: " | echohl Function | echon "[generate] SUCCESS"| echohl None endif - let &makeprg = default_makeprg endfunction " --------------------- diff --git a/sources_non_forked/vim-go/autoload/go/config.vim b/sources_non_forked/vim-go/autoload/go/config.vim index 097b7ad2..02371d98 100644 --- a/sources_non_forked/vim-go/autoload/go/config.vim +++ b/sources_non_forked/vim-go/autoload/go/config.vim @@ -388,8 +388,9 @@ function! go#config#HighlightFunctions() abort return get(g:, 'go_highlight_functions', 0) endfunction -function! go#config#HighlightFunctionArguments() abort - return get(g:, 'go_highlight_function_arguments', 0) +function! go#config#HighlightFunctionParameters() abort + " fallback to highlight_function_arguments for backwards compatibility + return get(g:, 'go_highlight_function_parameters', get(g:, 'go_highlight_function_arguments', 0)) endfunction function! go#config#HighlightFunctionCalls() abort diff --git a/sources_non_forked/vim-go/autoload/go/coverage.vim b/sources_non_forked/vim-go/autoload/go/coverage.vim index cfd5f4cb..bb57cd86 100644 --- a/sources_non_forked/vim-go/autoload/go/coverage.vim +++ b/sources_non_forked/vim-go/autoload/go/coverage.vim @@ -85,7 +85,7 @@ function! go#coverage#Clear() abort " remove the autocmd we defined augroup vim-go-coverage - autocmd! + autocmd! * augroup end endfunction @@ -242,7 +242,7 @@ function! go#coverage#overlay(file) abort " clear the matches if we leave the buffer augroup vim-go-coverage - autocmd! + autocmd! * autocmd BufWinLeave call go#coverage#Clear() augroup end diff --git a/sources_non_forked/vim-go/autoload/go/debug.vim b/sources_non_forked/vim-go/autoload/go/debug.vim index 1562efbb..aeba4fdf 100644 --- a/sources_non_forked/vim-go/autoload/go/debug.vim +++ b/sources_non_forked/vim-go/autoload/go/debug.vim @@ -30,6 +30,21 @@ function! s:groutineID() abort endfunction function! s:complete(job, exit_status, data) abort + let l:gotready = get(s:state, 'ready', 0) + " copy messages to a:data _only_ when dlv exited non-zero and it was never + " detected as ready (e.g. there was a compiler error). + if a:exit_status > 0 && !l:gotready + " copy messages to data so that vim-go's usual handling of errors from + " async jobs will occur. + call extend(a:data, s:state['message']) + endif + + " return early instead of clearing any variables when the current job is not + " a:job + if has_key(s:state, 'job') && s:state['job'] != a:job + return + endif + if has_key(s:state, 'job') call remove(s:state, 'job') endif @@ -38,10 +53,11 @@ function! s:complete(job, exit_status, data) abort call remove(s:state, 'ready') endif - call s:clearState() - if a:exit_status > 0 - call go#util#EchoError(s:state['message']) + if has_key(s:state, 'ch') + call remove(s:state, 'ch') endif + + call s:clearState() endfunction function! s:logger(prefix, ch, msg) abort @@ -217,8 +233,8 @@ endfunction function! s:stop() abort let l:res = s:call_jsonrpc('RPCServer.Detach', {'kill': v:true}) - call s:clearState() if has_key(s:state, 'job') + call go#job#Wait(s:state['job']) call remove(s:state, 'job') endif @@ -230,9 +246,7 @@ function! s:stop() abort call remove(s:state, 'ch') endif - if has_key( s:state, 'data') - call remove(s:state, 'data') - endif + call s:clearState() endfunction function! go#debug#Stop() abort @@ -473,7 +487,7 @@ function! s:start_cb(res) abort exe bufwinnr(oldbuf) 'wincmd w' augroup vim-go-debug - autocmd! + autocmd! * autocmd FileType go nmap (go-debug-continue) autocmd FileType go nmap (go-debug-print) autocmd FileType go nmap (go-debug-breakpoint) @@ -489,7 +503,6 @@ function! s:err_cb(ch, msg) abort return endif - call go#util#EchoError(a:msg) let s:state['message'] += [a:msg] endfunction @@ -499,7 +512,6 @@ function! s:out_cb(ch, msg) abort return endif - call go#util#EchoProgress(a:msg) let s:state['message'] += [a:msg] if stridx(a:msg, go#config#DebugAddress()) != -1 @@ -572,7 +584,7 @@ function! go#debug#Start(is_test, ...) abort " It's already running. if has_key(s:state, 'job') - return + return s:state['job'] endif let s:start_args = a:000 @@ -634,7 +646,7 @@ function! go#debug#Start(is_test, ...) abort let s:state['message'] = [] let l:opts = { - \ 'for': '_', + \ 'for': 'GoDebug', \ 'statustype': 'debug', \ 'complete': function('s:complete'), \ } @@ -647,6 +659,8 @@ function! go#debug#Start(is_test, ...) abort catch call go#util#EchoError(v:exception) endtry + + return s:state['job'] endfunction " Translate a reflect kind constant to a human string. @@ -872,7 +886,7 @@ function! go#debug#Restart() abort call go#cmd#autowrite() try - call go#job#Stop(s:state['job']) + call s:stop() let l:breaks = s:state['breakpoint'] let s:state = { diff --git a/sources_non_forked/vim-go/autoload/go/debug_test.vim b/sources_non_forked/vim-go/autoload/go/debug_test.vim index b8192619..d90bd54d 100644 --- a/sources_non_forked/vim-go/autoload/go/debug_test.vim +++ b/sources_non_forked/vim-go/autoload/go/debug_test.vim @@ -7,11 +7,49 @@ function! Test_GoDebugStart_Empty() abort endfunction function! Test_GoDebugStart_RelativePackage() abort - call s:debug('./debugmain') + call s:debug('./debug/debugmain') endfunction function! Test_GoDebugStart_Package() abort - call s:debug('debugmain') + call s:debug('debug/debugmain') +endfunction + +function! Test_GoDebugStart_Errors() abort + if !go#util#has_job() + return + endif + + try + let l:expected = [ + \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': '# debug/compilerror'}, + \ {'lnum': 6, 'bufnr': 7, 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ' syntax error: unexpected newline, expecting comma or )'}, + \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exit status 2'} + \] + call setqflist([], 'r') + + let l:tmp = gotest#load_fixture('debug/compilerror/main.go') + call assert_false(exists(':GoDebugStop')) + + let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' + execute l:cd . ' debug/compilerror' + + call go#debug#Start(0) + + let l:actual = getqflist() + let l:start = reltime() + while len(l:actual) == 0 && reltimefloat(reltime(l:start)) < 10 + sleep 100m + let l:actual = getqflist() + endwhile + + call gotest#assert_quickfix(l:actual, l:expected) + call assert_false(exists(':GoDebugStop')) + + finally + call delete(l:tmp, 'rf') + " clear the quickfix lists + call setqflist([], 'r') + endtry endfunction function! s:debug(...) abort @@ -20,7 +58,7 @@ function! s:debug(...) abort endif try - let l:tmp = gotest#load_fixture('debugmain/debugmain.go') + let l:tmp = gotest#load_fixture('debug/debugmain/debugmain.go') call go#debug#Breakpoint(6) @@ -28,10 +66,10 @@ function! s:debug(...) abort if a:0 == 0 let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - execute l:cd . ' debugmain' - call go#debug#Start(0) + execute l:cd . ' debug/debugmain' + let l:job = go#debug#Start(0) else - call go#debug#Start(0, a:1) + let l:job = go#debug#Start(0, a:1) endif let l:start = reltime() @@ -39,9 +77,17 @@ function! s:debug(...) abort sleep 100m endwhile + call assert_true(exists(':GoDebugStop')) + call gotest#assert_quickfix(getqflist(), []) + call go#debug#Stop() + if !has('nvim') + call assert_equal(job_status(l:job), 'dead') + endif + call assert_false(exists(':GoDebugStop')) + finally call delete(l:tmp, 'rf') endtry diff --git a/sources_non_forked/vim-go/autoload/go/def.vim b/sources_non_forked/vim-go/autoload/go/def.vim index 2fc1b007..fb52af56 100644 --- a/sources_non_forked/vim-go/autoload/go/def.vim +++ b/sources_non_forked/vim-go/autoload/go/def.vim @@ -84,7 +84,6 @@ function! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort endif call go#def#jump_to_declaration(a:data[0], a:mode, a:bin_name) - call go#util#EchoSuccess(fnamemodify(a:data[0], ":t")) " capture the active window so that after the exit_cb and close_cb callbacks " can return to it when a:mode caused a split. diff --git a/sources_non_forked/vim-go/autoload/go/guru.vim b/sources_non_forked/vim-go/autoload/go/guru.vim index 87265c57..12e70c30 100644 --- a/sources_non_forked/vim-go/autoload/go/guru.vim +++ b/sources_non_forked/vim-go/autoload/go/guru.vim @@ -486,7 +486,7 @@ function! s:same_ids_highlight(exit_val, output, mode) abort " re-apply SameIds at the current cursor position at the time the buffer " is redisplayed: e.g. :edit, :GoRename, etc. augroup vim-go-sameids - autocmd! + autocmd! * autocmd BufWinEnter nested call go#guru#SameIds(0) augroup end endif @@ -511,7 +511,7 @@ function! go#guru#ClearSameIds() abort " remove the autocmds we defined augroup vim-go-sameids - autocmd! + autocmd! * augroup end return 0 diff --git a/sources_non_forked/vim-go/autoload/go/job.vim b/sources_non_forked/vim-go/autoload/go/job.vim index 2a14e6b0..bc2f0e87 100644 --- a/sources_non_forked/vim-go/autoload/go/job.vim +++ b/sources_non_forked/vim-go/autoload/go/job.vim @@ -343,77 +343,19 @@ function! s:neooptions(options) continue endif - " dealing with the channel lines of Neovim sucks. The docs (:help - " channel-lines) say: - " stream event handlers may receive partial (incomplete) lines. For a - " given invocation of on_stdout etc, `a:data` is not guaranteed to end - " with a newline. - " - `abcdefg` may arrive as `['abc']`, `['defg']`. - " - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`, - " `['','efg']`, or even `['ab']`, `['c','efg']`. if key == 'callback' let l:options['callback'] = a:options['callback'] if !has_key(a:options, 'out_cb') function! s:callback2on_stdout(ch, data, event) dict - " a single empty string means EOF was reached. - if len(a:data) == 1 && a:data[0] == '' - " when there's nothing buffered, return early so that an - " erroneous message will not be added. - if self.stdout_buf == '' - return - endif - - let l:data = [self.stdout_buf] - let self.stdout_buf = '' - else - let l:data = copy(a:data) - let l:data[0] = self.stdout_buf . l:data[0] - - " The last element may be a partial line; save it for next time. - let self.stdout_buf = l:data[-1] - - let l:data = l:data[:-2] - - if len(l:data) == 0 - return - endif - endif - - for l:msg in l:data - call self.callback(a:ch, l:msg) - endfor + let self.stdout_buf = s:neocb(a:ch, self.stdout_buf, a:data, self.callback) endfunction let l:options['on_stdout'] = function('s:callback2on_stdout', [], l:options) endif if !has_key(a:options, 'err_cb') function! s:callback2on_stderr(ch, data, event) dict - " a single empty string means EOF was reached. - if len(a:data) == 1 && a:data[0] == '' - " when there's nothing buffered, return early so that an - " erroneous message will not be added. - if self.stderr_buf == '' - return - endif - let l:data = [self.stderr_buf] - let self.stderr_buf = '' - else - let l:data = copy(a:data) - let l:data[0] = self.stderr_buf . l:data[0] - - " The last element may be a partial line; save it for next time. - let self.stderr_buf = l:data[-1] - - let l:data = l:data[:-2] - if len(l:data) == 0 - return - endif - endif - - for l:msg in l:data - call self.callback(a:ch, l:msg) - endfor + let self.stderr_buf = s:neocb(a:ch, self.stderr_buf, a:data, self.callback) endfunction let l:options['on_stderr'] = function('s:callback2on_stderr', [], l:options) endif @@ -424,31 +366,7 @@ function! s:neooptions(options) if key == 'out_cb' let l:options['out_cb'] = a:options['out_cb'] function! s:on_stdout(ch, data, event) dict - " a single empty string means EOF was reached. - if len(a:data) == 1 && a:data[0] == '' - " when there's nothing buffered, return early so that an - " erroneous message will not be added. - if self.stdout_buf == '' - return - endif - let l:data = [self.stdout_buf] - let self.stdout_buf = '' - else - let l:data = copy(a:data) - let l:data[0] = self.stdout_buf . l:data[0] - - " The last element may be a partial line; save it for next time. - let self.stdout_buf = l:data[-1] - - let l:data = l:data[:-2] - if len(l:data) == 0 - return - endif - endif - - for l:msg in l:data - call self.out_cb(a:ch, l:msg) - endfor + let self.stdout_buf = s:neocb(a:ch, self.stdout_buf, a:data, self.out_cb) endfunction let l:options['on_stdout'] = function('s:on_stdout', [], l:options) @@ -458,31 +376,7 @@ function! s:neooptions(options) if key == 'err_cb' let l:options['err_cb'] = a:options['err_cb'] function! s:on_stderr(ch, data, event) dict - " a single empty string means EOF was reached. - if len(a:data) == 1 && a:data[0] == '' - " when there's nothing buffered, return early so that an - " erroneous message will not be added. - if self.stderr_buf == '' - return - endif - let l:data = [self.stderr_buf] - let self.stderr_buf = '' - else - let l:data = copy(a:data) - let l:data[0] = self.stderr_buf . l:data[0] - - " The last element may be a partial line; save it for next time. - let self.stderr_buf = l:data[-1] - - let l:data = l:data[:-2] - if len(l:data) == 0 - return - endif - endif - - for l:msg in l:data - call self.err_cb(a:ch, l:msg) - endfor + let self.stderr_buf = s:neocb(a:ch, self.stderr_buf, a:data, self.err_cb ) endfunction let l:options['on_stderr'] = function('s:on_stderr', [], l:options) @@ -542,6 +436,43 @@ function! s:winjobarg(idx, val) abort return a:val endfunction +function! s:neocb(ch, buf, data, callback) + " dealing with the channel lines of Neovim is awful. The docs (:help + " channel-lines) say: + " stream event handlers may receive partial (incomplete) lines. For a + " given invocation of on_stdout etc, `a:data` is not guaranteed to end + " with a newline. + " - `abcdefg` may arrive as `['abc']`, `['defg']`. + " - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`, + " `['','efg']`, or even `['ab']`, `['c','efg']`. + + " a single empty string means EOF was reached. + if len(a:data) == 1 && a:data[0] == '' + " when there's nothing buffered, return early so that an + " erroneous message will not be added. + if a:buf == '' + return '' + endif + + let l:data = [a:buf] + let l:buf = '' + else + let l:data = copy(a:data) + let l:data[0] = a:buf . l:data[0] + + " The last element may be a partial line; save it for next time. + let l:buf = l:data[-1] + + let l:data = l:data[:-2] + endif + + for l:msg in l:data + call a:callback(a:ch, l:msg) + endfor + + return l:buf +endfunction + " restore Vi compatibility settings let &cpo = s:cpo_save unlet s:cpo_save diff --git a/sources_non_forked/vim-go/autoload/go/lint.vim b/sources_non_forked/vim-go/autoload/go/lint.vim index 46effcc2..d99bfb0d 100644 --- a/sources_non_forked/vim-go/autoload/go/lint.vim +++ b/sources_non_forked/vim-go/autoload/go/lint.vim @@ -9,15 +9,22 @@ function! go#lint#Gometa(bang, autosave, ...) abort let goargs = a:000 endif - let bin_path = go#path#CheckBinPath("gometalinter") - if empty(bin_path) - return - endif + if empty(go#config#MetalinterCommand()) + let bin_path = go#path#CheckBinPath("gometalinter") + if empty(bin_path) + return + endif - let cmd = [bin_path] - let cmd += ["--disable-all"] + let cmd = [bin_path] + let cmd += ["--disable-all"] + + " gometalinter has a --tests flag to tell its linters whether to run + " against tests. While not all of its linters respect this flag, for those + " that do, it means if we don't pass --tests, the linter won't run against + " test files. One example of a linter that will not run against tests if + " we do not specify this flag is errcheck. + let cmd += ["--tests"] - if a:autosave || empty(go#config#MetalinterCommand()) " linters let linters = a:autosave ? go#config#MetalinterAutosaveEnabled() : go#config#MetalinterEnabled() for linter in linters @@ -27,16 +34,9 @@ function! go#lint#Gometa(bang, autosave, ...) abort for linter in go#config#MetalinterDisabled() let cmd += ["--disable=".linter] endfor - - " gometalinter has a --tests flag to tell its linters whether to run - " against tests. While not all of its linters respect this flag, for those - " that do, it means if we don't pass --tests, the linter won't run against - " test files. One example of a linter that will not run against tests if - " we do not specify this flag is errcheck. - let cmd += ["--tests"] else " the user wants something else, let us use it. - let cmd += split(go#config#MetalinterCommand(), " ") + let cmd = split(go#config#MetalinterCommand(), " ") endif if a:autosave @@ -78,8 +78,8 @@ function! go#lint#Gometa(bang, autosave, ...) abort echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None else " GoMetaLinter can output one of the two, so we look for both: - " ::[]: () - " ::: () + " :::: () + " :::: () " This can be defined by the following errorformat: let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m" @@ -123,7 +123,9 @@ endfunction function! go#lint#Vet(bang, ...) abort call go#cmd#autowrite() - call go#util#EchoProgress('calling vet...') + if go#config#EchoCommandInfo() + call go#util#EchoProgress('calling vet...') + endif if a:0 == 0 let [l:out, l:err] = go#util#Exec(['go', 'vet', go#package#ImportPath()]) @@ -140,7 +142,6 @@ function! go#lint#Vet(bang, ...) abort if !empty(errors) && !a:bang call go#list#JumpToFirst(l:listtype) endif - call go#util#EchoError('[vet] FAIL') else call go#list#Clean(l:listtype) call go#util#EchoSuccess('[vet] PASS') diff --git a/sources_non_forked/vim-go/autoload/go/list.vim b/sources_non_forked/vim-go/autoload/go/list.vim index f7a43ec1..1805d4d3 100644 --- a/sources_non_forked/vim-go/autoload/go/list.vim +++ b/sources_non_forked/vim-go/autoload/go/list.vim @@ -138,6 +138,7 @@ endfunction " in g:go_list_type_commands. let s:default_list_type_commands = { \ "GoBuild": "quickfix", + \ "GoDebug": "quickfix", \ "GoErrCheck": "quickfix", \ "GoFmt": "locationlist", \ "GoGenerate": "quickfix", diff --git a/sources_non_forked/vim-go/autoload/go/rename.vim b/sources_non_forked/vim-go/autoload/go/rename.vim index 72e8d8dc..1cc221b5 100644 --- a/sources_non_forked/vim-go/autoload/go/rename.vim +++ b/sources_non_forked/vim-go/autoload/go/rename.vim @@ -89,7 +89,6 @@ function s:parse_errors(exit_val, bang, out) let l:listtype = go#list#Type("GoRename") if a:exit_val != 0 - call go#util#EchoError("FAILED") let errors = go#tool#ParseErrors(a:out) call go#list#Populate(l:listtype, errors, 'Rename') call go#list#Window(l:listtype, len(errors)) diff --git a/sources_non_forked/vim-go/autoload/go/template.vim b/sources_non_forked/vim-go/autoload/go/template.vim index 5062464b..3f5e5381 100644 --- a/sources_non_forked/vim-go/autoload/go/template.vim +++ b/sources_non_forked/vim-go/autoload/go/template.vim @@ -8,39 +8,34 @@ function! go#template#create() abort let l:go_template_use_pkg = go#config#TemplateUsePkg() let l:root_dir = fnamemodify(s:current_file, ':h:h:h') - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - let l:package_name = -1 + let l:package_name = go#tool#PackageName() - if isdirectory(expand('%:p:h')) - execute cd . fnameescape(expand('%:p:h')) - let l:package_name = go#tool#PackageName() - endif - - " if we can't figure out any package name(no Go files or non Go package - " files) from the directory create the template or use the cwd - " as the name - if l:package_name == -1 && l:go_template_use_pkg != 1 - let l:filename = fnamemodify(expand("%"), ':t') - if l:filename =~ "_test.go$" - let l:template_file = go#config#TemplateTestFile() + " if we can't figure out any package name (i.e. no Go files in the directory) + " from the directory create the template or use the directory as the name. + if l:package_name == -1 + if l:go_template_use_pkg == 1 + let l:path = fnamemodify(expand('%:p:h'), ':t') + let l:content = printf("package %s", l:path) + call append(0, l:content) else - let l:template_file = go#config#TemplateFile() + let l:filename = expand('%:t') + if l:filename =~ "_test.go$" + let l:template_file = go#config#TemplateTestFile() + else + let l:template_file = go#config#TemplateFile() + endif + let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file) + silent exe 'keepalt 0r ' . fnameescape(l:template_path) endif - let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file) - silent exe 'keepalt 0r ' . fnameescape(l:template_path) - elseif l:package_name == -1 && l:go_template_use_pkg == 1 - " cwd is now the dir of the package - let l:path = fnamemodify(getcwd(), ':t') - let l:content = printf("package %s", l:path) - call append(0, l:content) else let l:content = printf("package %s", l:package_name) call append(0, l:content) endif - $delete _ - - execute cd . fnameescape(dir) + " checking that the last line is empty shouldn't be necessary, but for some + " reason the last line isn't the expected empty line when run via tests. + if getline('$') is '' + $delete _ + endif endfunction function! go#template#ToggleAutoCreate() abort diff --git a/sources_non_forked/vim-go/autoload/go/template_test.vim b/sources_non_forked/vim-go/autoload/go/template_test.vim new file mode 100644 index 00000000..2e02580d --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/template_test.vim @@ -0,0 +1,62 @@ +" don't spam the user when Vim is started in Vi compatibility mode +let s:cpo_save = &cpo +set cpo&vim + +func! Test_TemplateCreate() abort + try + let l:tmp = gotest#write_file('foo/empty.txt', ['']) + + edit foo/bar.go + + call gotest#assert_buffer(1, [ + \ 'func main() {', + \ '\tfmt.Println("vim-go")', + \ '}']) + finally + call delete(l:tmp, 'rf') + endtry + + try + let l:tmp = gotest#write_file('foo/empty.txt', ['']) + edit foo/bar_test.go + + call gotest#assert_buffer(1, [ + \ 'func TestHelloWorld(t *testing.T) {', + \ '\t// t.Fatal("not implemented")', + \ '}']) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +func! Test_TemplateCreate_UsePkg() abort + try + let l:tmp = gotest#write_file('foo/empty.txt', ['']) + + let g:go_template_use_pkg = 1 + edit foo/bar.go + + call gotest#assert_buffer(0, ['package foo']) + finally + unlet g:go_template_use_pkg + call delete(l:tmp, 'rf') + endtry +endfunc + +func! Test_TemplateCreate_PackageExists() abort + try + let l:tmp = gotest#write_file('quux/quux.go', ['package foo']) + + edit quux/bar.go + + call gotest#assert_buffer(0, ['package foo']) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +" restore Vi compatibility settings +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/debug/compilerror/main.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/debug/compilerror/main.go new file mode 100644 index 00000000..3f3dc7c2 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/debug/compilerror/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("vim-go" +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/debugmain/debugmain.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/debug/debugmain/debugmain.go similarity index 100% rename from sources_non_forked/vim-go/autoload/go/test-fixtures/debugmain/debugmain.go rename to sources_non_forked/vim-go/autoload/go/test-fixtures/debug/debugmain/debugmain.go diff --git a/sources_non_forked/vim-go/autoload/go/test.vim b/sources_non_forked/vim-go/autoload/go/test.vim index 5a2ee64b..bb847a21 100644 --- a/sources_non_forked/vim-go/autoload/go/test.vim +++ b/sources_non_forked/vim-go/autoload/go/test.vim @@ -84,7 +84,6 @@ function! go#test#Test(bang, compile, ...) abort " failed to parse errors, output the original content call go#util#EchoError(out) endif - call go#util#EchoError("[test] FAIL") else call go#list#Clean(l:listtype) diff --git a/sources_non_forked/vim-go/autoload/go/tool.vim b/sources_non_forked/vim-go/autoload/go/tool.vim index c293b67e..f4ee8545 100644 --- a/sources_non_forked/vim-go/autoload/go/tool.vim +++ b/sources_non_forked/vim-go/autoload/go/tool.vim @@ -130,8 +130,8 @@ function! go#tool#ParseErrors(lines) abort return errors endfunction -"FilterValids filters the given items with only items that have a valid -"filename. Any non valid filename is filtered out. +" FilterValids filters the given items with only items that have a valid +" filename. Any non valid filename is filtered out. function! go#tool#FilterValids(items) abort " Remove any nonvalid filename from the location list to avoid opening an " empty buffer. See https://github.com/fatih/vim-go/issues/287 for diff --git a/sources_non_forked/vim-go/doc/vim-go.txt b/sources_non_forked/vim-go/doc/vim-go.txt index 1fd87d80..3c99eecd 100644 --- a/sources_non_forked/vim-go/doc/vim-go.txt +++ b/sources_non_forked/vim-go/doc/vim-go.txt @@ -1836,13 +1836,13 @@ Highlight function and method declarations. > let g:go_highlight_functions = 0 < - *'g:go_highlight_function_arguments'* + *'g:go_highlight_function_parameters'* -Highlight the variable names in arguments and return values in function -declarations. Setting this implies the functionality from +Highlight the variable names in parameters (including named return parameters) +in function declarations. Setting this implies the functionality from |'g:go_highlight_functions'|. > - let g:go_highlight_function_arguments = 0 + let g:go_highlight_function_parameters = 0 < *'g:go_highlight_function_calls'* diff --git a/sources_non_forked/vim-go/ftdetect/gofiletype.vim b/sources_non_forked/vim-go/ftdetect/gofiletype.vim index ebbe7c29..09f6ac75 100644 --- a/sources_non_forked/vim-go/ftdetect/gofiletype.vim +++ b/sources_non_forked/vim-go/ftdetect/gofiletype.vim @@ -25,11 +25,11 @@ function! s:gofiletype_post() endfunction " Note: should not use augroup in ftdetect (see :help ftdetect) -au BufNewFile *.go setfiletype go | setlocal fileencoding=utf-8 fileformat=unix +au BufNewFile *.go setfiletype go | if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif au BufRead *.go call s:gofiletype_pre("go") au BufReadPost *.go call s:gofiletype_post() -au BufNewFile *.s setfiletype asm | setlocal fileencoding=utf-8 fileformat=unix +au BufNewFile *.s setfiletype asm | if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif au BufRead *.s call s:gofiletype_pre("asm") au BufReadPost *.s call s:gofiletype_post() diff --git a/sources_non_forked/vim-go/plugin/go.vim b/sources_non_forked/vim-go/plugin/go.vim index e0e41476..947d7e71 100644 --- a/sources_non_forked/vim-go/plugin/go.vim +++ b/sources_non_forked/vim-go/plugin/go.vim @@ -277,7 +277,7 @@ endfunction function! s:template_autocreate() " create new template from scratch - if get(g:, "go_template_autocreate", 1) + if get(g:, "go_template_autocreate", 1) && &modifiable call go#template#create() endif endfunction diff --git a/sources_non_forked/vim-go/scripts/runtest.vim b/sources_non_forked/vim-go/scripts/runtest.vim index ddb40af4..9d20b76a 100644 --- a/sources_non_forked/vim-go/scripts/runtest.vim +++ b/sources_non_forked/vim-go/scripts/runtest.vim @@ -48,7 +48,7 @@ redir @q redir END let s:tests = split(substitute(@q, 'function \(\k\+()\)', '\1', 'g')) -" log any messages that we may already accumulated. +" log any messages already accumulated. call s:logmessages() " Iterate over all tests and execute them. for s:test in sort(s:tests) diff --git a/sources_non_forked/vim-go/syntax/go.vim b/sources_non_forked/vim-go/syntax/go.vim index 104aaf78..37dbb4d2 100644 --- a/sources_non_forked/vim-go/syntax/go.vim +++ b/sources_non_forked/vim-go/syntax/go.vim @@ -148,14 +148,14 @@ endif " var, const if go#config#FoldEnable('varconst') syn region goVar start='var (' end='^\s*)$' transparent fold - \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goArgumentName,goArgumentType,goSimpleArguments,goPointerOperator + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator syn region goConst start='const (' end='^\s*)$' transparent fold - \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goArgumentName,goArgumentType,goSimpleArguments,goPointerOperator + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator else syn region goVar start='var (' end='^\s*)$' transparent - \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goArgumentName,goArgumentType,goSimpleArguments,goPointerOperator + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator syn region goConst start='const (' end='^\s*)$' transparent - \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goArgumentName,goArgumentType,goSimpleArguments,goPointerOperator + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator endif " Single-line var, const, and import. @@ -263,19 +263,20 @@ endif hi def link goOperator Operator " Functions; -if go#config#HighlightFunctions() || go#config#HighlightFunctionArguments() - syn match goDeclaration /\/ nextgroup=goReceiver,goFunction,goSimpleArguments skipwhite skipnl +if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters() + syn match goDeclaration /\/ nextgroup=goReceiver,goFunction,goSimpleParams skipwhite skipnl syn match goReceiverVar /\w\+\ze\s\+\(\w\|\*\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained syn match goPointerOperator /\*/ nextgroup=goReceiverType contained skipwhite skipnl - syn match goFunction /\w\+/ nextgroup=goSimpleArguments contained skipwhite skipnl + syn match goFunction /\w\+/ nextgroup=goSimpleParams contained skipwhite skipnl syn match goReceiverType /\w\+/ contained -if go#config#HighlightFunctionArguments() - syn match goSimpleArguments /(\(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goArgumentName nextgroup=goSimpleArguments skipwhite skipnl - syn match goArgumentName /\w\+\(\s*,\s*\w\+\)*\ze\s\+\(\w\|\.\|\*\|\[\)/ contained nextgroup=goArgumentType skipwhite skipnl - syn match goArgumentType /\([^,)]\|\_s\)\+,\?/ contained nextgroup=goArgumentName skipwhite skipnl +if go#config#HighlightFunctionParameters() + syn match goSimpleParams /(\(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl + syn match goFunctionReturn /(\(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType skipwhite skipnl + syn match goParamName /\w\+\(\s*,\s*\w\+\)*\ze\s\+\(\w\|\.\|\*\|\[\)/ contained nextgroup=goParamType skipwhite skipnl + syn match goParamType /\([^,)]\|\_s\)\+,\?/ contained nextgroup=goParamName skipwhite skipnl \ contains=goVarArgs,goType,goSignedInts,goUnsignedInts,goFloats,goComplexes,goDeclType,goBlock - hi def link goReceiverVar goArgumentName - hi def link goArgumentName Identifier + hi def link goReceiverVar goParamName + hi def link goParamName Identifier endif syn match goReceiver /(\s*\w\+\(\s\+\*\?\s*\w\+\)\?\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverVar skipwhite skipnl else diff --git a/sources_non_forked/vim-isort b/sources_non_forked/vim-isort new file mode 160000 index 00000000..2fbab340 --- /dev/null +++ b/sources_non_forked/vim-isort @@ -0,0 +1 @@ +Subproject commit 2fbab3401b7f81ac7f629e34e4f40a7e52934a99 diff --git a/sources_non_forked/vim-markdown/ftdetect/markdown.vim b/sources_non_forked/vim-markdown/ftdetect/markdown.vim index 611ecaa0..07682da4 100644 --- a/sources_non_forked/vim-markdown/ftdetect/markdown.vim +++ b/sources_non_forked/vim-markdown/ftdetect/markdown.vim @@ -1,3 +1,8 @@ +if !has('patch-7.4.480') + " Before this patch, vim used modula2 for .md. + au! filetypedetect BufRead,BufNewFile *.md +endif + " markdown filetype file -au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn} set filetype=markdown -au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn}.{des3,des,bf,bfa,aes,idea,cast,rc2,rc4,rc5,desx} set filetype=markdown +au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn} setfiletype markdown +au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn}.{des3,des,bf,bfa,aes,idea,cast,rc2,rc4,rc5,desx} setfiletype markdown diff --git a/sources_non_forked/vim-markdown/ftplugin/markdown.vim b/sources_non_forked/vim-markdown/ftplugin/markdown.vim index 68d1d3d9..659df917 100644 --- a/sources_non_forked/vim-markdown/ftplugin/markdown.vim +++ b/sources_non_forked/vim-markdown/ftplugin/markdown.vim @@ -734,7 +734,7 @@ function! s:MarkdownHighlightSources(force) let include = '@' . toupper(filetype) endif let command = 'syntax region %s matchgroup=%s start="^\s*```\s*%s$" matchgroup=%s end="\s*```$" keepend contains=%s%s' - execute printf(command, group, startgroup, ft, endgroup, include, has('conceal') && get(g:, 'vim_markdown_conceal', 1) ? ' concealends' : '') + execute printf(command, group, startgroup, ft, endgroup, include, has('conceal') && get(g:, 'vim_markdown_conceal', 1) && get(g:, 'vim_markdown_conceal_code_blocks', 1) ? ' concealends' : '') execute printf('syntax cluster mkdNonListItem add=%s', group) let b:mkd_known_filetypes[ft] = 1 diff --git a/sources_non_forked/vim-markdown/syntax/markdown.vim b/sources_non_forked/vim-markdown/syntax/markdown.vim index 5056af48..e9df1ca0 100644 --- a/sources_non_forked/vim-markdown/syntax/markdown.vim +++ b/sources_non_forked/vim-markdown/syntax/markdown.vim @@ -36,10 +36,14 @@ syn sync linebreaks=1 let s:conceal = '' let s:concealends = '' +let s:concealcode = '' if has('conceal') && get(g:, 'vim_markdown_conceal', 1) let s:conceal = ' conceal' let s:concealends = ' concealends' endif +if has('conceal') && get(g:, 'vim_markdown_conceal_code_blocks', 1) + let s:concealcode = ' concealends' +endif " additions to HTML groups if get(g:, 'vim_markdown_emphasis_multiline', 1) @@ -94,13 +98,13 @@ syn match htmlH2 /^.\+\n-\+$/ contains=mkdLink,mkdInlineURL,@Spell "define Markdown groups syn match mkdLineBreak / \+$/ syn region mkdBlockquote start=/^\s*>/ end=/$/ contains=mkdLink,mkdInlineURL,mkdLineBreak,@Spell -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@]*\\\@" end=""' . s:concealends -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="]*\\\@" end=""' . s:concealends +execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@]*\\\@" end=""' . s:concealcode +execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="]*\\\@" end=""' . s:concealcode syn region mkdFootnote start="\[^" end="\]" syn match mkdCode /^\s*\n\(\(\s\{8,}[^ ]\|\t\t\+[^\t]\).*\n\)\+/ syn match mkdCode /\%^\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/ diff --git a/sources_non_forked/vim-snippets/UltiSnips/javascript.snippets b/sources_non_forked/vim-snippets/UltiSnips/javascript.snippets index 602a56b9..bae39ae8 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/javascript.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/javascript.snippets @@ -56,19 +56,28 @@ ${1:class_name}.prototype.${2:method_name} = function`!p snip.rv = space_before_ endsnippet -snippet fun "function (fun)" w +snippet fun "function (named)" b function ${1:function_name}`!p snip.rv = space_before_function_paren(snip)`(${2:argument}) { ${VISUAL}$0 } endsnippet -snippet vf "Function assigned to var" +snippet vf "function (assigned to var)" ${1:var }${2:function_name} = function $2`!p snip.rv = space_before_function_paren(snip)`($3) { ${VISUAL}$0 }`!p snip.rv = semi(snip)` endsnippet -snippet anf "Anonymous Function" i +# Drop priority so this only triggers when not beginning of line. +priority -51 +snippet fun "function (anonymous)" w +function`!p snip.rv = space_before_function_paren(snip)`($1) { + ${VISUAL}$0 +}$2 +endsnippet +priority -50 + +snippet anf "function (anonymous)" i function`!p snip.rv = space_before_function_paren(snip)`($1) { ${VISUAL}$0 } diff --git a/sources_non_forked/vim-snippets/UltiSnips/rust.snippets b/sources_non_forked/vim-snippets/UltiSnips/rust.snippets index 56351525..fbf459d1 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/rust.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/rust.snippets @@ -28,7 +28,7 @@ snippet fmt "format!(..)" format!("$1"${2/..*/, /}$2); endsnippet -snippet it ".iter()" i +snippet .it ".iter()" i .iter()$0 endsnippet diff --git a/sources_non_forked/vim-snippets/snippets/python.snippets b/sources_non_forked/vim-snippets/snippets/python.snippets index c1b930ab..0e513cb8 100644 --- a/sources_non_forked/vim-snippets/snippets/python.snippets +++ b/sources_non_forked/vim-snippets/snippets/python.snippets @@ -22,6 +22,11 @@ snippet docs Description: ${0} """ +# Unittest skip +snippet sk "skip unittests" b +@unittest.skip(${1:skip_reason}) +endsnippet + snippet wh while ${1:condition}: ${0:${VISUAL}}