mirror of
				https://github.com/amix/vimrc
				synced 2025-10-31 14:43:35 +08:00 
			
		
		
		
	Updated plugins
This commit is contained in:
		| @ -15,9 +15,9 @@ function! ale_linters#awk#gawk#GetCommand(buffer) abort | |||||||
|     " note the --source 'BEGIN ...' is to prevent |     " note the --source 'BEGIN ...' is to prevent | ||||||
|     " gawk from attempting to execute the body of the script |     " gawk from attempting to execute the body of the script | ||||||
|     " it is linting. |     " it is linting. | ||||||
|     return ale_linters#awk#gawk#GetExecutable(a:buffer) |     return ale#Escape(ale_linters#awk#gawk#GetExecutable(a:buffer)) | ||||||
|     \   . " --source 'BEGIN { exit } END { exit 1 }'" |     \   . " --source 'BEGIN { exit } END { exit 1 }'" | ||||||
|     \   . ' ' . ale#Var(a:buffer, 'awk_gawk_options') |     \   .  ale#Pad(ale#Var(a:buffer, 'awk_gawk_options')) | ||||||
|     \   . ' ' . '-f %t --lint /dev/null' |     \   . ' ' . '-f %t --lint /dev/null' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | |||||||
| @ -30,5 +30,4 @@ call ale#linter#Define('cpp', { | |||||||
| \   'command_callback': 'ale_linters#cpp#cquery#GetCommand', | \   'command_callback': 'ale_linters#cpp#cquery#GetCommand', | ||||||
| \   'project_root_callback': 'ale_linters#cpp#cquery#GetProjectRoot', | \   'project_root_callback': 'ale_linters#cpp#cquery#GetProjectRoot', | ||||||
| \   'initialization_options_callback': 'ale_linters#cpp#cquery#GetInitializationOptions', | \   'initialization_options_callback': 'ale_linters#cpp#cquery#GetInitializationOptions', | ||||||
| \   'language': 'cpp', |  | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -1,7 +1,11 @@ | |||||||
| let g:ale_cs_mcs_options = get(g:, 'ale_cs_mcs_options', '') | let g:ale_cs_mcs_options = get(g:, 'ale_cs_mcs_options', '') | ||||||
|  |  | ||||||
| function! ale_linters#cs#mcs#GetCommand(buffer) abort | function! ale_linters#cs#mcs#GetCommand(buffer) abort | ||||||
|     return 'mcs -unsafe --parse ' . ale#Var(a:buffer, 'cs_mcs_options') . ' %t' |     let l:options = ale#Var(a:buffer, 'cs_mcs_options') | ||||||
|  |  | ||||||
|  |     return 'mcs -unsafe --parse' | ||||||
|  |     \   . (!empty(l:options) ? ' ' . l:options : '') | ||||||
|  |     \   . ' %t' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#cs#mcs#Handle(buffer, lines) abort | function! ale_linters#cs#mcs#Handle(buffer, lines) abort | ||||||
|  | |||||||
| @ -29,16 +29,16 @@ function! ale_linters#cs#mcsc#GetCommand(buffer) abort | |||||||
|     \   : '' |     \   : '' | ||||||
|  |  | ||||||
|     " register temporary module target file with ale |     " register temporary module target file with ale | ||||||
|     let l:out = tempname() |     " register temporary module target file with ALE. | ||||||
|     call ale#engine#ManageFile(a:buffer, l:out) |     let l:out = ale#engine#CreateFile(a:buffer) | ||||||
|  |  | ||||||
|     " The code is compiled as a module and the output is redirected to a |     " The code is compiled as a module and the output is redirected to a | ||||||
|     " temporary file. |     " temporary file. | ||||||
|     return ale#path#CdString(s:GetWorkingDirectory(a:buffer)) |     return ale#path#CdString(s:GetWorkingDirectory(a:buffer)) | ||||||
|     \    . 'mcs -unsafe' |     \    . 'mcs -unsafe' | ||||||
|     \    . ' ' . ale#Var(a:buffer, 'cs_mcsc_options') |     \    . ale#Pad(ale#Var(a:buffer, 'cs_mcsc_options')) | ||||||
|     \    . ' ' . l:lib_option |     \    . ale#Pad(l:lib_option) | ||||||
|     \    . ' ' . l:r_option |     \    . ale#Pad(l:r_option) | ||||||
|     \    . ' -out:' . l:out |     \    . ' -out:' . l:out | ||||||
|     \    . ' -t:module' |     \    . ' -t:module' | ||||||
|     \    . ' -recurse:' . ale#Escape('*.cs') |     \    . ' -recurse:' . ale#Escape('*.cs') | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ endfunction | |||||||
|  |  | ||||||
| function! ale_linters#cuda#nvcc#GetCommand(buffer) abort | function! ale_linters#cuda#nvcc#GetCommand(buffer) abort | ||||||
|     " Unused: use ale#util#nul_file |     " Unused: use ale#util#nul_file | ||||||
|     " let l:output_file = tempname() . '.ii' |     " let l:output_file = ale#util#Tempname() . '.ii' | ||||||
|     " call ale#engine#ManageFile(a:buffer, l:output_file) |     " call ale#engine#ManageFile(a:buffer, l:output_file) | ||||||
|  |  | ||||||
|     return ale#Escape(ale_linters#cuda#nvcc#GetExecutable(a:buffer)) |     return ale#Escape(ale_linters#cuda#nvcc#GetExecutable(a:buffer)) | ||||||
|  | |||||||
| @ -20,6 +20,5 @@ call ale#linter#Define('dart', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#dart#language_server#GetExecutable', | \   'executable_callback': 'ale_linters#dart#language_server#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#dart#language_server#GetExecutable', | \   'command_callback': 'ale_linters#dart#language_server#GetExecutable', | ||||||
| \   'language': 'dart', |  | ||||||
| \   'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot', | \   'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -128,14 +128,7 @@ function! ale_linters#elm#make#HandleElm018Line(line, output) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#elm#make#FileIsBuffer(path) abort | function! ale_linters#elm#make#FileIsBuffer(path) abort | ||||||
|     let l:is_windows = has('win32') |     return ale#path#IsTempName(a:path) | ||||||
|     let l:temp_dir = l:is_windows ? $TMP : $TMPDIR |  | ||||||
|  |  | ||||||
|     if has('win32') |  | ||||||
|         return a:path[0:len(l:temp_dir) - 1] is? l:temp_dir |  | ||||||
|     else |  | ||||||
|         return a:path[0:len(l:temp_dir) - 1] is# l:temp_dir |  | ||||||
|     endif |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#elm#make#ParseMessage(message) abort | function! ale_linters#elm#make#ParseMessage(message) abort | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
| let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '') | let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '') | ||||||
|  |  | ||||||
| function! ale_linters#erlang#erlc#GetCommand(buffer) abort | function! ale_linters#erlang#erlc#GetCommand(buffer) abort | ||||||
|     let l:output_file = tempname() |     let l:output_file = ale#util#Tempname() | ||||||
|     call ale#engine#ManageFile(a:buffer, l:output_file) |     call ale#engine#ManageFile(a:buffer, l:output_file) | ||||||
|  |  | ||||||
|     return 'erlc -o ' . ale#Escape(l:output_file) |     return 'erlc -o ' . ale#Escape(l:output_file) | ||||||
|  | |||||||
| @ -1,11 +1,8 @@ | |||||||
| " Author: RyanSquared <vandor2012@gmail.com> | " Author: RyanSquared <vandor2012@gmail.com> | ||||||
| " Description: `fusion-lint` linter for FusionScript files | " Description: `fusion-lint` linter for FusionScript files | ||||||
|  |  | ||||||
| let g:ale_fuse_fusionlint_executable = | call ale#Set('fuse_fusionlint_executable', 'fusion-lint') | ||||||
| \   get(g:, 'ale_fuse_fusionlint_executable', 'fusion-lint') | call ale#Set('fuse_fusionlint_options', '') | ||||||
|  |  | ||||||
| let g:ale_fuse_fusionlint_options = |  | ||||||
| \   get(g:, 'ale_fuse_fusionlint_options', '') |  | ||||||
|  |  | ||||||
| function! ale_linters#fuse#fusionlint#GetExecutable(buffer) abort | function! ale_linters#fuse#fusionlint#GetExecutable(buffer) abort | ||||||
|     return ale#Var(a:buffer, 'fuse_fusionlint_executable') |     return ale#Var(a:buffer, 'fuse_fusionlint_executable') | ||||||
| @ -13,7 +10,7 @@ endfunction | |||||||
|  |  | ||||||
| function! ale_linters#fuse#fusionlint#GetCommand(buffer) abort | function! ale_linters#fuse#fusionlint#GetCommand(buffer) abort | ||||||
|     return ale#Escape(ale_linters#fuse#fusionlint#GetExecutable(a:buffer)) |     return ale#Escape(ale_linters#fuse#fusionlint#GetExecutable(a:buffer)) | ||||||
|     \   . ' ' . ale#Var(a:buffer, 'fuse_fusionlint_options') |     \   . ale#Pad(ale#Var(a:buffer, 'fuse_fusionlint_options')) | ||||||
|     \   . ' --filename %s -i' |     \   . ' --filename %s -i' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | |||||||
| @ -14,9 +14,9 @@ function! ale_linters#glsl#glslang#GetExecutable(buffer) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#glsl#glslang#GetCommand(buffer) abort | function! ale_linters#glsl#glslang#GetCommand(buffer) abort | ||||||
|     return ale_linters#glsl#glslang#GetExecutable(a:buffer) |     return ale#Escape(ale_linters#glsl#glslang#GetExecutable(a:buffer)) | ||||||
|     \   . ' ' . ale#Var(a:buffer, 'glsl_glslang_options') |     \   . ale#Pad(ale#Var(a:buffer, 'glsl_glslang_options')) | ||||||
|     \   . ' ' . '-C %t' |     \   . ' -C %t' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#glsl#glslang#Handle(buffer, lines) abort | function! ale_linters#glsl#glslang#Handle(buffer, lines) abort | ||||||
|  | |||||||
| @ -29,6 +29,5 @@ call ale#linter#Define('glsl', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#glsl#glslls#GetExecutable', | \   'executable_callback': 'ale_linters#glsl#glslls#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#glsl#glslls#GetCommand', | \   'command_callback': 'ale_linters#glsl#glslls#GetCommand', | ||||||
| \   'language': 'glsl', |  | ||||||
| \   'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot', | \   'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -3,10 +3,9 @@ | |||||||
|  |  | ||||||
| function! ale_linters#go#gotype#GetCommand(buffer) abort | function! ale_linters#go#gotype#GetCommand(buffer) abort | ||||||
|     if expand('#' . a:buffer . ':p') =~# '_test\.go$' |     if expand('#' . a:buffer . ':p') =~# '_test\.go$' | ||||||
|         return |         return '' | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|  |  | ||||||
|     return ale#path#BufferCdString(a:buffer) . ' gotype .' |     return ale#path#BufferCdString(a:buffer) . ' gotype .' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | |||||||
| @ -84,10 +84,10 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort | |||||||
|     return ale#path#BufferCdString(a:buffer) |     return ale#path#BufferCdString(a:buffer) | ||||||
|     \ . ale#Escape(l:executable) |     \ . ale#Escape(l:executable) | ||||||
|     \ . ' -Xlint' |     \ . ' -Xlint' | ||||||
|     \ . ' ' . l:cp_option |     \ . ale#Pad(l:cp_option) | ||||||
|     \ . ' ' . l:sp_option |     \ . ale#Pad(l:sp_option) | ||||||
|     \ . ' -d ' . ale#Escape(l:class_file_directory) |     \ . ' -d ' . ale#Escape(l:class_file_directory) | ||||||
|     \ . ' ' . ale#Var(a:buffer, 'java_javac_options') |     \ . ale#Pad(ale#Var(a:buffer, 'java_javac_options')) | ||||||
|     \ . ' %t' |     \ . ' %t' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										38
									
								
								sources_non_forked/ale/ale_linters/javascript/flow_ls.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								sources_non_forked/ale/ale_linters/javascript/flow_ls.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | " Author: t_t <jamestthompson3@gmail.com> | ||||||
|  | " Description: Integrate ALE with flow-language-server. | ||||||
|  |  | ||||||
|  | call ale#Set('javascript_flow_ls_executable', 'flow') | ||||||
|  | call ale#Set('javascript_flow_ls_use_global', | ||||||
|  | \    get(g:, 'ale_use_global_executables', 0) | ||||||
|  | \) | ||||||
|  |  | ||||||
|  | function! ale_linters#javascript#flow_ls#GetExecutable(buffer) abort | ||||||
|  |     return ale#node#FindExecutable(a:buffer, 'javascript_flow_ls', [ | ||||||
|  |     \   'node_modules/.bin/flow', | ||||||
|  |     \]) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#javascript#flow_ls#GetCommand(buffer) abort | ||||||
|  |     let l:executable = ale_linters#javascript#flow_ls#GetExecutable(a:buffer) | ||||||
|  |  | ||||||
|  |     return ale#Escape(l:executable) . ' lsp --from ale-lsp' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#javascript#flow_ls#FindProjectRoot(buffer) abort | ||||||
|  |     let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig') | ||||||
|  |  | ||||||
|  |     if !empty(l:flow_config) | ||||||
|  |         return fnamemodify(l:flow_config, ':h') | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     return '' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | call ale#linter#Define('javascript', { | ||||||
|  | \   'name': 'flow-language-server', | ||||||
|  | \   'lsp': 'stdio', | ||||||
|  | \   'executable_callback': 'ale_linters#javascript#flow_ls#GetExecutable', | ||||||
|  | \   'command_callback': 'ale_linters#javascript#flow_ls#GetCommand', | ||||||
|  | \   'project_root_callback': 'ale_linters#javascript#flow_ls#FindProjectRoot', | ||||||
|  | \   'language': 'javascript', | ||||||
|  | \}) | ||||||
							
								
								
									
										38
									
								
								sources_non_forked/ale/ale_linters/kotlin/languageserver.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								sources_non_forked/ale/ale_linters/kotlin/languageserver.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | " Author: MTDL9 <https://github.com/MTDL9> | ||||||
|  | " Description: Support for the Kotlin language server https://github.com/fwcd/KotlinLanguageServer | ||||||
|  |  | ||||||
|  | call ale#Set('kotlin_languageserver_executable', 'kotlin-language-server') | ||||||
|  |  | ||||||
|  | function! ale_linters#kotlin#languageserver#GetExecutable(buffer) abort | ||||||
|  |     return ale#Var(a:buffer, 'kotlin_languageserver_executable') | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#kotlin#languageserver#GetCommand(buffer) abort | ||||||
|  |     let l:executable = ale_linters#kotlin#languageserver#GetExecutable(a:buffer) | ||||||
|  |     return ale#Escape(l:executable) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#kotlin#languageserver#GetProjectRoot(buffer) abort | ||||||
|  |     let l:gradle_root = ale#gradle#FindProjectRoot(a:buffer) | ||||||
|  |  | ||||||
|  |     if !empty(l:gradle_root) | ||||||
|  |         return l:gradle_root | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let l:maven_pom_file = ale#path#FindNearestFile(a:buffer, 'pom.xml') | ||||||
|  |  | ||||||
|  |     if !empty(l:maven_pom_file) | ||||||
|  |         return fnamemodify(l:maven_pom_file, ':h') | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     return '' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | call ale#linter#Define('kotlin', { | ||||||
|  | \   'name': 'languageserver', | ||||||
|  | \   'lsp': 'stdio', | ||||||
|  | \   'executable_callback': 'ale_linters#kotlin#languageserver#GetExecutable', | ||||||
|  | \   'command_callback': 'ale_linters#kotlin#languageserver#GetCommand', | ||||||
|  | \   'language': 'kotlin', | ||||||
|  | \   'project_root_callback': 'ale_linters#kotlin#languageserver#GetProjectRoot', | ||||||
|  | \}) | ||||||
| @ -9,8 +9,7 @@ endfunction | |||||||
|  |  | ||||||
| function! ale_linters#llvm#llc#GetCommand(buffer) abort | function! ale_linters#llvm#llc#GetCommand(buffer) abort | ||||||
|     return ale#Escape(ale_linters#llvm#llc#GetExecutable(a:buffer)) |     return ale#Escape(ale_linters#llvm#llc#GetExecutable(a:buffer)) | ||||||
|     \   . ' -filetype=null -o=' |     \   . ' -filetype=null -o=' . g:ale#util#nul_file | ||||||
|     \   . ale#Escape(g:ale#util#nul_file) |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#llvm#llc#HandleErrors(buffer, lines) abort | function! ale_linters#llvm#llc#HandleErrors(buffer, lines) abort | ||||||
|  | |||||||
| @ -1,5 +1,23 @@ | |||||||
| " Author rhysd https://rhysd.github.io/, Dirk Roorda (dirkroorda), Adrián González Rus (@adrigzr) | " Author rhysd https://rhysd.github.io/, Dirk Roorda (dirkroorda), Adrián González Rus (@adrigzr) | ||||||
| " Description: remark-lint for Markdown files | " Description: remark-lint for Markdown files | ||||||
|  | call ale#Set('markdown_remark_lint_executable', 'remark') | ||||||
|  | call ale#Set('markdown_remark_lint_use_global', get(g:, 'ale_use_global_executables', 0)) | ||||||
|  | call ale#Set('markdown_remark_lint_options', '') | ||||||
|  |  | ||||||
|  | function! ale_linters#markdown#remark_lint#GetExecutable(buffer) abort | ||||||
|  |     return ale#node#FindExecutable(a:buffer, 'markdown_remark_lint', [ | ||||||
|  |     \   'node_modules/.bin/remark', | ||||||
|  |     \]) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#markdown#remark_lint#GetCommand(buffer) abort | ||||||
|  |     let l:executable = ale_linters#markdown#remark_lint#GetExecutable(a:buffer) | ||||||
|  |     let l:options = ale#Var(a:buffer, 'markdown_remark_lint_options') | ||||||
|  |  | ||||||
|  |     return ale#node#Executable(a:buffer, l:executable) | ||||||
|  |     \    . (!empty(l:options) ? ' ' . l:options : '') | ||||||
|  |     \    . ' --no-stdout --no-color' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#markdown#remark_lint#Handle(buffer, lines) abort | function! ale_linters#markdown#remark_lint#Handle(buffer, lines) abort | ||||||
|     " matches: '  1:4  warning  Incorrect list-item indent: add 1 space  list-item-indent  remark-lint' |     " matches: '  1:4  warning  Incorrect list-item indent: add 1 space  list-item-indent  remark-lint' | ||||||
| @ -26,9 +44,8 @@ endfunction | |||||||
|  |  | ||||||
| call ale#linter#Define('markdown', { | call ale#linter#Define('markdown', { | ||||||
| \   'name': 'remark-lint', | \   'name': 'remark-lint', | ||||||
| \   'executable': 'remark', | \   'executable_callback': 'ale_linters#markdown#remark_lint#GetExecutable', | ||||||
| \   'command': 'remark --no-stdout --no-color %s', | \   'command_callback': 'ale_linters#markdown#remark_lint#GetCommand', | ||||||
| \   'callback': 'ale_linters#markdown#remark_lint#Handle', | \   'callback': 'ale_linters#markdown#remark_lint#Handle', | ||||||
| \   'lint_file': 1, |  | ||||||
| \   'output_stream': 'stderr', | \   'output_stream': 'stderr', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -42,9 +42,9 @@ endfunction | |||||||
|  |  | ||||||
| call ale#linter#Define('nasm', { | call ale#linter#Define('nasm', { | ||||||
| \   'name': 'nasm', | \   'name': 'nasm', | ||||||
| \   'executable': 'nasm', |  | ||||||
| \   'output_stream': 'stderr', | \   'output_stream': 'stderr', | ||||||
| \   'lint_file': 1, | \   'lint_file': 1, | ||||||
|  | \   'executable_callback': 'ale_linters#nasm#nasm#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#nasm#nasm#GetCommand', | \   'command_callback': 'ale_linters#nasm#nasm#GetCommand', | ||||||
| \   'callback': 'ale_linters#nasm#nasm#Handle', | \   'callback': 'ale_linters#nasm#nasm#Handle', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -25,6 +25,5 @@ call ale#linter#Define('php', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#php#langserver#GetExecutable', | \   'executable_callback': 'ale_linters#php#langserver#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#php#langserver#GetCommand', | \   'command_callback': 'ale_linters#php#langserver#GetCommand', | ||||||
| \   'language': 'php', |  | ||||||
| \   'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot', | \   'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot', | ||||||
| \}) | \}) | ||||||
|  | |||||||
							
								
								
									
										45
									
								
								sources_non_forked/ale/ale_linters/puppet/languageserver.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								sources_non_forked/ale/ale_linters/puppet/languageserver.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | " Author: Alexander Olofsson <alexander.olofsson@liu.se> | ||||||
|  | " Description: Puppet Language Server integration for ALE | ||||||
|  |  | ||||||
|  | call ale#Set('puppet_languageserver_executable', 'puppet-languageserver') | ||||||
|  |  | ||||||
|  | function! ale_linters#puppet#languageserver#GetExecutable(buffer) abort | ||||||
|  |     return ale#Var(a:buffer, 'puppet_languageserver_executable') | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#puppet#languageserver#GetCommand(buffer) abort | ||||||
|  |     let l:exe = ale#Escape(ale_linters#puppet#languageserver#GetExecutable(a:buffer)) | ||||||
|  |  | ||||||
|  |     return l:exe . ' --stdio' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#puppet#languageserver#GetProjectRoot(buffer) abort | ||||||
|  |     " Note: The metadata.json file is recommended for Puppet 4+ modules, but | ||||||
|  |     " there's no requirement to have it, so fall back to the other possible | ||||||
|  |     " Puppet module directories | ||||||
|  |     let l:root_path = ale#path#FindNearestFile(a:buffer, 'metadata.json') | ||||||
|  |     if !empty(l:root_path) | ||||||
|  |         return fnamemodify(l:root_path, ':h') | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     for l:test_path in [ | ||||||
|  |     \   'manifests', | ||||||
|  |     \   'templates', | ||||||
|  |     \] | ||||||
|  |         let l:root_path = ale#path#FindNearestDirectory(a:buffer, l:test_path) | ||||||
|  |         if !empty(l:root_path) | ||||||
|  |             return fnamemodify(l:root_path, ':h:h') | ||||||
|  |         endif | ||||||
|  |     endfor | ||||||
|  |  | ||||||
|  |     return '' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | call ale#linter#Define('puppet', { | ||||||
|  | \   'name': 'languageserver', | ||||||
|  | \   'lsp': 'stdio', | ||||||
|  | \   'executable_callback': 'ale_linters#puppet#languageserver#GetExecutable', | ||||||
|  | \   'command_callback': 'ale_linters#puppet#languageserver#GetCommand', | ||||||
|  | \   'language': 'puppet', | ||||||
|  | \   'project_root_callback': 'ale_linters#puppet#languageserver#GetProjectRoot', | ||||||
|  | \}) | ||||||
| @ -23,7 +23,6 @@ call ale#linter#Define('python', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#python#pyls#GetExecutable', | \   'executable_callback': 'ale_linters#python#pyls#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#python#pyls#GetCommand', | \   'command_callback': 'ale_linters#python#pyls#GetCommand', | ||||||
| \   'language': 'python', |  | ||||||
| \   'project_root_callback': 'ale#python#FindProjectRoot', | \   'project_root_callback': 'ale#python#FindProjectRoot', | ||||||
| \   'completion_filter': 'ale#completion#python#CompletionItemFilter', | \   'completion_filter': 'ale#completion#python#CompletionItemFilter', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -23,7 +23,6 @@ call ale#linter#Define('python', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#python#pyre#GetExecutable', | \   'executable_callback': 'ale_linters#python#pyre#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#python#pyre#GetCommand', | \   'command_callback': 'ale_linters#python#pyre#GetCommand', | ||||||
| \   'language': 'python', |  | ||||||
| \   'project_root_callback': 'ale#python#FindProjectRoot', | \   'project_root_callback': 'ale#python#FindProjectRoot', | ||||||
| \   'completion_filter': 'ale#completion#python#CompletionItemFilter', | \   'completion_filter': 'ale#completion#python#CompletionItemFilter', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| " Author: Eddie Lebow https://github.com/elebow | " Author: Eddie Lebow https://github.com/elebow | ||||||
| " Description: rails_best_practices, a code metric tool for rails projects | " Description: rails_best_practices, a code metric tool for rails projects | ||||||
|  |  | ||||||
| let g:ale_ruby_rails_best_practices_options = | call ale#Set('ruby_rails_best_practices_options', '') | ||||||
| \   get(g:, 'ale_ruby_rails_best_practices_options', '') | call ale#Set('ruby_rails_best_practices_executable', 'rails_best_practices') | ||||||
|  |  | ||||||
| function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort | function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort | ||||||
|     let l:output = [] |     let l:output = [] | ||||||
| @ -22,8 +22,12 @@ function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort | |||||||
|     return l:output |     return l:output | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#ruby#rails_best_practices#GetExecutable(buffer) abort | ||||||
|  |     return ale#Var(a:buffer, 'ruby_rails_best_practices_executable') | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| function! ale_linters#ruby#rails_best_practices#GetCommand(buffer) abort | function! ale_linters#ruby#rails_best_practices#GetCommand(buffer) abort | ||||||
|     let l:executable = ale#handlers#rails_best_practices#GetExecutable(a:buffer) |     let l:executable = ale_linters#ruby#rails_best_practices#GetExecutable(a:buffer) | ||||||
|     let l:exec_args = l:executable =~? 'bundle$' |     let l:exec_args = l:executable =~? 'bundle$' | ||||||
|     \   ? ' exec rails_best_practices' |     \   ? ' exec rails_best_practices' | ||||||
|     \   : '' |     \   : '' | ||||||
| @ -46,7 +50,7 @@ endfunction | |||||||
|  |  | ||||||
| call ale#linter#Define('ruby', { | call ale#linter#Define('ruby', { | ||||||
| \    'name': 'rails_best_practices', | \    'name': 'rails_best_practices', | ||||||
| \    'executable_callback': 'ale#handlers#rails_best_practices#GetExecutable', | \    'executable_callback': 'ale_linters#ruby#rails_best_practices#GetExecutable', | ||||||
| \    'command_callback': 'ale_linters#ruby#rails_best_practices#GetCommand', | \    'command_callback': 'ale_linters#ruby#rails_best_practices#GetCommand', | ||||||
| \    'callback': 'ale_linters#ruby#rails_best_practices#Handle', | \    'callback': 'ale_linters#ruby#rails_best_practices#Handle', | ||||||
| \    'lint_file': 1, | \    'lint_file': 1, | ||||||
|  | |||||||
| @ -30,6 +30,5 @@ call ale#linter#Define('rust', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#rust#rls#GetExecutable', | \   'executable_callback': 'ale_linters#rust#rls#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#rust#rls#GetCommand', | \   'command_callback': 'ale_linters#rust#rls#GetCommand', | ||||||
| \   'language': 'rust', |  | ||||||
| \   'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot', | \   'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| " Author: Kevin Kays - https://github.com/okkays | " Author: Kevin Kays - https://github.com/okkays | ||||||
| " Description: Support for the scalastyle checker. | " Description: Support for the scalastyle checker. | ||||||
|  |  | ||||||
| let g:ale_scala_scalastyle_options = | call ale#Set('scala_scalastyle_options', '') | ||||||
| \   get(g:, 'ale_scala_scalastyle_options', '') | " TODO: Remove support for the old option name in ALE 3.0. | ||||||
|  | call ale#Set('scala_scalastyle_config', | ||||||
| let g:ale_scalastyle_config_loc = |  | ||||||
| \   get(g:, 'ale_scalastyle_config_loc', '') | \   get(g:, 'ale_scalastyle_config_loc', '') | ||||||
|  | \) | ||||||
|  |  | ||||||
| function! ale_linters#scala#scalastyle#Handle(buffer, lines) abort | function! ale_linters#scala#scalastyle#Handle(buffer, lines) abort | ||||||
|     " Look for help output from scalastyle first, which indicates that no |     " Look for help output from scalastyle first, which indicates that no | ||||||
| @ -66,23 +66,13 @@ function! ale_linters#scala#scalastyle#GetCommand(buffer) abort | |||||||
|  |  | ||||||
|     " If all else fails, try the global config. |     " If all else fails, try the global config. | ||||||
|     if empty(l:scalastyle_config) |     if empty(l:scalastyle_config) | ||||||
|         let l:scalastyle_config = get(g:, 'ale_scalastyle_config_loc', '') |         let l:scalastyle_config = ale#Var(a:buffer, 'scala_scalastyle_config') | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     " Build the command using the config file and additional options. |     return 'scalastyle' | ||||||
|     let l:command = 'scalastyle' |     \ . (!empty(l:scalastyle_config) ? ' --config ' . ale#Escape(l:scalastyle_config) : '') | ||||||
|  |     \ . ale#Pad(ale#Var(a:buffer, 'scala_scalastyle_options')) | ||||||
|     if !empty(l:scalastyle_config) |     \ . ' %t' | ||||||
|         let l:command .= ' --config ' . ale#Escape(l:scalastyle_config) |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     if !empty(g:ale_scala_scalastyle_options) |  | ||||||
|         let l:command .= ' ' . g:ale_scala_scalastyle_options |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     let l:command .= ' %t' |  | ||||||
|  |  | ||||||
|     return l:command |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| call ale#linter#Define('scala', { | call ale#linter#Define('scala', { | ||||||
|  | |||||||
| @ -28,6 +28,5 @@ call ale#linter#Define('sh', { | |||||||
| \   'lsp': 'stdio', | \   'lsp': 'stdio', | ||||||
| \   'executable_callback': 'ale_linters#sh#language_server#GetExecutable', | \   'executable_callback': 'ale_linters#sh#language_server#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#sh#language_server#GetCommand', | \   'command_callback': 'ale_linters#sh#language_server#GetCommand', | ||||||
| \   'language': 'sh', |  | ||||||
| \   'project_root_callback': 'ale_linters#sh#language_server#GetProjectRoot', | \   'project_root_callback': 'ale_linters#sh#language_server#GetProjectRoot', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -20,14 +20,12 @@ function! ale_linters#thrift#thrift#GetCommand(buffer) abort | |||||||
|         let l:generators = ['cpp'] |         let l:generators = ['cpp'] | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     let l:output_dir = tempname() |     let l:output_dir = ale#engine#CreateDirectory(a:buffer) | ||||||
|     call mkdir(l:output_dir) |  | ||||||
|     call ale#engine#ManageDirectory(a:buffer, l:output_dir) |  | ||||||
|  |  | ||||||
|     return ale#Escape(ale_linters#thrift#thrift#GetExecutable(a:buffer)) |     return ale#Escape(ale_linters#thrift#thrift#GetExecutable(a:buffer)) | ||||||
|     \   . ' ' . join(map(copy(l:generators), "'--gen ' . v:val")) |     \   . ale#Pad(join(map(copy(l:generators), "'--gen ' . v:val"))) | ||||||
|     \   . ' ' . join(map(copy(l:includes), "'-I ' . v:val")) |     \   . ale#Pad(join(map(copy(l:includes), "'-I ' . v:val"))) | ||||||
|     \   . ' ' . ale#Var(a:buffer, 'thrift_thrift_options') |     \   . ale#Pad(ale#Var(a:buffer, 'thrift_thrift_options')) | ||||||
|     \   . ' -out ' . ale#Escape(l:output_dir) |     \   . ' -out ' . ale#Escape(l:output_dir) | ||||||
|     \   . ' %t' |     \   . ' %t' | ||||||
| endfunction | endfunction | ||||||
|  | |||||||
| @ -1,17 +1,7 @@ | |||||||
| " Author: Prashanth Chandra <https://github.com/prashcr>, Jonathan Clem <https://jclem.net> | " Author: Prashanth Chandra <https://github.com/prashcr>, Jonathan Clem <https://jclem.net> | ||||||
| " Description: tslint for TypeScript files | " Description: tslint for TypeScript files | ||||||
|  |  | ||||||
| call ale#Set('typescript_tslint_executable', 'tslint') | call ale#handlers#tslint#InitVariables() | ||||||
| call ale#Set('typescript_tslint_config_path', '') |  | ||||||
| call ale#Set('typescript_tslint_rules_dir', '') |  | ||||||
| call ale#Set('typescript_tslint_use_global', get(g:, 'ale_use_global_executables', 0)) |  | ||||||
| call ale#Set('typescript_tslint_ignore_empty_files', 0) |  | ||||||
|  |  | ||||||
| function! ale_linters#typescript#tslint#GetExecutable(buffer) abort |  | ||||||
|     return ale#node#FindExecutable(a:buffer, 'typescript_tslint', [ |  | ||||||
|     \   'node_modules/.bin/tslint', |  | ||||||
|     \]) |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| function! ale_linters#typescript#tslint#Handle(buffer, lines) abort | function! ale_linters#typescript#tslint#Handle(buffer, lines) abort | ||||||
|     " Do not output any errors for empty files if the option is on. |     " Do not output any errors for empty files if the option is on. | ||||||
| @ -70,7 +60,7 @@ function! ale_linters#typescript#tslint#GetCommand(buffer) abort | |||||||
|     \  : '' |     \  : '' | ||||||
|  |  | ||||||
|     return ale#path#BufferCdString(a:buffer) |     return ale#path#BufferCdString(a:buffer) | ||||||
|     \   . ale#Escape(ale_linters#typescript#tslint#GetExecutable(a:buffer)) |     \   . ale#Escape(ale#handlers#tslint#GetExecutable(a:buffer)) | ||||||
|     \   . ' --format json' |     \   . ' --format json' | ||||||
|     \   . l:tslint_config_option |     \   . l:tslint_config_option | ||||||
|     \   . l:tslint_rules_option |     \   . l:tslint_rules_option | ||||||
| @ -79,7 +69,7 @@ endfunction | |||||||
|  |  | ||||||
| call ale#linter#Define('typescript', { | call ale#linter#Define('typescript', { | ||||||
| \   'name': 'tslint', | \   'name': 'tslint', | ||||||
| \   'executable_callback': 'ale_linters#typescript#tslint#GetExecutable', | \   'executable_callback': 'ale#handlers#tslint#GetExecutable', | ||||||
| \   'command_callback': 'ale_linters#typescript#tslint#GetCommand', | \   'command_callback': 'ale_linters#typescript#tslint#GetCommand', | ||||||
| \   'callback': 'ale_linters#typescript#tslint#Handle', | \   'callback': 'ale_linters#typescript#tslint#Handle', | ||||||
| \}) | \}) | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ if !exists('g:ale_verilog_verilator_options') | |||||||
| endif | endif | ||||||
|  |  | ||||||
| function! ale_linters#verilog#verilator#GetCommand(buffer) abort | function! ale_linters#verilog#verilator#GetCommand(buffer) abort | ||||||
|     let l:filename = tempname() . '_verilator_linted.v' |     let l:filename = ale#util#Tempname() . '_verilator_linted.v' | ||||||
|  |  | ||||||
|     " Create a special filename, so we can detect it in the handler. |     " Create a special filename, so we can detect it in the handler. | ||||||
|     call ale#engine#ManageFile(a:buffer, l:filename) |     call ale#engine#ManageFile(a:buffer, l:filename) | ||||||
|  | |||||||
							
								
								
									
										32
									
								
								sources_non_forked/ale/ale_linters/vue/vls.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								sources_non_forked/ale/ale_linters/vue/vls.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | " Author: Alexander Olofsson <alexander.olofsson@liu.se> | ||||||
|  | " Description: Vue vls Language Server integration for ALE | ||||||
|  |  | ||||||
|  | call ale#Set('vue_vls_executable', 'vls') | ||||||
|  | call ale#Set('vue_vls_use_global', get(g:, 'ale_use_global_executables', 0)) | ||||||
|  |  | ||||||
|  | function! ale_linters#vue#vls#GetExecutable(buffer) abort | ||||||
|  |     return ale#node#FindExecutable(a:buffer, 'vue_vls', [ | ||||||
|  |     \   'node_modules/.bin/vls', | ||||||
|  |     \]) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#vue#vls#GetCommand(buffer) abort | ||||||
|  |     let l:exe = ale#Escape(ale_linters#vue#vls#GetExecutable(a:buffer)) | ||||||
|  |  | ||||||
|  |     return l:exe . ' --stdio' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale_linters#vue#vls#GetProjectRoot(buffer) abort | ||||||
|  |     let l:package_path = ale#path#FindNearestFile(a:buffer, 'package.json') | ||||||
|  |  | ||||||
|  |     return !empty(l:package_path) ? fnamemodify(l:package_path, ':h') : '' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | call ale#linter#Define('vue', { | ||||||
|  | \   'name': 'vls', | ||||||
|  | \   'lsp': 'stdio', | ||||||
|  | \   'executable_callback': 'ale_linters#vue#vls#GetExecutable', | ||||||
|  | \   'command_callback': 'ale_linters#vue#vls#GetCommand', | ||||||
|  | \   'language': 'vue', | ||||||
|  | \   'project_root_callback': 'ale_linters#vue#vls#GetProjectRoot', | ||||||
|  | \}) | ||||||
| @ -11,7 +11,7 @@ endfunction | |||||||
|  |  | ||||||
| function! ale_linters#xml#xmllint#GetCommand(buffer) abort | function! ale_linters#xml#xmllint#GetCommand(buffer) abort | ||||||
|     return ale#Escape(ale_linters#xml#xmllint#GetExecutable(a:buffer)) |     return ale#Escape(ale_linters#xml#xmllint#GetExecutable(a:buffer)) | ||||||
|     \   . ' ' . ale#Var(a:buffer, 'xml_xmllint_options') |     \   . ale#Pad(ale#Var(a:buffer, 'xml_xmllint_options')) | ||||||
|     \   . ' --noout -' |     \   . ' --noout -' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | |||||||
| @ -191,15 +191,12 @@ endfunction | |||||||
| " | " | ||||||
| " Every variable name will be prefixed with 'ale_'. | " Every variable name will be prefixed with 'ale_'. | ||||||
| function! ale#Var(buffer, variable_name) abort | function! ale#Var(buffer, variable_name) abort | ||||||
|     let l:nr = str2nr(a:buffer) |  | ||||||
|     let l:full_name = 'ale_' . a:variable_name |     let l:full_name = 'ale_' . a:variable_name | ||||||
|  |     let l:vars = getbufvar(str2nr(a:buffer), '', 0) | ||||||
|  |  | ||||||
|     if bufexists(l:nr) |     if l:vars is 0 | ||||||
|         let l:vars = getbufvar(l:nr, '') |         " Look for variables from deleted buffers, saved from :ALEFix | ||||||
|     elseif has_key(g:, 'ale_fix_buffer_data') |         let l:vars = get(get(g:ale_fix_buffer_data, a:buffer, {}), 'vars', {}) | ||||||
|         let l:vars = get(g:ale_fix_buffer_data, l:nr, {'vars': {}}).vars |  | ||||||
|     else |  | ||||||
|         let l:vars = {} |  | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     return get(l:vars, l:full_name, g:[l:full_name]) |     return get(l:vars, l:full_name, g:[l:full_name]) | ||||||
| @ -210,10 +207,29 @@ endfunction | |||||||
| " Every variable name will be prefixed with 'ale_'. | " Every variable name will be prefixed with 'ale_'. | ||||||
| function! ale#Set(variable_name, default) abort | function! ale#Set(variable_name, default) abort | ||||||
|     let l:full_name = 'ale_' . a:variable_name |     let l:full_name = 'ale_' . a:variable_name | ||||||
|     let l:value = get(g:, l:full_name, a:default) |  | ||||||
|     let g:[l:full_name] = l:value |  | ||||||
|  |  | ||||||
|     return l:value |     if !has_key(g:, l:full_name) | ||||||
|  |         let g:[l:full_name] = a:default | ||||||
|  |     endif | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " Given a string for adding to a command, return the string padded with a | ||||||
|  | " space on the left if it is not empty. Otherwise return an empty string. | ||||||
|  | " | ||||||
|  | " This can be used for making command strings cleaner and easier to test. | ||||||
|  | function! ale#Pad(string) abort | ||||||
|  |     return !empty(a:string) ? ' ' . a:string : '' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " Given a environment variable name and a value, produce part of a command for | ||||||
|  | " setting an environment variable before running a command. The syntax will be | ||||||
|  | " valid for cmd on Windows, or most shells on Unix. | ||||||
|  | function! ale#Env(variable_name, value) abort | ||||||
|  |     if has('win32') | ||||||
|  |         return 'set ' . a:variable_name . '=' . ale#Escape(a:value) . ' && ' | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     return a:variable_name . '=' . ale#Escape(a:value) . ' ' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " Escape a string suitably for each platform. | " Escape a string suitably for each platform. | ||||||
|  | |||||||
							
								
								
									
										159
									
								
								sources_non_forked/ale/autoload/ale/assert.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								sources_non_forked/ale/autoload/ale/assert.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,159 @@ | |||||||
|  | let s:chain_results = [] | ||||||
|  |  | ||||||
|  | function! ale#assert#WithChainResults(...) abort | ||||||
|  |     let s:chain_results = a:000 | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:GetLinter() abort | ||||||
|  |     let l:linters = ale#linter#GetLintersLoaded() | ||||||
|  |     let l:filetype_linters = get(values(l:linters), 0, []) | ||||||
|  |  | ||||||
|  |     if len(l:linters) is 0 || len(l:filetype_linters) is 0 | ||||||
|  |         throw 'No linters were loaded' | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     if len(l:linters) > 1 || len(l:filetype_linters) > 1 | ||||||
|  |         throw 'More than one linter was loaded' | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     return l:filetype_linters[0] | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " Load the currently loaded linter for a test case, and check that the command | ||||||
|  | " matches the given string. | ||||||
|  | function! ale#assert#Linter(expected_executable, expected_command) abort | ||||||
|  |     let l:buffer = bufnr('') | ||||||
|  |     let l:linter = s:GetLinter() | ||||||
|  |     let l:executable = ale#linter#GetExecutable(l:buffer, l:linter) | ||||||
|  |  | ||||||
|  |     if has_key(l:linter, 'command_chain') | ||||||
|  |         let l:callbacks = map(copy(l:linter.command_chain), 'v:val.callback') | ||||||
|  |  | ||||||
|  |         " If the expected command is a string, just check the last one. | ||||||
|  |         if type(a:expected_command) is type('') | ||||||
|  |             if len(l:callbacks) is 1 | ||||||
|  |                 let l:command = call(l:callbacks[0], [l:buffer]) | ||||||
|  |             else | ||||||
|  |                 let l:input = get(s:chain_results, len(l:callbacks) - 2, []) | ||||||
|  |                 let l:command = call(l:callbacks[-1], [l:buffer, l:input]) | ||||||
|  |             endif | ||||||
|  |         else | ||||||
|  |             let l:command = [] | ||||||
|  |             let l:chain_index = 0 | ||||||
|  |  | ||||||
|  |             for l:Callback in l:callbacks | ||||||
|  |                 if l:chain_index is 0 | ||||||
|  |                     call add(l:command, call(l:Callback, [l:buffer])) | ||||||
|  |                 else | ||||||
|  |                     let l:input = get(s:chain_results, l:chain_index - 1, []) | ||||||
|  |                     call add(l:command, call(l:Callback, [l:buffer, l:input])) | ||||||
|  |                 endif | ||||||
|  |  | ||||||
|  |                 let l:chain_index += 1 | ||||||
|  |             endfor | ||||||
|  |         endif | ||||||
|  |     else | ||||||
|  |         let l:command = ale#linter#GetCommand(l:buffer, l:linter) | ||||||
|  |         " Replace %e with the escaped executable, so tests keep passing after | ||||||
|  |         " linters are changed to use %e. | ||||||
|  |         let l:command = substitute(l:command, '%e', '\=ale#Escape(l:executable)', 'g') | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     AssertEqual | ||||||
|  |     \   [a:expected_executable, a:expected_command], | ||||||
|  |     \   [l:executable, l:command] | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale#assert#LinterNotExecuted() abort | ||||||
|  |     let l:buffer = bufnr('') | ||||||
|  |     let l:linter = s:GetLinter() | ||||||
|  |     let l:executable = ale#linter#GetExecutable(l:buffer, l:linter) | ||||||
|  |  | ||||||
|  |     Assert empty(l:executable), "The linter will be executed when it shouldn't be" | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale#assert#LSPOptions(expected_options) abort | ||||||
|  |     let l:buffer = bufnr('') | ||||||
|  |     let l:linter = s:GetLinter() | ||||||
|  |     let l:initialization_options = ale#lsp_linter#GetOptions(l:buffer, l:linter) | ||||||
|  |  | ||||||
|  |     AssertEqual a:expected_options, l:initialization_options | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale#assert#LSPLanguage(expected_language) abort | ||||||
|  |     let l:buffer = bufnr('') | ||||||
|  |     let l:linter = s:GetLinter() | ||||||
|  |     let l:language = ale#util#GetFunction(l:linter.language_callback)(l:buffer) | ||||||
|  |  | ||||||
|  |     AssertEqual a:expected_language, l:language | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale#assert#LSPProject(expected_root) abort | ||||||
|  |     let l:buffer = bufnr('') | ||||||
|  |     let l:linter = s:GetLinter() | ||||||
|  |     let l:root = ale#util#GetFunction(l:linter.project_root_callback)(l:buffer) | ||||||
|  |  | ||||||
|  |     AssertEqual a:expected_root, l:root | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " A dummy function for making sure this module is loaded. | ||||||
|  | function! ale#assert#SetUpLinterTest(filetype, name) abort | ||||||
|  |     " Set up a marker so ALE doesn't create real random temporary filenames. | ||||||
|  |     let g:ale_create_dummy_temporary_file = 1 | ||||||
|  |  | ||||||
|  |     " Remove current linters. | ||||||
|  |     call ale#linter#Reset() | ||||||
|  |     call ale#linter#PreventLoading(a:filetype) | ||||||
|  |  | ||||||
|  |     let l:prefix = 'ale_' . a:filetype . '_' . a:name | ||||||
|  |     let b:filter_expr = 'v:val[: len(l:prefix) - 1] is# l:prefix' | ||||||
|  |  | ||||||
|  |     Save g:ale_c_build_dir | ||||||
|  |     unlet! g:ale_c_build_dir | ||||||
|  |  | ||||||
|  |     " Save and clear linter variables. | ||||||
|  |     " We'll load the runtime file to reset them to defaults. | ||||||
|  |     for l:key in filter(keys(g:), b:filter_expr) | ||||||
|  |         execute 'Save g:' . l:key | ||||||
|  |         unlet g:[l:key] | ||||||
|  |     endfor | ||||||
|  |  | ||||||
|  |     unlet! b:ale_c_build_dir | ||||||
|  |  | ||||||
|  |     for l:key in filter(keys(b:), b:filter_expr) | ||||||
|  |         unlet b:[l:key] | ||||||
|  |     endfor | ||||||
|  |  | ||||||
|  |     execute 'runtime ale_linters/' . a:filetype . '/' . a:name . '.vim' | ||||||
|  |  | ||||||
|  |     call ale#test#SetDirectory('/testplugin/test/command_callback') | ||||||
|  |  | ||||||
|  |     command! -nargs=+ WithChainResults :call ale#assert#WithChainResults(<args>) | ||||||
|  |     command! -nargs=+ AssertLinter :call ale#assert#Linter(<args>) | ||||||
|  |     command! -nargs=0 AssertLinterNotExecuted :call ale#assert#LinterNotExecuted() | ||||||
|  |     command! -nargs=+ AssertLSPOptions :call ale#assert#LSPOptions(<args>) | ||||||
|  |     command! -nargs=+ AssertLSPLanguage :call ale#assert#LSPLanguage(<args>) | ||||||
|  |     command! -nargs=+ AssertLSPProject :call ale#assert#LSPProject(<args>) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale#assert#TearDownLinterTest() abort | ||||||
|  |     unlet! g:ale_create_dummy_temporary_file | ||||||
|  |     let s:chain_results = [] | ||||||
|  |  | ||||||
|  |     delcommand WithChainResults | ||||||
|  |     delcommand AssertLinter | ||||||
|  |     delcommand AssertLinterNotExecuted | ||||||
|  |     delcommand AssertLSPOptions | ||||||
|  |     delcommand AssertLSPLanguage | ||||||
|  |     delcommand AssertLSPProject | ||||||
|  |  | ||||||
|  |     call ale#test#RestoreDirectory() | ||||||
|  |  | ||||||
|  |     Restore | ||||||
|  |  | ||||||
|  |     call ale#linter#Reset() | ||||||
|  |  | ||||||
|  |     if exists('*ale#semver#ResetVersionCache') | ||||||
|  |         call ale#semver#ResetVersionCache() | ||||||
|  |     endif | ||||||
|  | endfunction | ||||||
| @ -13,14 +13,14 @@ function! s:TemporaryFilename(buffer) abort | |||||||
|  |  | ||||||
|     " Create a temporary filename, <temp_dir>/<original_basename> |     " Create a temporary filename, <temp_dir>/<original_basename> | ||||||
|     " The file itself will not be created by this function. |     " The file itself will not be created by this function. | ||||||
|     return tempname() . (has('win32') ? '\' : '/') . l:filename |     return ale#util#Tempname() . (has('win32') ? '\' : '/') . l:filename | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " Given a command string, replace every... | " Given a command string, replace every... | ||||||
| " %s -> with the current filename | " %s -> with the current filename | ||||||
| " %t -> with the name of an unused file in a temporary directory | " %t -> with the name of an unused file in a temporary directory | ||||||
| " %% -> with a literal % | " %% -> with a literal % | ||||||
| function! ale#command#FormatCommand(buffer, command, pipe_file_if_needed) abort | function! ale#command#FormatCommand(buffer, executable, command, pipe_file_if_needed) abort | ||||||
|     let l:temporary_file = '' |     let l:temporary_file = '' | ||||||
|     let l:command = a:command |     let l:command = a:command | ||||||
|  |  | ||||||
| @ -28,6 +28,11 @@ function! ale#command#FormatCommand(buffer, command, pipe_file_if_needed) abort | |||||||
|     " with an ugly string. |     " with an ugly string. | ||||||
|     let l:command = substitute(l:command, '%%', '<<PERCENTS>>', 'g') |     let l:command = substitute(l:command, '%%', '<<PERCENTS>>', 'g') | ||||||
|  |  | ||||||
|  |     " Replace %e with the escaped executable, if available. | ||||||
|  |     if !empty(a:executable) && l:command =~# '%e' | ||||||
|  |         let l:command = substitute(l:command, '%e', '\=ale#Escape(a:executable)', 'g') | ||||||
|  |     endif | ||||||
|  |  | ||||||
|     " Replace all %s occurrences in the string with the name of the current |     " Replace all %s occurrences in the string with the name of the current | ||||||
|     " file. |     " file. | ||||||
|     if l:command =~# '%s' |     if l:command =~# '%s' | ||||||
|  | |||||||
| @ -1,6 +1,17 @@ | |||||||
| " Author: w0rp <devw0rp@gmail.com> | " Author: w0rp <devw0rp@gmail.com> | ||||||
| " Description: Completion support for LSP linters | " Description: Completion support for LSP linters | ||||||
|  |  | ||||||
|  | " The omnicompletion menu is shown through a special Plug mapping which is | ||||||
|  | " only valid in Insert mode. This way, feedkeys() won't send these keys if you | ||||||
|  | " quit Insert mode quickly enough. | ||||||
|  | inoremap <silent> <Plug>(ale_show_completion_menu) <C-x><C-o> | ||||||
|  | " If we hit the key sequence in normal mode, then we won't show the menu, so | ||||||
|  | " we should restore the old settings right away. | ||||||
|  | nnoremap <silent> <Plug>(ale_show_completion_menu) :call ale#completion#RestoreCompletionOptions()<CR> | ||||||
|  | cnoremap <silent> <Plug>(ale_show_completion_menu) <Nop> | ||||||
|  | vnoremap <silent> <Plug>(ale_show_completion_menu) <Nop> | ||||||
|  | onoremap <silent> <Plug>(ale_show_completion_menu) <Nop> | ||||||
|  |  | ||||||
| let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100) | let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100) | ||||||
| let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', []) | let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', []) | ||||||
| let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50) | let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50) | ||||||
| @ -129,7 +140,16 @@ function! ale#completion#Filter(buffer, suggestions, prefix) abort | |||||||
|     return l:filtered_suggestions |     return l:filtered_suggestions | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:ReplaceCompleteopt() abort | function! s:ReplaceCompletionOptions() abort | ||||||
|  |     " Remember the old omnifunc value, if there is one. | ||||||
|  |     " If we don't store an old one, we'll just never reset the option. | ||||||
|  |     " This will stop some random exceptions from appearing. | ||||||
|  |     if !exists('b:ale_old_omnifunc') && !empty(&l:omnifunc) | ||||||
|  |         let b:ale_old_omnifunc = &l:omnifunc | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let &l:omnifunc = 'ale#completion#OmniFunc' | ||||||
|  |  | ||||||
|     if !exists('b:ale_old_completopt') |     if !exists('b:ale_old_completopt') | ||||||
|         let b:ale_old_completopt = &l:completeopt |         let b:ale_old_completopt = &l:completeopt | ||||||
|     endif |     endif | ||||||
| @ -141,6 +161,22 @@ function! s:ReplaceCompleteopt() abort | |||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! ale#completion#RestoreCompletionOptions() abort | ||||||
|  |     " Reset settings when completion is done. | ||||||
|  |     if exists('b:ale_old_omnifunc') | ||||||
|  |         if b:ale_old_omnifunc isnot# 'pythoncomplete#Complete' | ||||||
|  |             let &l:omnifunc = b:ale_old_omnifunc | ||||||
|  |         endif | ||||||
|  |  | ||||||
|  |         unlet b:ale_old_omnifunc | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     if exists('b:ale_old_completopt') | ||||||
|  |         let &l:completeopt = b:ale_old_completopt | ||||||
|  |         unlet b:ale_old_completopt | ||||||
|  |     endif | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| function! ale#completion#OmniFunc(findstart, base) abort | function! ale#completion#OmniFunc(findstart, base) abort | ||||||
|     if a:findstart |     if a:findstart | ||||||
|         let l:line = b:ale_completion_info.line |         let l:line = b:ale_completion_info.line | ||||||
| @ -163,33 +199,30 @@ function! ale#completion#OmniFunc(findstart, base) abort | |||||||
|             let b:ale_completion_result = function(l:parser)(l:response) |             let b:ale_completion_result = function(l:parser)(l:response) | ||||||
|         endif |         endif | ||||||
|  |  | ||||||
|         call s:ReplaceCompleteopt() |         call s:ReplaceCompletionOptions() | ||||||
|  |  | ||||||
|         return get(b:, 'ale_completion_result', []) |         return get(b:, 'ale_completion_result', []) | ||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#completion#Show(response, completion_parser) abort | function! ale#completion#Show(response, completion_parser) abort | ||||||
|     " Remember the old omnifunc value, if there is one. |     if ale#util#Mode() isnot# 'i' | ||||||
|     " If we don't store an old one, we'll just never reset the option. |         return | ||||||
|     " This will stop some random exceptions from appearing. |  | ||||||
|     if !exists('b:ale_old_omnifunc') && !empty(&l:omnifunc) |  | ||||||
|         let b:ale_old_omnifunc = &l:omnifunc |  | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     " Set the list in the buffer, temporarily replace omnifunc with our |     " Set the list in the buffer, temporarily replace omnifunc with our | ||||||
|     " function, and then start omni-completion. |     " function, and then start omni-completion. | ||||||
|     let b:ale_completion_response = a:response |     let b:ale_completion_response = a:response | ||||||
|     let b:ale_completion_parser = a:completion_parser |     let b:ale_completion_parser = a:completion_parser | ||||||
|     let &l:omnifunc = 'ale#completion#OmniFunc' |     call s:ReplaceCompletionOptions() | ||||||
|     call s:ReplaceCompleteopt() |     call ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)") | ||||||
|     call ale#util#FeedKeys("\<C-x>\<C-o>", 'n') |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:CompletionStillValid(request_id) abort | function! s:CompletionStillValid(request_id) abort | ||||||
|     let [l:line, l:column] = getcurpos()[1:2] |     let [l:line, l:column] = getcurpos()[1:2] | ||||||
|  |  | ||||||
|     return has_key(b:, 'ale_completion_info') |     return ale#util#Mode() is# 'i' | ||||||
|  |     \&& has_key(b:, 'ale_completion_info') | ||||||
|     \&& b:ale_completion_info.request_id == a:request_id |     \&& b:ale_completion_info.request_id == a:request_id | ||||||
|     \&& b:ale_completion_info.line == l:line |     \&& b:ale_completion_info.line == l:line | ||||||
|     \&& b:ale_completion_info.column == l:column |     \&& b:ale_completion_info.column == l:column | ||||||
| @ -477,7 +510,7 @@ function! s:TimerHandler(...) abort | |||||||
|  |  | ||||||
|     " When running the timer callback, we have to be sure that the cursor |     " When running the timer callback, we have to be sure that the cursor | ||||||
|     " hasn't moved from where it was when we requested completions by typing. |     " hasn't moved from where it was when we requested completions by typing. | ||||||
|     if s:timer_pos == [l:line, l:column] |     if s:timer_pos == [l:line, l:column] && ale#util#Mode() is# 'i' | ||||||
|         call ale#completion#GetCompletions() |         call ale#completion#GetCompletions() | ||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
| @ -518,19 +551,7 @@ endfunction | |||||||
| function! ale#completion#Done() abort | function! ale#completion#Done() abort | ||||||
|     silent! pclose |     silent! pclose | ||||||
|  |  | ||||||
|     " Reset settings when completion is done. |     call ale#completion#RestoreCompletionOptions() | ||||||
|     if exists('b:ale_old_omnifunc') |  | ||||||
|         if b:ale_old_omnifunc isnot# 'pythoncomplete#Complete' |  | ||||||
|             let &l:omnifunc = b:ale_old_omnifunc |  | ||||||
|         endif |  | ||||||
|  |  | ||||||
|         unlet b:ale_old_omnifunc |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     if exists('b:ale_old_completopt') |  | ||||||
|         let &l:completeopt = b:ale_old_completopt |  | ||||||
|         unlet b:ale_old_completopt |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     let s:last_done_pos = getcurpos()[1:2] |     let s:last_done_pos = getcurpos()[1:2] | ||||||
| endfunction | endfunction | ||||||
|  | |||||||
| @ -96,9 +96,26 @@ function! ale#engine#ManageDirectory(buffer, directory) abort | |||||||
|     call add(g:ale_buffer_info[a:buffer].temporary_directory_list, a:directory) |     call add(g:ale_buffer_info[a:buffer].temporary_directory_list, a:directory) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! ale#engine#CreateFile(buffer) abort | ||||||
|  |     " This variable can be set to 1 in tests to stub this out. | ||||||
|  |     if get(g:, 'ale_create_dummy_temporary_file') | ||||||
|  |         return 'TEMP' | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let l:temporary_file = ale#util#Tempname() | ||||||
|  |     call ale#engine#ManageFile(a:buffer, l:temporary_file) | ||||||
|  |  | ||||||
|  |     return l:temporary_file | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| " Create a new temporary directory and manage it in one go. | " Create a new temporary directory and manage it in one go. | ||||||
| function! ale#engine#CreateDirectory(buffer) abort | function! ale#engine#CreateDirectory(buffer) abort | ||||||
|     let l:temporary_directory = tempname() |     " This variable can be set to 1 in tests to stub this out. | ||||||
|  |     if get(g:, 'ale_create_dummy_temporary_file') | ||||||
|  |         return 'TEMP_DIR' | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let l:temporary_directory = ale#util#Tempname() | ||||||
|     " Create the temporary directory for the file, unreadable by 'other' |     " Create the temporary directory for the file, unreadable by 'other' | ||||||
|     " users. |     " users. | ||||||
|     call mkdir(l:temporary_directory, '', 0750) |     call mkdir(l:temporary_directory, '', 0750) | ||||||
| @ -189,6 +206,7 @@ function! s:HandleExit(job_id, exit_code) abort | |||||||
|     let l:linter = l:job_info.linter |     let l:linter = l:job_info.linter | ||||||
|     let l:output = l:job_info.output |     let l:output = l:job_info.output | ||||||
|     let l:buffer = l:job_info.buffer |     let l:buffer = l:job_info.buffer | ||||||
|  |     let l:executable = l:job_info.executable | ||||||
|     let l:next_chain_index = l:job_info.next_chain_index |     let l:next_chain_index = l:job_info.next_chain_index | ||||||
|  |  | ||||||
|     if g:ale_history_enabled |     if g:ale_history_enabled | ||||||
| @ -212,7 +230,7 @@ function! s:HandleExit(job_id, exit_code) abort | |||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     if l:next_chain_index < len(get(l:linter, 'command_chain', [])) |     if l:next_chain_index < len(get(l:linter, 'command_chain', [])) | ||||||
|         call s:InvokeChain(l:buffer, l:linter, l:next_chain_index, l:output) |         call s:InvokeChain(l:buffer, l:executable, l:linter, l:next_chain_index, l:output) | ||||||
|         return |         return | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
| @ -221,7 +239,12 @@ function! s:HandleExit(job_id, exit_code) abort | |||||||
|         call ale#history#RememberOutput(l:buffer, a:job_id, l:output[:]) |         call ale#history#RememberOutput(l:buffer, a:job_id, l:output[:]) | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output) |     try | ||||||
|  |         let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output) | ||||||
|  |     " Handle the function being unknown, or being deleted. | ||||||
|  |     catch /E700/ | ||||||
|  |         let l:loclist = [] | ||||||
|  |     endtry | ||||||
|  |  | ||||||
|     call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist) |     call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist) | ||||||
| endfunction | endfunction | ||||||
| @ -440,6 +463,12 @@ endfunction | |||||||
| " Returns 1 when the job was started successfully. | " Returns 1 when the job was started successfully. | ||||||
| function! s:RunJob(options) abort | function! s:RunJob(options) abort | ||||||
|     let l:command = a:options.command |     let l:command = a:options.command | ||||||
|  |  | ||||||
|  |     if empty(l:command) | ||||||
|  |         return 0 | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let l:executable = a:options.executable | ||||||
|     let l:buffer = a:options.buffer |     let l:buffer = a:options.buffer | ||||||
|     let l:linter = a:options.linter |     let l:linter = a:options.linter | ||||||
|     let l:output_stream = a:options.output_stream |     let l:output_stream = a:options.output_stream | ||||||
| @ -447,11 +476,12 @@ function! s:RunJob(options) abort | |||||||
|     let l:read_buffer = a:options.read_buffer |     let l:read_buffer = a:options.read_buffer | ||||||
|     let l:info = g:ale_buffer_info[l:buffer] |     let l:info = g:ale_buffer_info[l:buffer] | ||||||
|  |  | ||||||
|     if empty(l:command) |     let [l:temporary_file, l:command] = ale#command#FormatCommand( | ||||||
|         return 0 |     \   l:buffer, | ||||||
|     endif |     \   l:executable, | ||||||
|  |     \   l:command, | ||||||
|     let [l:temporary_file, l:command] = ale#command#FormatCommand(l:buffer, l:command, l:read_buffer) |     \   l:read_buffer, | ||||||
|  |     \) | ||||||
|  |  | ||||||
|     if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file) |     if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file) | ||||||
|         " If a temporary filename has been formatted in to the command, then |         " If a temporary filename has been formatted in to the command, then | ||||||
| @ -512,6 +542,7 @@ function! s:RunJob(options) abort | |||||||
|         let s:job_info_map[l:job_id] = { |         let s:job_info_map[l:job_id] = { | ||||||
|         \   'linter': l:linter, |         \   'linter': l:linter, | ||||||
|         \   'buffer': l:buffer, |         \   'buffer': l:buffer, | ||||||
|  |         \   'executable': l:executable, | ||||||
|         \   'output': [], |         \   'output': [], | ||||||
|         \   'next_chain_index': l:next_chain_index, |         \   'next_chain_index': l:next_chain_index, | ||||||
|         \} |         \} | ||||||
| @ -604,8 +635,9 @@ function! ale#engine#ProcessChain(buffer, linter, chain_index, input) abort | |||||||
|     \} |     \} | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:InvokeChain(buffer, linter, chain_index, input) abort | function! s:InvokeChain(buffer, executable, linter, chain_index, input) abort | ||||||
|     let l:options = ale#engine#ProcessChain(a:buffer, a:linter, a:chain_index, a:input) |     let l:options = ale#engine#ProcessChain(a:buffer, a:linter, a:chain_index, a:input) | ||||||
|  |     let l:options.executable = a:executable | ||||||
|  |  | ||||||
|     return s:RunJob(l:options) |     return s:RunJob(l:options) | ||||||
| endfunction | endfunction | ||||||
| @ -699,7 +731,7 @@ function! s:RunLinter(buffer, linter) abort | |||||||
|         let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) |         let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) | ||||||
|  |  | ||||||
|         if ale#engine#IsExecutable(a:buffer, l:executable) |         if ale#engine#IsExecutable(a:buffer, l:executable) | ||||||
|             return s:InvokeChain(a:buffer, a:linter, 0, []) |             return s:InvokeChain(a:buffer, l:executable, a:linter, 0, []) | ||||||
|         endif |         endif | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|  | |||||||
| @ -39,35 +39,48 @@ function! ale#events#SaveEvent(buffer) abort | |||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:LintOnEnter(buffer) abort | function! ale#events#LintOnEnter(buffer) abort | ||||||
|     if ale#Var(a:buffer, 'enabled') |     " Unmark a file as being changed outside of Vim after we try to check it. | ||||||
|     \&& g:ale_lint_on_enter |     call setbufvar(a:buffer, 'ale_file_changed', 0) | ||||||
|     \&& has_key(b:, 'ale_file_changed') |  | ||||||
|         call remove(b:, 'ale_file_changed') |     if ale#Var(a:buffer, 'enabled') && g:ale_lint_on_enter | ||||||
|         call ale#Queue(0, 'lint_file', a:buffer) |         call ale#Queue(0, 'lint_file', a:buffer) | ||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#events#EnterEvent(buffer) abort | function! ale#events#ReadOrEnterEvent(buffer) abort | ||||||
|  |     " Apply pattern options if the variable is set. | ||||||
|  |     if get(g:, 'ale_pattern_options_enabled', 1) | ||||||
|  |     \&& !empty(get(g:, 'ale_pattern_options')) | ||||||
|  |         call ale#pattern_options#SetOptions(a:buffer) | ||||||
|  |     endif | ||||||
|  |  | ||||||
|     " When entering a buffer, we are no longer quitting it. |     " When entering a buffer, we are no longer quitting it. | ||||||
|     call setbufvar(a:buffer, 'ale_quitting', 0) |     call setbufvar(a:buffer, 'ale_quitting', 0) | ||||||
|     let l:filetype = getbufvar(a:buffer, '&filetype') |     let l:filetype = getbufvar(a:buffer, '&filetype') | ||||||
|     call setbufvar(a:buffer, 'ale_original_filetype', l:filetype) |     call setbufvar(a:buffer, 'ale_original_filetype', l:filetype) | ||||||
|  |  | ||||||
|     call s:LintOnEnter(a:buffer) |     " If the file changed outside of Vim, check it on BufEnter,BufRead | ||||||
|  |     if getbufvar(a:buffer, 'ale_file_changed') | ||||||
|  |         call ale#events#LintOnEnter(a:buffer) | ||||||
|  |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#events#FileTypeEvent(buffer, new_filetype) abort | function! ale#events#FileTypeEvent(buffer, new_filetype) abort | ||||||
|     let l:filetype = getbufvar(a:buffer, 'ale_original_filetype', '') |     " The old filetype will be set to an empty string by the BuFEnter event, | ||||||
|  |     " and not linting when the old filetype hasn't been set yet prevents | ||||||
|  |     " buffers being checked when you enter them when linting on enter is off. | ||||||
|  |     let l:old_filetype = getbufvar(a:buffer, 'ale_original_filetype', v:null) | ||||||
|  |  | ||||||
|     " If we're setting the filetype for the first time after it was blank, |     if l:old_filetype isnot v:null | ||||||
|     " and the option for linting on enter is off, then we should set this |     \&& !empty(a:new_filetype) | ||||||
|     " filetype as the original filetype. Otherwise ALE will still appear to |     \&& a:new_filetype isnot# l:old_filetype | ||||||
|     " lint files because of the BufEnter event, etc. |         " Remember what the new filetype is. | ||||||
|     if empty(l:filetype) && !ale#Var(a:buffer, 'lint_on_enter') |  | ||||||
|         call setbufvar(a:buffer, 'ale_original_filetype', a:new_filetype) |         call setbufvar(a:buffer, 'ale_original_filetype', a:new_filetype) | ||||||
|     elseif a:new_filetype isnot# l:filetype |  | ||||||
|         call ale#Queue(300, 'lint_file', a:buffer) |         if g:ale_lint_on_filetype_changed | ||||||
|  |             call ale#Queue(300, 'lint_file', a:buffer) | ||||||
|  |         endif | ||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| @ -75,7 +88,7 @@ function! ale#events#FileChangedEvent(buffer) abort | |||||||
|     call setbufvar(a:buffer, 'ale_file_changed', 1) |     call setbufvar(a:buffer, 'ale_file_changed', 1) | ||||||
|  |  | ||||||
|     if bufnr('') == a:buffer |     if bufnr('') == a:buffer | ||||||
|         call s:LintOnEnter(a:buffer) |         call ale#events#LintOnEnter(a:buffer) | ||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| @ -87,7 +100,7 @@ function! ale#events#Init() abort | |||||||
|         autocmd! |         autocmd! | ||||||
|  |  | ||||||
|         " These events always need to be set up. |         " These events always need to be set up. | ||||||
|         autocmd BufEnter,BufRead * call ale#pattern_options#SetOptions(str2nr(expand('<abuf>'))) |         autocmd BufEnter,BufRead * call ale#events#ReadOrEnterEvent(str2nr(expand('<abuf>'))) | ||||||
|         autocmd BufWritePost * call ale#events#SaveEvent(str2nr(expand('<abuf>'))) |         autocmd BufWritePost * call ale#events#SaveEvent(str2nr(expand('<abuf>'))) | ||||||
|  |  | ||||||
|         if g:ale_enabled |         if g:ale_enabled | ||||||
| @ -99,11 +112,8 @@ function! ale#events#Init() abort | |||||||
|                 autocmd TextChangedI * call ale#Queue(g:ale_lint_delay) |                 autocmd TextChangedI * call ale#Queue(g:ale_lint_delay) | ||||||
|             endif |             endif | ||||||
|  |  | ||||||
|             " Handle everything that needs to happen when buffers are entered. |  | ||||||
|             autocmd BufEnter * call ale#events#EnterEvent(str2nr(expand('<abuf>'))) |  | ||||||
|  |  | ||||||
|             if g:ale_lint_on_enter |             if g:ale_lint_on_enter | ||||||
|                 autocmd BufWinEnter,BufRead * call ale#Queue(0, 'lint_file', str2nr(expand('<abuf>'))) |                 autocmd BufWinEnter * call ale#events#LintOnEnter(str2nr(expand('<abuf>'))) | ||||||
|                 " Track when the file is changed outside of Vim. |                 " Track when the file is changed outside of Vim. | ||||||
|                 autocmd FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand('<abuf>'))) |                 autocmd FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand('<abuf>'))) | ||||||
|             endif |             endif | ||||||
|  | |||||||
| @ -1,10 +1,3 @@ | |||||||
| " This global Dictionary tracks the ALE fix data for jobs, etc. |  | ||||||
| " This Dictionary should not be accessed outside of the plugin. It is only |  | ||||||
| " global so it can be modified in Vader tests. |  | ||||||
| if !has_key(g:, 'ale_fix_buffer_data') |  | ||||||
|     let g:ale_fix_buffer_data = {} |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| if !has_key(s:, 'job_info_map') | if !has_key(s:, 'job_info_map') | ||||||
|     let s:job_info_map = {} |     let s:job_info_map = {} | ||||||
| endif | endif | ||||||
| @ -219,6 +212,7 @@ function! s:RunJob(options) abort | |||||||
|  |  | ||||||
|     let [l:temporary_file, l:command] = ale#command#FormatCommand( |     let [l:temporary_file, l:command] = ale#command#FormatCommand( | ||||||
|     \   l:buffer, |     \   l:buffer, | ||||||
|  |     \   '', | ||||||
|     \   l:command, |     \   l:command, | ||||||
|     \   l:read_buffer, |     \   l:read_buffer, | ||||||
|     \) |     \) | ||||||
|  | |||||||
| @ -242,6 +242,9 @@ endfunction | |||||||
| " Add a function for fixing problems to the registry. | " Add a function for fixing problems to the registry. | ||||||
| " (name, func, filetypes, desc, aliases) | " (name, func, filetypes, desc, aliases) | ||||||
| function! ale#fix#registry#Add(name, func, filetypes, desc, ...) abort | function! ale#fix#registry#Add(name, func, filetypes, desc, ...) abort | ||||||
|  |     " This command will throw from the sandbox. | ||||||
|  |     let &equalprg=&equalprg | ||||||
|  |  | ||||||
|     if type(a:name) != type('') |     if type(a:name) != type('') | ||||||
|         throw '''name'' must be a String' |         throw '''name'' must be a String' | ||||||
|     endif |     endif | ||||||
|  | |||||||
| @ -2,9 +2,12 @@ | |||||||
| " Description: Fixing Python imports with isort. | " Description: Fixing Python imports with isort. | ||||||
|  |  | ||||||
| call ale#Set('python_isort_executable', 'isort') | call ale#Set('python_isort_executable', 'isort') | ||||||
|  | call ale#Set('python_isort_options', '') | ||||||
| call ale#Set('python_isort_use_global', get(g:, 'ale_use_global_executables', 0)) | call ale#Set('python_isort_use_global', get(g:, 'ale_use_global_executables', 0)) | ||||||
|  |  | ||||||
| function! ale#fixers#isort#Fix(buffer) abort | function! ale#fixers#isort#Fix(buffer) abort | ||||||
|  |     let l:options = ale#Var(a:buffer, 'python_isort_options') | ||||||
|  |  | ||||||
|     let l:executable = ale#python#FindExecutable( |     let l:executable = ale#python#FindExecutable( | ||||||
|     \   a:buffer, |     \   a:buffer, | ||||||
|     \   'python_isort', |     \   'python_isort', | ||||||
| @ -17,6 +20,6 @@ function! ale#fixers#isort#Fix(buffer) abort | |||||||
|  |  | ||||||
|     return { |     return { | ||||||
|     \   'command': ale#path#BufferCdString(a:buffer) |     \   'command': ale#path#BufferCdString(a:buffer) | ||||||
|     \   .   ale#Escape(l:executable) . ' -', |     \   .   ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '') . ' -', | ||||||
|     \} |     \} | ||||||
| endfunction | endfunction | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| " Description: Fixing files with tslint. | " Description: Fixing files with tslint. | ||||||
|  |  | ||||||
| function! ale#fixers#tslint#Fix(buffer) abort | function! ale#fixers#tslint#Fix(buffer) abort | ||||||
|     let l:executable = ale_linters#typescript#tslint#GetExecutable(a:buffer) |     let l:executable = ale#handlers#tslint#GetExecutable(a:buffer) | ||||||
|  |  | ||||||
|     let l:tslint_config_path = ale#path#ResolveLocalPath( |     let l:tslint_config_path = ale#path#ResolveLocalPath( | ||||||
|     \   a:buffer, |     \   a:buffer, | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| " Description: Error handling for the format GHC outputs. | " Description: Error handling for the format GHC outputs. | ||||||
|  |  | ||||||
| " Remember the directory used for temporary files for Vim. | " Remember the directory used for temporary files for Vim. | ||||||
| let s:temp_dir = fnamemodify(tempname(), ':h') | let s:temp_dir = fnamemodify(ale#util#Tempname(), ':h') | ||||||
| " Build part of a regular expression for matching ALE temporary filenames. | " Build part of a regular expression for matching ALE temporary filenames. | ||||||
| let s:temp_regex_prefix = | let s:temp_regex_prefix = | ||||||
| \   '\M' | \   '\M' | ||||||
|  | |||||||
| @ -1,6 +0,0 @@ | |||||||
| call ale#Set('ruby_rails_best_practices_options', '') |  | ||||||
| call ale#Set('ruby_rails_best_practices_executable', 'rails_best_practices') |  | ||||||
|  |  | ||||||
| function! ale#handlers#rails_best_practices#GetExecutable(buffer) abort |  | ||||||
|     return ale#Var(a:buffer, 'ruby_rails_best_practices_executable') |  | ||||||
| endfunction |  | ||||||
							
								
								
									
										13
									
								
								sources_non_forked/ale/autoload/ale/handlers/tslint.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								sources_non_forked/ale/autoload/ale/handlers/tslint.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | function! ale#handlers#tslint#InitVariables() abort | ||||||
|  |     call ale#Set('typescript_tslint_executable', 'tslint') | ||||||
|  |     call ale#Set('typescript_tslint_config_path', '') | ||||||
|  |     call ale#Set('typescript_tslint_rules_dir', '') | ||||||
|  |     call ale#Set('typescript_tslint_use_global', get(g:, 'ale_use_global_executables', 0)) | ||||||
|  |     call ale#Set('typescript_tslint_ignore_empty_files', 0) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! ale#handlers#tslint#GetExecutable(buffer) abort | ||||||
|  |     return ale#node#FindExecutable(a:buffer, 'typescript_tslint', [ | ||||||
|  |     \   'node_modules/.bin/tslint', | ||||||
|  |     \]) | ||||||
|  | endfunction | ||||||
| @ -1,4 +1,3 @@ | |||||||
| call ale#Set('wrap_command_as_one_argument', 0) |  | ||||||
| " Author: w0rp <devw0rp@gmail.com> | " Author: w0rp <devw0rp@gmail.com> | ||||||
| " Description: Linter registration and lazy-loading | " Description: Linter registration and lazy-loading | ||||||
| "   Retrieves linters as requested by the engine, loading them if needed. | "   Retrieves linters as requested by the engine, loading them if needed. | ||||||
| @ -47,6 +46,16 @@ function! ale#linter#Reset() abort | |||||||
|     let s:linters = {} |     let s:linters = {} | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | " Return a reference to the linters loaded. | ||||||
|  | " This is only for tests. | ||||||
|  | " Do not call this function. | ||||||
|  | function! ale#linter#GetLintersLoaded() abort | ||||||
|  |     " This command will throw from the sandbox. | ||||||
|  |     let &equalprg=&equalprg | ||||||
|  |  | ||||||
|  |     return s:linters | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| function! s:IsCallback(value) abort | function! s:IsCallback(value) abort | ||||||
|     return type(a:value) == type('') || type(a:value) == type(function('type')) |     return type(a:value) == type('') || type(a:value) == type(function('type')) | ||||||
| endfunction | endfunction | ||||||
| @ -59,7 +68,7 @@ function! s:LanguageGetter(buffer) dict abort | |||||||
|     return l:self.language |     return l:self.language | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#linter#PreProcess(linter) abort | function! ale#linter#PreProcess(filetype, linter) abort | ||||||
|     if type(a:linter) != type({}) |     if type(a:linter) != type({}) | ||||||
|         throw 'The linter object must be a Dictionary' |         throw 'The linter object must be a Dictionary' | ||||||
|     endif |     endif | ||||||
| @ -193,13 +202,20 @@ function! ale#linter#PreProcess(linter) abort | |||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     if l:needs_lsp_details |     if l:needs_lsp_details | ||||||
|         if has_key(a:linter, 'language') |         if has_key(a:linter, 'language_callback') | ||||||
|             if has_key(a:linter, 'language_callback') |             if has_key(a:linter, 'language') | ||||||
|                 throw 'Only one of `language` or `language_callback` ' |                 throw 'Only one of `language` or `language_callback` ' | ||||||
|                 \   . 'should be set' |                 \   . 'should be set' | ||||||
|             endif |             endif | ||||||
|  |  | ||||||
|             let l:obj.language = get(a:linter, 'language') |             let l:obj.language_callback = get(a:linter, 'language_callback') | ||||||
|  |  | ||||||
|  |             if !s:IsCallback(l:obj.language_callback) | ||||||
|  |                 throw '`language_callback` must be a callback for LSP linters' | ||||||
|  |             endif | ||||||
|  |         else | ||||||
|  |             " Default to using the filetype as the language. | ||||||
|  |             let l:obj.language = get(a:linter, 'language', a:filetype) | ||||||
|  |  | ||||||
|             if type(l:obj.language) != type('') |             if type(l:obj.language) != type('') | ||||||
|                 throw '`language` must be a string' |                 throw '`language` must be a string' | ||||||
| @ -207,12 +223,6 @@ function! ale#linter#PreProcess(linter) abort | |||||||
|  |  | ||||||
|             " Make 'language_callback' return the 'language' value. |             " Make 'language_callback' return the 'language' value. | ||||||
|             let l:obj.language_callback = function('s:LanguageGetter') |             let l:obj.language_callback = function('s:LanguageGetter') | ||||||
|         else |  | ||||||
|             let l:obj.language_callback = get(a:linter, 'language_callback') |  | ||||||
|  |  | ||||||
|             if !s:IsCallback(l:obj.language_callback) |  | ||||||
|                 throw '`language_callback` must be a callback for LSP linters' |  | ||||||
|             endif |  | ||||||
|         endif |         endif | ||||||
|  |  | ||||||
|         let l:obj.project_root_callback = get(a:linter, 'project_root_callback') |         let l:obj.project_root_callback = get(a:linter, 'project_root_callback') | ||||||
| @ -282,11 +292,14 @@ function! ale#linter#PreProcess(linter) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#linter#Define(filetype, linter) abort | function! ale#linter#Define(filetype, linter) abort | ||||||
|  |     " This command will throw from the sandbox. | ||||||
|  |     let &equalprg=&equalprg | ||||||
|  |  | ||||||
|     if !has_key(s:linters, a:filetype) |     if !has_key(s:linters, a:filetype) | ||||||
|         let s:linters[a:filetype] = [] |         let s:linters[a:filetype] = [] | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     let l:new_linter = ale#linter#PreProcess(a:linter) |     let l:new_linter = ale#linter#PreProcess(a:filetype, a:linter) | ||||||
|  |  | ||||||
|     call add(s:linters[a:filetype], l:new_linter) |     call add(s:linters[a:filetype], l:new_linter) | ||||||
| endfunction | endfunction | ||||||
| @ -297,6 +310,12 @@ function! ale#linter#PreventLoading(filetype) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#linter#GetAll(filetypes) abort | function! ale#linter#GetAll(filetypes) abort | ||||||
|  |     " Don't return linters in the sandbox. | ||||||
|  |     " Otherwise a sandboxed script could modify them. | ||||||
|  |     if ale#util#InSandbox() | ||||||
|  |         return [] | ||||||
|  |     endif | ||||||
|  |  | ||||||
|     let l:combined_linters = [] |     let l:combined_linters = [] | ||||||
|  |  | ||||||
|     for l:filetype in a:filetypes |     for l:filetype in a:filetypes | ||||||
|  | |||||||
| @ -105,11 +105,17 @@ function! ale#lsp#response#GetErrorMessage(response) abort | |||||||
|         return '' |         return '' | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     " Include the traceback as details, if it's there. |     " Include the traceback or error data as details, if present. | ||||||
|     let l:traceback = get(get(a:response.error, 'data', {}), 'traceback', []) |     let l:error_data = get(a:response.error, 'data', {}) | ||||||
|  |  | ||||||
|     if type(l:traceback) is type([]) && !empty(l:traceback) |     if type(l:error_data) is type('') | ||||||
|         let l:message .= "\n" . join(l:traceback, "\n") |         let l:message .= "\n" . l:error_data | ||||||
|  |     else | ||||||
|  |         let l:traceback = get(l:error_data, 'traceback', []) | ||||||
|  |  | ||||||
|  |         if type(l:traceback) is type([]) && !empty(l:traceback) | ||||||
|  |             let l:message .= "\n" . join(l:traceback, "\n") | ||||||
|  |         endif | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     return l:message |     return l:message | ||||||
|  | |||||||
| @ -114,6 +114,18 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort | |||||||
|     endif |     endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! ale#lsp_linter#GetOptions(buffer, linter) abort | ||||||
|  |     let l:initialization_options = {} | ||||||
|  |  | ||||||
|  |     if has_key(a:linter, 'initialization_options_callback') | ||||||
|  |         let l:initialization_options = ale#util#GetFunction(a:linter.initialization_options_callback)(a:buffer) | ||||||
|  |     elseif has_key(a:linter, 'initialization_options') | ||||||
|  |         let l:initialization_options = a:linter.initialization_options | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     return l:initialization_options | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| " Given a buffer, an LSP linter, and a callback to register for handling | " Given a buffer, an LSP linter, and a callback to register for handling | ||||||
| " messages, start up an LSP linter and get ready to receive errors or | " messages, start up an LSP linter and get ready to receive errors or | ||||||
| " completions. | " completions. | ||||||
| @ -128,13 +140,7 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort | |||||||
|         return {} |         return {} | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     let l:initialization_options = {} |     let l:initialization_options = ale#lsp_linter#GetOptions(a:buffer, a:linter) | ||||||
|  |  | ||||||
|     if has_key(a:linter, 'initialization_options_callback') |  | ||||||
|         let l:initialization_options = ale#util#GetFunction(a:linter.initialization_options_callback)(a:buffer) |  | ||||||
|     elseif has_key(a:linter, 'initialization_options') |  | ||||||
|         let l:initialization_options = a:linter.initialization_options |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     if a:linter.lsp is# 'socket' |     if a:linter.lsp is# 'socket' | ||||||
|         let l:address = ale#linter#GetAddress(a:buffer, a:linter) |         let l:address = ale#linter#GetAddress(a:buffer, a:linter) | ||||||
| @ -147,14 +153,14 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort | |||||||
|     else |     else | ||||||
|         let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) |         let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) | ||||||
|  |  | ||||||
|         if !executable(l:executable) |         if empty(l:executable) || !executable(l:executable) | ||||||
|             return {} |             return {} | ||||||
|         endif |         endif | ||||||
|  |  | ||||||
|         let l:command = ale#job#PrepareCommand( |         let l:command = ale#linter#GetCommand(a:buffer, a:linter) | ||||||
|         \   a:buffer, |         " Format the command, so %e can be formatted into it. | ||||||
|         \   ale#linter#GetCommand(a:buffer, a:linter), |         let l:command = ale#command#FormatCommand(a:buffer, l:executable, l:command, 0)[1] | ||||||
|         \) |         let l:command = ale#job#PrepareCommand(a:buffer, l:command) | ||||||
|         let l:conn_id = ale#lsp#StartProgram( |         let l:conn_id = ale#lsp#StartProgram( | ||||||
|         \   l:executable, |         \   l:executable, | ||||||
|         \   l:command, |         \   l:command, | ||||||
|  | |||||||
| @ -84,7 +84,7 @@ function! ale#path#IsAbsolute(filename) abort | |||||||
|     return a:filename[:0] is# '/' || a:filename[1:2] is# ':\' |     return a:filename[:0] is# '/' || a:filename[1:2] is# ':\' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| let s:temp_dir = ale#path#Simplify(fnamemodify(tempname(), ':h')) | let s:temp_dir = ale#path#Simplify(fnamemodify(ale#util#Tempname(), ':h')) | ||||||
|  |  | ||||||
| " Given a filename, return 1 if the file represents some temporary file | " Given a filename, return 1 if the file represents some temporary file | ||||||
| " created by Vim. | " created by Vim. | ||||||
|  | |||||||
| @ -1,11 +1,6 @@ | |||||||
| " Author: w0rp <devw0rp@gmail.com> | " Author: w0rp <devw0rp@gmail.com> | ||||||
| " Description: Set options in files based on regex patterns. | " Description: Set options in files based on regex patterns. | ||||||
|  |  | ||||||
| " A dictionary mapping regular expression patterns to arbitrary buffer |  | ||||||
| " variables to be set. Useful for configuring ALE based on filename patterns. |  | ||||||
| let g:ale_pattern_options = get(g:, 'ale_pattern_options', {}) |  | ||||||
| let g:ale_pattern_options_enabled = get(g:, 'ale_pattern_options_enabled', !empty(g:ale_pattern_options)) |  | ||||||
|  |  | ||||||
| " These variables are used to cache the sorting of patterns below. | " These variables are used to cache the sorting of patterns below. | ||||||
| let s:last_pattern_options = {} | let s:last_pattern_options = {} | ||||||
| let s:sorted_items = [] | let s:sorted_items = [] | ||||||
| @ -23,17 +18,19 @@ function! s:CmpPatterns(left_item, right_item) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! ale#pattern_options#SetOptions(buffer) abort | function! ale#pattern_options#SetOptions(buffer) abort | ||||||
|     if !get(g:, 'ale_pattern_options_enabled', 0) |     let l:pattern_options = get(g:, 'ale_pattern_options', {}) | ||||||
|     \|| empty(get(g:, 'ale_pattern_options', 0)) |  | ||||||
|  |     if empty(l:pattern_options) | ||||||
|  |         " Stop if no options are set. | ||||||
|         return |         return | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     " The items will only be sorted whenever the patterns change. |     " The items will only be sorted whenever the patterns change. | ||||||
|     if g:ale_pattern_options != s:last_pattern_options |     if l:pattern_options != s:last_pattern_options | ||||||
|         let s:last_pattern_options = deepcopy(g:ale_pattern_options) |         let s:last_pattern_options = deepcopy(l:pattern_options) | ||||||
|         " The patterns are sorted, so they are applied consistently. |         " The patterns are sorted, so they are applied consistently. | ||||||
|         let s:sorted_items = sort( |         let s:sorted_items = sort( | ||||||
|         \   items(g:ale_pattern_options), |         \   items(l:pattern_options), | ||||||
|         \   function('s:CmpPatterns') |         \   function('s:CmpPatterns') | ||||||
|         \) |         \) | ||||||
|     endif |     endif | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ let s:sep = has('win32') ? '\' : '/' | |||||||
| let s:bin_dir = has('unix') ? 'bin' : 'Scripts' | let s:bin_dir = has('unix') ? 'bin' : 'Scripts' | ||||||
| let g:ale_virtualenv_dir_names = get(g:, 'ale_virtualenv_dir_names', [ | let g:ale_virtualenv_dir_names = get(g:, 'ale_virtualenv_dir_names', [ | ||||||
| \   '.env', | \   '.env', | ||||||
|  | \   '.venv', | ||||||
| \   'env', | \   'env', | ||||||
| \   've-py3', | \   've-py3', | ||||||
| \   've', | \   've', | ||||||
| @ -23,6 +24,8 @@ function! ale#python#FindProjectRootIni(buffer) abort | |||||||
|         \|| filereadable(l:path . '/mypy.ini') |         \|| filereadable(l:path . '/mypy.ini') | ||||||
|         \|| filereadable(l:path . '/pycodestyle.cfg') |         \|| filereadable(l:path . '/pycodestyle.cfg') | ||||||
|         \|| filereadable(l:path . '/flake8.cfg') |         \|| filereadable(l:path . '/flake8.cfg') | ||||||
|  |         \|| filereadable(l:path . '/Pipfile') | ||||||
|  |         \|| filereadable(l:path . '/Pipfile.lock') | ||||||
|             return l:path |             return l:path | ||||||
|         endif |         endif | ||||||
|     endfor |     endfor | ||||||
|  | |||||||
| @ -45,25 +45,23 @@ if !hlexists('ALESignColumnWithErrors') | |||||||
|     highlight link ALESignColumnWithErrors error |     highlight link ALESignColumnWithErrors error | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | function! ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() abort | ||||||
|  |     redir => l:output | ||||||
|  |         0verbose silent highlight SignColumn | ||||||
|  |     redir end | ||||||
|  |  | ||||||
|  |     let l:highlight_syntax = join(split(l:output)[2:]) | ||||||
|  |     let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$') | ||||||
|  |  | ||||||
|  |     if !empty(l:match) | ||||||
|  |         execute 'highlight link ALESignColumnWithoutErrors ' . l:match[1] | ||||||
|  |     elseif l:highlight_syntax isnot# 'cleared' | ||||||
|  |         execute 'highlight ALESignColumnWithoutErrors ' . l:highlight_syntax | ||||||
|  |     endif | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| if !hlexists('ALESignColumnWithoutErrors') | if !hlexists('ALESignColumnWithoutErrors') | ||||||
|     function! s:SetSignColumnWithoutErrorsHighlight() abort |     call ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() | ||||||
|         redir => l:output |  | ||||||
|             silent highlight SignColumn |  | ||||||
|         redir end |  | ||||||
|  |  | ||||||
|         let l:highlight_syntax = join(split(l:output)[2:]) |  | ||||||
|  |  | ||||||
|         let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$') |  | ||||||
|  |  | ||||||
|         if !empty(l:match) |  | ||||||
|             execute 'highlight link ALESignColumnWithoutErrors ' . l:match[1] |  | ||||||
|         elseif l:highlight_syntax isnot# 'cleared' |  | ||||||
|             execute 'highlight ALESignColumnWithoutErrors ' . l:highlight_syntax |  | ||||||
|         endif |  | ||||||
|     endfunction |  | ||||||
|  |  | ||||||
|     call s:SetSignColumnWithoutErrorsHighlight() |  | ||||||
|     delfunction s:SetSignColumnWithoutErrorsHighlight |  | ||||||
| endif | endif | ||||||
|  |  | ||||||
| " Signs show up on the left for error markers. | " Signs show up on the left for error markers. | ||||||
|  | |||||||
| @ -268,9 +268,8 @@ endfunction | |||||||
| " See :help sandbox | " See :help sandbox | ||||||
| function! ale#util#InSandbox() abort | function! ale#util#InSandbox() abort | ||||||
|     try |     try | ||||||
|         function! s:SandboxCheck() abort |         let &equalprg=&equalprg | ||||||
|         endfunction |     catch /E48/ | ||||||
|     catch /^Vim\%((\a\+)\)\=:E48/ |  | ||||||
|         " E48 is the sandbox error. |         " E48 is the sandbox error. | ||||||
|         return 1 |         return 1 | ||||||
|     endtry |     endtry | ||||||
| @ -278,6 +277,25 @@ function! ale#util#InSandbox() abort | |||||||
|     return 0 |     return 0 | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! ale#util#Tempname() abort | ||||||
|  |     let l:clear_tempdir = 0 | ||||||
|  |  | ||||||
|  |     if exists('$TMPDIR') && empty($TMPDIR) | ||||||
|  |         let l:clear_tempdir = 1 | ||||||
|  |         let $TMPDIR = '/tmp' | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     try | ||||||
|  |         let l:name = tempname() " no-custom-checks | ||||||
|  |     finally | ||||||
|  |         if l:clear_tempdir | ||||||
|  |             let $TMPDIR = '' | ||||||
|  |         endif | ||||||
|  |     endtry | ||||||
|  |  | ||||||
|  |     return l:name | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| " Given a single line, or a List of lines, and a single pattern, or a List | " Given a single line, or a List of lines, and a single pattern, or a List | ||||||
| " of patterns, return all of the matches for the lines(s) from the given | " of patterns, return all of the matches for the lines(s) from the given | ||||||
| " patterns, using matchlist(). | " patterns, using matchlist(). | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ CONTENTS                                             *ale-development-contents* | |||||||
|   2. Design Goals.........................|ale-design-goals| |   2. Design Goals.........................|ale-design-goals| | ||||||
|   3. Coding Standards.....................|ale-coding-standards| |   3. Coding Standards.....................|ale-coding-standards| | ||||||
|   4. Testing ALE..........................|ale-development-tests| |   4. Testing ALE..........................|ale-development-tests| | ||||||
|  |     4.1. Writing Linter Tests.............|ale-development-linter-tests| | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
| 1. Introduction                                  *ale-development-introduction* | 1. Introduction                                  *ale-development-introduction* | ||||||
| @ -111,6 +112,9 @@ these are reported with ALE's `custom-linting-rules` script. See | |||||||
| * Don't use the `shellescape()` function. It doesn't escape arguments properly | * Don't use the `shellescape()` function. It doesn't escape arguments properly | ||||||
|   on Windows. Use `ale#Escape()` instead, which will avoid escaping where it |   on Windows. Use `ale#Escape()` instead, which will avoid escaping where it | ||||||
|   isn't needed, and generally escape arguments better on Windows. |   isn't needed, and generally escape arguments better on Windows. | ||||||
|  | * Don't use the `tempname()` function. It doesn't work when `$TMPDIR` isn't | ||||||
|  |   set. Use `ale#util#Tempname()` instead, which temporarily sets `$TMPDIR` | ||||||
|  |   appropriately where needed. | ||||||
|  |  | ||||||
| Apply the following guidelines when writing Vader test files. | Apply the following guidelines when writing Vader test files. | ||||||
|  |  | ||||||
| @ -170,6 +174,9 @@ Look at existing tests in the codebase for examples of how to write tests. | |||||||
| Refer to the Vader documentation for general information on how to write Vader | Refer to the Vader documentation for general information on how to write Vader | ||||||
| tests: https://github.com/junegunn/vader.vim | tests: https://github.com/junegunn/vader.vim | ||||||
|  |  | ||||||
|  | See |ale-development-linter-tests| for more information on how to write linter | ||||||
|  | tests. | ||||||
|  |  | ||||||
| When you add new linters or fixers, make sure to add them into the table in | When you add new linters or fixers, make sure to add them into the table in | ||||||
| the README, and also into the |ale-support| list in the main help file. If you | the README, and also into the |ale-support| list in the main help file. If you | ||||||
| forget to keep them both in sync, you should see an error like the following | forget to keep them both in sync, you should see an error like the following | ||||||
| @ -219,5 +226,82 @@ margin. For example, if you add a heading for an `aardvark` tool to | |||||||
| Make sure to make the table of contents match the headings, and to keep the | Make sure to make the table of contents match the headings, and to keep the | ||||||
| doc tags on the right margin. | doc tags on the right margin. | ||||||
|  |  | ||||||
|  | =============================================================================== | ||||||
|  | 4.1 Writing Linter Tests                         *ale-development-linter-tests* | ||||||
|  |  | ||||||
|  | Tests for ALE linters take two forms. | ||||||
|  |  | ||||||
|  | 1. Tests for handling the output of commands. | ||||||
|  | 2. Tests for checking which commands are run, or connections are made. | ||||||
|  |  | ||||||
|  | Tests of the first form should go in the `test/handler` directory, and should | ||||||
|  | be written like so. > | ||||||
|  |  | ||||||
|  |   Before: | ||||||
|  |     " Load the file which defines the linter. | ||||||
|  |     runtime ale_linters/filetype/linter_name_here.vim | ||||||
|  |  | ||||||
|  |   After: | ||||||
|  |     " Unload all linters again. | ||||||
|  |     call ale#linter#Reset() | ||||||
|  |  | ||||||
|  |   Execute(The output should be correct): | ||||||
|  |  | ||||||
|  |   " Test that the right loclist items are parsed from the handler. | ||||||
|  |   AssertEqual | ||||||
|  |   \ [ | ||||||
|  |   \   { | ||||||
|  |   \     'lnum': 1, | ||||||
|  |   \     'type': 'E', | ||||||
|  |   \     'text': 'Something went wrong', | ||||||
|  |   \   }, | ||||||
|  |   \ ], | ||||||
|  |   \ ale_linters#filetype#linter_name#Handle(bufnr(''), [ | ||||||
|  |   \ '1:Something went wrong', | ||||||
|  |   \ ] | ||||||
|  | < | ||||||
|  | Tests for what ALE runs should go in the `test/command_callback` directory, | ||||||
|  | and should be written like so. > | ||||||
|  |  | ||||||
|  |   Before: | ||||||
|  |     " Load the linter and set up a series of commands, reset linter variables, | ||||||
|  |     " clear caches, etc. | ||||||
|  |     " | ||||||
|  |     " Vader's 'Save' command will be called here for linter variables. | ||||||
|  |     call ale#assert#SetUpLinterTest('filetype', 'linter_name') | ||||||
|  |  | ||||||
|  |   After: | ||||||
|  |     " Reset linters, variables, etc. | ||||||
|  |     " | ||||||
|  |     " Vader's 'Restore' command will be called here. | ||||||
|  |     call ale#assert#TearDownLinterTest() | ||||||
|  |  | ||||||
|  |   Execute(The default command should be correct): | ||||||
|  |     " AssertLinter checks the executable and command. | ||||||
|  |     " Pass expected_executable, expected_command | ||||||
|  |     AssertLinter 'some-command', ale#Escape('some-command') . ' --foo' | ||||||
|  |  | ||||||
|  |   Execute(Check chained commands): | ||||||
|  |     " WithChainResults can be called with 1 or more list for passing output | ||||||
|  |     " to chained commands. The output for each callback defaults to an empty | ||||||
|  |     " list. | ||||||
|  |     WithChainResults ['v2.1.2'] | ||||||
|  |     " Given a List of commands, check all of them. | ||||||
|  |     " Given a String, only the last command in the chain will be checked. | ||||||
|  |     AssertLinter 'some-command', [ | ||||||
|  |     \ ale#Escape('some-command') . ' --version', | ||||||
|  |     \ ale#Escape('some-command') . ' --foo', | ||||||
|  |     \] | ||||||
|  | < | ||||||
|  | The full list of commands that will be temporarily defined for linter tests | ||||||
|  | given the above setup are as follows. | ||||||
|  |  | ||||||
|  | `WithChainResults [...]`           - Define output for command chain functions. | ||||||
|  | `AssertLinter executable, command` - Check the executable and command. | ||||||
|  | `AssertLinterNotExecuted`          - Check that linters will not be executed. | ||||||
|  | `AssertLSPLanguage language`       - Check the language given to an LSP server. | ||||||
|  | `AssertLSPOptions options_dict`    - Check the options given to an LSP server. | ||||||
|  | `AssertLSPProject project_root`    - Check the root given to an LSP server. | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
|   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: |   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: | ||||||
|  | |||||||
| @ -87,4 +87,19 @@ g:ale_kotlin_ktlint_rulesets                     *g:ale_kotlin_ktlint_rulesets* | |||||||
|   let g:ale_kotlin_ktlint_rulesets = ['/path/to/custom-rulset.jar', |   let g:ale_kotlin_ktlint_rulesets = ['/path/to/custom-rulset.jar', | ||||||
|   'com.ktlint.rulesets:mycustomrule:1.0.0'] |   'com.ktlint.rulesets:mycustomrule:1.0.0'] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | =============================================================================== | ||||||
|  | languageserver                                      *ale-kotlin-languageserver* | ||||||
|  |  | ||||||
|  | g:ale_kotlin_languageserver_executable *g:ale_kotlin_languageserver_executable* | ||||||
|  |   Type: |String| | ||||||
|  |   Default: `''` | ||||||
|  |  | ||||||
|  |   The kotlin-language-server executable. | ||||||
|  |  | ||||||
|  |   Executables are located inside the bin/ folder of the language server | ||||||
|  |   release. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | =============================================================================== | ||||||
|   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: |   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: | ||||||
|  | |||||||
| @ -28,6 +28,33 @@ prettier                                                *ale-markdown-prettier* | |||||||
| See |ale-javascript-prettier| for information about the available options. | See |ale-javascript-prettier| for information about the available options. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | =============================================================================== | ||||||
|  | remark-lint                                          *ale-markdown-remark-lint* | ||||||
|  |  | ||||||
|  | g:ale_markdown_remark_lint_executable   *g:ale_markdown_remark_lint_executable* | ||||||
|  |                                         *b:ale_markdown_remark_lint_executable* | ||||||
|  |   Type: |String| | ||||||
|  |   Default: `'remark'` | ||||||
|  |  | ||||||
|  |   See |ale-integrations-local-executables| | ||||||
|  |  | ||||||
|  |  | ||||||
|  | g:ale_markdown_remark_lint_options         *g:ale_markdown_remark_lint_options* | ||||||
|  |                                            *b:ale_markdown_remark_lint_options* | ||||||
|  |   Type: |String| | ||||||
|  |   Default: `''` | ||||||
|  |  | ||||||
|  |   This variable can be set to pass additional options to remark-lint. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | g:ale_markdown_remark_lint_use_global   *g:ale_markdown_remark_lint_use_global* | ||||||
|  |                                         *b:ale_markdown_remark_lint_use_global* | ||||||
|  |   Type: |Number| | ||||||
|  |   Default: `get(g:, 'ale_use_global_executables', 0)` | ||||||
|  |  | ||||||
|  |   See |ale-integrations-local-executables| | ||||||
|  |  | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
| textlint                                                *ale-markdown-textlint* | textlint                                                *ale-markdown-textlint* | ||||||
|  |  | ||||||
|  | |||||||
| @ -22,5 +22,16 @@ g:ale_puppet_puppetlint_options               *g:ale_puppet_puppetlint_options* | |||||||
|   puppet-lint invocation. |   puppet-lint invocation. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | =============================================================================== | ||||||
|  | puppet-languageserver                               *ale-puppet-languageserver* | ||||||
|  |  | ||||||
|  | g:ale_puppet_languageserver_executable  *g:ale_puppet_languageserver_executable* | ||||||
|  |                                         *b:ale_puppet_languageserver_executable* | ||||||
|  |   type: |String| | ||||||
|  |   Default: `'puppet-languageserver'` | ||||||
|  |  | ||||||
|  |   This variable can be used to specify the executable used for | ||||||
|  |   puppet-languageserver. | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
|   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: |   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: | ||||||
|  | |||||||
| @ -22,6 +22,8 @@ ALE will look for configuration files with the following filenames. > | |||||||
|   mypy.ini |   mypy.ini | ||||||
|   pycodestyle.cfg |   pycodestyle.cfg | ||||||
|   flake8.cfg |   flake8.cfg | ||||||
|  |   Pipfile | ||||||
|  |   Pipfile.lock | ||||||
| < | < | ||||||
|  |  | ||||||
| The first directory containing any of the files named above will be used. | The first directory containing any of the files named above will be used. | ||||||
| @ -145,6 +147,14 @@ g:ale_python_isort_executable                   *g:ale_python_isort_executable* | |||||||
|   See |ale-integrations-local-executables| |   See |ale-integrations-local-executables| | ||||||
|  |  | ||||||
|  |  | ||||||
|  | g:ale_python_isort_options                         *g:ale_python_isort_options* | ||||||
|  |                                                    *b:ale_python_isort_options* | ||||||
|  |   Type: |String| | ||||||
|  |   Default: `''` | ||||||
|  |  | ||||||
|  |   This variable can be set to pass extra options to isort. | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_python_isort_use_global                   *g:ale_python_isort_use_global* | g:ale_python_isort_use_global                   *g:ale_python_isort_use_global* | ||||||
|                                                 *b:ale_python_isort_use_global* |                                                 *b:ale_python_isort_use_global* | ||||||
|   Type: |Number| |   Type: |Number| | ||||||
|  | |||||||
| @ -41,8 +41,8 @@ To disable `scalastyle` globally, use |g:ale_linters| like so: > | |||||||
| See |g:ale_linters| for more information on disabling linters. | See |g:ale_linters| for more information on disabling linters. | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_scalastyle_config_loc                       *g:ale_scalastyle_config_loc* | g:ale_scala_scalastyle_config                   *g:ale_scala_scalastyle_config* | ||||||
|  |                                                 *b:ale_scala_scalastyle_config* | ||||||
|   Type: |String| |   Type: |String| | ||||||
|   Default: `''` |   Default: `''` | ||||||
|  |  | ||||||
| @ -54,7 +54,7 @@ g:ale_scalastyle_config_loc                       *g:ale_scalastyle_config_loc* | |||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_scala_scalastyle_options                 *g:ale_scala_scalastyle_options* | g:ale_scala_scalastyle_options                 *g:ale_scala_scalastyle_options* | ||||||
|  |                                                *b:ale_scala_scalastyle_options* | ||||||
|   Type: |String| |   Type: |String| | ||||||
|   Default: `''` |   Default: `''` | ||||||
|  |  | ||||||
|  | |||||||
| @ -7,5 +7,25 @@ prettier                                                     *ale-vue-prettier* | |||||||
|  |  | ||||||
| See |ale-javascript-prettier| for information about the available options. | See |ale-javascript-prettier| for information about the available options. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | =============================================================================== | ||||||
|  | vls                                                               *ale-vue-vls* | ||||||
|  |  | ||||||
|  | g:ale_vue_vls_executable                             *g:ale_vue_vls_executable* | ||||||
|  |                                                      *b:ale_vue_vls_executable* | ||||||
|  |   Type: |String| | ||||||
|  |   Default: `'vls'` | ||||||
|  |  | ||||||
|  |   See |ale-integrations-local-executables| | ||||||
|  |  | ||||||
|  |  | ||||||
|  | g:ale_vue_vls_use_global                             *g:ale_vue_vls_use_global* | ||||||
|  |                                                      *b:ale_vue_vls_use_global* | ||||||
|  |   Type: |Number| | ||||||
|  |   Default: `get(g:, 'ale_use_global_executables', 0)` | ||||||
|  |  | ||||||
|  |   See |ale-integrations-local-executables| | ||||||
|  |  | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
|   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: |   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: | ||||||
|  | |||||||
| @ -131,6 +131,7 @@ CONTENTS                                                         *ale-contents* | |||||||
|     kotlin................................|ale-kotlin-options| |     kotlin................................|ale-kotlin-options| | ||||||
|       kotlinc.............................|ale-kotlin-kotlinc| |       kotlinc.............................|ale-kotlin-kotlinc| | ||||||
|       ktlint..............................|ale-kotlin-ktlint| |       ktlint..............................|ale-kotlin-ktlint| | ||||||
|  |       languageserver......................|ale-kotlin-languageserver| | ||||||
|     latex.................................|ale-latex-options| |     latex.................................|ale-latex-options| | ||||||
|       write-good..........................|ale-latex-write-good| |       write-good..........................|ale-latex-write-good| | ||||||
|     less..................................|ale-less-options| |     less..................................|ale-less-options| | ||||||
| @ -145,6 +146,7 @@ CONTENTS                                                         *ale-contents* | |||||||
|     markdown..............................|ale-markdown-options| |     markdown..............................|ale-markdown-options| | ||||||
|       mdl.................................|ale-markdown-mdl| |       mdl.................................|ale-markdown-mdl| | ||||||
|       prettier............................|ale-markdown-prettier| |       prettier............................|ale-markdown-prettier| | ||||||
|  |       remark-lint.........................|ale-markdown-remark-lint| | ||||||
|       textlint............................|ale-markdown-textlint| |       textlint............................|ale-markdown-textlint| | ||||||
|       write-good..........................|ale-markdown-write-good| |       write-good..........................|ale-markdown-write-good| | ||||||
|     mercury...............................|ale-mercury-options| |     mercury...............................|ale-mercury-options| | ||||||
| @ -186,6 +188,7 @@ CONTENTS                                                         *ale-contents* | |||||||
|       puglint.............................|ale-pug-puglint| |       puglint.............................|ale-pug-puglint| | ||||||
|     puppet................................|ale-puppet-options| |     puppet................................|ale-puppet-options| | ||||||
|       puppetlint..........................|ale-puppet-puppetlint| |       puppetlint..........................|ale-puppet-puppetlint| | ||||||
|  |       puppet-languageserver...............|ale-puppet-languageserver| | ||||||
|     pyrex (cython)........................|ale-pyrex-options| |     pyrex (cython)........................|ale-pyrex-options| | ||||||
|       cython..............................|ale-pyrex-cython| |       cython..............................|ale-pyrex-cython| | ||||||
|     python................................|ale-python-options| |     python................................|ale-python-options| | ||||||
| @ -273,6 +276,7 @@ CONTENTS                                                         *ale-contents* | |||||||
|       write-good..........................|ale-vim-help-write-good| |       write-good..........................|ale-vim-help-write-good| | ||||||
|     vue...................................|ale-vue-options| |     vue...................................|ale-vue-options| | ||||||
|       prettier............................|ale-vue-prettier| |       prettier............................|ale-vue-prettier| | ||||||
|  |       vls.................................|ale-vue-vls| | ||||||
|     xhtml.................................|ale-xhtml-options| |     xhtml.................................|ale-xhtml-options| | ||||||
|       write-good..........................|ale-xhtml-write-good| |       write-good..........................|ale-xhtml-write-good| | ||||||
|     xml...................................|ale-xml-options| |     xml...................................|ale-xml-options| | ||||||
| @ -366,7 +370,7 @@ Notes: | |||||||
| * Java: `checkstyle`, `javac`, `google-java-format`, `PMD` | * Java: `checkstyle`, `javac`, `google-java-format`, `PMD` | ||||||
| * JavaScript: `eslint`, `flow`, `jscs`, `jshint`, `prettier`, `prettier-eslint`, `prettier-standard`, `standard`, `xo` | * JavaScript: `eslint`, `flow`, `jscs`, `jshint`, `prettier`, `prettier-eslint`, `prettier-standard`, `standard`, `xo` | ||||||
| * JSON: `fixjson`, `jsonlint`, `jq`, `prettier` | * JSON: `fixjson`, `jsonlint`, `jq`, `prettier` | ||||||
| * Kotlin: `kotlinc`, `ktlint` | * Kotlin: `kotlinc`!!, `ktlint`!!, `languageserver` | ||||||
| * LaTeX (tex): `alex`!!, `chktex`, `lacheck`, `proselint`, `redpen`, `vale`, `write-good` | * LaTeX (tex): `alex`!!, `chktex`, `lacheck`, `proselint`, `redpen`, `vale`, `write-good` | ||||||
| * Less: `lessc`, `prettier`, `stylelint` | * Less: `lessc`, `prettier`, `stylelint` | ||||||
| * LLVM: `llc` | * LLVM: `llc` | ||||||
| @ -390,7 +394,7 @@ Notes: | |||||||
| * Pony: `ponyc` | * Pony: `ponyc` | ||||||
| * proto: `protoc-gen-lint` | * proto: `protoc-gen-lint` | ||||||
| * Pug: `pug-lint` | * Pug: `pug-lint` | ||||||
| * Puppet: `puppet`, `puppet-lint` | * Puppet: `languageserver`, `puppet`, `puppet-lint` | ||||||
| * Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pyls`, `pyre`, `pylint`!!, `yapf` | * Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pyls`, `pyre`, `pylint`!!, `yapf` | ||||||
| * QML: `qmlfmt`, `qmllint` | * QML: `qmlfmt`, `qmllint` | ||||||
| * R: `lintr` | * R: `lintr` | ||||||
| @ -418,7 +422,7 @@ Notes: | |||||||
| * Verilog: `iverilog`, `verilator` | * Verilog: `iverilog`, `verilator` | ||||||
| * Vim: `vint` | * Vim: `vint` | ||||||
| * Vim help^: `alex`!!, `proselint`, `write-good` | * Vim help^: `alex`!!, `proselint`, `write-good` | ||||||
| * Vue: `prettier` | * Vue: `prettier`, `vls` | ||||||
| * XHTML: `alex`!!, `proselint`, `write-good` | * XHTML: `alex`!!, `proselint`, `write-good` | ||||||
| * XML: `xmllint` | * XML: `xmllint` | ||||||
| * YAML: `swaglint`, `yamllint` | * YAML: `swaglint`, `yamllint` | ||||||
| @ -444,14 +448,20 @@ have even saved your changes. ALE will check your code in the following | |||||||
| circumstances, which can be configured with the associated options. | circumstances, which can be configured with the associated options. | ||||||
|  |  | ||||||
| * When you modify a buffer.                - |g:ale_lint_on_text_changed| | * When you modify a buffer.                - |g:ale_lint_on_text_changed| | ||||||
|  | * On leaving insert mode. (off by default) - |g:ale_lint_on_insert_leave| | ||||||
| * When you open a new or modified buffer.  - |g:ale_lint_on_enter| | * When you open a new or modified buffer.  - |g:ale_lint_on_enter| | ||||||
| * When you save a buffer.                  - |g:ale_lint_on_save| | * When you save a buffer.                  - |g:ale_lint_on_save| | ||||||
| * When the filetype changes for a buffer.  - |g:ale_lint_on_filetype_changed| | * When the filetype changes for a buffer.  - |g:ale_lint_on_filetype_changed| | ||||||
| * If ALE is used to check code manually.   - |:ALELint| | * If ALE is used to check code manually.   - |:ALELint| | ||||||
|  |  | ||||||
| In addition to the above options, ALE can also check buffers for errors when |                                                  *ale-lint-settings-on-startup* | ||||||
| you leave insert mode with |g:ale_lint_on_insert_leave|, which is off by |  | ||||||
| default. It is worth reading the documentation for every option. | It is worth reading the documentation for every option. You should configure | ||||||
|  | which events ALE will use before ALE is loaded, so it can optimize which | ||||||
|  | autocmd commands to run. You can force autocmd commands to be reloaded with | ||||||
|  | `:ALEDisable | ALEEnable` | ||||||
|  |  | ||||||
|  | This also applies to the autocmd commands used for |g:ale_echo_cursor|. | ||||||
|  |  | ||||||
|                                                         *ale-lint-file-linters* |                                                         *ale-lint-file-linters* | ||||||
|  |  | ||||||
| @ -641,9 +651,6 @@ ALE supports the following LSP/tsserver features. | |||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| 5.1 Completion                                                 *ale-completion* | 5.1 Completion                                                 *ale-completion* | ||||||
|  |  | ||||||
| NOTE: At the moment, only `tsserver` for TypeScript code is supported for |  | ||||||
| completion. |  | ||||||
|  |  | ||||||
| ALE offers limited support for automatic completion of code while you type. | ALE offers limited support for automatic completion of code while you type. | ||||||
| Completion is only supported while a least one LSP linter is enabled. ALE | Completion is only supported while a least one LSP linter is enabled. ALE | ||||||
| will only suggest symbols provided by the LSP servers. | will only suggest symbols provided by the LSP servers. | ||||||
| @ -842,6 +849,9 @@ g:ale_echo_cursor                                           *g:ale_echo_cursor* | |||||||
|   this behaviour. |   this behaviour. | ||||||
|   The format of the message can be customizable in |g:ale_echo_msg_format|. |   The format of the message can be customizable in |g:ale_echo_msg_format|. | ||||||
|  |  | ||||||
|  |   You should set this setting once before ALE is loaded, and restart Vim if | ||||||
|  |   you want to change your preferences. See |ale-lint-settings-on-startup|. | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_echo_delay                                             *g:ale_echo_delay* | g:ale_echo_delay                                             *g:ale_echo_delay* | ||||||
|                                                              *b:ale_echo_delay* |                                                              *b:ale_echo_delay* | ||||||
| @ -1042,19 +1052,16 @@ g:ale_lint_on_enter                                       *g:ale_lint_on_enter* | |||||||
|   Type: |Number| |   Type: |Number| | ||||||
|   Default: `1` |   Default: `1` | ||||||
|  |  | ||||||
|   When this option is set to `1`, the |BufWinEnter| and |BufRead| events will |   When this option is set to `1`, the |BufWinEnter| event will be used to | ||||||
|   be used to apply linters when buffers are first opened. If this is not |   apply linters when buffers are first opened. If this is not desired, this | ||||||
|   desired, this variable can be set to `0` in your vimrc file to disable this |   variable can be set to `0` in your vimrc file to disable this behavior. | ||||||
|   behaviour. |  | ||||||
|  |  | ||||||
|   The |FileChangedShellPost| and |BufEnter| events will be used to check if |   The |FileChangedShellPost| and |BufEnter| events will be used to check if | ||||||
|   files have been changed outside of Vim. If a file is changed outside of |   files have been changed outside of Vim. If a file is changed outside of | ||||||
|   Vim, it will be checked when it is next opened. |   Vim, it will be checked when it is next opened. | ||||||
|  |  | ||||||
|   A |BufWinLeave| event will be used to look for the |E924|, |E925|, or |E926| |   You should set this setting once before ALE is loaded, and restart Vim if | ||||||
|   errors after moving from a loclist or quickfix window to a new buffer. If |   you want to change your preferences. See |ale-lint-settings-on-startup|. | ||||||
|   prompts for these errors are opened after moving to new buffers, then ALE |  | ||||||
|   will automatically send the `<CR>` key needed to close the prompt. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_lint_on_filetype_changed                 *g:ale_lint_on_filetype_changed* | g:ale_lint_on_filetype_changed                 *g:ale_lint_on_filetype_changed* | ||||||
| @ -1062,14 +1069,13 @@ g:ale_lint_on_filetype_changed                 *g:ale_lint_on_filetype_changed* | |||||||
|   Type: |Number| |   Type: |Number| | ||||||
|   Default: `1` |   Default: `1` | ||||||
|  |  | ||||||
|   This option will cause ALE to run whenever the filetype is changed. A short |   This option will cause ALE to run when the filetype for a file is changed | ||||||
|   delay will be used before linting will be done, so the filetype can be |   after a buffer has first been loaded. A short delay will be used before | ||||||
|   changed quickly several times in a row, but resulting in only one lint |   linting will be done, so the filetype can be changed quickly several times | ||||||
|   cycle. |   in a row, but resulting in only one lint cycle. | ||||||
|  |  | ||||||
|   If |g:ale_lint_on_enter| is set to `0`, then ALE will not lint a file when |   You should set this setting once before ALE is loaded, and restart Vim if | ||||||
|   the filetype is initially set. Otherwise ALE would still lint files when |   you want to change your preferences. See |ale-lint-settings-on-startup|. | ||||||
|   buffers are opened, and the option for doing so is turned off. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_lint_on_save                                         *g:ale_lint_on_save* | g:ale_lint_on_save                                         *g:ale_lint_on_save* | ||||||
| @ -1087,17 +1093,22 @@ g:ale_lint_on_save                                         *g:ale_lint_on_save* | |||||||
| g:ale_lint_on_text_changed                         *g:ale_lint_on_text_changed* | g:ale_lint_on_text_changed                         *g:ale_lint_on_text_changed* | ||||||
|  |  | ||||||
|   Type: |String| |   Type: |String| | ||||||
|   Default: `always` |   Default: `'always'` | ||||||
|  |  | ||||||
|   By default, ALE will check files with the various supported programs when |   This option controls how ALE will check your files as you make changes. | ||||||
|   text is changed by using the |TextChanged| event. If this behaviour is not |   The following values can be used. | ||||||
|   desired, then this option can be disabled by setting it to `never`. The |  | ||||||
|   |g:ale_lint_delay| variable will be used to set a |timer_start()| on a |   `'always'`, `'1'`, or `1` - Check buffers on |TextChanged| or |TextChangedI|. | ||||||
|   delay, and each change to a file will continue to call |timer_stop()| and |   `'normal'`            - Check buffers only on |TextChanged|. | ||||||
|   |timer_start()| repeatedly until the timer ticks by, and the linters will be |   `'insert'`            - Check buffers only on |TextChangedI|. | ||||||
|   run. The checking of files will run in the background, so it should not |   `'never'`, `'0'`, or `0`  - Never check buffers on changes. | ||||||
|   inhibit editing files. This option can also be set to `insert` or `normal` |  | ||||||
|   to lint when text is changed only in insert or normal mode respectively. |   ALE will check buffers after a short delay, with a timer which resets on | ||||||
|  |   each change. The delay can be configured by adjusting the |g:ale_lint_delay| | ||||||
|  |   variable. | ||||||
|  |  | ||||||
|  |   You should set this setting once before ALE is loaded, and restart Vim if | ||||||
|  |   you want to change your preferences. See |ale-lint-settings-on-startup|. | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_lint_on_insert_leave                         *g:ale_lint_on_insert_leave* | g:ale_lint_on_insert_leave                         *g:ale_lint_on_insert_leave* | ||||||
| @ -1115,6 +1126,9 @@ g:ale_lint_on_insert_leave                         *g:ale_lint_on_insert_leave* | |||||||
|     " Make using Ctrl+C do the same as Escape, to trigger autocmd commands |     " Make using Ctrl+C do the same as Escape, to trigger autocmd commands | ||||||
|     inoremap <C-c> <Esc> |     inoremap <C-c> <Esc> | ||||||
| < | < | ||||||
|  |   You should set this setting once before ALE is loaded, and restart Vim if | ||||||
|  |   you want to change your preferences. See |ale-lint-settings-on-startup|. | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_linter_aliases                                     *g:ale_linter_aliases* | g:ale_linter_aliases                                     *g:ale_linter_aliases* | ||||||
|                                                          *b:ale_linter_aliases* |                                                          *b:ale_linter_aliases* | ||||||
| @ -1360,7 +1374,7 @@ g:ale_open_list                                               *g:ale_open_list* | |||||||
| g:ale_pattern_options                                   *g:ale_pattern_options* | g:ale_pattern_options                                   *g:ale_pattern_options* | ||||||
|  |  | ||||||
|   Type: |Dictionary| |   Type: |Dictionary| | ||||||
|   Default: `{}` |   Default: undefined | ||||||
|  |  | ||||||
|   This option maps regular expression patterns to |Dictionary| values for |   This option maps regular expression patterns to |Dictionary| values for | ||||||
|   buffer variables. This option can be set to automatically configure |   buffer variables. This option can be set to automatically configure | ||||||
| @ -1389,12 +1403,10 @@ g:ale_pattern_options                                   *g:ale_pattern_options* | |||||||
| g:ale_pattern_options_enabled                   *g:ale_pattern_options_enabled* | g:ale_pattern_options_enabled                   *g:ale_pattern_options_enabled* | ||||||
|  |  | ||||||
|   Type: |Number| |   Type: |Number| | ||||||
|   Default: `!empty(g:ale_pattern_options)` |   Default: undefined | ||||||
|  |  | ||||||
|   This option can be used for turning the behaviour of setting |   This option can be used for disabling pattern options. If set to `0`, ALE | ||||||
|   |g:ale_pattern_options| on or off. By default, setting a single key for |   will not set buffer variables per |g:ale_pattern_options|. | ||||||
|   |g:ale_pattern_options| will turn this option on, as long as the setting is |  | ||||||
|   configured before ALE is loaded. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| g:ale_set_balloons                                         *g:ale_set_balloons* | g:ale_set_balloons                                         *g:ale_set_balloons* | ||||||
| @ -1636,7 +1648,7 @@ g:ale_virtualenv_dir_names                         *g:ale_virtualenv_dir_names* | |||||||
| b:ale_virtualenv_dir_names                         *b:ale_virtualenv_dir_names* | b:ale_virtualenv_dir_names                         *b:ale_virtualenv_dir_names* | ||||||
|  |  | ||||||
|   Type: |List| |   Type: |List| | ||||||
|   Default: `['.env', 'env', 've-py3', 've', 'virtualenv', 'venv']` |   Default: `['.env', '.venv', 'env', 've-py3', 've', 'virtualenv', 'venv']` | ||||||
|  |  | ||||||
|   A list of directory names to be used when searching upwards from Python |   A list of directory names to be used when searching upwards from Python | ||||||
|   files to discover virtulenv directories with. |   files to discover virtulenv directories with. | ||||||
| @ -2075,6 +2087,29 @@ ALEStopAllLSPs                                                 *ALEStopAllLSPs* | |||||||
| =============================================================================== | =============================================================================== | ||||||
| 9. API                                                                *ale-api* | 9. API                                                                *ale-api* | ||||||
|  |  | ||||||
|  | ALE offers a number of functions for running linters or fixers, or defining | ||||||
|  | them. The following functions are part of the publicly documented part of that | ||||||
|  | API, and should be expected to continue to work. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ale#Env(variable_name, value)                                       *ale#Env()* | ||||||
|  |  | ||||||
|  |   Given a variable name and a string value, produce a string for including in | ||||||
|  |   a command for setting environment variables. This function can be used for | ||||||
|  |   building a command like so. > | ||||||
|  |  | ||||||
|  |     :echo string(ale#Env('VAR', 'some value') . 'command') | ||||||
|  |     'VAR=''some value'' command'      # On Linux or Mac OSX | ||||||
|  |     'set VAR="some value" && command' # On Windows | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ale#Pad(string)                                                     *ale#Pad()* | ||||||
|  |  | ||||||
|  |   Given a string or any |empty()| value, return either the string prefixed | ||||||
|  |   with a single space, or an empty string. This function can be used to build | ||||||
|  |   parts of a command from variables. | ||||||
|  |  | ||||||
|  |  | ||||||
| ale#Queue(delay, [linting_flag, buffer_number])                   *ale#Queue()* | ale#Queue(delay, [linting_flag, buffer_number])                   *ale#Queue()* | ||||||
|  |  | ||||||
|   Run linters for the current buffer, based on the filetype of the buffer, |   Run linters for the current buffer, based on the filetype of the buffer, | ||||||
| @ -2099,8 +2134,17 @@ ale#Queue(delay, [linting_flag, buffer_number])                   *ale#Queue()* | |||||||
| ale#engine#CreateDirectory(buffer)               *ale#engine#CreateDirectory()* | ale#engine#CreateDirectory(buffer)               *ale#engine#CreateDirectory()* | ||||||
|  |  | ||||||
|   Create a new temporary directory with a unique name, and manage that |   Create a new temporary directory with a unique name, and manage that | ||||||
|   directory with |ale#engine#ManageDirectory()|, so it will be removed as |   directory with |ale#engine#ManageDirectory()|, so it will be removed as soon | ||||||
|   soon as possible. |   as possible. | ||||||
|  |  | ||||||
|  |   It is advised to only call this function from a callback function for | ||||||
|  |   returning a linter command to run. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ale#engine#CreateFile(buffer)                         *ale#engine#CreateFile()* | ||||||
|  |  | ||||||
|  |   Create a new temporary file with a unique name, and manage that file with | ||||||
|  |   |ale#engine#ManageFile()|, so it will be removed as soon as possible. | ||||||
|  |  | ||||||
|   It is advised to only call this function from a callback function for |   It is advised to only call this function from a callback function for | ||||||
|   returning a linter command to run. |   returning a linter command to run. | ||||||
| @ -2206,6 +2250,10 @@ ale#linter#Define(filetype, linter)                       *ale#linter#Define()* | |||||||
|                          defined, as LSP linters handle diagnostics |                          defined, as LSP linters handle diagnostics | ||||||
|                          automatically. See |ale-lsp-linters|. |                          automatically. See |ale-lsp-linters|. | ||||||
|  |  | ||||||
|  |                          If the function named does not exist, including if | ||||||
|  |                          the function is later deleted, ALE will behave as if | ||||||
|  |                          the callback returned an empty list. | ||||||
|  |  | ||||||
|                          The keys for each item in the List will be handled in |                          The keys for each item in the List will be handled in | ||||||
|                          the following manner: |                          the following manner: | ||||||
|                                                            *ale-loclist-format* |                                                            *ale-loclist-format* | ||||||
| @ -2383,9 +2431,12 @@ ale#linter#Define(filetype, linter)                       *ale#linter#Define()* | |||||||
|                          with a callback returning an address to connect to. |                          with a callback returning an address to connect to. | ||||||
|                          ALE will not start a server automatically. |                          ALE will not start a server automatically. | ||||||
|  |  | ||||||
|                          When this argument is not empty, only one of either |                          When this argument is not empty | ||||||
|                          `language` or `language_callback` must be defined, |                          `project_root_callback` must be defined. | ||||||
|                          and `project_root_callback` must be defined. |  | ||||||
|  |                          `language` or `language_callback` can be defined to | ||||||
|  |                          describe the language for a file. The filetype will | ||||||
|  |                          be used as the language by default. | ||||||
|  |  | ||||||
|                          LSP linters handle diagnostics automatically, so |                          LSP linters handle diagnostics automatically, so | ||||||
|                          the `callback` argument must not be defined. |                          the `callback` argument must not be defined. | ||||||
| @ -2418,8 +2469,9 @@ ale#linter#Define(filetype, linter)                       *ale#linter#Define()* | |||||||
|                          being checked. This string will be sent to the LSP to |                          being checked. This string will be sent to the LSP to | ||||||
|                          tell it what type of language is being checked. |                          tell it what type of language is being checked. | ||||||
|  |  | ||||||
|                          This argument must only be set if the `lsp` argument |                          If this or `language_callback` isn't set, the | ||||||
|                          is also set to a non-empty string. |                          language will default to the value of the filetype | ||||||
|  |                          given to |ale#linter#Define|. | ||||||
|  |  | ||||||
|   `language_callback`      A |String| or |Funcref| for a callback function |   `language_callback`      A |String| or |Funcref| for a callback function | ||||||
|                          accepting a buffer number. A |String| should be |                          accepting a buffer number. A |String| should be | ||||||
| @ -2489,15 +2541,23 @@ ale#linter#Define(filetype, linter)                       *ale#linter#Define()* | |||||||
|  |  | ||||||
|   For example: > |   For example: > | ||||||
|   'command': 'ghc -fno-code -v0 %t', |   'command': 'ghc -fno-code -v0 %t', | ||||||
|  | < | ||||||
|  |   Any substring `%e` will be replaced with the escaped executable supplied | ||||||
|  |   with `executable` or `executable_callback`. This provides a convenient way | ||||||
|  |   to define a command string which needs to include a dynamic executable name, | ||||||
|  |   but which is otherwise static. | ||||||
|  |  | ||||||
|  |   For example: > | ||||||
|  |   'command': '%e --some-argument', | ||||||
| < | < | ||||||
|   The character sequence `%%` can be used to emit a literal `%` into a |   The character sequence `%%` can be used to emit a literal `%` into a | ||||||
|   command, so literal character sequences `%s` and `%t` can be escaped by |   command, so literal character sequences `%s` and `%t` can be escaped by | ||||||
|   using `%%s` and `%%t` instead, etc. |   using `%%s` and `%%t` instead, etc. | ||||||
|  |  | ||||||
|   If a callback for a command generates part of a command string which might |   If a callback for a command generates part of a command string which might | ||||||
|   possibly contain `%%`, `%s`, or `%t` where the special formatting behaviour |   possibly contain `%%`, `%s`, `%t`, or `%e`, where the special formatting | ||||||
|   is not desired, the |ale#engine#EscapeCommandPart()| function can be used to |   behavior is not desired, the |ale#engine#EscapeCommandPart()| function can | ||||||
|   replace those characters to avoid formatting issues. |   be used to replace those characters to avoid formatting issues. | ||||||
|  |  | ||||||
|                                                   *ale-linter-loading-behavior* |                                                   *ale-linter-loading-behavior* | ||||||
|                                                  *ale-linter-loading-behaviour* |                                                  *ale-linter-loading-behaviour* | ||||||
|  | |||||||
| @ -35,15 +35,11 @@ endif | |||||||
| " Set this flag so that other plugins can use it, like airline. | " Set this flag so that other plugins can use it, like airline. | ||||||
| let g:loaded_ale = 1 | let g:loaded_ale = 1 | ||||||
|  |  | ||||||
| " Set the TMPDIR environment variable if it is not set automatically. |  | ||||||
| " This can automatically fix some environments. |  | ||||||
| if has('unix') && empty($TMPDIR) |  | ||||||
|     let $TMPDIR = '/tmp' |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| " This global variable is used internally by ALE for tracking information for | " This global variable is used internally by ALE for tracking information for | ||||||
| " each buffer which linters are being run against. | " each buffer which linters are being run against. | ||||||
| let g:ale_buffer_info = {} | let g:ale_buffer_info = {} | ||||||
|  | " This global Dictionary tracks data for fixing code. Don't mess with it. | ||||||
|  | let g:ale_fix_buffer_data = {} | ||||||
|  |  | ||||||
| " User Configuration | " User Configuration | ||||||
|  |  | ||||||
|  | |||||||
| @ -92,7 +92,7 @@ add the following configuration to your `.vimrc`. | |||||||
| set laststatus=2 | set laststatus=2 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| If the statusline does not be coloured like | If the statusline is not coloured like | ||||||
|  |  | ||||||
|  |  | ||||||
| then modify `TERM` in your shell configuration (`.zshrc` for example) | then modify `TERM` in your shell configuration (`.zshrc` for example) | ||||||
|  | |||||||
| @ -18,15 +18,13 @@ uncomments a set of adjacent commented lines. | |||||||
|  |  | ||||||
| ## Installation | ## Installation | ||||||
|  |  | ||||||
| If you don't have a preferred installation method, I recommend | Install using your favorite package manager, or use Vim's built-in package | ||||||
| installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and | support: | ||||||
| then simply copy and paste: |  | ||||||
|  |  | ||||||
|     cd ~/.vim/bundle |     mkdir -p ~/.vim/pack/tpope/start | ||||||
|     git clone git://github.com/tpope/vim-commentary.git |     cd ~/.vim/pack/tpope/start | ||||||
|  |     git clone https://tpope.io/vim/commentary.git | ||||||
| Once help tags have been generated, you can view the manual with |     vim -u NONE -c "helptags commentary/doc" -c q | ||||||
| `:help commentary`. |  | ||||||
|  |  | ||||||
| ## FAQ | ## FAQ | ||||||
|  |  | ||||||
|  | |||||||
| @ -93,7 +93,7 @@ command! -range -bar Commentary call s:go(<line1>,<line2>) | |||||||
| xnoremap <expr>   <Plug>Commentary     <SID>go() | xnoremap <expr>   <Plug>Commentary     <SID>go() | ||||||
| nnoremap <expr>   <Plug>Commentary     <SID>go() | nnoremap <expr>   <Plug>Commentary     <SID>go() | ||||||
| nnoremap <expr>   <Plug>CommentaryLine <SID>go() . '_' | nnoremap <expr>   <Plug>CommentaryLine <SID>go() . '_' | ||||||
| onoremap <silent> <Plug>Commentary        :<C-U>call <SID>textobject(0)<CR> | onoremap <silent> <Plug>Commentary        :<C-U>call <SID>textobject(get(v:, 'operator', '') ==# 'c')<CR> | ||||||
| nnoremap <silent> <Plug>ChangeCommentary c:<C-U>call <SID>textobject(1)<CR> | nnoremap <silent> <Plug>ChangeCommentary c:<C-U>call <SID>textobject(1)<CR> | ||||||
| nmap <silent> <Plug>CommentaryUndo :echoerr "Change your <Plug>CommentaryUndo map to <Plug>Commentary<Plug>Commentary"<CR> | nmap <silent> <Plug>CommentaryUndo :echoerr "Change your <Plug>CommentaryUndo map to <Plug>Commentary<Plug>Commentary"<CR> | ||||||
|  |  | ||||||
| @ -102,7 +102,7 @@ if !hasmapto('<Plug>Commentary') || maparg('gc','n') ==# '' | |||||||
|   nmap gc  <Plug>Commentary |   nmap gc  <Plug>Commentary | ||||||
|   omap gc  <Plug>Commentary |   omap gc  <Plug>Commentary | ||||||
|   nmap gcc <Plug>CommentaryLine |   nmap gcc <Plug>CommentaryLine | ||||||
|   if maparg('c','n') ==# '' |   if maparg('c','n') ==# '' && !exists('v:operator') | ||||||
|     nmap cgc <Plug>ChangeCommentary |     nmap cgc <Plug>ChangeCommentary | ||||||
|   endif |   endif | ||||||
|   nmap gcu <Plug>Commentary<Plug>Commentary |   nmap gcu <Plug>Commentary<Plug>Commentary | ||||||
|  | |||||||
| @ -46,6 +46,14 @@ function! s:fnameescape(file) abort | |||||||
|   endif |   endif | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! s:tempname() abort | ||||||
|  |   let temp = resolve(tempname()) | ||||||
|  |   if has('win32') | ||||||
|  |     let temp = fnamemodify(fnamemodify(temp, ':h'), ':p').fnamemodify(temp, ':t') | ||||||
|  |   endif | ||||||
|  |   return temp | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| function! s:throw(string) abort | function! s:throw(string) abort | ||||||
|   let v:errmsg = 'fugitive: '.a:string |   let v:errmsg = 'fugitive: '.a:string | ||||||
|   throw v:errmsg |   throw v:errmsg | ||||||
| @ -83,12 +91,21 @@ function! s:executable(binary) abort | |||||||
|   return s:executables[a:binary] |   return s:executables[a:binary] | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| let s:git_versions = {} |  | ||||||
|  |  | ||||||
| function! s:git_command() abort | function! s:git_command() abort | ||||||
|   return get(g:, 'fugitive_git_command', g:fugitive_git_executable) |   return get(g:, 'fugitive_git_command', g:fugitive_git_executable) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! fugitive#Prepare(...) abort | ||||||
|  |   let args = copy(a:000) | ||||||
|  |   if empty(args) | ||||||
|  |     return g:fugitive_git_executable | ||||||
|  |   elseif args[0] !~# '^-' && args[0] =~# '[\/.]' | ||||||
|  |     let args[0] = '--git-dir=' . args[0] | ||||||
|  |   endif | ||||||
|  |   return g:fugitive_git_executable . ' ' . join(map(args, 's:shellesc(v:val)'), ' ') | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | let s:git_versions = {} | ||||||
| function! fugitive#GitVersion(...) abort | function! fugitive#GitVersion(...) abort | ||||||
|   if !has_key(s:git_versions, g:fugitive_git_executable) |   if !has_key(s:git_versions, g:fugitive_git_executable) | ||||||
|     let s:git_versions[g:fugitive_git_executable] = matchstr(system(g:fugitive_git_executable.' --version'), "\\S\\+\\ze\n") |     let s:git_versions[g:fugitive_git_executable] = matchstr(system(g:fugitive_git_executable.' --version'), "\\S\\+\\ze\n") | ||||||
| @ -173,7 +190,7 @@ function! fugitive#Init() abort | |||||||
|     call s:map('n', 'y<C-G>', ':call setreg(v:register, <SID>recall())<CR>', '<silent>') |     call s:map('n', 'y<C-G>', ':call setreg(v:register, <SID>recall())<CR>', '<silent>') | ||||||
|   endif |   endif | ||||||
|   let buffer = fugitive#buffer() |   let buffer = fugitive#buffer() | ||||||
|   if expand('%:p') =~# '://' |   if expand('%:p') =~# ':[\/][\/]' | ||||||
|     call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', '')) |     call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', '')) | ||||||
|   endif |   endif | ||||||
|   if stridx(buffer.getvar('&tags'), escape(b:git_dir, ', ')) == -1 |   if stridx(buffer.getvar('&tags'), escape(b:git_dir, ', ')) == -1 | ||||||
| @ -315,9 +332,7 @@ function! s:repo_git_command(...) dict abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:repo_git_chomp(...) dict abort | function! s:repo_git_chomp(...) dict abort | ||||||
|   let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) |   return s:sub(system(call('fugitive#Prepare', [self.git_dir] + a:000)),'\n$','') | ||||||
|   let output = git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'') |  | ||||||
|   return s:sub(system(output),'\n$','') |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:repo_git_chomp_in_tree(...) dict abort | function! s:repo_git_chomp_in_tree(...) dict abort | ||||||
| @ -429,11 +444,16 @@ call s:add_methods('repo',['keywordprg']) | |||||||
| " Section: Buffer | " Section: Buffer | ||||||
|  |  | ||||||
| function! s:DirCommitFile(path) abort | function! s:DirCommitFile(path) abort | ||||||
|   let vals = matchlist(s:shellslash(a:path), '\c^fugitive:\%(//\)\=\(.\{-\}\)\%(//\|::\)\(\w\+\)\(/.*\)\=$') |   let vals = matchlist(s:shellslash(a:path), '\c^fugitive:\%(//\)\=\(.\{-\}\)\%(//\|::\)\(\x\{40\}\|[0-3]\)\(/.*\)\=$') | ||||||
|   if empty(vals) |   if empty(vals) | ||||||
|     return ['', '', ''] |     return ['', '', ''] | ||||||
|   endif |   endif | ||||||
|   return [vals[1], (vals[2] =~# '^.$' ? ':' : '') . vals[2], vals[3]] |   return vals[1:3] | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:DirRev(url) abort | ||||||
|  |   let [dir, commit, file] = s:DirCommitFile(a:url) | ||||||
|  |   return [dir, (commit =~# '^.$' ? ':' : '') . commit . substitute(file, '^/', ':', '')] | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! fugitive#Path(url) abort | function! fugitive#Path(url) abort | ||||||
| @ -454,7 +474,7 @@ endfunction | |||||||
| let s:trees = {} | let s:trees = {} | ||||||
| let s:indexes = {} | let s:indexes = {} | ||||||
| function! s:TreeInfo(dir, commit) abort | function! s:TreeInfo(dir, commit) abort | ||||||
|   let git = g:fugitive_git_executable . ' --git-dir=' . s:shellesc(a:dir) |   let git = fugitive#Prepare(a:dir) | ||||||
|   if a:commit =~# '^:\=[0-3]$' |   if a:commit =~# '^:\=[0-3]$' | ||||||
|     let index = get(s:indexes, a:dir, []) |     let index = get(s:indexes, a:dir, []) | ||||||
|     let newftime = getftime(a:dir . '/index') |     let newftime = getftime(a:dir . '/index') | ||||||
| @ -547,7 +567,7 @@ function! fugitive#getfsize(url) abort | |||||||
|   let entry = s:PathInfo(a:url) |   let entry = s:PathInfo(a:url) | ||||||
|   if entry[4] == -2 && entry[2] ==# 'blob' && len(entry[3]) |   if entry[4] == -2 && entry[2] ==# 'blob' && len(entry[3]) | ||||||
|     let dir = s:DirCommitFile(a:url)[0] |     let dir = s:DirCommitFile(a:url)[0] | ||||||
|     let size = +system(g:fugitive_git_executable . ' ' . s:shellesc('--git-dir=' . dir) . ' cat-file -s ' . entry[3]) |     let size = +system(fugitive#Prepare(dir, 'cat-file', '-s', entry[3])) | ||||||
|     let entry[4] = v:shell_error ? -1 : size |     let entry[4] = v:shell_error ? -1 : size | ||||||
|   endif |   endif | ||||||
|   return entry[4] |   return entry[4] | ||||||
| @ -572,9 +592,8 @@ function! fugitive#readfile(url, ...) abort | |||||||
|   if entry[2] !=# 'blob' |   if entry[2] !=# 'blob' | ||||||
|     return [] |     return [] | ||||||
|   endif |   endif | ||||||
|   let [dir, commit, file] = s:DirCommitFile(a:url) |   let [dir, rev] = s:DirRev(a:url) | ||||||
|   let cmd = g:fugitive_git_executable . ' --git-dir=' . s:shellesc(dir) . |   let cmd = fugitive#Prepare(dir, 'cat-file', 'blob', rev) | ||||||
|         \ ' cat-file blob ' . s:shellesc(commit . ':' . file[1:-1]) |  | ||||||
|   if max > 0 && s:executable('head') |   if max > 0 && s:executable('head') | ||||||
|     let cmd .= '|head -' . max |     let cmd .= '|head -' . max | ||||||
|   endif |   endif | ||||||
| @ -634,7 +653,7 @@ function! s:buffer(...) abort | |||||||
|   if buffer.getvar('git_dir') !=# '' |   if buffer.getvar('git_dir') !=# '' | ||||||
|     return buffer |     return buffer | ||||||
|   endif |   endif | ||||||
|   call s:throw('not a git repository: '.expand('%:p')) |   call s:throw('not a git repository: '.bufname(buffer['#'])) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! fugitive#buffer(...) abort | function! fugitive#buffer(...) abort | ||||||
| @ -658,9 +677,9 @@ function! s:buffer_repo() dict abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:buffer_type(...) dict abort | function! s:buffer_type(...) dict abort | ||||||
|   if self.getvar('fugitive_type') != '' |   if !empty(self.getvar('fugitive_type')) | ||||||
|     let type = self.getvar('fugitive_type') |     let type = self.getvar('fugitive_type') | ||||||
|   elseif fnamemodify(self.spec(),':p') =~# '.\git/refs/\|\.git/\w*HEAD$' |   elseif fnamemodify(self.spec(),':p') =~# '\.git/refs/\|\.git/\w*HEAD$' | ||||||
|     let type = 'head' |     let type = 'head' | ||||||
|   elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == '' |   elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == '' | ||||||
|     let type = 'tree' |     let type = 'tree' | ||||||
| @ -843,9 +862,9 @@ function! s:Git(bang, mods, args) abort | |||||||
|     let git .= ' --no-pager' |     let git .= ' --no-pager' | ||||||
|   endif |   endif | ||||||
|   let args = matchstr(a:args,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=') |   let args = matchstr(a:args,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=') | ||||||
|   if exists(':terminal') && has('nvim') |   if exists(':terminal') && has('nvim') && !get(g:, 'fugitive_force_bang_command') | ||||||
|     let dir = s:repo().tree() |     let dir = s:repo().tree() | ||||||
|     if expand('%') != '' |     if len(@%) | ||||||
|       -tabedit % |       -tabedit % | ||||||
|     else |     else | ||||||
|       -tabnew |       -tabnew | ||||||
| @ -1239,7 +1258,14 @@ function! s:Commit(mods, args, ...) abort | |||||||
|         let args = a:args |         let args = a:args | ||||||
|         let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-[esp]|--edit|--interactive|--patch|--signoff)%($| )','') |         let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-[esp]|--edit|--interactive|--patch|--signoff)%($| )','') | ||||||
|         let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-c|--reedit-message|--reuse-message|-F|--file|-m|--message)%(\s+|\=)%(''[^'']*''|"%(\\.|[^"])*"|\\.|\S)*','') |         let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-c|--reedit-message|--reuse-message|-F|--file|-m|--message)%(\s+|\=)%(''[^'']*''|"%(\\.|[^"])*"|\\.|\S)*','') | ||||||
|         let args = s:gsub(args,'%(^| )@<=[%#]%(:\w)*','\=expand(submatch(0))') |         let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' | ||||||
|  |         let cwd = getcwd() | ||||||
|  |         try | ||||||
|  |           exe cd s:fnameescape(repo.tree()) | ||||||
|  |           let args = s:gsub(args,'\\@<!(\%|##=|#\<=\d+)(:\w)*','\=fnamemodify(FugitivePath(expand(submatch(1))),":." . submatch(2))') | ||||||
|  |         finally | ||||||
|  |           exe cd cwd | ||||||
|  |         endtry | ||||||
|         let args = s:sub(args, '\ze -- |$', ' --no-edit --no-interactive --no-signoff') |         let args = s:sub(args, '\ze -- |$', ' --no-edit --no-interactive --no-signoff') | ||||||
|         let args = '-F '.s:shellesc(msgfile).' '.args |         let args = '-F '.s:shellesc(msgfile).' '.args | ||||||
|         if args !~# '\%(^\| \)--cleanup\>' |         if args !~# '\%(^\| \)--cleanup\>' | ||||||
| @ -1560,10 +1586,7 @@ function! s:Edit(cmd, bang, mods, ...) abort | |||||||
|       diffupdate |       diffupdate | ||||||
|       return 'redraw|echo '.string(':!'.git.' '.args) |       return 'redraw|echo '.string(':!'.git.' '.args) | ||||||
|     else |     else | ||||||
|       let temp = resolve(tempname()) |       let temp = s:tempname() | ||||||
|       if has('win32') |  | ||||||
|         let temp = fnamemodify(fnamemodify(temp, ':h'), ':p').fnamemodify(temp, ':t') |  | ||||||
|       endif |  | ||||||
|       let s:temp_files[s:cpath(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist } |       let s:temp_files[s:cpath(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist } | ||||||
|       silent execute mods a:cmd temp |       silent execute mods a:cmd temp | ||||||
|       if a:cmd =~# 'pedit' |       if a:cmd =~# 'pedit' | ||||||
| @ -2113,7 +2136,7 @@ augroup fugitive_blame | |||||||
|   autocmd! |   autocmd! | ||||||
|   autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif |   autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif | ||||||
|   autocmd Syntax fugitiveblame call s:BlameSyntax() |   autocmd Syntax fugitiveblame call s:BlameSyntax() | ||||||
|   autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,[<f-args>])" | endif |   autocmd User Fugitive if s:buffer().type('file', 'blob', 'blame') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,[<f-args>])" | endif | ||||||
|   autocmd ColorScheme,GUIEnter * call s:RehighlightBlame() |   autocmd ColorScheme,GUIEnter * call s:RehighlightBlame() | ||||||
|   autocmd BufWinLeave * execute getwinvar(+bufwinnr(+expand('<abuf>')), 'fugitive_leave') |   autocmd BufWinLeave * execute getwinvar(+bufwinnr(+expand('<abuf>')), 'fugitive_leave') | ||||||
| augroup END | augroup END | ||||||
| @ -2157,7 +2180,7 @@ function! s:Blame(bang,line1,line2,count,args) abort | |||||||
|       if a:count |       if a:count | ||||||
|         execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g') |         execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g') | ||||||
|       else |       else | ||||||
|         let error = resolve(tempname()) |         let error = s:tempname() | ||||||
|         let temp = error.'.fugitiveblame' |         let temp = error.'.fugitiveblame' | ||||||
|         if &shell =~# 'csh' |         if &shell =~# 'csh' | ||||||
|           silent! execute '%write !('.basecmd.' > '.temp.') >& '.error |           silent! execute '%write !('.basecmd.' > '.temp.') >& '.error | ||||||
| @ -2197,12 +2220,10 @@ function! s:Blame(bang,line1,line2,count,args) abort | |||||||
|         endif |         endif | ||||||
|         let top = line('w0') + &scrolloff |         let top = line('w0') + &scrolloff | ||||||
|         let current = line('.') |         let current = line('.') | ||||||
|         if has('win32') |  | ||||||
|           let temp = fnamemodify(fnamemodify(temp, ':h'), ':p').fnamemodify(temp, ':t') |  | ||||||
|         endif |  | ||||||
|         let s:temp_files[s:cpath(temp)] = { 'dir': s:repo().dir(), 'args': cmd } |         let s:temp_files[s:cpath(temp)] = { 'dir': s:repo().dir(), 'args': cmd } | ||||||
|         exe 'keepalt leftabove vsplit '.temp |         exe 'keepalt leftabove vsplit '.temp | ||||||
|         let b:fugitive_blamed_bufnr = bufnr |         let b:fugitive_blamed_bufnr = bufnr | ||||||
|  |         let b:fugitive_type = 'blame' | ||||||
|         let w:fugitive_leave = restore |         let w:fugitive_leave = restore | ||||||
|         let b:fugitive_blame_arguments = join(a:args,' ') |         let b:fugitive_blame_arguments = join(a:args,' ') | ||||||
|         execute top |         execute top | ||||||
| @ -2633,12 +2654,10 @@ call extend(g:fugitive_browse_handlers, | |||||||
|  |  | ||||||
| " Section: File access | " Section: File access | ||||||
|  |  | ||||||
| function! s:ReplaceCmd(cmd,...) abort | function! s:WriteCmd(out, cmd, ...) abort | ||||||
|   let fn = expand('%:p') |  | ||||||
|   let tmp = tempname() |  | ||||||
|   let prefix = '' |   let prefix = '' | ||||||
|   try |   try | ||||||
|     if a:0 && a:1 != '' |     if a:0 && len(a:1) | ||||||
|       if s:winshell() |       if s:winshell() | ||||||
|         let old_index = $GIT_INDEX_FILE |         let old_index = $GIT_INDEX_FILE | ||||||
|         let $GIT_INDEX_FILE = a:1 |         let $GIT_INDEX_FILE = a:1 | ||||||
| @ -2646,23 +2665,29 @@ function! s:ReplaceCmd(cmd,...) abort | |||||||
|         let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' ' |         let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' ' | ||||||
|       endif |       endif | ||||||
|     endif |     endif | ||||||
|     let redir = ' > '.tmp |     let redir = ' > '.a:out | ||||||
|     if &shellpipe =~ '2>&1' |  | ||||||
|       let redir .= ' 2>&1' |  | ||||||
|     endif |  | ||||||
|     if s:winshell() |     if s:winshell() | ||||||
|       let cmd_escape_char = &shellxquote == '(' ?  '^' : '^^^' |       let cmd_escape_char = &shellxquote == '(' ?  '^' : '^^^' | ||||||
|       call system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').redir.'"') |       return system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').redir.'"') | ||||||
|     elseif &shell =~# 'fish' |     elseif &shell =~# 'fish' | ||||||
|       call system(' begin;'.prefix.a:cmd.redir.';end ') |       return system(' begin;'.prefix.a:cmd.redir.';end ') | ||||||
|     else |     else | ||||||
|       call system(' ('.prefix.a:cmd.redir.') ') |       return system(' ('.prefix.a:cmd.redir.') ') | ||||||
|     endif |     endif | ||||||
|   finally |   finally | ||||||
|     if exists('old_index') |     if exists('old_index') | ||||||
|       let $GIT_INDEX_FILE = old_index |       let $GIT_INDEX_FILE = old_index | ||||||
|     endif |     endif | ||||||
|   endtry |   endtry | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:ReplaceCmd(cmd, ...) abort | ||||||
|  |   let tmp = tempname() | ||||||
|  |   let err = s:WriteCmd(tmp, a:cmd, a:0 ? a:1 : '') | ||||||
|  |   if v:shell_error | ||||||
|  |     call s:throw((len(err) ? err : filereadable(tmp) ? join(readfile(tmp), ' ') : 'unknown error running ' . a:cmd)) | ||||||
|  |   endif | ||||||
|  |   let fn = expand('%:p') | ||||||
|   silent exe 'doau BufReadPre '.s:fnameescape(fn) |   silent exe 'doau BufReadPre '.s:fnameescape(fn) | ||||||
|   silent exe 'keepalt file '.tmp |   silent exe 'keepalt file '.tmp | ||||||
|   try |   try | ||||||
| @ -2729,10 +2754,10 @@ function! fugitive#BufReadStatus() abort | |||||||
|     nnoremap <buffer> <silent> <C-P> :<C-U>execute <SID>StagePrevious(v:count1)<CR> |     nnoremap <buffer> <silent> <C-P> :<C-U>execute <SID>StagePrevious(v:count1)<CR> | ||||||
|     nnoremap <buffer> <silent> - :<C-U>silent execute <SID>StageToggle(line('.'),line('.')+v:count1-1)<CR> |     nnoremap <buffer> <silent> - :<C-U>silent execute <SID>StageToggle(line('.'),line('.')+v:count1-1)<CR> | ||||||
|     xnoremap <buffer> <silent> - :<C-U>silent execute <SID>StageToggle(line("'<"),line("'>"))<CR> |     xnoremap <buffer> <silent> - :<C-U>silent execute <SID>StageToggle(line("'<"),line("'>"))<CR> | ||||||
|     nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += 1<Bar>exe fugitive#BufReadIndex()<CR> |     nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += 1<Bar>exe fugitive#BufReadStatus()<CR> | ||||||
|     nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= 1<Bar>exe fugitive#BufReadIndex()<CR> |     nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= 1<Bar>exe fugitive#BufReadStatus()<CR> | ||||||
|     nnoremap <buffer> <silent> C :<C-U>Gcommit<CR>:echohl WarningMsg<Bar>echo ':Gstatus C is deprecated in favor of cc'<Bar>echohl NONE<CR> |     nnoremap <buffer> <silent> C :<C-U>Gcommit<CR>:echohl WarningMsg<Bar>echo ':Gstatus C is deprecated in favor of cc'<Bar>echohl NONE<CR> | ||||||
|     nnoremap <buffer> <silent> cA :<C-U>Gcommit --amend --reuse-message=HEAD<CR>:echohl WarningMsg<Bar>echo ':Gstatus cA is deprecated in favor of ce'<CR> |     nnoremap <buffer> <silent> cA :<C-U>Gcommit --amend --reuse-message=HEAD<CR>:echohl WarningMsg<Bar>echo ':Gstatus cA is deprecated in favor of ce'<Bar>echohl NONE<CR> | ||||||
|     nnoremap <buffer> <silent> ca :<C-U>Gcommit --amend<CR> |     nnoremap <buffer> <silent> ca :<C-U>Gcommit --amend<CR> | ||||||
|     nnoremap <buffer> <silent> cc :<C-U>Gcommit<CR> |     nnoremap <buffer> <silent> cc :<C-U>Gcommit<CR> | ||||||
|     nnoremap <buffer> <silent> ce :<C-U>Gcommit --amend --no-edit<CR> |     nnoremap <buffer> <silent> ce :<C-U>Gcommit --amend --no-edit<CR> | ||||||
| @ -2761,21 +2786,16 @@ function! fugitive#BufReadStatus() abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! fugitive#FileRead() abort | function! fugitive#FileRead() abort | ||||||
|   try |   let [dir, rev] = s:DirRev(expand('<amatch>')) | ||||||
|     let [dir, commit, file] = s:DirCommitFile(expand('<amatch>')) |   if empty(dir) | ||||||
|     let repo = s:repo(dir) |     return "noautocmd '[read <amatch>" | ||||||
|     let path = commit . substitute(file, '^/', ':', '') |   endif | ||||||
|     let hash = repo.rev_parse(path) |   if rev !~# ':' | ||||||
|     if path =~ '^:' |     let cmd = fugitive#Prepare(dir, 'log', '--pretty=format:%B', '-1', rev) | ||||||
|       let type = 'blob' |   else | ||||||
|     else |     let cmd = fugitive#Prepare(dir, 'cat-file', '-p', rev) | ||||||
|       let type = repo.git_chomp('cat-file','-t',hash) |   endif | ||||||
|     endif |   return "'[read !" . escape(cmd, '!#%') | ||||||
|     " TODO: use count, if possible |  | ||||||
|     return "read !".escape(repo.git_command('cat-file',type,hash),'%#\') |  | ||||||
|   catch /^fugitive:/ |  | ||||||
|     return 'echoerr v:errmsg' |  | ||||||
|   endtry |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! fugitive#BufReadIndex() abort | function! fugitive#BufReadIndex() abort | ||||||
| @ -2916,10 +2936,6 @@ function! fugitive#BufReadObject() abort | |||||||
|   endtry |   endtry | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| augroup fugitive_files |  | ||||||
|   autocmd! |  | ||||||
| augroup END |  | ||||||
|  |  | ||||||
| " Section: Temp files | " Section: Temp files | ||||||
|  |  | ||||||
| if !exists('s:temp_files') | if !exists('s:temp_files') | ||||||
| @ -2931,7 +2947,7 @@ augroup fugitive_temp | |||||||
|   autocmd BufNewFile,BufReadPost * |   autocmd BufNewFile,BufReadPost * | ||||||
|         \ if has_key(s:temp_files,s:cpath(expand('<afile>:p'))) | |         \ if has_key(s:temp_files,s:cpath(expand('<afile>:p'))) | | ||||||
|         \   let b:git_dir = s:temp_files[s:cpath(expand('<afile>:p'))].dir | |         \   let b:git_dir = s:temp_files[s:cpath(expand('<afile>:p'))].dir | | ||||||
|         \   let b:git_type = 'temp' | |         \   call extend(b:, {'fugitive_type': 'temp'}, 'keep') | | ||||||
|         \   let b:git_args = s:temp_files[s:cpath(expand('<afile>:p'))].args | |         \   let b:git_args = s:temp_files[s:cpath(expand('<afile>:p'))].args | | ||||||
|         \   call FugitiveDetect(expand('<afile>:p')) | |         \   call FugitiveDetect(expand('<afile>:p')) | | ||||||
|         \   setlocal bufhidden=delete nobuflisted | |         \   setlocal bufhidden=delete nobuflisted | | ||||||
|  | |||||||
| @ -54,8 +54,8 @@ that are part of Git repositories). | |||||||
|                         dv    |:Gvdiff| |                         dv    |:Gvdiff| | ||||||
|                         O     |:Gtabedit| |                         O     |:Gtabedit| | ||||||
|                         o     |:Gsplit| |                         o     |:Gsplit| | ||||||
|                         p     |:Git| add --patch |                         P     |:Git| add --patch | ||||||
|                         p     |:Git| reset --patch (staged files) |                         P     |:Git| reset --patch (staged files) | ||||||
|                         q     close status |                         q     close status | ||||||
|                         r     reload status |                         r     reload status | ||||||
|                         S     |:Gvsplit| |                         S     |:Gvsplit| | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| " fugitive.vim - A Git wrapper so awesome, it should be illegal | " fugitive.vim - A Git wrapper so awesome, it should be illegal | ||||||
| " Maintainer:   Tim Pope <http://tpo.pe/> | " Maintainer:   Tim Pope <http://tpo.pe/> | ||||||
| " Version:      2.3 | " Version:      2.4 | ||||||
| " GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim | " GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim | ||||||
|  |  | ||||||
| if exists('g:loaded_fugitive') | if exists('g:loaded_fugitive') | ||||||
| @ -110,7 +110,7 @@ function! FugitiveExtractGitDir(path) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! FugitiveDetect(path) abort | function! FugitiveDetect(path) abort | ||||||
|   if exists('b:git_dir') && (b:git_dir ==# '' || b:git_dir =~# '/$') |   if exists('b:git_dir') && b:git_dir =~# '^$\|/$\|^fugitive:' | ||||||
|     unlet b:git_dir |     unlet b:git_dir | ||||||
|   endif |   endif | ||||||
|   if !exists('b:git_dir') |   if !exists('b:git_dir') | ||||||
| @ -156,7 +156,10 @@ augroup fugitive | |||||||
|  |  | ||||||
|   autocmd BufNewFile,BufReadPost * call FugitiveDetect(expand('%:p')) |   autocmd BufNewFile,BufReadPost * call FugitiveDetect(expand('%:p')) | ||||||
|   autocmd FileType           netrw call FugitiveDetect(fnamemodify(get(b:, 'netrw_curdir', @%), ':p')) |   autocmd FileType           netrw call FugitiveDetect(fnamemodify(get(b:, 'netrw_curdir', @%), ':p')) | ||||||
|   autocmd User NERDTreeInit,NERDTreeNewRoot call FugitiveDetect(b:NERDTree.root.path.str()) |   autocmd User NERDTreeInit,NERDTreeNewRoot | ||||||
|  |         \ if exists('b:NERDTree.root.path.str') | | ||||||
|  |         \   call FugitiveDetect(b:NERDTree.root.path.str()) | | ||||||
|  |         \ endif | ||||||
|   autocmd VimEnter * if expand('<amatch>')==''|call FugitiveDetect(getcwd())|endif |   autocmd VimEnter * if expand('<amatch>')==''|call FugitiveDetect(getcwd())|endif | ||||||
|   autocmd CmdWinEnter * call FugitiveDetect(expand('#:p')) |   autocmd CmdWinEnter * call FugitiveDetect(expand('#:p')) | ||||||
|  |  | ||||||
|  | |||||||
| @ -3,11 +3,19 @@ let s:t_string = type('') | |||||||
| " Primary functions {{{ | " Primary functions {{{ | ||||||
|  |  | ||||||
| function! gitgutter#all(force) abort | function! gitgutter#all(force) abort | ||||||
|   for bufnr in s:uniq(tabpagebuflist()) |   let visible = tabpagebuflist() | ||||||
|     let file = expand('#'.bufnr.':p') |  | ||||||
|     if !empty(file) |   for bufnr in range(1, bufnr('$') + 1) | ||||||
|       call gitgutter#init_buffer(bufnr) |     if buflisted(bufnr) | ||||||
|       call gitgutter#process_buffer(bufnr, a:force) |       let file = expand('#'.bufnr.':p') | ||||||
|  |       if !empty(file) | ||||||
|  |         if index(visible, bufnr) != -1 | ||||||
|  |           call gitgutter#init_buffer(bufnr) | ||||||
|  |           call gitgutter#process_buffer(bufnr, a:force) | ||||||
|  |         elseif a:force | ||||||
|  |           call s:reset_tick(bufnr) | ||||||
|  |         endif | ||||||
|  |       endif | ||||||
|     endif |     endif | ||||||
|   endfor |   endfor | ||||||
| endfunction | endfunction | ||||||
| @ -16,10 +24,10 @@ endfunction | |||||||
| " Finds the file's path relative to the repo root. | " Finds the file's path relative to the repo root. | ||||||
| function! gitgutter#init_buffer(bufnr) | function! gitgutter#init_buffer(bufnr) | ||||||
|   if gitgutter#utility#is_active(a:bufnr) |   if gitgutter#utility#is_active(a:bufnr) | ||||||
|     call s:setup_maps() |  | ||||||
|     let p = gitgutter#utility#repo_path(a:bufnr, 0) |     let p = gitgutter#utility#repo_path(a:bufnr, 0) | ||||||
|     if type(p) != s:t_string || empty(p) |     if type(p) != s:t_string || empty(p) | ||||||
|       call gitgutter#utility#set_repo_path(a:bufnr) |       call gitgutter#utility#set_repo_path(a:bufnr) | ||||||
|  |       call s:setup_maps() | ||||||
|     endif |     endif | ||||||
|   endif |   endif | ||||||
| endfunction | endfunction | ||||||
| @ -52,15 +60,12 @@ endfunction | |||||||
|  |  | ||||||
| function! gitgutter#disable() abort | function! gitgutter#disable() abort | ||||||
|   " get list of all buffers (across all tabs) |   " get list of all buffers (across all tabs) | ||||||
|   let buflist = [] |   for bufnr in range(1, bufnr('$') + 1) | ||||||
|   for i in range(tabpagenr('$')) |     if buflisted(bufnr) | ||||||
|     call extend(buflist, tabpagebuflist(i + 1)) |       let file = expand('#'.bufnr.':p') | ||||||
|   endfor |       if !empty(file) | ||||||
|  |         call s:clear(bufnr) | ||||||
|   for bufnr in s:uniq(buflist) |       endif | ||||||
|     let file = expand('#'.bufnr.':p') |  | ||||||
|     if !empty(file) |  | ||||||
|       call s:clear(bufnr) |  | ||||||
|     endif |     endif | ||||||
|   endfor |   endfor | ||||||
|  |  | ||||||
| @ -132,19 +137,3 @@ function! s:clear(bufnr) | |||||||
|   call gitgutter#hunk#reset(a:bufnr) |   call gitgutter#hunk#reset(a:bufnr) | ||||||
|   call s:reset_tick(a:bufnr) |   call s:reset_tick(a:bufnr) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| if exists('*uniq')  " Vim 7.4.218 |  | ||||||
|   function! s:uniq(list) |  | ||||||
|     return uniq(sort(a:list)) |  | ||||||
|   endfunction |  | ||||||
| else |  | ||||||
|   function! s:uniq(list) |  | ||||||
|     let processed = [] |  | ||||||
|     for e in a:list |  | ||||||
|       if index(processed, e) == -1 |  | ||||||
|         call add(processed, e) |  | ||||||
|       endif |  | ||||||
|     endfor |  | ||||||
|     return processed |  | ||||||
|   endfunction |  | ||||||
| endif |  | ||||||
|  | |||||||
| @ -173,26 +173,10 @@ nnoremap <silent> <Plug>GitGutterPreviewHunk :GitGutterPreviewHunk<CR> | |||||||
|  |  | ||||||
| " }}} | " }}} | ||||||
|  |  | ||||||
| function! s:flag_inactive_tabs() |  | ||||||
|   let active_tab = tabpagenr() |  | ||||||
|   for i in range(1, tabpagenr('$')) |  | ||||||
|     if i != active_tab |  | ||||||
|       call settabvar(i, 'gitgutter_force', 1) |  | ||||||
|     endif |  | ||||||
|   endfor |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| function! s:on_bufenter() | function! s:on_bufenter() | ||||||
|   if exists('t:gitgutter_didtabenter') && t:gitgutter_didtabenter |   if exists('t:gitgutter_didtabenter') && t:gitgutter_didtabenter | ||||||
|     let t:gitgutter_didtabenter = 0 |     let t:gitgutter_didtabenter = 0 | ||||||
|     let force = !g:gitgutter_terminal_reports_focus |     call gitgutter#all(!g:gitgutter_terminal_reports_focus) | ||||||
|  |  | ||||||
|     if exists('t:gitgutter_force') && t:gitgutter_force |  | ||||||
|       let t:gitgutter_force = 0 |  | ||||||
|       let force = 1 |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     call gitgutter#all(force) |  | ||||||
|   else |   else | ||||||
|     call gitgutter#init_buffer(bufnr('')) |     call gitgutter#init_buffer(bufnr('')) | ||||||
|     call gitgutter#process_buffer(bufnr(''), !g:gitgutter_terminal_reports_focus) |     call gitgutter#process_buffer(bufnr(''), !g:gitgutter_terminal_reports_focus) | ||||||
| @ -208,15 +192,15 @@ augroup gitgutter | |||||||
|  |  | ||||||
|   autocmd BufEnter * call s:on_bufenter() |   autocmd BufEnter * call s:on_bufenter() | ||||||
|  |  | ||||||
|   autocmd CursorHold,CursorHoldI            * call gitgutter#process_buffer(bufnr(''), 0) |   autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 0) | ||||||
|   autocmd FileChangedShellPost,ShellCmdPost * call gitgutter#process_buffer(bufnr(''), 1) |   autocmd FileChangedShellPost   * call gitgutter#process_buffer(bufnr(''), 1) | ||||||
|  |  | ||||||
|   " Ensure that all buffers are processed when opening vim with multiple files, e.g.: |   " Ensure that all buffers are processed when opening vim with multiple files, e.g.: | ||||||
|   " |   " | ||||||
|   "   vim -o file1 file2 |   "   vim -o file1 file2 | ||||||
|   autocmd VimEnter * if winnr() != winnr('$') | call gitgutter#all(0) | endif |   autocmd VimEnter * if winnr() != winnr('$') | call gitgutter#all(0) | endif | ||||||
|  |  | ||||||
|   autocmd FocusGained * call gitgutter#all(1) | call s:flag_inactive_tabs() |   autocmd FocusGained,ShellCmdPost * call gitgutter#all(1) | ||||||
|  |  | ||||||
|   autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights() |   autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights() | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,9 +8,16 @@ matrix: | |||||||
|     - env: SCRIPT="test -c" VIM_VERSION=vim-7.4 |     - env: SCRIPT="test -c" VIM_VERSION=vim-7.4 | ||||||
|     - env: SCRIPT="test -c" VIM_VERSION=vim-8.0 |     - env: SCRIPT="test -c" VIM_VERSION=vim-8.0 | ||||||
|     - env: SCRIPT="test -c" VIM_VERSION=nvim |     - env: SCRIPT="test -c" VIM_VERSION=nvim | ||||||
|     - env: SCRIPT=lint VIM_VERSION=vim-8.0 |     - env: ENV=vimlint SCRIPT=lint VIM_VERSION=vim-8.0 | ||||||
|  |       language: python | ||||||
|  |       python: 3.6 | ||||||
| install: | install: | ||||||
|   - ./scripts/install-vim $VIM_VERSION |   - ./scripts/install-vim $VIM_VERSION | ||||||
|   - pip install --user vim-vint covimerage codecov |   - | | ||||||
|  |     if [ "$ENV" = "vimlint" ]; then | ||||||
|  |       pip install vim-vint covimerage codecov pathlib | ||||||
|  |     else | ||||||
|  |       pip install --user vim-vint covimerage codecov pathlib | ||||||
|  |     fi | ||||||
| script: | script: | ||||||
|   - ./scripts/$SCRIPT $VIM_VERSION |   - ./scripts/$SCRIPT $VIM_VERSION | ||||||
|  | |||||||
| @ -1,5 +1,11 @@ | |||||||
| ## unplanned | ## unplanned | ||||||
|  |  | ||||||
|  | IMPROVEMENTS: | ||||||
|  | * Unify async job handling for Vim8 and Neovim. | ||||||
|  |   [[GH-1864]](https://github.com/fatih/vim-go/pull/1864) | ||||||
|  |  | ||||||
|  | ## 1.18 - (July 18, 2018) | ||||||
|  |  | ||||||
| FEATURES: | FEATURES: | ||||||
|  |  | ||||||
| * Add **:GoIfErr** command together with the `<Plug>(go-iferr)` plug key to | * Add **:GoIfErr** command together with the `<Plug>(go-iferr)` plug key to | ||||||
| @ -7,21 +13,22 @@ FEATURES: | |||||||
|   automatically which infer the type of return values and the numbers. |   automatically which infer the type of return values and the numbers. | ||||||
|   For example: |   For example: | ||||||
|  |  | ||||||
| ``` |   ``` | ||||||
| func doSomething() (string, error) { |   func doSomething() (string, error) { | ||||||
|     f, err := os.Open("file") |       f, err := os.Open("file") | ||||||
| } |   } | ||||||
| ``` |   ``` | ||||||
| Becomes: |    | ||||||
|  |   Becomes: | ||||||
|  |  | ||||||
| ``` |   ``` | ||||||
| func doSomething() (string, error) { |   func doSomething() (string, error) { | ||||||
|     f, err := os.Open("file") |       f, err := os.Open("file") | ||||||
|     if err != nil { |       if err != nil { | ||||||
|         return "", err |           return "", err | ||||||
|     } |       } | ||||||
| } |   } | ||||||
| ``` |   ``` | ||||||
|  |  | ||||||
| * Two new text objects has been added:  | * Two new text objects has been added:  | ||||||
|   * `ic` (inner comment) selects the content of the comment, excluding the start/end markers (i.e: `//`, `/*`) |   * `ic` (inner comment) selects the content of the comment, excluding the start/end markers (i.e: `//`, `/*`) | ||||||
| @ -56,6 +63,10 @@ IMPROVEMENTS: | |||||||
|   manually. [[GH-1861]](https://github.com/fatih/vim-go/pull/1861). |   manually. [[GH-1861]](https://github.com/fatih/vim-go/pull/1861). | ||||||
| * Cleanup title of terminal window. | * Cleanup title of terminal window. | ||||||
|   [[GH-1861]](https://github.com/fatih/vim-go/pull/1861). |   [[GH-1861]](https://github.com/fatih/vim-go/pull/1861). | ||||||
|  | * Add `:GoImpl` is able to complete interfaces by their full import path in | ||||||
|  |   addition to the current package name (i.e: `:GoImpl t *T github.com/BurntSushi/toml.Unmarshaller`  | ||||||
|  |   is now possible) | ||||||
|  |   [[GH-1884]](https://github.com/fatih/vim-go/pull/1884) | ||||||
|  |  | ||||||
| BUG FIXES: | BUG FIXES: | ||||||
|  |  | ||||||
| @ -76,24 +87,14 @@ BUG FIXES: | |||||||
|   [[GH-1818]](https://github.com/fatih/vim-go/pull/1818) |   [[GH-1818]](https://github.com/fatih/vim-go/pull/1818) | ||||||
| * Fix Neovim handling of guru output. | * Fix Neovim handling of guru output. | ||||||
|   [[GH-1846]](https://github.com/fatih/vim-go/pull/1846) |   [[GH-1846]](https://github.com/fatih/vim-go/pull/1846) | ||||||
|  | * Execute commands correctly when they are in $GOBIN but not $PATH. | ||||||
| BACKWARDS INCOMPATIBILITIES: |   [[GH-1866]](https://github.com/fatih/vim-go/pull/1866) | ||||||
|  | * Open files correctly with ctrlp. | ||||||
| * We switched to a [maintained fork of * gocode](https://github.com/mdempsky/gocode).  |   [[GH-1878]](https://github.com/fatih/vim-go/pull/1878) | ||||||
|   The new fork doesn't support the following settings anymore and therefore are  | * Fix checking guru binary path  | ||||||
|   invalid. Please remove them from your vimrc until those are again supported  |   [[GH-1886]](https://github.com/fatih/vim-go/pull/1886) | ||||||
|   by `gocode`. | * Add build tags to `:GoDef` if only it's present  | ||||||
|  |   [[GH-1882]](https://github.com/fatih/vim-go/pull/1882) | ||||||
| ``` |  | ||||||
| g:go_gocode_autobuild |  | ||||||
| g:go_gocode_propose_builtins |  | ||||||
| g:go_gocode_unimported_packages |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
|   Checkout the issue for more details [[GH-1851]](https://github.com/fatih/vim-go/pull/1851) |  | ||||||
|  |  | ||||||
|   |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ## 1.17 - (March 27, 2018) | ## 1.17 - (March 27, 2018) | ||||||
|  |  | ||||||
|  | |||||||
| @ -117,7 +117,7 @@ function! ctrlp#decls#enter() abort | |||||||
|     call add(s:decls, printf("%s\t%s |%s:%s:%s|\t%s", |     call add(s:decls, printf("%s\t%s |%s:%s:%s|\t%s", | ||||||
|           \ decl.ident . space, |           \ decl.ident . space, | ||||||
|           \ decl.keyword, |           \ decl.keyword, | ||||||
|           \ fnamemodify(decl.filename, ":t"), |           \ fnamemodify(decl.filename, ":."), | ||||||
|           \ decl.line, |           \ decl.line, | ||||||
|           \ decl.col, |           \ decl.col, | ||||||
|           \ decl.full, |           \ decl.full, | ||||||
|  | |||||||
| @ -30,8 +30,8 @@ function! go#cmd#Build(bang, ...) abort | |||||||
|         \ map(copy(a:000), "expand(v:val)") + |         \ map(copy(a:000), "expand(v:val)") + | ||||||
|         \ [".", "errors"] |         \ [".", "errors"] | ||||||
|  |  | ||||||
|   " Vim async. |   " Vim and Neovim async. | ||||||
|   if go#util#has_job() |   if go#util#has_job() || has('nvim') | ||||||
|     if go#config#EchoCommandInfo() |     if go#config#EchoCommandInfo() | ||||||
|       call go#util#EchoProgress("building dispatched ...") |       call go#util#EchoProgress("building dispatched ...") | ||||||
|     endif |     endif | ||||||
| @ -42,14 +42,6 @@ function! go#cmd#Build(bang, ...) abort | |||||||
|           \ 'for': 'GoBuild', |           \ 'for': 'GoBuild', | ||||||
|           \}) |           \}) | ||||||
|  |  | ||||||
|   " Nvim async. |  | ||||||
|   elseif has('nvim') |  | ||||||
|     if go#config#EchoCommandInfo() |  | ||||||
|       call go#util#EchoProgress("building dispatched ...") |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     call go#jobcontrol#Spawn(a:bang, "build", "GoBuild", args) |  | ||||||
|  |  | ||||||
|   " Vim 7.4 without async |   " Vim 7.4 without async | ||||||
|   else |   else | ||||||
|     let default_makeprg = &makeprg |     let default_makeprg = &makeprg | ||||||
| @ -297,44 +289,7 @@ function s:cmd_job(args) abort | |||||||
|   " autowrite is not enabled for jobs |   " autowrite is not enabled for jobs | ||||||
|   call go#cmd#autowrite() |   call go#cmd#autowrite() | ||||||
|  |  | ||||||
|   function! s:complete(job, exit_status, data) closure abort |   call go#job#Spawn(a:args.cmd, a:args) | ||||||
|     let status = { |  | ||||||
|           \ 'desc': 'last status', |  | ||||||
|           \ 'type': a:args.cmd[1], |  | ||||||
|           \ 'state': "success", |  | ||||||
|           \ } |  | ||||||
|  |  | ||||||
|     if a:exit_status |  | ||||||
|       let status.state = "failed" |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     let elapsed_time = reltimestr(reltime(started_at)) |  | ||||||
|     " strip whitespace |  | ||||||
|     let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') |  | ||||||
|     let status.state .= printf(" (%ss)", elapsed_time) |  | ||||||
|  |  | ||||||
|     call go#statusline#Update(status_dir, status) |  | ||||||
|   endfunction |  | ||||||
|  |  | ||||||
|   let a:args.complete = funcref('s:complete') |  | ||||||
|   let callbacks = go#job#Spawn(a:args) |  | ||||||
|  |  | ||||||
|   let start_options = { |  | ||||||
|         \ 'callback': callbacks.callback, |  | ||||||
|         \ 'exit_cb': callbacks.exit_cb, |  | ||||||
|         \ 'close_cb': callbacks.close_cb, |  | ||||||
|         \ } |  | ||||||
|  |  | ||||||
|   " pre start |  | ||||||
|   let dir = getcwd() |  | ||||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |  | ||||||
|   let jobdir = fnameescape(expand("%:p:h")) |  | ||||||
|   execute cd . jobdir |  | ||||||
|  |  | ||||||
|   call job_start(a:args.cmd, start_options) |  | ||||||
|  |  | ||||||
|   " post start |  | ||||||
|   execute cd . fnameescape(dir) |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " vim: sw=2 ts=2 et | " vim: sw=2 ts=2 et | ||||||
|  | |||||||
| @ -48,12 +48,13 @@ function! go#coverage#Buffer(bang, ...) abort | |||||||
|     call go#util#EchoProgress("testing...") |     call go#util#EchoProgress("testing...") | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   if go#util#has_job() |   if go#util#has_job() || has('nvim') | ||||||
|     call s:coverage_job({ |     call s:coverage_job({ | ||||||
|           \ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname] + a:000, |           \ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname] + a:000, | ||||||
|           \ 'complete': function('s:coverage_callback', [l:tmpname]), |           \ 'complete': function('s:coverage_callback', [l:tmpname]), | ||||||
|           \ 'bang': a:bang, |           \ 'bang': a:bang, | ||||||
|           \ 'for': 'GoTest', |           \ 'for': 'GoTest', | ||||||
|  |           \ 'statustype': 'coverage', | ||||||
|           \ }) |           \ }) | ||||||
|     return |     return | ||||||
|   endif |   endif | ||||||
| @ -63,24 +64,8 @@ function! go#coverage#Buffer(bang, ...) abort | |||||||
|     call extend(args, a:000) |     call extend(args, a:000) | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   let disabled_term = 0 |  | ||||||
|   if go#config#TermEnabled() |  | ||||||
|     let disabled_term = 1 |  | ||||||
|     call go#config#SetTermEnabled(0) |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   let id = call('go#test#Test', args) |   let id = call('go#test#Test', args) | ||||||
|  |  | ||||||
|   if disabled_term |  | ||||||
|     call go#config#SetTermEnabled(1) |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   if has('nvim') |  | ||||||
|     call go#jobcontrol#AddHandler(function('s:coverage_handler')) |  | ||||||
|     let s:coverage_handler_jobs[id] = l:tmpname |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   if go#util#ShellError() == 0 |   if go#util#ShellError() == 0 | ||||||
|     call go#coverage#overlay(l:tmpname) |     call go#coverage#overlay(l:tmpname) | ||||||
|   endif |   endif | ||||||
| @ -104,7 +89,7 @@ endfunction | |||||||
| " a new HTML coverage page from that profile in a new browser | " a new HTML coverage page from that profile in a new browser | ||||||
| function! go#coverage#Browser(bang, ...) abort | function! go#coverage#Browser(bang, ...) abort | ||||||
|   let l:tmpname = tempname() |   let l:tmpname = tempname() | ||||||
|   if go#util#has_job() |   if go#util#has_job() || has('nvim') | ||||||
|     call s:coverage_job({ |     call s:coverage_job({ | ||||||
|           \ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname], |           \ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname], | ||||||
|           \ 'complete': function('s:coverage_browser_callback', [l:tmpname]), |           \ 'complete': function('s:coverage_browser_callback', [l:tmpname]), | ||||||
| @ -120,11 +105,6 @@ function! go#coverage#Browser(bang, ...) abort | |||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   let id = call('go#test#Test', args) |   let id = call('go#test#Test', args) | ||||||
|   if has('nvim') |  | ||||||
|     call go#jobcontrol#AddHandler(function('s:coverage_browser_handler')) |  | ||||||
|     let s:coverage_browser_handler_jobs[id] = l:tmpname |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   if go#util#ShellError() == 0 |   if go#util#ShellError() == 0 | ||||||
|     call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . l:tmpname]) |     call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . l:tmpname]) | ||||||
| @ -275,48 +255,17 @@ function s:coverage_job(args) | |||||||
|   " autowrite is not enabled for jobs |   " autowrite is not enabled for jobs | ||||||
|   call go#cmd#autowrite() |   call go#cmd#autowrite() | ||||||
|  |  | ||||||
|   let status_dir =  expand('%:p:h') |   let disabled_term = 0 | ||||||
|   let Complete = a:args.complete |   if go#config#TermEnabled() | ||||||
|   function! s:complete(job, exit_status, data) closure |     let disabled_term = 1 | ||||||
|     let status = { |     call go#config#SetTermEnabled(0) | ||||||
|           \ 'desc': 'last status', |   endif | ||||||
|           \ 'type': "coverage", |  | ||||||
|           \ 'state': "finished", |  | ||||||
|           \ } |  | ||||||
|  |  | ||||||
|     if a:exit_status |   call go#job#Spawn(a:args.cmd, a:args) | ||||||
|       let status.state = "failed" |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     call go#statusline#Update(status_dir, status) |   if disabled_term | ||||||
|     return Complete(a:job, a:exit_status, a:data) |     call go#config#SetTermEnabled(1) | ||||||
|   endfunction |   endif | ||||||
|  |  | ||||||
|   let a:args.complete = funcref('s:complete') |  | ||||||
|   let callbacks = go#job#Spawn(a:args) |  | ||||||
|  |  | ||||||
|   let start_options = { |  | ||||||
|         \ 'callback': callbacks.callback, |  | ||||||
|         \ 'exit_cb': callbacks.exit_cb, |  | ||||||
|         \ 'close_cb': callbacks.close_cb, |  | ||||||
|         \ } |  | ||||||
|  |  | ||||||
|   " pre start |  | ||||||
|   let dir = getcwd() |  | ||||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |  | ||||||
|   let jobdir = fnameescape(expand("%:p:h")) |  | ||||||
|   execute cd . jobdir |  | ||||||
|  |  | ||||||
|   call go#statusline#Update(status_dir, { |  | ||||||
|         \ 'desc': "current status", |  | ||||||
|         \ 'type': "coverage", |  | ||||||
|         \ 'state': "started", |  | ||||||
|         \}) |  | ||||||
|  |  | ||||||
|   call job_start(a:args.cmd, start_options) |  | ||||||
|  |  | ||||||
|   " post start |  | ||||||
|   execute cd . fnameescape(dir) |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " coverage_callback is called when the coverage execution is finished | " coverage_callback is called when the coverage execution is finished | ||||||
| @ -336,39 +285,4 @@ function! s:coverage_browser_callback(coverfile, job, exit_status, data) | |||||||
|   call delete(a:coverfile) |   call delete(a:coverfile) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " ----------------------- |  | ||||||
| " | Neovim job handlers | |  | ||||||
| " ----------------------- |  | ||||||
|  |  | ||||||
| let s:coverage_handler_jobs = {} |  | ||||||
| let s:coverage_browser_handler_jobs = {} |  | ||||||
|  |  | ||||||
| function! s:coverage_handler(job, exit_status, data) abort |  | ||||||
|   if !has_key(s:coverage_handler_jobs, a:job.id) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|   let l:tmpname = s:coverage_handler_jobs[a:job.id] |  | ||||||
|   if a:exit_status == 0 |  | ||||||
|     call go#coverage#overlay(l:tmpname) |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   call delete(l:tmpname) |  | ||||||
|   unlet s:coverage_handler_jobs[a:job.id] |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| function! s:coverage_browser_handler(job, exit_status, data) abort |  | ||||||
|   if !has_key(s:coverage_browser_handler_jobs, a:job.id) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   let l:tmpname = s:coverage_browser_handler_jobs[a:job.id] |  | ||||||
|   if a:exit_status == 0 |  | ||||||
|     call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . l:tmpname]) |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   call delete(l:tmpname) |  | ||||||
|   unlet s:coverage_browser_handler_jobs[a:job.id] |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
|  |  | ||||||
| " vim: sw=2 ts=2 et | " vim: sw=2 ts=2 et | ||||||
|  | |||||||
| @ -26,7 +26,12 @@ function! go#def#Jump(mode) abort | |||||||
|     endif |     endif | ||||||
|  |  | ||||||
|   elseif bin_name == 'guru' |   elseif bin_name == 'guru' | ||||||
|     let cmd = [bin_name, '-tags', go#config#BuildTags()] |     let cmd = [go#path#CheckBinPath(bin_name)] | ||||||
|  |     let buildtags = go#config#BuildTags() | ||||||
|  |     if buildtags isnot '' | ||||||
|  |       let cmd += ['-tags', buildtags] | ||||||
|  |     endif | ||||||
|  |  | ||||||
|     let stdin_content = "" |     let stdin_content = "" | ||||||
|  |  | ||||||
|     if &modified |     if &modified | ||||||
| @ -278,13 +283,7 @@ function! go#def#Stack(...) abort | |||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function s:def_job(args) abort | function s:def_job(args) abort | ||||||
|   let callbacks = go#job#Spawn(a:args) |   let l:start_options = go#job#Options(a:args) | ||||||
|  |  | ||||||
|   let start_options = { |  | ||||||
|         \ 'callback': callbacks.callback, |  | ||||||
|         \ 'exit_cb': callbacks.exit_cb, |  | ||||||
|         \ 'close_cb': callbacks.close_cb, |  | ||||||
|         \ } |  | ||||||
|  |  | ||||||
|   if &modified |   if &modified | ||||||
|     let l:tmpname = tempname() |     let l:tmpname = tempname() | ||||||
| @ -293,7 +292,7 @@ function s:def_job(args) abort | |||||||
|     let l:start_options.in_name = l:tmpname |     let l:start_options.in_name = l:tmpname | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   call job_start(a:args.cmd, start_options) |   call go#job#Start(a:args.cmd, start_options) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " vim: sw=2 ts=2 et | " vim: sw=2 ts=2 et | ||||||
|  | |||||||
| @ -101,13 +101,29 @@ function! s:root_dirs() abort | |||||||
|   return dirs |   return dirs | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:go_packages(dirs) abort | function! s:go_packages(dirs, arglead) abort | ||||||
|   let pkgs = [] |   let pkgs = [] | ||||||
|   for d in a:dirs |   for dir in a:dirs | ||||||
|     let pkg_root = expand(d . '/pkg/' . go#util#osarch()) |       " this may expand to multiple lines | ||||||
|     call extend(pkgs, split(globpath(pkg_root, '**/*.a', 1), "\n")) |       let scr_root = expand(dir . '/src/') | ||||||
|  |       for pkg in split(globpath(scr_root, a:arglead.'*'), "\n") | ||||||
|  |           if isdirectory(pkg) | ||||||
|  |               let pkg .= '/' | ||||||
|  |           elseif pkg !~ '\.a$' | ||||||
|  |               continue | ||||||
|  |           endif | ||||||
|  |  | ||||||
|  |           " without this the result can have duplicates in form of | ||||||
|  |           " 'encoding/json' and '/encoding/json/' | ||||||
|  |           let pkg = go#util#StripPathSep(pkg) | ||||||
|  |  | ||||||
|  |           " remove the scr root and keep the package in tact | ||||||
|  |           let pkg = substitute(pkg, scr_root, "", "") | ||||||
|  |           call add(pkgs, pkg) | ||||||
|  |       endfor | ||||||
|   endfor |   endfor | ||||||
|   return map(pkgs, "fnamemodify(v:val, ':t:r')") |  | ||||||
|  |   return pkgs | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:interface_list(pkg) abort | function! s:interface_list(pkg) abort | ||||||
| @ -124,13 +140,24 @@ endfunction | |||||||
| " Complete package and interface for {interface} | " Complete package and interface for {interface} | ||||||
| function! go#impl#Complete(arglead, cmdline, cursorpos) abort | function! go#impl#Complete(arglead, cmdline, cursorpos) abort | ||||||
|   let words = split(a:cmdline, '\s\+', 1) |   let words = split(a:cmdline, '\s\+', 1) | ||||||
|  |  | ||||||
|   if words[-1] ==# '' |   if words[-1] ==# '' | ||||||
|     return s:uniq(sort(s:go_packages(s:root_dirs()))) |     " if no words are given, just start completing the first package we found | ||||||
|   elseif words[-1] =~# '^\h\w*$' |     return s:uniq(sort(s:go_packages(s:root_dirs(), a:arglead))) | ||||||
|     return s:uniq(sort(filter(s:go_packages(s:root_dirs()), 'stridx(v:val, words[-1]) == 0'))) |   elseif words[-1] =~# '^\(\h\w.*\.\%(\h\w*\)\=$\)\@!\S*$' | ||||||
|   elseif words[-1] =~# '^\h\w*\.\%(\h\w*\)\=$' |     " start matching go packages. It's negate match of the below match | ||||||
|     let [pkg, interface] = split(words[-1], '\.', 1) |     return s:uniq(sort(s:go_packages(s:root_dirs(), a:arglead))) | ||||||
|     echomsg pkg |   elseif words[-1] =~# '^\h\w.*\.\%(\h\w*\)\=$' | ||||||
|  |     " match the following, anything that could indicate an interface candidate | ||||||
|  |     "  | ||||||
|  |     "  io. | ||||||
|  |     "  io.Wr | ||||||
|  |     "  github.com/fatih/color. | ||||||
|  |     "  github.com/fatih/color.U | ||||||
|  |     "  github.com/fatih/color.Un | ||||||
|  |     let splitted = split(words[-1], '\.', 1) | ||||||
|  |     let pkg = join(splitted[:-2], '.') | ||||||
|  |     let interface = splitted[-1] | ||||||
|     return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]'))) |     return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]'))) | ||||||
|   else |   else | ||||||
|     return [] |     return [] | ||||||
|  | |||||||
| @ -1,7 +1,25 @@ | |||||||
| " Spawn returns callbacks to be used with job_start. It is abstracted to be | " Spawn starts an asynchronous job. See the description of go#job#Options to | ||||||
|  | " understand the args parameter. | ||||||
|  | " | ||||||
|  | " Spawn returns a job. | ||||||
|  | function! go#job#Spawn(cmd, args) | ||||||
|  |   let l:options = go#job#Options(a:args) | ||||||
|  |   return go#job#Start(a:cmd, l:options) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " Spawn starts an asynchronous job. See the description of go#job#Options to | ||||||
|  | " understand the args parameter. | ||||||
|  | " | ||||||
|  | " Spawn returns a job. | ||||||
|  | function! go#job#Spawn(cmd, args) | ||||||
|  |   let l:options = go#job#Options(a:args) | ||||||
|  |   return go#job#Start(a:cmd, l:options) | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " Options returns callbacks to be used with job_start. It is abstracted to be | ||||||
| " used with various go commands, such as build, test, install, etc.. This | " used with various go commands, such as build, test, install, etc.. This | ||||||
| " allows us to avoid writing the same callback over and over for some | " allows us to avoid writing the same callback over and over for some | ||||||
| " commands. It's fully customizable so each command can change it to it's own | " commands. It's fully customizable so each command can change it to its own | ||||||
| " logic. | " logic. | ||||||
| " | " | ||||||
| " args is a dictionary with the these keys: | " args is a dictionary with the these keys: | ||||||
| @ -10,9 +28,16 @@ | |||||||
| "   'bang': | "   'bang': | ||||||
| "     Set to 0 to jump to the first error in the error list. | "     Set to 0 to jump to the first error in the error list. | ||||||
| "     Defaults to 0. | "     Defaults to 0. | ||||||
|  | "   'statustype': | ||||||
|  | "     The status type to use when updating the status. | ||||||
|  | "     See statusline.vim. | ||||||
| "   'for': | "   'for': | ||||||
| "     The g:go_list_type_command key to use to get the error list type to use. | "     The g:go_list_type_command key to use to get the error list type to use. | ||||||
| "     Defaults to '_job' | "     Defaults to '_job' | ||||||
|  | "   'errorformat': | ||||||
|  | "     The errorformat string to use when parsing errors. Defaults to | ||||||
|  | "     &errorformat. | ||||||
|  | "     See :help 'errorformat'. | ||||||
| "   'complete': | "   'complete': | ||||||
| "     A function to call after the job exits and the channel is closed. The | "     A function to call after the job exits and the channel is closed. The | ||||||
| "     function will be passed three arguments: the job, its exit code, and the | "     function will be passed three arguments: the job, its exit code, and the | ||||||
| @ -30,22 +55,28 @@ | |||||||
| "   'close_cb': | "   'close_cb': | ||||||
| "     A function suitable to be passed as a job close_cb handler. See | "     A function suitable to be passed as a job close_cb handler. See | ||||||
| "     job-close_cb. | "     job-close_cb. | ||||||
| function go#job#Spawn(args) | "   'cwd': | ||||||
|  | "     The path to the directory which contains the current buffer. | ||||||
|  | function! go#job#Options(args) | ||||||
|   let cbs = {} |   let cbs = {} | ||||||
|   let state = { |   let state = { | ||||||
|         \ 'winid': win_getid(winnr()), |         \ 'winid': win_getid(winnr()), | ||||||
|         \ 'dir': getcwd(), |         \ 'dir': getcwd(), | ||||||
|         \ 'jobdir': fnameescape(expand("%:p:h")), |         \ 'jobdir': fnameescape(expand("%:p:h")), | ||||||
|         \ 'messages': [], |         \ 'messages': [], | ||||||
|         \ 'args': a:args.cmd, |  | ||||||
|         \ 'bang': 0, |         \ 'bang': 0, | ||||||
|         \ 'for': "_job", |         \ 'for': "_job", | ||||||
|         \ 'exited': 0, |         \ 'exited': 0, | ||||||
|         \ 'exit_status': 0, |         \ 'exit_status': 0, | ||||||
|         \ 'closed': 0, |         \ 'closed': 0, | ||||||
|         \ 'errorformat': &errorformat |         \ 'errorformat': &errorformat, | ||||||
|  |         \ 'statustype' : '' | ||||||
|       \ } |       \ } | ||||||
|  |  | ||||||
|  |   if has("patch-8.0.0902") || has('nvim') | ||||||
|  |     let cbs.cwd = state.jobdir | ||||||
|  |   endif | ||||||
|  |  | ||||||
|   if has_key(a:args, 'bang') |   if has_key(a:args, 'bang') | ||||||
|     let state.bang = a:args.bang |     let state.bang = a:args.bang | ||||||
|   endif |   endif | ||||||
| @ -54,14 +85,78 @@ function go#job#Spawn(args) | |||||||
|     let state.for = a:args.for |     let state.for = a:args.for | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|  |   if has_key(a:args, 'statustype') | ||||||
|  |     let state.statustype = a:args.statustype | ||||||
|  |   endif | ||||||
|  |  | ||||||
|  |   if has_key(a:args, 'errorformat') | ||||||
|  |     let state.errorformat = a:args.errorformat | ||||||
|  |   endif | ||||||
|  |  | ||||||
|   " do nothing in state.complete by default. |   " do nothing in state.complete by default. | ||||||
|   function state.complete(job, exit_status, data) |   function state.complete(job, exit_status, data) | ||||||
|   endfunction |   endfunction | ||||||
|  |  | ||||||
|  |   function state.show_status(job, exit_status) dict | ||||||
|  |     if go#config#EchoCommandInfo() | ||||||
|  |       let prefix = "" | ||||||
|  |       if self.statustype != '' | ||||||
|  |         let prefix = '[' . self.statustype . '] ' | ||||||
|  |       endif | ||||||
|  |       if a:exit_status == 0 | ||||||
|  |         call go#util#EchoSuccess(prefix . "SUCCESS") | ||||||
|  |       else | ||||||
|  |         call go#util#EchoError(prefix . "FAIL") | ||||||
|  |       endif | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     if self.statustype == '' | ||||||
|  |       return | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let status = { | ||||||
|  |           \ 'desc': 'last status', | ||||||
|  |           \ 'type': self.statustype, | ||||||
|  |           \ 'state': "success", | ||||||
|  |           \ } | ||||||
|  |  | ||||||
|  |     if a:exit_status | ||||||
|  |       let status.state = "failed" | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     if has_key(self, 'started_at') | ||||||
|  |       let elapsed_time = reltimestr(reltime(self.started_at)) | ||||||
|  |       " strip whitespace | ||||||
|  |       let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') | ||||||
|  |       let status.state .= printf(" (%ss)", elapsed_time) | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     call go#statusline#Update(self.jobdir, status) | ||||||
|  |   endfunction | ||||||
|  |  | ||||||
|   if has_key(a:args, 'complete') |   if has_key(a:args, 'complete') | ||||||
|     let state.complete = a:args.complete |     let state.complete = a:args.complete | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|  |   function! s:start(args) dict | ||||||
|  |     if self.statustype != '' | ||||||
|  |       let status = { | ||||||
|  |             \ 'desc': 'current status', | ||||||
|  |             \ 'type': self.statustype, | ||||||
|  |             \ 'state': "started", | ||||||
|  |             \ } | ||||||
|  |  | ||||||
|  |       call go#statusline#Update(self.jobdir, status) | ||||||
|  |     endif | ||||||
|  |     let self.started_at = reltime() | ||||||
|  |   endfunction | ||||||
|  |   " explicitly bind _start to state so that within it, self will | ||||||
|  |   " always refer to state. See :help Partial for more information. | ||||||
|  |   " | ||||||
|  |   " _start is intended only for internal use and should not be referenced | ||||||
|  |   " outside of this file. | ||||||
|  |   let cbs._start = function('s:start', [''], state) | ||||||
|  |  | ||||||
|   function! s:callback(chan, msg) dict |   function! s:callback(chan, msg) dict | ||||||
|     call add(self.messages, a:msg) |     call add(self.messages, a:msg) | ||||||
|   endfunction |   endfunction | ||||||
| @ -73,15 +168,9 @@ function go#job#Spawn(args) | |||||||
|     let self.exit_status = a:exitval |     let self.exit_status = a:exitval | ||||||
|     let self.exited = 1 |     let self.exited = 1 | ||||||
|  |  | ||||||
|     if go#config#EchoCommandInfo() |     call self.show_status(a:job, a:exitval) | ||||||
|       if a:exitval == 0 |  | ||||||
|         call go#util#EchoSuccess("SUCCESS") |  | ||||||
|       else |  | ||||||
|         call go#util#EchoError("FAILED") |  | ||||||
|       endif |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     if self.closed |     if self.closed || has('nvim') | ||||||
|       call self.complete(a:job, self.exit_status, self.messages) |       call self.complete(a:job, self.exit_status, self.messages) | ||||||
|       call self.show_errors(a:job, self.exit_status, self.messages) |       call self.show_errors(a:job, self.exit_status, self.messages) | ||||||
|     endif |     endif | ||||||
| @ -123,14 +212,14 @@ function go#job#Spawn(args) | |||||||
|  |  | ||||||
|     let out = join(self.messages, "\n") |     let out = join(self.messages, "\n") | ||||||
|  |  | ||||||
|     let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |     let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' | ||||||
|     try |     try | ||||||
|       " parse the errors relative to self.jobdir |       " parse the errors relative to self.jobdir | ||||||
|       execute cd self.jobdir |       execute l:cd self.jobdir | ||||||
|       call go#list#ParseFormat(l:listtype, self.errorformat, out, self.for) |       call go#list#ParseFormat(l:listtype, self.errorformat, out, self.for) | ||||||
|       let errors = go#list#Get(l:listtype) |       let errors = go#list#Get(l:listtype) | ||||||
|     finally |     finally | ||||||
|       execute cd . fnameescape(self.dir) |       execute l:cd fnameescape(self.dir) | ||||||
|     endtry |     endtry | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -149,7 +238,178 @@ function go#job#Spawn(args) | |||||||
|     endif |     endif | ||||||
|   endfunction |   endfunction | ||||||
|  |  | ||||||
|  |   if has('nvim') | ||||||
|  |     return s:neooptions(cbs) | ||||||
|  |   endif | ||||||
|  |  | ||||||
|   return cbs |   return cbs | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! go#job#Start(cmd, options) | ||||||
|  |   let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' | ||||||
|  |   let l:options = copy(a:options) | ||||||
|  |  | ||||||
|  |   if !has_key(l:options, 'cwd') | ||||||
|  |     " pre start | ||||||
|  |     let dir = getcwd() | ||||||
|  |     execute l:cd fnameescape(expand("%:p:h")) | ||||||
|  |   endif | ||||||
|  |  | ||||||
|  |   if has_key(l:options, '_start') | ||||||
|  |     call l:options._start() | ||||||
|  |     " remove _start to play nicely with vim (when vim encounters an unexpected | ||||||
|  |     " job option it reports an "E475: invalid argument" error. | ||||||
|  |     unlet l:options._start | ||||||
|  |   endif | ||||||
|  |  | ||||||
|  |   if has('nvim') | ||||||
|  |     let l:input = [] | ||||||
|  |     if has_key(l:options, 'in_io') && l:options.in_io ==# 'file' && !empty(l:options.in_name) | ||||||
|  |       let l:input = readfile(l:options.in_name, 1) | ||||||
|  |     endif | ||||||
|  |  | ||||||
|  |     let job = jobstart(a:cmd, l:options) | ||||||
|  |  | ||||||
|  |     if len(l:input) > 0 | ||||||
|  |       call chansend(job, l:input) | ||||||
|  |       " close stdin to signal that no more bytes will be sent. | ||||||
|  |       call chanclose(job, 'stdin') | ||||||
|  |     endif | ||||||
|  |   else | ||||||
|  |     let job = job_start(a:cmd, l:options) | ||||||
|  |   endif | ||||||
|  |  | ||||||
|  |   if !has_key(l:options, 'cwd') | ||||||
|  |     " post start | ||||||
|  |     execute l:cd fnameescape(dir) | ||||||
|  |   endif | ||||||
|  |  | ||||||
|  |   return job | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | " s:neooptions returns a dictionary of job options suitable for use by Neovim | ||||||
|  | " based on a dictionary of job options suitable for Vim8. | ||||||
|  | function! s:neooptions(options) | ||||||
|  |   let l:options = {} | ||||||
|  |   let l:options['stdout_buf'] = '' | ||||||
|  |   let l:options['stderr_buf'] = '' | ||||||
|  |  | ||||||
|  |   for key in keys(a:options) | ||||||
|  |       if key == 'callback' | ||||||
|  |         let l:options['callback'] = a:options['callback'] | ||||||
|  |  | ||||||
|  |         if !has_key(a:options, 'out_cb') | ||||||
|  |           let l:options['stdout_buffered'] = v:true | ||||||
|  |  | ||||||
|  |           function! s:callback2on_stdout(ch, data, event) dict | ||||||
|  |             let l:data = a:data | ||||||
|  |             let l:data[0] = self.stdout_buf . l:data[0] | ||||||
|  |             let self.stdout_buf = "" | ||||||
|  |  | ||||||
|  |             if l:data[-1] != "" | ||||||
|  |               let self.stdout_buf = l:data[-1] | ||||||
|  |             endif | ||||||
|  |  | ||||||
|  |             let l:data = l:data[:-2] | ||||||
|  |             if len(l:data) == 0 | ||||||
|  |               return | ||||||
|  |             endif | ||||||
|  |  | ||||||
|  |             call self.callback(a:ch, join(l:data, "\n")) | ||||||
|  |           endfunction | ||||||
|  |           let l:options['on_stdout'] = function('s:callback2on_stdout', [], l:options) | ||||||
|  |         endif | ||||||
|  |  | ||||||
|  |         if !has_key(a:options, 'err_cb') | ||||||
|  |           let l:options['stderr_buffered'] = v:true | ||||||
|  |  | ||||||
|  |           function! s:callback2on_stderr(ch, data, event) dict | ||||||
|  |             let l:data = a:data | ||||||
|  |             let l:data[0] = self.stderr_buf . l:data[0] | ||||||
|  |             let self.stderr_buf = "" | ||||||
|  |  | ||||||
|  |             if l:data[-1] != "" | ||||||
|  |               let self.stderr_buf = l:data[-1] | ||||||
|  |             endif | ||||||
|  |  | ||||||
|  |             let l:data = l:data[:-2] | ||||||
|  |             if len(l:data) == 0 | ||||||
|  |               return | ||||||
|  |             endif | ||||||
|  |  | ||||||
|  |             call self.callback(a:ch, join(l:data, "\n")) | ||||||
|  |           endfunction | ||||||
|  |           let l:options['on_stderr'] = function('s:callback2on_stderr', [], l:options) | ||||||
|  |         endif | ||||||
|  |  | ||||||
|  |         continue | ||||||
|  |       endif | ||||||
|  |  | ||||||
|  |       if key == 'out_cb' | ||||||
|  |         let l:options['out_cb'] = a:options['out_cb'] | ||||||
|  |         let l:options['stdout_buffered'] = v:true | ||||||
|  |         function! s:on_stdout(ch, data, event) dict | ||||||
|  |           let l:data = a:data | ||||||
|  |           let l:data[0] = self.stdout_buf . l:data[0] | ||||||
|  |           let self.stdout_buf = "" | ||||||
|  |  | ||||||
|  |           if l:data[-1] != "" | ||||||
|  |             let self.stdout_buf = l:data[-1] | ||||||
|  |           endif | ||||||
|  |  | ||||||
|  |           let l:data = l:data[:-2] | ||||||
|  |           if len(l:data) == 0 | ||||||
|  |             return | ||||||
|  |           endif | ||||||
|  |  | ||||||
|  |           call self.out_cb(a:ch, join(l:data, "\n")) | ||||||
|  |         endfunction | ||||||
|  |         let l:options['on_stdout'] = function('s:on_stdout', [], l:options) | ||||||
|  |  | ||||||
|  |         continue | ||||||
|  |       endif | ||||||
|  |  | ||||||
|  |       if key == 'err_cb' | ||||||
|  |         let l:options['err_cb'] = a:options['err_cb'] | ||||||
|  |         let l:options['stderr_buffered'] = v:true | ||||||
|  |         function! s:on_stderr(ch, data, event) dict | ||||||
|  |           let l:data = a:data | ||||||
|  |           let l:data[0] = self.stderr_buf . l:data[0] | ||||||
|  |           let self.stderr_buf = "" | ||||||
|  |  | ||||||
|  |           if l:data[-1] != "" | ||||||
|  |             let self.stderr_buf = l:data[-1] | ||||||
|  |           endif | ||||||
|  |  | ||||||
|  |           let l:data = l:data[:-2] | ||||||
|  |           if len(l:data) == 0 | ||||||
|  |             return | ||||||
|  |           endif | ||||||
|  |  | ||||||
|  |           call self.err_cb(a:ch, join(l:data, "\n")) | ||||||
|  |         endfunction | ||||||
|  |         let l:options['on_stderr'] = function('s:on_stderr', [], l:options) | ||||||
|  |  | ||||||
|  |         continue | ||||||
|  |       endif | ||||||
|  |  | ||||||
|  |       if key == 'exit_cb' | ||||||
|  |         let l:options['exit_cb'] = a:options['exit_cb'] | ||||||
|  |         function! s:on_exit(jobid, exitval, event) dict | ||||||
|  |           call self.exit_cb(a:jobid, a:exitval) | ||||||
|  |         endfunction | ||||||
|  |         let l:options['on_exit'] = function('s:on_exit', [], l:options) | ||||||
|  |  | ||||||
|  |         continue | ||||||
|  |       endif | ||||||
|  |  | ||||||
|  |       if key == 'close_cb' | ||||||
|  |         continue | ||||||
|  |       endif | ||||||
|  |  | ||||||
|  |   endfor | ||||||
|  |   return l:options | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  |  | ||||||
| " vim: sw=2 ts=2 et | " vim: sw=2 ts=2 et | ||||||
|  | |||||||
| @ -1,195 +0,0 @@ | |||||||
| " s:jobs is a global reference to all jobs started with Spawn() or with the |  | ||||||
| " internal function s:spawn |  | ||||||
| let s:jobs = {} |  | ||||||
|  |  | ||||||
| " s:handlers is a global event handlers for all jobs started with Spawn() or |  | ||||||
| " with the internal function s:spawn |  | ||||||
| let s:handlers = {} |  | ||||||
|  |  | ||||||
| " Spawn is a wrapper around s:spawn. It can be executed by other files and |  | ||||||
| " scripts if needed. Desc defines the description for printing the status |  | ||||||
| " during the job execution (useful for statusline integration). |  | ||||||
| function! go#jobcontrol#Spawn(bang, desc, for, args) abort |  | ||||||
|   " autowrite is not enabled for jobs |  | ||||||
|   call go#cmd#autowrite() |  | ||||||
|  |  | ||||||
|   let job = s:spawn(a:bang, a:desc, a:for, a:args) |  | ||||||
|   return job.id |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " AddHandler adds a on_exit callback handler and returns the id. |  | ||||||
| function! go#jobcontrol#AddHandler(handler) abort |  | ||||||
|   let i = len(s:handlers) |  | ||||||
|   while has_key(s:handlers, string(i)) |  | ||||||
|     let i += 1 |  | ||||||
|     break |  | ||||||
|   endwhile |  | ||||||
|   let s:handlers[string(i)] = a:handler |  | ||||||
|   return string(i) |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " RemoveHandler removes a callback handler by id. |  | ||||||
| function! go#jobcontrol#RemoveHandler(id) abort |  | ||||||
|   unlet s:handlers[a:id] |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " spawn spawns a go subcommand with the name and arguments with jobstart. Once a |  | ||||||
| " job is started a reference will be stored inside s:jobs. The job is started |  | ||||||
| " inside the current files folder. |  | ||||||
| function! s:spawn(bang, desc, for, args) abort |  | ||||||
|   let status_type = a:args[0] |  | ||||||
|   let status_dir = expand('%:p:h') |  | ||||||
|   let started_at = reltime() |  | ||||||
|  |  | ||||||
|   call go#statusline#Update(status_dir, { |  | ||||||
|         \ 'desc': "current status", |  | ||||||
|         \ 'type': status_type, |  | ||||||
|         \ 'state': "started", |  | ||||||
|         \}) |  | ||||||
|  |  | ||||||
|   let job = { |  | ||||||
|         \ 'desc': a:desc, |  | ||||||
|         \ 'bang': a:bang, |  | ||||||
|         \ 'winid': win_getid(winnr()), |  | ||||||
|         \ 'importpath': go#package#ImportPath(), |  | ||||||
|         \ 'state': "RUNNING", |  | ||||||
|         \ 'stderr' : [], |  | ||||||
|         \ 'stdout' : [], |  | ||||||
|         \ 'on_stdout': function('s:on_stdout'), |  | ||||||
|         \ 'on_stderr': function('s:on_stderr'), |  | ||||||
|         \ 'on_exit' : function('s:on_exit'), |  | ||||||
|         \ 'status_type' : status_type, |  | ||||||
|         \ 'status_dir' : status_dir, |  | ||||||
|         \ 'started_at' : started_at, |  | ||||||
|         \ 'for' : a:for, |  | ||||||
|         \ 'errorformat': &errorformat, |  | ||||||
|         \ } |  | ||||||
|  |  | ||||||
|   " execute go build in the files directory |  | ||||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |  | ||||||
|  |  | ||||||
|   " cleanup previous jobs for this file |  | ||||||
|   for jb in values(s:jobs) |  | ||||||
|     if jb.importpath == job.importpath |  | ||||||
|       unlet s:jobs[jb.id] |  | ||||||
|     endif |  | ||||||
|   endfor |  | ||||||
|  |  | ||||||
|   let dir = getcwd() |  | ||||||
|   let jobdir = fnameescape(expand("%:p:h")) |  | ||||||
|   execute cd . jobdir |  | ||||||
|  |  | ||||||
|   " append the subcommand, such as 'build' |  | ||||||
|   let argv = ['go'] + a:args |  | ||||||
|  |  | ||||||
|   " run, forrest, run! |  | ||||||
|   let id = jobstart(argv, job) |  | ||||||
|   let job.id = id |  | ||||||
|   let job.dir = jobdir |  | ||||||
|   let s:jobs[id] = job |  | ||||||
|  |  | ||||||
|   execute cd . fnameescape(dir) |  | ||||||
|  |  | ||||||
|   return job |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " on_exit is the exit handler for jobstart(). It handles cleaning up the job |  | ||||||
| " references and also displaying errors in the quickfix window collected by |  | ||||||
| " on_stderr handler. If there are no errors and a quickfix window is open, |  | ||||||
| " it'll be closed. |  | ||||||
| function! s:on_exit(job_id, exit_status, event) dict abort |  | ||||||
|   let l:winid = win_getid(winnr()) |  | ||||||
|   call win_gotoid(self.winid) |  | ||||||
|  |  | ||||||
|   let status = { |  | ||||||
|         \ 'desc': 'last status', |  | ||||||
|         \ 'type': self.status_type, |  | ||||||
|         \ 'state': "success", |  | ||||||
|         \ } |  | ||||||
|  |  | ||||||
|   if a:exit_status |  | ||||||
|     let status.state = "failed" |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   let elapsed_time = reltimestr(reltime(self.started_at)) |  | ||||||
|   " strip whitespace |  | ||||||
|   let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') |  | ||||||
|   let status.state .= printf(" (%ss)", elapsed_time) |  | ||||||
|  |  | ||||||
|   call go#statusline#Update(self.status_dir, status) |  | ||||||
|  |  | ||||||
|   let std_combined = self.stderr + self.stdout |  | ||||||
|  |  | ||||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |  | ||||||
|   let dir = getcwd() |  | ||||||
|   execute cd self.dir |  | ||||||
|  |  | ||||||
|   call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined) |  | ||||||
|  |  | ||||||
|   let l:listtype = go#list#Type(self.for) |  | ||||||
|   if a:exit_status == 0 |  | ||||||
|     call go#list#Clean(l:listtype) |  | ||||||
|  |  | ||||||
|     let self.state = "SUCCESS" |  | ||||||
|  |  | ||||||
|     if go#config#EchoCommandInfo() |  | ||||||
|       call go#util#EchoSuccess("[" . self.status_type . "] SUCCESS") |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     execute cd . fnameescape(dir) |  | ||||||
|     call win_gotoid(l:winid) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   let self.state = "FAILED" |  | ||||||
|  |  | ||||||
|   if go#config#EchoCommandInfo() |  | ||||||
|     call go#util#EchoError("[" . self.status_type . "] FAILED") |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   " parse the errors relative to self.jobdir |  | ||||||
|   call go#list#ParseFormat(l:listtype, self.errorformat, std_combined, self.for) |  | ||||||
|   let errors = go#list#Get(l:listtype) |  | ||||||
|  |  | ||||||
|   execute cd . fnameescape(dir) |  | ||||||
|  |  | ||||||
|   if !len(errors) |  | ||||||
|     " failed to parse errors, output the original content |  | ||||||
|     call go#util#EchoError(std_combined[0]) |  | ||||||
|     call win_gotoid(l:winid) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   " if we are still in the same windows show the list |  | ||||||
|   if self.winid == l:winid |  | ||||||
|     call go#list#Window(l:listtype, len(errors)) |  | ||||||
|     if !empty(errors) && !self.bang |  | ||||||
|       call go#list#JumpToFirst(l:listtype) |  | ||||||
|     endif |  | ||||||
|   endif |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " callback_handlers_on_exit runs all handlers for job on exit event. |  | ||||||
| function! s:callback_handlers_on_exit(job, exit_status, data) abort |  | ||||||
|   if empty(s:handlers) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   for s:handler in values(s:handlers) |  | ||||||
|     call s:handler(a:job, a:exit_status, a:data) |  | ||||||
|   endfor |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " on_stdout is the stdout handler for jobstart(). It collects the output of |  | ||||||
| " stderr and stores them to the jobs internal stdout list. |  | ||||||
| function! s:on_stdout(job_id, data, event) dict abort |  | ||||||
|   call extend(self.stdout, a:data) |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " on_stderr is the stderr handler for jobstart(). It collects the output of |  | ||||||
| " stderr and stores them to the jobs internal stderr list. |  | ||||||
| function! s:on_stderr(job_id, data, event) dict abort |  | ||||||
|   call extend(self.stderr, a:data) |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
| " vim: sw=2 ts=2 et |  | ||||||
| @ -34,28 +34,21 @@ function! go#test#Test(bang, compile, ...) abort | |||||||
|     endif |     endif | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   if go#util#has_job() |   if go#util#has_job() || has('nvim') | ||||||
|     " use vim's job functionality to call it asynchronously |     " use vim's job functionality to call it asynchronously | ||||||
|     let job_args = { |     let job_options  = { | ||||||
|           \ 'cmd': ['go'] + args, |  | ||||||
|           \ 'bang': a:bang, |           \ 'bang': a:bang, | ||||||
|           \ 'winid': win_getid(winnr()), |           \ 'for': 'GoTest', | ||||||
|           \ 'dir': getcwd(), |           \ 'statustype': 'test', | ||||||
|           \ 'compile_test': a:compile, |           \ 'errorformat': s:errorformat(), | ||||||
|           \ 'jobdir': fnameescape(expand("%:p:h")), |  | ||||||
|           \ } |           \ } | ||||||
|  |  | ||||||
|     call s:test_job(job_args) |     if a:compile | ||||||
|     return |       let job_options.statustype = 'compile ' . job_options.statustype | ||||||
|   elseif has('nvim') |  | ||||||
|     " use nvims's job functionality |  | ||||||
|     if go#config#TermEnabled() |  | ||||||
|       let id = go#term#new(a:bang, ["go"] + args) |  | ||||||
|     else |  | ||||||
|       let id = go#jobcontrol#Spawn(a:bang, "test", "GoTest", args) |  | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
|     return id |     call s:test_job(['go'] + args, job_options) | ||||||
|  |     return | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   call go#cmd#autowrite() |   call go#cmd#autowrite() | ||||||
| @ -129,156 +122,13 @@ function! go#test#Func(bang, ...) abort | |||||||
|   call call('go#test#Test', args) |   call call('go#test#Test', args) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:test_job(args) abort | function! s:test_job(cmd, args) abort | ||||||
|   let status = { |  | ||||||
|         \ 'desc': 'current status', |  | ||||||
|         \ 'type': "test", |  | ||||||
|         \ 'state': "started", |  | ||||||
|         \ } |  | ||||||
|  |  | ||||||
|   if a:args.compile_test |  | ||||||
|     let status.state = "compiling" |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   " autowrite is not enabled for jobs |   " autowrite is not enabled for jobs | ||||||
|   call go#cmd#autowrite() |   call go#cmd#autowrite() | ||||||
|  |  | ||||||
|   let state = { |   call go#job#Spawn(a:cmd, a:args) | ||||||
|         \ 'exited': 0, |  | ||||||
|         \ 'closed': 0, |  | ||||||
|         \ 'exitval': 0, |  | ||||||
|         \ 'messages': [], |  | ||||||
|         \ 'args': a:args, |  | ||||||
|         \ 'compile_test': a:args.compile_test, |  | ||||||
|         \ 'status_dir': expand('%:p:h'), |  | ||||||
|         \ 'started_at': reltime() |  | ||||||
|       \ } |  | ||||||
|  |  | ||||||
|   call go#statusline#Update(state.status_dir, status) |  | ||||||
|  |  | ||||||
|   function! s:callback(chan, msg) dict |  | ||||||
|     call add(self.messages, a:msg) |  | ||||||
|   endfunction |  | ||||||
|  |  | ||||||
|   function! s:exit_cb(job, exitval) dict |  | ||||||
|     let self.exited = 1 |  | ||||||
|     let self.exitval = a:exitval |  | ||||||
|  |  | ||||||
|     let status = { |  | ||||||
|           \ 'desc': 'last status', |  | ||||||
|           \ 'type': "test", |  | ||||||
|           \ 'state': "pass", |  | ||||||
|           \ } |  | ||||||
|  |  | ||||||
|     if self.compile_test |  | ||||||
|       let status.state = "success" |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     if a:exitval |  | ||||||
|       let status.state = "failed" |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     if go#config#EchoCommandInfo() |  | ||||||
|       if a:exitval == 0 |  | ||||||
|         if self.compile_test |  | ||||||
|           call go#util#EchoSuccess("[test] SUCCESS") |  | ||||||
|         else |  | ||||||
|           call go#util#EchoSuccess("[test] PASS") |  | ||||||
|         endif |  | ||||||
|       else |  | ||||||
|         call go#util#EchoError("[test] FAIL") |  | ||||||
|       endif |  | ||||||
|     endif |  | ||||||
|  |  | ||||||
|     let elapsed_time = reltimestr(reltime(self.started_at)) |  | ||||||
|     " strip whitespace |  | ||||||
|     let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') |  | ||||||
|     let status.state .= printf(" (%ss)", elapsed_time) |  | ||||||
|  |  | ||||||
|     call go#statusline#Update(self.status_dir, status) |  | ||||||
|  |  | ||||||
|     if self.closed |  | ||||||
|       call s:show_errors(self.args, self.exitval, self.messages) |  | ||||||
|     endif |  | ||||||
|   endfunction |  | ||||||
|  |  | ||||||
|   function! s:close_cb(ch) dict |  | ||||||
|     let self.closed = 1 |  | ||||||
|  |  | ||||||
|     if self.exited |  | ||||||
|       call s:show_errors(self.args, self.exitval, self.messages) |  | ||||||
|     endif |  | ||||||
|   endfunction |  | ||||||
|  |  | ||||||
|   " explicitly bind the callbacks to state so that self within them always |  | ||||||
|   " refers to state. See :help Partial for more information. |  | ||||||
|   let start_options = { |  | ||||||
|         \ 'callback': funcref("s:callback", [], state), |  | ||||||
|         \ 'exit_cb': funcref("s:exit_cb", [], state), |  | ||||||
|         \ 'close_cb': funcref("s:close_cb", [], state) |  | ||||||
|       \ } |  | ||||||
|  |  | ||||||
|   " pre start |  | ||||||
|   let dir = getcwd() |  | ||||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |  | ||||||
|   let jobdir = fnameescape(expand("%:p:h")) |  | ||||||
|   execute cd . jobdir |  | ||||||
|  |  | ||||||
|   call job_start(a:args.cmd, start_options) |  | ||||||
|  |  | ||||||
|   " post start |  | ||||||
|   execute cd . fnameescape(dir) |  | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| " show_errors parses the given list of lines of a 'go test' output and returns |  | ||||||
| " a quickfix compatible list of errors. It's intended to be used only for go |  | ||||||
| " test output. |  | ||||||
| function! s:show_errors(args, exit_val, messages) abort |  | ||||||
|   let l:winid = win_getid(winnr()) |  | ||||||
|  |  | ||||||
|   call win_gotoid(a:args.winid) |  | ||||||
|  |  | ||||||
|   let l:listtype = go#list#Type("GoTest") |  | ||||||
|   if a:exit_val == 0 |  | ||||||
|     call go#list#Clean(l:listtype) |  | ||||||
|     call win_gotoid(l:winid) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   " TODO(bc): When messages is JSON, the JSON should be run through a |  | ||||||
|   " filter to produce lines that are more easily described by errorformat. |  | ||||||
|  |  | ||||||
|   let l:listtype = go#list#Type("GoTest") |  | ||||||
|  |  | ||||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' |  | ||||||
|   try |  | ||||||
|     execute cd a:args.jobdir |  | ||||||
|     call go#list#ParseFormat(l:listtype, s:errorformat(), a:messages, join(a:args.cmd)) |  | ||||||
|     let errors = go#list#Get(l:listtype) |  | ||||||
|   finally |  | ||||||
|     execute cd . fnameescape(a:args.dir) |  | ||||||
|   endtry |  | ||||||
|  |  | ||||||
|   if !len(errors) |  | ||||||
|     " failed to parse errors, output the original content |  | ||||||
|     call go#util#EchoError(a:messages) |  | ||||||
|     call go#util#EchoError(a:args.dir) |  | ||||||
|     call win_gotoid(l:winid) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   if a:args.winid != l:winid |  | ||||||
|     call win_gotoid(l:winid) |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|  |  | ||||||
|   call go#list#Window(l:listtype, len(errors)) |  | ||||||
|   if !empty(errors) && !a:args.bang |  | ||||||
|     call go#list#JumpToFirst(l:listtype) |  | ||||||
|   endif |  | ||||||
| endfunction |  | ||||||
|  |  | ||||||
|  |  | ||||||
| let s:efm = "" | let s:efm = "" | ||||||
| let s:go_test_show_name = 0 | let s:go_test_show_name = 0 | ||||||
|  |  | ||||||
|  | |||||||
| @ -89,15 +89,6 @@ func! Test_GoTestTestCompilerError() abort | |||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
| func! s:test(file, expected, ...) abort | func! s:test(file, expected, ...) abort | ||||||
|   if has('nvim') |  | ||||||
|     " nvim mostly shows test errors correctly, but the the expected errors are |  | ||||||
|     " slightly different; buffer numbers are not the same and stderr doesn't |  | ||||||
|     " seem to be redirected to the job, so the lines from the panic aren't in |  | ||||||
|     " the output to be parsed, and hence are not in the quickfix lists. Once |  | ||||||
|     " those two issues are resolved, this early return should be removed so |  | ||||||
|     " the tests will run for Neovim, too. |  | ||||||
|     return |  | ||||||
|   endif |  | ||||||
|   let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/test' |   let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/test' | ||||||
|   silent exe 'e ' . $GOPATH . '/src/' . a:file |   silent exe 'e ' . $GOPATH . '/src/' . a:file | ||||||
|  |  | ||||||
|  | |||||||
| @ -167,13 +167,16 @@ function! go#util#Exec(cmd, ...) abort | |||||||
|  |  | ||||||
|   let l:bin = a:cmd[0] |   let l:bin = a:cmd[0] | ||||||
|  |  | ||||||
|  |   " Lookup the full path, respecting settings such as 'go_bin_path'. On errors, | ||||||
|   " CheckBinPath will show a warning for us. |   " CheckBinPath will show a warning for us. | ||||||
|   let l:bin = go#path#CheckBinPath(l:bin) |   let l:bin = go#path#CheckBinPath(l:bin) | ||||||
|   if empty(l:bin) |   if empty(l:bin) | ||||||
|     return ['', 1] |     return ['', 1] | ||||||
|   endif |   endif | ||||||
|  |  | ||||||
|   return call('s:exec', [a:cmd] + a:000) |   " Finally execute the command using the full, resolved path. Do not pass the | ||||||
|  |   " unmodified command as the correct program might not exist in $PATH. | ||||||
|  |   return call('s:exec', [[l:bin] + a:cmd[1:]] + a:000) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
| function! s:exec(cmd, ...) abort | function! s:exec(cmd, ...) abort | ||||||
|  | |||||||
| @ -39,9 +39,23 @@ Vim command sequence: `df[$r,0f,v<C-n>…<C-n>c<CR><Up><Del><Right><Right><Right | |||||||
| To see what keystrokes are used for the above examples, see [the wiki page](https://github.com/terryma/vim-multiple-cursors/wiki/Keystrokes-for-example-gifs). | To see what keystrokes are used for the above examples, see [the wiki page](https://github.com/terryma/vim-multiple-cursors/wiki/Keystrokes-for-example-gifs). | ||||||
|  |  | ||||||
| ## Installation | ## Installation | ||||||
| Install using [Pathogen], [Vundle], [Neobundle], or your favorite Vim package manager. | Install using [Pathogen], [Vundle], [Neobundle], [vim-plug], or your favorite Vim package manager. | ||||||
|  |  | ||||||
| Requires vim 7.4 or later for full functionality. | Requires vim 7.4 or newer for full functionality. | ||||||
|  |  | ||||||
|  | ### vim-plug instructions | ||||||
|  |  | ||||||
|  | 1. Paste this block into the top of `~/.vimrc`. | ||||||
|  |  | ||||||
|  | ```vim script | ||||||
|  | call plug#begin() | ||||||
|  |  | ||||||
|  | Plug 'terryma/vim-multiple-cursors' | ||||||
|  |  | ||||||
|  | call plug#end() | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 2. Start vim and execute `:PlugInstall`. | ||||||
|  |  | ||||||
| ## Quick Start | ## Quick Start | ||||||
| ### normal mode / visual mode | ### normal mode / visual mode | ||||||
| @ -213,4 +227,5 @@ Obviously inspired by Sublime Text's [multiple selection][sublime-multiple-selec | |||||||
| [Pathogen]:http://github.com/tpope/vim-pathogen | [Pathogen]:http://github.com/tpope/vim-pathogen | ||||||
| [Vundle]:http://github.com/gmarik/vundle | [Vundle]:http://github.com/gmarik/vundle | ||||||
| [Neobundle]:http://github.com/Shougo/neobundle.vim | [Neobundle]:http://github.com/Shougo/neobundle.vim | ||||||
|  | [vim-plug]:https://github.com/junegunn/vim-plug | ||||||
| [emacs-multiple-cursors]:https://github.com/magnars/multiple-cursors.el | [emacs-multiple-cursors]:https://github.com/magnars/multiple-cursors.el | ||||||
|  | |||||||
| @ -9,94 +9,10 @@ ${1:pattern}${2: when ${3:guard}} -> | |||||||
| 	${4:body} | 	${4:body} | ||||||
| endsnippet | endsnippet | ||||||
|  |  | ||||||
| snippet beh "Behaviour Directive" b |  | ||||||
| -behaviour(${1:behaviour}). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet case "Case Expression" |  | ||||||
| case ${1:expression} of |  | ||||||
| 	${2:pattern}${3: when ${4:guard}} -> |  | ||||||
| 		${5:body} |  | ||||||
| end |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet def "Define Directive" b |  | ||||||
| -define(${1:macro}${2: (${3:param})}, ${4:body}). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet exp "Export Directive" b |  | ||||||
| -export([${1:function}/${2:arity}]). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet fun "Fun Expression" |  | ||||||
| fun |  | ||||||
| 	(${1:pattern})${2: when ${3:guard}} -> |  | ||||||
| 		${4:body} |  | ||||||
| end |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet fu "Function" |  | ||||||
| ${1:function}(${2:param})${3: when ${4:guard}} -> |  | ||||||
| 	${5:body} |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet if "If Expression" |  | ||||||
| if |  | ||||||
| 	${1:guard} -> |  | ||||||
| 		${2:body} |  | ||||||
| end |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet ifdef "Ifdef Directive" b |  | ||||||
| -ifdef(${1:macro}). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet ifndef "Ifndef Directive" b |  | ||||||
| -ifndef(${1:macro}). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet imp "Import Directive" b |  | ||||||
| -import(${1:module}, [${2:function}/${3:arity}]). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet inc "Include Directive" b |  | ||||||
| -include("${1:file}"). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet mod "Module Directive" b | snippet mod "Module Directive" b | ||||||
| -module(${1:`!p snip.rv = snip.basename or "module"`}). | -module(${1:`!p snip.rv = snip.basename or "module"`}). | ||||||
| endsnippet | endsnippet | ||||||
|  |  | ||||||
| snippet rcv "Receive Expression" |  | ||||||
| receive |  | ||||||
| ${1:	${2:pattern}${3: when ${4:guard}} -> |  | ||||||
| 		${5:body}} |  | ||||||
| ${6:after |  | ||||||
| 	${7:expression} -> |  | ||||||
| 		${8:body}} |  | ||||||
| end |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet rec "Record Directive" b |  | ||||||
| -record(${1:record}, {${2:field}${3: = ${4:value}}}). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet try "Try Expression" |  | ||||||
| try${1: ${2:expression}${3: of |  | ||||||
| 	${4:pattern}${5: when ${6:guard}} -> |  | ||||||
| 		${7:body}}} |  | ||||||
| ${8:catch |  | ||||||
| 	${9:pattern}${10: when ${11:guard}} -> |  | ||||||
| 		${12:body}} |  | ||||||
| ${13:after |  | ||||||
| 	${14:body}} |  | ||||||
| end |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet undef "Undef Directive" b |  | ||||||
| -undef(${1:macro}). |  | ||||||
| endsnippet |  | ||||||
|  |  | ||||||
| snippet || "List Comprehension" | snippet || "List Comprehension" | ||||||
| [${1:X} || ${2:X} <- ${3:List}${4:, gen}] | [${1:X} || ${2:X} <- ${3:List}${4:, gen}] | ||||||
| endsnippet | endsnippet | ||||||
|  | |||||||
| @ -50,6 +50,23 @@ snippet spar "Paragraph" b | |||||||
| $0 | $0 | ||||||
| endsnippet | endsnippet | ||||||
|  |  | ||||||
|  | ################### | ||||||
|  | # Text formatting # | ||||||
|  | ################### | ||||||
|  |  | ||||||
|  | snippet * "italics" | ||||||
|  | *${1:${VISUAL}}*$0 | ||||||
|  | endsnippet | ||||||
|  |  | ||||||
|  | snippet ** "bold" | ||||||
|  | **${1:${VISUAL}}**$0 | ||||||
|  | endsnippet | ||||||
|  |  | ||||||
|  | snippet *** "bold italics" | ||||||
|  | ***${1:${VISUAL}}***$0 | ||||||
|  | endsnippet | ||||||
|  |  | ||||||
|  |  | ||||||
| ################ | ################ | ||||||
| # Common stuff # | # Common stuff # | ||||||
| ################ | ################ | ||||||
|  | |||||||
| @ -7,10 +7,10 @@ endsnippet | |||||||
|  |  | ||||||
| snippet t "Simple tag" b | snippet t "Simple tag" b | ||||||
| <${1:tag}> | <${1:tag}> | ||||||
| 	${2:content} | 	${2:${VISUAL}} | ||||||
| </${1/([\w:._-]+).*/$1/}> | </${1/([\w:._-]+).*/$1/}> | ||||||
| endsnippet | endsnippet | ||||||
|  |  | ||||||
| snippet ti "Inline tag" b | snippet ti "Inline tag" b | ||||||
| <${1:tag}>${2:content}</${1/([\w:._-]+).*/$1/}> | <${1:tag}>${2:${VISUAL}}</${1/([\w:._-]+).*/$1/}> | ||||||
| endsnippet | endsnippet | ||||||
|  | |||||||
| @ -5,12 +5,16 @@ snippet mod | |||||||
| snippet modall | snippet modall | ||||||
| 	-module(${1:`vim_snippets#Filename()`}). | 	-module(${1:`vim_snippets#Filename()`}). | ||||||
| 	-compile([export_all]). | 	-compile([export_all]). | ||||||
| 	  |  | ||||||
| 	start() -> | 	start() -> | ||||||
| 		${0} | 		${0} | ||||||
| 	  |  | ||||||
| 	stop() -> | 	stop() -> | ||||||
| 		ok. | 		ok. | ||||||
|  | snippet d | ||||||
|  | 	erlang:display(${0}), | ||||||
|  | snippet dt | ||||||
|  | 	erlang:display({${1}, ${0}}), | ||||||
| # define directive | # define directive | ||||||
| snippet def | snippet def | ||||||
| 	-define(${1:macro}, ${2:body}). | 	-define(${1:macro}, ${2:body}). | ||||||
| @ -30,17 +34,23 @@ snippet ifd | |||||||
| 	-ifdef(${1:TEST}). | 	-ifdef(${1:TEST}). | ||||||
| 	${0} | 	${0} | ||||||
| 	-endif. | 	-endif. | ||||||
|  | snippet ifnd | ||||||
|  | 	-ifndef(${1:TEST}). | ||||||
|  | 	${0} | ||||||
|  | 	-endif. | ||||||
|  | snippet undef | ||||||
|  | 	-undef(${1:macro}). | ||||||
| # if expression | # if expression | ||||||
| snippet if | snippet if | ||||||
| 	if | 	if | ||||||
| 	    ${1:guard} -> | 		${1:guard} -> | ||||||
| 	        ${0:body} | 			${0:body} | ||||||
| 	end | 	end | ||||||
| # case expression | # case expression | ||||||
| snippet case | snippet case | ||||||
| 	case ${1:expression} of | 	case ${1:expression} of | ||||||
| 	    ${2:pattern} -> | 		${2:pattern} -> | ||||||
| 	        ${0:body}; | 			${0:body}; | ||||||
| 	end | 	end | ||||||
| # anonymous function | # anonymous function | ||||||
| snippet fun | snippet fun | ||||||
| @ -48,14 +58,21 @@ snippet fun | |||||||
| # try...catch | # try...catch | ||||||
| snippet try | snippet try | ||||||
| 	try | 	try | ||||||
| 	    ${1:${VISUAL}} | 		${1:${VISUAL}} | ||||||
| 	catch | 	catch | ||||||
| 	    ${2:_:_} -> ${0:got_some_exception} | 		${2:_:_} -> ${0:got_some_exception} | ||||||
|  | 	end | ||||||
|  | snippet rcv "Receive Expression" | ||||||
|  | 	receive | ||||||
|  | 	${1:	${2:pattern}${3: when ${4:guard}} -> | ||||||
|  | 			${5:body}} | ||||||
|  | 	${6:after | ||||||
|  | 		${7:expression} -> | ||||||
|  | 			${8:body}} | ||||||
| 	end | 	end | ||||||
| # record directive | # record directive | ||||||
| snippet rec | snippet rec | ||||||
| 	-record(${1:record}, { | 	-record(${1:record}, {${2:field}=${3:value}}). | ||||||
| 	    ${2:field}=${3:value}}). |  | ||||||
| # todo comment | # todo comment | ||||||
| snippet todo | snippet todo | ||||||
| 	%% TODO: ${0} | 	%% TODO: ${0} | ||||||
| @ -82,15 +99,15 @@ snippet application | |||||||
| 	-export([start/2, stop/1]). | 	-export([start/2, stop/1]). | ||||||
|  |  | ||||||
| 	start(_Type, _StartArgs) -> | 	start(_Type, _StartArgs) -> | ||||||
| 	    case ${0:root_supervisor}:start_link() of | 		case ${0:root_supervisor}:start_link() of | ||||||
| 	        {ok, Pid} -> | 			{ok, Pid} -> | ||||||
| 	            {ok, Pid}; | 				{ok, Pid}; | ||||||
| 	        Other -> | 			Other -> | ||||||
| 		          {error, Other} | 				{error, Other} | ||||||
| 	    end. | 		end. | ||||||
|  |  | ||||||
| 	stop(_State) -> | 	stop(_State) -> | ||||||
| 	    ok. | 		ok. | ||||||
| # OTP supervisor | # OTP supervisor | ||||||
| snippet supervisor | snippet supervisor | ||||||
| 	-module(${1:`vim_snippets#Filename()`}). | 	-module(${1:`vim_snippets#Filename()`}). | ||||||
| @ -106,14 +123,14 @@ snippet supervisor | |||||||
| 	-define(SERVER, ?MODULE). | 	-define(SERVER, ?MODULE). | ||||||
|  |  | ||||||
| 	start_link() -> | 	start_link() -> | ||||||
| 	    supervisor:start_link({local, ?SERVER}, ?MODULE, []). | 			supervisor:start_link({local, ?SERVER}, ?MODULE, []). | ||||||
|  |  | ||||||
| 	init([]) -> | 	init([]) -> | ||||||
| 	    Server = {${0:my_server}, {${2}, start_link, []}, | 		Server = {${0:my_server}, {${2}, start_link, []}, | ||||||
| 	      permanent, 2000, worker, [${2}]}, | 			permanent, 2000, worker, [${2}]}, | ||||||
| 	    Children = [Server], | 		Children = [Server], | ||||||
| 	    RestartStrategy = {one_for_one, 0, 1}, | 		RestartStrategy = {one_for_one, 0, 1}, | ||||||
| 	    {ok, {RestartStrategy, Children}}. | 		{ok, {RestartStrategy, Children}}. | ||||||
| # OTP gen_server | # OTP gen_server | ||||||
| snippet gen_server | snippet gen_server | ||||||
| 	-module(${0:`vim_snippets#Filename()`}). | 	-module(${0:`vim_snippets#Filename()`}). | ||||||
| @ -121,17 +138,10 @@ snippet gen_server | |||||||
| 	-behaviour(gen_server). | 	-behaviour(gen_server). | ||||||
|  |  | ||||||
| 	%% API | 	%% API | ||||||
| 	-export([ | 	-export([start_link/0]). | ||||||
| 	         start_link/0 |  | ||||||
| 	        ]). |  | ||||||
|  |  | ||||||
| 	%% gen_server callbacks | 	%% gen_server callbacks | ||||||
| 	-export([init/1, | 	-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). | ||||||
| 	         handle_call/3, |  | ||||||
| 	         handle_cast/2, |  | ||||||
| 	         handle_info/2, |  | ||||||
| 	         terminate/2, |  | ||||||
| 	         code_change/3]). |  | ||||||
|  |  | ||||||
| 	-define(SERVER, ?MODULE). | 	-define(SERVER, ?MODULE). | ||||||
|  |  | ||||||
| @ -142,30 +152,30 @@ snippet gen_server | |||||||
| 	%%%=================================================================== | 	%%%=================================================================== | ||||||
|  |  | ||||||
| 	start_link() -> | 	start_link() -> | ||||||
| 	    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). | 		gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). | ||||||
|  |  | ||||||
| 	%%%=================================================================== | 	%%%=================================================================== | ||||||
| 	%%% gen_server callbacks | 	%%% gen_server callbacks | ||||||
| 	%%%=================================================================== | 	%%%=================================================================== | ||||||
|  |  | ||||||
| 	init([]) -> | 	init([]) -> | ||||||
| 	    {ok, #state{}}. | 		{ok, #state{}}. | ||||||
|  |  | ||||||
| 	handle_call(_Request, _From, State) -> | 	handle_call(_Request, _From, State) -> | ||||||
| 	    Reply = ok, | 		Reply = ok, | ||||||
| 	    {reply, Reply, State}. | 		{reply, Reply, State}. | ||||||
|  |  | ||||||
| 	handle_cast(_Msg, State) -> | 	handle_cast(_Msg, State) -> | ||||||
| 	    {noreply, State}. | 		{noreply, State}. | ||||||
|  |  | ||||||
| 	handle_info(_Info, State) -> | 	handle_info(_Info, State) -> | ||||||
| 	    {noreply, State}. | 		{noreply, State}. | ||||||
|  |  | ||||||
| 	terminate(_Reason, _State) -> | 	terminate(_Reason, _State) -> | ||||||
| 	    ok. | 		ok. | ||||||
|  |  | ||||||
| 	code_change(_OldVsn, State, _Extra) -> | 	code_change(_OldVsn, State, _Extra) -> | ||||||
| 	    {ok, State}. | 		{ok, State}. | ||||||
|  |  | ||||||
| 	%%%=================================================================== | 	%%%=================================================================== | ||||||
| 	%%% Internal functions | 	%%% Internal functions | ||||||
| @ -180,14 +190,8 @@ snippet gen_fsm | |||||||
| 	-export([start_link/0]). | 	-export([start_link/0]). | ||||||
|  |  | ||||||
| 	%% gen_fsm callbacks | 	%% gen_fsm callbacks | ||||||
| 	-export([init/1, | 	-export([init/1, state_name/2, state_name/3, handle_event/3, handle_sync_event/4, | ||||||
| 			 state_name/2, | 		handle_info/3, terminate/3, code_change/4]). | ||||||
| 			 state_name/3, |  | ||||||
| 			 handle_event/3, |  | ||||||
| 			 handle_sync_event/4, |  | ||||||
| 			 handle_info/3, |  | ||||||
| 			 terminate/3, |  | ||||||
| 			 code_change/4]). |  | ||||||
|  |  | ||||||
| 	-record(state, {}). | 	-record(state, {}). | ||||||
|  |  | ||||||
| @ -356,15 +360,15 @@ snippet gen_event | |||||||
|  |  | ||||||
| 	%% API | 	%% API | ||||||
| 	-export([start_link/0, | 	-export([start_link/0, | ||||||
| 			 add_handler/2]). | 		add_handler/2]). | ||||||
|  |  | ||||||
| 	%% gen_event callbacks | 	%% gen_event callbacks | ||||||
| 	-export([init/1, | 	-export([init/1, | ||||||
| 			 handle_event/2, | 		handle_event/2, | ||||||
| 			 handle_call/2, | 		handle_call/2, | ||||||
| 			 handle_info/2, | 		handle_info/2, | ||||||
| 			 terminate/2, | 		terminate/2, | ||||||
| 			 code_change/3]). | 		code_change/3]). | ||||||
|  |  | ||||||
| 	-record(state, {}). | 	-record(state, {}). | ||||||
|  |  | ||||||
| @ -497,6 +501,16 @@ snippet ieunit | |||||||
| 	${0} | 	${0} | ||||||
|  |  | ||||||
| 	-endif. | 	-endif. | ||||||
|  | snippet itest | ||||||
|  | 	-ifdef(TEST). | ||||||
|  |  | ||||||
|  | 	${1}_test() -> | ||||||
|  | 		${0} | ||||||
|  |  | ||||||
|  | 	-endif. | ||||||
|  | snippet test | ||||||
|  | 	${1}_test() -> | ||||||
|  | 		${0} | ||||||
| snippet as | snippet as | ||||||
| 	?assert(${0}) | 	?assert(${0}) | ||||||
| snippet asn | snippet asn | ||||||
| @ -523,9 +537,9 @@ snippet testsuite | |||||||
|  |  | ||||||
| 	%% Test server callbacks | 	%% Test server callbacks | ||||||
| 	-export([suite/0, all/0, groups/0, | 	-export([suite/0, all/0, groups/0, | ||||||
| 		 init_per_suite/1, end_per_suite/1, | 		init_per_suite/1, end_per_suite/1, | ||||||
| 		 init_per_group/2, end_per_group/2, | 		init_per_group/2, end_per_group/2, | ||||||
| 		 init_per_testcase/2, end_per_testcase/2]). | 		init_per_testcase/2, end_per_testcase/2]). | ||||||
|  |  | ||||||
| 	%% Test cases | 	%% Test cases | ||||||
| 	-export([ | 	-export([ | ||||||
|  | |||||||
| @ -0,0 +1 @@ | |||||||
|  | extends typescript | ||||||
		Reference in New Issue
	
	Block a user
	 Amir Salihefendic
					Amir Salihefendic