mirror of https://github.com/amix/vimrc.git
parent
96e10ed101
commit
72bdaba47e
@ -0,0 +1,35 @@ |
||||
" Author: Andreww Hayworth <ahayworth@gmail.com> |
||||
" Description: Integrate ALE with ink-language-server |
||||
|
||||
call ale#Set('ink_ls_executable', 'ink-language-server') |
||||
call ale#Set('ink_ls_use_global', get(g:, 'ale_use_global_executables', 0)) |
||||
call ale#Set('ink_ls_initialization_options', {}) |
||||
|
||||
function! ale_linters#ink#ls#GetExecutable(buffer) abort |
||||
return ale#node#FindExecutable(a:buffer, 'ink_ls', [ |
||||
\ 'ink-language-server', |
||||
\ 'node_modules/.bin/ink-language-server', |
||||
\]) |
||||
endfunction |
||||
|
||||
function! ale_linters#ink#ls#GetCommand(buffer) abort |
||||
let l:executable = ale_linters#ink#ls#GetExecutable(a:buffer) |
||||
|
||||
return ale#Escape(l:executable) . ' --stdio' |
||||
endfunction |
||||
|
||||
function! ale_linters#ink#ls#FindProjectRoot(buffer) abort |
||||
let l:main_file = get(ale#Var(a:buffer, 'ink_ls_initialization_options'), 'mainStoryPath', 'main.ink') |
||||
let l:config = ale#path#ResolveLocalPath(a:buffer, l:main_file, expand('#' . a:buffer . ':p')) |
||||
|
||||
return ale#path#Dirname(l:config) |
||||
endfunction |
||||
|
||||
call ale#linter#Define('ink', { |
||||
\ 'name': 'ink-language-server', |
||||
\ 'lsp': 'stdio', |
||||
\ 'executable': function('ale_linters#ink#ls#GetExecutable'), |
||||
\ 'command': function('ale_linters#ink#ls#GetCommand'), |
||||
\ 'project_root': function('ale_linters#ink#ls#FindProjectRoot'), |
||||
\ 'initialization_options': {b -> ale#Var(b, 'ink_ls_initialization_options')}, |
||||
\}) |
@ -0,0 +1,33 @@ |
||||
" Author: jeremija <https://github.com/jeremija> |
||||
" Description: Support for nimlsp (language server for nim) |
||||
|
||||
call ale#Set('nim_nimlsp_nim_sources', '') |
||||
|
||||
function! ale_linters#nim#nimlsp#GetProjectRoot(buffer) abort |
||||
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git') |
||||
|
||||
if !empty(l:project_root) |
||||
return fnamemodify(l:project_root, ':h:h') |
||||
endif |
||||
|
||||
return '' |
||||
endfunction |
||||
|
||||
function! ale_linters#nim#nimlsp#GetCommand(buffer) abort |
||||
let l:nim_sources = ale#Var(a:buffer, 'nim_nimlsp_nim_sources') |
||||
|
||||
if !empty(l:nim_sources) |
||||
let l:nim_sources = ale#Escape(l:nim_sources) |
||||
endif |
||||
|
||||
return '%e' . ale#Pad(l:nim_sources) |
||||
endfunction |
||||
|
||||
call ale#linter#Define('nim', { |
||||
\ 'name': 'nimlsp', |
||||
\ 'lsp': 'stdio', |
||||
\ 'executable': 'nimlsp', |
||||
\ 'command': function('ale_linters#nim#nimlsp#GetCommand'), |
||||
\ 'language': 'nim', |
||||
\ 'project_root': function('ale_linters#nim#nimlsp#GetProjectRoot'), |
||||
\}) |
@ -0,0 +1,42 @@ |
||||
" Author: Eddie Lebow https://github.com/elebow |
||||
" Description: debride, a dead method detector for Ruby files |
||||
|
||||
call ale#Set('ruby_debride_executable', 'debride') |
||||
call ale#Set('ruby_debride_options', '') |
||||
|
||||
function! ale_linters#ruby#debride#GetCommand(buffer) abort |
||||
let l:executable = ale#Var(a:buffer, 'ruby_debride_executable') |
||||
|
||||
return ale#ruby#EscapeExecutable(l:executable, 'debride') |
||||
\ . ale#Var(a:buffer, 'ruby_debride_options') |
||||
\ . ' %s' |
||||
endfunction |
||||
|
||||
function! ale_linters#ruby#debride#HandleOutput(buffer, lines) abort |
||||
let l:output = [] |
||||
|
||||
for l:line in a:lines |
||||
if l:line !~# '^ ' |
||||
continue |
||||
endif |
||||
|
||||
let l:elements = split(l:line) |
||||
let l:method_name = l:elements[0] |
||||
let l:lnum = split(l:elements[1], ':')[1] |
||||
|
||||
call add(l:output, { |
||||
\ 'lnum': 0 + l:lnum, |
||||
\ 'text': 'Possible unused method: ' . l:method_name, |
||||
\ 'type': 'W', |
||||
\}) |
||||
endfor |
||||
|
||||
return l:output |
||||
endfunction |
||||
|
||||
call ale#linter#Define('ruby', { |
||||
\ 'name': 'debride', |
||||
\ 'executable': {b -> ale#Var(b, 'ruby_debride_executable')}, |
||||
\ 'command': function('ale_linters#ruby#debride#GetCommand'), |
||||
\ 'callback': 'ale_linters#ruby#debride#HandleOutput', |
||||
\}) |
@ -0,0 +1,48 @@ |
||||
" Author: Jeffrey Lau - https://github.com/zoonfafer |
||||
" Description: Metals Language Server for Scala https://scalameta.org/metals/ |
||||
|
||||
call ale#Set('scala_metals_executable', 'metals-vim') |
||||
call ale#Set('scala_metals_project_root', '') |
||||
|
||||
function! ale_linters#scala#metals#GetProjectRoot(buffer) abort |
||||
let l:project_root = ale#Var(a:buffer, 'scala_metals_project_root') |
||||
|
||||
if !empty(l:project_root) |
||||
return l:project_root |
||||
endif |
||||
|
||||
let l:potential_roots = [ |
||||
\ 'build.sc', |
||||
\ 'build.sbt', |
||||
\ '.bloop', |
||||
\ '.metals', |
||||
\] |
||||
|
||||
for l:root in l:potential_roots |
||||
let l:project_root = ale#path#ResolveLocalPath( |
||||
\ a:buffer, |
||||
\ l:root, |
||||
\ '' |
||||
\) |
||||
|
||||
if !empty(l:project_root) |
||||
return fnamemodify( |
||||
\ l:project_root, |
||||
\ ':h', |
||||
\) |
||||
endif |
||||
endfor |
||||
endfunction |
||||
|
||||
function! ale_linters#scala#metals#GetCommand(buffer) abort |
||||
return '%e' . ale#Pad('stdio') |
||||
endfunction |
||||
|
||||
call ale#linter#Define('scala', { |
||||
\ 'name': 'metals', |
||||
\ 'lsp': 'stdio', |
||||
\ 'language': 'scala', |
||||
\ 'executable': {b -> ale#Var(b, 'scala_metals_executable')}, |
||||
\ 'command': function('ale_linters#scala#metals#GetCommand'), |
||||
\ 'project_root': function('ale_linters#scala#metals#GetProjectRoot'), |
||||
\}) |
@ -0,0 +1,35 @@ |
||||
" Author: Karl Bartel <karl42@gmail.com> - http://karl.berlin/ |
||||
" Description: Report solc compiler errors in Solidity code |
||||
|
||||
call ale#Set('solidity_solc_options', '') |
||||
|
||||
function! ale_linters#solidity#solc#Handle(buffer, lines) abort |
||||
" Matches patterns like the following: |
||||
" /path/to/file/file.sol:1:10: Error: Identifier not found or not unique. |
||||
let l:pattern = '\v^[^:]+:(\d+):(\d+): (Error|Warning): (.*)$' |
||||
let l:output = [] |
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern) |
||||
let l:isError = l:match[3] is? 'error' |
||||
call add(l:output, { |
||||
\ 'lnum': l:match[1] + 0, |
||||
\ 'col': l:match[2] + 0, |
||||
\ 'text': l:match[4], |
||||
\ 'type': l:isError ? 'E' : 'W', |
||||
\}) |
||||
endfor |
||||
|
||||
return l:output |
||||
endfunction |
||||
|
||||
function! ale_linters#solidity#solc#GetCommand(buffer) abort |
||||
return 'solc' . ale#Pad(ale#Var(a:buffer, 'solidity_solc_options')) . ' %s' |
||||
endfunction |
||||
|
||||
call ale#linter#Define('solidity', { |
||||
\ 'name': 'solc', |
||||
\ 'executable': 'solc', |
||||
\ 'command': function('ale_linters#solidity#solc#GetCommand'), |
||||
\ 'callback': 'ale_linters#solidity#solc#Handle', |
||||
\ 'output_stream': 'stderr', |
||||
\}) |
@ -0,0 +1,31 @@ |
||||
" Author: Ahmed El Gabri <@ahmedelgabri> |
||||
" Description: standardjs for typescript files |
||||
|
||||
call ale#Set('typescript_standard_executable', 'standard') |
||||
call ale#Set('typescript_standard_use_global', get(g:, 'ale_use_global_executables', 0)) |
||||
call ale#Set('typescript_standard_options', '') |
||||
|
||||
function! ale_linters#typescript#standard#GetExecutable(buffer) abort |
||||
return ale#node#FindExecutable(a:buffer, 'typescript_standard', [ |
||||
\ 'node_modules/standardx/bin/cmd.js', |
||||
\ 'node_modules/standard/bin/cmd.js', |
||||
\ 'node_modules/.bin/standard', |
||||
\]) |
||||
endfunction |
||||
|
||||
function! ale_linters#typescript#standard#GetCommand(buffer) abort |
||||
let l:executable = ale_linters#typescript#standard#GetExecutable(a:buffer) |
||||
let l:options = ale#Var(a:buffer, 'typescript_standard_options') |
||||
|
||||
return ale#node#Executable(a:buffer, l:executable) |
||||
\ . (!empty(l:options) ? ' ' . l:options : '') |
||||
\ . ' --stdin %s' |
||||
endfunction |
||||
|
||||
" standard uses eslint and the output format is the same |
||||
call ale#linter#Define('typescript', { |
||||
\ 'name': 'standard', |
||||
\ 'executable': function('ale_linters#typescript#standard#GetExecutable'), |
||||
\ 'command': function('ale_linters#typescript#standard#GetCommand'), |
||||
\ 'callback': 'ale#handlers#eslint#Handle', |
||||
\}) |
@ -0,0 +1,163 @@ |
||||
" Author: Jerko Steiner <jerko.steiner@gmail.com> |
||||
" Description: Code action support for LSP / tsserver |
||||
|
||||
function! ale#code_action#HandleCodeAction(code_action) abort |
||||
let l:current_buffer = bufnr('') |
||||
let l:changes = a:code_action.changes |
||||
|
||||
for l:file_code_edit in l:changes |
||||
let l:buf = bufnr(l:file_code_edit.fileName) |
||||
|
||||
if l:buf != -1 && l:buf != l:current_buffer && getbufvar(l:buf, '&mod') |
||||
call ale#util#Execute('echom ''Aborting action, file is unsaved''') |
||||
|
||||
return |
||||
endif |
||||
endfor |
||||
|
||||
for l:file_code_edit in l:changes |
||||
call ale#code_action#ApplyChanges( |
||||
\ l:file_code_edit.fileName, l:file_code_edit.textChanges) |
||||
endfor |
||||
endfunction |
||||
|
||||
function! ale#code_action#ApplyChanges(filename, changes) abort |
||||
let l:current_buffer = bufnr('') |
||||
" The buffer is used to determine the fileformat, if available. |
||||
let l:buffer = bufnr(a:filename) |
||||
let l:is_current_buffer = l:buffer > 0 && l:buffer == l:current_buffer |
||||
|
||||
if l:buffer > 0 |
||||
let l:lines = getbufline(l:buffer, 1, '$') |
||||
else |
||||
let l:lines = readfile(a:filename, 'b') |
||||
endif |
||||
|
||||
if l:is_current_buffer |
||||
let l:pos = getpos('.')[1:2] |
||||
else |
||||
let l:pos = [1, 1] |
||||
endif |
||||
|
||||
" We have to keep track of how many lines we have added, and offset |
||||
" changes accordingly. |
||||
let l:line_offset = 0 |
||||
let l:column_offset = 0 |
||||
let l:last_end_line = 0 |
||||
|
||||
for l:code_edit in a:changes |
||||
if l:code_edit.start.line isnot l:last_end_line |
||||
let l:column_offset = 0 |
||||
endif |
||||
|
||||
let l:line = l:code_edit.start.line + l:line_offset |
||||
let l:column = l:code_edit.start.offset + l:column_offset |
||||
let l:end_line = l:code_edit.end.line + l:line_offset |
||||
let l:end_column = l:code_edit.end.offset + l:column_offset |
||||
let l:text = l:code_edit.newText |
||||
|
||||
let l:cur_line = l:pos[0] |
||||
let l:cur_column = l:pos[1] |
||||
|
||||
let l:last_end_line = l:end_line |
||||
|
||||
" Adjust the ends according to previous edits. |
||||
if l:end_line > len(l:lines) |
||||
let l:end_line_len = 0 |
||||
else |
||||
let l:end_line_len = len(l:lines[l:end_line - 1]) |
||||
endif |
||||
|
||||
let l:insertions = split(l:text, '\n', 1) |
||||
|
||||
if l:line is 1 |
||||
" Same logic as for column below. Vimscript's slice [:-1] will not |
||||
" be an empty list. |
||||
let l:start = [] |
||||
else |
||||
let l:start = l:lines[: l:line - 2] |
||||
endif |
||||
|
||||
if l:column is 1 |
||||
" We need to handle column 1 specially, because we can't slice an |
||||
" empty string ending on index 0. |
||||
let l:middle = [l:insertions[0]] |
||||
else |
||||
let l:middle = [l:lines[l:line - 1][: l:column - 2] . l:insertions[0]] |
||||
endif |
||||
|
||||
call extend(l:middle, l:insertions[1:]) |
||||
let l:middle[-1] .= l:lines[l:end_line - 1][l:end_column - 1 :] |
||||
|
||||
let l:lines_before_change = len(l:lines) |
||||
let l:lines = l:start + l:middle + l:lines[l:end_line :] |
||||
|
||||
let l:current_line_offset = len(l:lines) - l:lines_before_change |
||||
let l:line_offset += l:current_line_offset |
||||
let l:column_offset = len(l:middle[-1]) - l:end_line_len |
||||
|
||||
let l:pos = s:UpdateCursor(l:pos, |
||||
\ [l:line, l:column], |
||||
\ [l:end_line, l:end_column], |
||||
\ [l:current_line_offset, l:column_offset]) |
||||
endfor |
||||
|
||||
if l:lines[-1] is# '' |
||||
call remove(l:lines, -1) |
||||
endif |
||||
|
||||
call ale#util#Writefile(l:buffer, l:lines, a:filename) |
||||
|
||||
if l:is_current_buffer |
||||
call ale#util#Execute(':e!') |
||||
call setpos('.', [0, l:pos[0], l:pos[1], 0]) |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:UpdateCursor(cursor, start, end, offset) abort |
||||
let l:cur_line = a:cursor[0] |
||||
let l:cur_column = a:cursor[1] |
||||
let l:line = a:start[0] |
||||
let l:column = a:start[1] |
||||
let l:end_line = a:end[0] |
||||
let l:end_column = a:end[1] |
||||
let l:line_offset = a:offset[0] |
||||
let l:column_offset = a:offset[1] |
||||
|
||||
if l:end_line < l:cur_line |
||||
" both start and end lines are before the cursor. only line offset |
||||
" needs to be updated |
||||
let l:cur_line += l:line_offset |
||||
elseif l:end_line == l:cur_line |
||||
" end line is at the same location as cursor, which means |
||||
" l:line <= l:cur_line |
||||
if l:line < l:cur_line || l:column <= l:cur_column |
||||
" updates are happening either before or around the cursor |
||||
if l:end_column < l:cur_column |
||||
" updates are happening before the cursor, update the |
||||
" column offset for cursor |
||||
let l:cur_line += l:line_offset |
||||
let l:cur_column += l:column_offset |
||||
else |
||||
" updates are happening around the cursor, move the cursor |
||||
" to the end of the changes |
||||
let l:cur_line += l:line_offset |
||||
let l:cur_column = l:end_column + l:column_offset |
||||
endif |
||||
" else is not necessary, it means modifications are happening |
||||
" after the cursor so no cursor updates need to be done |
||||
endif |
||||
else |
||||
" end line is after the cursor |
||||
if l:line < l:cur_line || l:line == l:cur_line && l:column <= l:cur_column |
||||
" changes are happening around the cursor, move the cursor |
||||
" to the end of the changes |
||||
let l:cur_line = l:end_line + l:line_offset |
||||
let l:cur_column = l:end_column + l:column_offset |
||||
" else is not necesary, it means modifications are happening |
||||
" after the cursor so no cursor updates need to be done |
||||
endif |
||||
endif |
||||
|
||||
return [l:cur_line, l:cur_column] |
||||
endfunction |