/ plugin / ale.vim
ale.vim
  1  " Author: w0rp <devw0rp@gmail.com>
  2  " Description: Main entry point for the plugin: sets up prefs and autocommands
  3  "   Preferences can be set in vimrc files and so on to configure ale
  4  
  5  " Sanity Checks
  6  
  7  if exists('g:loaded_ale_dont_use_this_in_other_plugins_please')
  8      finish
  9  endif
 10  
 11  " Set a special flag used only by this plugin for preventing doubly
 12  " loading the script.
 13  let g:loaded_ale_dont_use_this_in_other_plugins_please = 1
 14  
 15  " A flag for detecting if the required features are set.
 16  if has('nvim')
 17      " We check for NeoVim 0.2.0+, but we only officially support NeoVim 0.6.0
 18      let s:has_features = has('timers') && has('nvim-0.2.0')
 19  else
 20      " Check if Job and Channel functions are available, instead of the
 21      " features. This works better on old MacVim versions.
 22      let s:has_features = has('timers') && exists('*job_start') && exists('*ch_close_in')
 23  endif
 24  
 25  if !s:has_features
 26      " Only output a warning if editing some special files.
 27      if index(['', 'gitcommit'], &filetype) == -1
 28          " no-custom-checks
 29          echoerr 'ALE requires NeoVim >= 0.6.0 or Vim 8 with +timers +job +channel'
 30          " no-custom-checks
 31          echoerr 'Please update your editor appropriately.'
 32      endif
 33  
 34      " Stop here, as it won't work.
 35      finish
 36  endif
 37  
 38  " Set this flag so that other plugins can use it, like airline.
 39  let g:loaded_ale = 1
 40  
 41  " This global variable is used internally by ALE for tracking information for
 42  " each buffer which linters are being run against.
 43  let g:ale_buffer_info = {}
 44  " This global Dictionary tracks data for fixing code. Don't mess with it.
 45  let g:ale_fix_buffer_data = {}
 46  
 47  " User Configuration
 48  
 49  " This option prevents ALE autocmd commands from being run for particular
 50  " filetypes which can cause issues.
 51  let g:ale_filetype_blacklist = [
 52  \   'dirvish',
 53  \   'nerdtree',
 54  \   'qf',
 55  \   'tags',
 56  \   'unite',
 57  \]
 58  
 59  " This Dictionary configures which linters are enabled for which languages.
 60  let g:ale_linters = get(g:, 'ale_linters', {})
 61  " This option can be changed to only enable explicitly selected linters.
 62  let g:ale_linters_explicit = get(g:, 'ale_linters_explicit', 0)
 63  " Ignoring linters, for disabling some, or ignoring LSP diagnostics.
 64  let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {})
 65  " Disabling all language server functionality.
 66  let g:ale_disable_lsp = get(g:, 'ale_disable_lsp', 'auto')
 67  
 68  " This Dictionary configures which functions will be used for fixing problems.
 69  let g:ale_fixers = get(g:, 'ale_fixers', {})
 70  
 71  " This Dictionary allows users to set up filetype aliases for new filetypes.
 72  let g:ale_linter_aliases = get(g:, 'ale_linter_aliases', {})
 73  
 74  " This flag can be set with a number of milliseconds for delaying the
 75  " execution of a linter when text is changed. The timeout will be set and
 76  " cleared each time text is changed, so repeated edits won't trigger the
 77  " jobs for linting until enough time has passed after editing is done.
 78  let g:ale_lint_delay = get(g:, 'ale_lint_delay', 200)
 79  
 80  " This flag can be set to 'never' to disable linting when text is changed.
 81  " This flag can also be set to 'always' or 'insert' to lint when text is
 82  " changed in both normal and insert mode, or only in insert mode respectively.
 83  let g:ale_lint_on_text_changed = get(g:, 'ale_lint_on_text_changed', 'normal')
 84  
 85  " This flag can be set to 1 to enable linting when leaving insert mode.
 86  let g:ale_lint_on_insert_leave = get(g:, 'ale_lint_on_insert_leave', 1)
 87  
 88  " This flag can be set to 0 to disable linting when the buffer is entered.
 89  let g:ale_lint_on_enter = get(g:, 'ale_lint_on_enter', 1)
 90  
 91  " This flag can be set to 1 to enable linting when a buffer is written.
 92  let g:ale_lint_on_save = get(g:, 'ale_lint_on_save', 1)
 93  
 94  " This flag can be set to 1 to enable linting when the filetype is changed.
 95  let g:ale_lint_on_filetype_changed = get(g:, 'ale_lint_on_filetype_changed', 1)
 96  
 97  " If set to 1, hints and suggestion from LSP servers and tsserver will be shown.
 98  let g:ale_lsp_suggestions = get(g:, 'ale_lsp_suggestions', 0)
 99  
100  " This flag can be set to 1 to enable automatically fixing files on save.
101  let g:ale_fix_on_save = get(g:, 'ale_fix_on_save', 0)
102  
103  " This flag may be set to 0 to disable ale. After ale is loaded, :ALEToggle
104  " should be used instead.
105  let g:ale_enabled = get(g:, 'ale_enabled', 1)
106  
107  " A Dictionary mapping linter or fixer names to Arrays of two-item Arrays
108  " mapping filename paths from one system to another.
109  let g:ale_filename_mappings = get(g:, 'ale_filename_mappings', {})
110  
111  " This Dictionary configures the default project roots for various linters.
112  let g:ale_root = get(g:, 'ale_root', {})
113  
114  " These flags dictates if ale uses the quickfix or the loclist (loclist is the
115  " default, quickfix overrides loclist).
116  let g:ale_set_loclist = get(g:, 'ale_set_loclist', 1)
117  let g:ale_set_quickfix = get(g:, 'ale_set_quickfix', 0)
118  
119  " This flag can be set to 0 to disable setting signs.
120  " This is enabled by default only if the 'signs' feature exists.
121  let g:ale_set_signs = get(g:, 'ale_set_signs', has('signs'))
122  
123  " This flag can be set to 0 to disable setting error highlights.
124  let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax'))
125  
126  " This List can be configured to exclude particular highlights.
127  let g:ale_exclude_highlights = get(g:, 'ale_exclude_highlights', [])
128  
129  " This flag can be set to 0 to disable echoing when the cursor moves.
130  let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
131  
132  " This flag can be set to 1 to automatically show errors in the preview window.
133  let g:ale_cursor_detail = get(g:, 'ale_cursor_detail', 0)
134  
135  " This flag can be changed to disable/enable virtual text.
136  let g:ale_virtualtext_cursor = get(g:, 'ale_virtualtext_cursor', (has('nvim-0.3.2') || has('patch-9.0.0297') && has('textprop') && has('popupwin')) ? 'all' : 'disabled')
137  
138  " This flag can be set to 1 to enable LSP hover messages at the cursor.
139  let g:ale_hover_cursor = get(g:, 'ale_hover_cursor', 1)
140  
141  " This flag can be set to 1 to automatically close the preview window upon
142  " entering Insert Mode.
143  let g:ale_close_preview_on_insert = get(g:, 'ale_close_preview_on_insert', 0)
144  
145  " This flag can be set to 0 to disable balloon support.
146  let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running'))
147  
148  " Use preview window for hover messages.
149  let g:ale_hover_to_preview = get(g:, 'ale_hover_to_preview', 0)
150  
151  " Float preview windows in Neovim
152  let g:ale_floating_preview = get(g:, 'ale_floating_preview', 0)
153  
154  " Hovers use floating windows in Neovim
155  let g:ale_hover_to_floating_preview = get(g:, 'ale_hover_to_floating_preview', 0)
156  
157  " Detail uses floating windows in Neovim
158  let g:ale_detail_to_floating_preview = get(g:, 'ale_detail_to_floating_preview', 0)
159  
160  " Border setting for floating preview windows
161  " The elements in the list set the characters for the left, top, top-left,
162  " top-right, bottom-right, bottom-left, right, and bottom of the border
163  " respectively
164  let g:ale_floating_window_border = get(g:, 'ale_floating_window_border', ['|', '-', '+', '+', '+', '+', '|', '-'])
165  
166  " This flag can be set to 0 to disable warnings for trailing whitespace
167  let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1)
168  " This flag can be set to 0 to disable warnings for trailing blank lines
169  let g:ale_warn_about_trailing_blank_lines = get(g:, 'ale_warn_about_trailing_blank_lines', 1)
170  
171  " A flag for enabling or disabling the command history.
172  let g:ale_history_enabled = get(g:, 'ale_history_enabled', 1)
173  
174  " A flag for storing the full output of commands in the history.
175  let g:ale_history_log_output = get(g:, 'ale_history_log_output', 1)
176  
177  " Enable automatic completion with LSP servers and tsserver
178  let g:ale_completion_enabled = get(g:, 'ale_completion_enabled', 0)
179  
180  " Enable automatic detection of pipenv for Python linters.
181  let g:ale_python_auto_pipenv = get(g:, 'ale_python_auto_pipenv', 0)
182  
183  " Enable automatic detection of poetry for Python linters.
184  let g:ale_python_auto_poetry = get(g:, 'ale_python_auto_poetry', 0)
185  
186  " Enable automatic detection of uv for Python linters.
187  let g:ale_python_auto_uv = get(g:, 'ale_python_auto_uv', 0)
188  
189  " Enable automatic adjustment of environment variables for Python linters.
190  " The variables are set based on ALE's virtualenv detection.
191  let g:ale_python_auto_virtualenv = get(g:, 'ale_python_auto_virtualenv', 0)
192  
193  " This variable can be overridden to set the GO111MODULE environment variable.
194  let g:ale_go_go111module = get(g:, 'ale_go_go111module', '')
195  
196  " Default executable for deno, needed set before plugin start
197  let g:ale_deno_executable = get(g:, 'ale_deno_executable', 'deno')
198  
199  " If 1, enable a popup menu for commands.
200  let g:ale_popup_menu_enabled = get(g:, 'ale_popup_menu_enabled', has('gui_running'))
201  
202  " If 0, save hidden files when code actions are applied.
203  let g:ale_save_hidden = get(g:, 'ale_save_hidden', 0)
204  
205  " If 1, disables ALE's built in error display. Instead, all errors are piped
206  " to the diagnostics API.
207  let g:ale_use_neovim_diagnostics_api = get(g:, 'ale_use_neovim_diagnostics_api', has('nvim-0.6'))
208  
209  if g:ale_use_neovim_diagnostics_api && !has('nvim-0.6')
210      " no-custom-checks
211      echoerr('Setting g:ale_use_neovim_diagnostics_api to 1 requires Neovim 0.6+.')
212  endif
213  
214  if g:ale_set_balloons is 1 || g:ale_set_balloons is# 'hover'
215      call ale#balloon#Enable()
216  endif
217  
218  if g:ale_completion_enabled
219      call ale#completion#Enable()
220  endif
221  
222  if g:ale_popup_menu_enabled
223      call ale#code_action#EnablePopUpMenu()
224  endif
225  
226  " Define commands for moving through warnings and errors.
227  command! -bar -nargs=* ALEPrevious
228  \    :call ale#loclist_jumping#WrapJump('before', <q-args>)
229  command! -bar -nargs=* ALENext
230  \    :call ale#loclist_jumping#WrapJump('after', <q-args>)
231  
232  command! -bar ALEPreviousWrap :call ale#loclist_jumping#Jump('before', 1)
233  command! -bar ALENextWrap :call ale#loclist_jumping#Jump('after', 1)
234  command! -bar ALEFirst :call ale#loclist_jumping#JumpToIndex(0)
235  command! -bar ALELast :call ale#loclist_jumping#JumpToIndex(-1)
236  
237  " A command for showing error details.
238  command! -bar ALEDetail :call ale#cursor#ShowCursorDetail()
239  
240  " Define commands for turning ALE on or off.
241  command! -bar ALEToggle :call ale#toggle#Toggle()
242  command! -bar ALEEnable :call ale#toggle#Enable()
243  command! -bar ALEDisable :call ale#toggle#Disable()
244  command! -bar ALEReset :call ale#toggle#Reset()
245  " Commands for turning ALE on or off for a buffer.
246  command! -bar ALEToggleBuffer :call ale#toggle#ToggleBuffer(bufnr(''))
247  command! -bar ALEEnableBuffer :call ale#toggle#EnableBuffer(bufnr(''))
248  command! -bar ALEDisableBuffer :call ale#toggle#DisableBuffer(bufnr(''))
249  command! -bar ALEResetBuffer :call ale#toggle#ResetBuffer(bufnr(''))
250  " A command to stop all LSP-like clients, including tsserver.
251  command! -bar ALEStopAllLSPs :call ale#lsp#reset#StopAllLSPs()
252  " A command to stop a specific language server, or tsseserver.
253  command! -bar -bang -nargs=1 -complete=customlist,ale#lsp#reset#Complete ALEStopLSP :call ale#lsp#reset#StopLSP(<f-args>, '<bang>')
254  
255  " A command for linting manually.
256  command! -bar ALELint :call ale#Queue(0, 'lint_file')
257  " Stop current jobs when linting.
258  command! -bar ALELintStop :call ale#engine#Stop(bufnr(''))
259  
260  " Commands to manually populate the quickfixes.
261  command! -bar ALEPopulateQuickfix :call ale#list#ForcePopulateErrorList(1)
262  command! -bar ALEPopulateLocList  :call ale#list#ForcePopulateErrorList(0)
263  
264  " Define a command to get information about current filetype.
265  command! -bar -nargs=* ALEInfo :call ale#debugging#InfoCommand(<f-args>)
266  " Deprecated and scheduled for removal in 4.0.0.
267  command! -bar ALEInfoToClipboard :call ale#debugging#InfoToClipboardDeprecatedCommand()
268  " Copy ALE information to a file.
269  command! -bar -nargs=1 ALEInfoToFile :call ale#debugging#InfoToFile(<f-args>)
270  
271  " Fix problems in files.
272  command! -bar -bang -nargs=* -complete=customlist,ale#fix#registry#CompleteFixers ALEFix :call ale#fix#Fix(bufnr(''), '<bang>', <f-args>)
273  " Suggest registered functions to use for fixing problems.
274  command! -bar ALEFixSuggest :call ale#fix#registry#Suggest(&filetype)
275  
276  " Go to definition for tsserver and LSP
277  command! -bar -nargs=* ALEGoToDefinition :call ale#definition#GoToCommandHandler('', <f-args>)
278  
279  " Go to type definition for tsserver and LSP
280  command! -bar -nargs=* ALEGoToTypeDefinition :call ale#definition#GoToCommandHandler('type', <f-args>)
281  
282  " Go to implementation for tsserver and LSP
283  command! -bar -nargs=* ALEGoToImplementation :call ale#definition#GoToCommandHandler('implementation', <f-args>)
284  
285  " Repeat a previous selection in the preview window
286  command! -bar ALERepeatSelection :call ale#preview#RepeatSelection()
287  
288  " Find references for tsserver and LSP
289  command! -bar -nargs=* ALEFindReferences :call ale#references#Find(<f-args>)
290  
291  " Show summary information for the cursor.
292  command! -bar ALEHover :call ale#hover#ShowAtCursor()
293  
294  " Show documentation for the cursor.
295  command! -bar ALEDocumentation :call ale#hover#ShowDocumentationAtCursor()
296  
297  " Search for appearances of a symbol, such as a type name or function name.
298  command! -nargs=1 ALESymbolSearch :call ale#symbol#Search(<q-args>)
299  
300  " Complete text with tsserver and LSP
301  command! -bar ALEComplete :call ale#completion#GetCompletions('ale-manual')
302  
303  " Try to find completions for the current symbol that add additional text.
304  command! -bar ALEImport :call ale#completion#Import()
305  
306  " Rename symbols using tsserver and LSP
307  command! -bar -bang ALERename :call ale#rename#Execute()
308  
309  " Rename file using tsserver
310  command! -bar -bang ALEFileRename :call ale#filerename#Execute()
311  
312  " Apply code actions to a range.
313  command! -bar -range ALECodeAction :call ale#codefix#Execute(<range>)
314  
315  " Organize import statements using tsserver
316  command! -bar ALEOrganizeImports :call ale#organize_imports#Execute()
317  
318  " <Plug> mappings for commands
319  nnoremap <silent> <Plug>(ale_previous) :ALEPrevious<Return>
320  nnoremap <silent> <Plug>(ale_previous_wrap) :ALEPreviousWrap<Return>
321  nnoremap <silent> <Plug>(ale_previous_error) :ALEPrevious -error<Return>
322  nnoremap <silent> <Plug>(ale_previous_wrap_error) :ALEPrevious -wrap -error<Return>
323  nnoremap <silent> <Plug>(ale_previous_warning) :ALEPrevious -warning<Return>
324  nnoremap <silent> <Plug>(ale_previous_wrap_warning) :ALEPrevious -wrap -warning<Return>
325  nnoremap <silent> <Plug>(ale_next) :ALENext<Return>
326  nnoremap <silent> <Plug>(ale_next_wrap) :ALENextWrap<Return>
327  nnoremap <silent> <Plug>(ale_next_error) :ALENext -error<Return>
328  nnoremap <silent> <Plug>(ale_next_wrap_error) :ALENext -wrap -error<Return>
329  nnoremap <silent> <Plug>(ale_next_warning) :ALENext -warning<Return>
330  nnoremap <silent> <Plug>(ale_next_wrap_warning) :ALENext -wrap -warning<Return>
331  nnoremap <silent> <Plug>(ale_first) :ALEFirst<Return>
332  nnoremap <silent> <Plug>(ale_last) :ALELast<Return>
333  nnoremap <silent> <Plug>(ale_toggle) :ALEToggle<Return>
334  nnoremap <silent> <Plug>(ale_enable) :ALEEnable<Return>
335  nnoremap <silent> <Plug>(ale_disable) :ALEDisable<Return>
336  nnoremap <silent> <Plug>(ale_reset) :ALEReset<Return>
337  nnoremap <silent> <Plug>(ale_toggle_buffer) :ALEToggleBuffer<Return>
338  nnoremap <silent> <Plug>(ale_enable_buffer) :ALEEnableBuffer<Return>
339  nnoremap <silent> <Plug>(ale_disable_buffer) :ALEDisableBuffer<Return>
340  nnoremap <silent> <Plug>(ale_reset_buffer) :ALEResetBuffer<Return>
341  nnoremap <silent> <Plug>(ale_lint) :ALELint<Return>
342  nnoremap <silent> <Plug>(ale_detail) :ALEDetail<Return>
343  nnoremap <silent> <Plug>(ale_fix) :ALEFix<Return>
344  nnoremap <silent> <Plug>(ale_go_to_definition) :ALEGoToDefinition<Return>
345  nnoremap <silent> <Plug>(ale_go_to_definition_in_tab) :ALEGoToDefinition -tab<Return>
346  nnoremap <silent> <Plug>(ale_go_to_definition_in_split) :ALEGoToDefinition -split<Return>
347  nnoremap <silent> <Plug>(ale_go_to_definition_in_vsplit) :ALEGoToDefinition -vsplit<Return>
348  nnoremap <silent> <Plug>(ale_go_to_type_definition) :ALEGoToTypeDefinition<Return>
349  nnoremap <silent> <Plug>(ale_go_to_type_definition_in_tab) :ALEGoToTypeDefinition -tab<Return>
350  nnoremap <silent> <Plug>(ale_go_to_type_definition_in_split) :ALEGoToTypeDefinition -split<Return>
351  nnoremap <silent> <Plug>(ale_go_to_type_definition_in_vsplit) :ALEGoToTypeDefinition -vsplit<Return>
352  nnoremap <silent> <Plug>(ale_go_to_implementation) :ALEGoToImplementation<Return>
353  nnoremap <silent> <Plug>(ale_go_to_implementation_in_tab) :ALEGoToImplementation -tab<Return>
354  nnoremap <silent> <Plug>(ale_go_to_implementation_in_split) :ALEGoToImplementation -split<Return>
355  nnoremap <silent> <Plug>(ale_go_to_implementation_in_vsplit) :ALEGoToImplementation -vsplit<Return>
356  nnoremap <silent> <Plug>(ale_find_references) :ALEFindReferences<Return>
357  nnoremap <silent> <Plug>(ale_hover) :ALEHover<Return>
358  nnoremap <silent> <Plug>(ale_documentation) :ALEDocumentation<Return>
359  inoremap <silent> <Plug>(ale_complete) <C-\><C-O>:ALEComplete<Return>
360  nnoremap <silent> <Plug>(ale_import) :ALEImport<Return>
361  nnoremap <silent> <Plug>(ale_rename) :ALERename<Return>
362  nnoremap <silent> <Plug>(ale_filerename) :ALEFileRename<Return>
363  nnoremap <silent> <Plug>(ale_code_action) :ALECodeAction<Return>
364  nnoremap <silent> <Plug>(ale_repeat_selection) :ALERepeatSelection<Return>
365  nnoremap <silent> <Plug>(ale_info) :ALEInfo<Return>
366  nnoremap <silent> <Plug>(ale_info_echo) :ALEInfo -echo<Return>
367  nnoremap <silent> <Plug>(ale_info_clipboard) :ALEInfo -clipboard<Return>
368  nnoremap <silent> <Plug>(ale_info_preview) :ALEInfo -preview<Return>
369  
370  " Set up autocmd groups now.
371  call ale#events#Init()
372  
373  " Housekeeping
374  
375  augroup ALECleanupGroup
376      autocmd!
377      " Clean up buffers automatically when they are unloaded.
378      autocmd BufDelete * if exists('*ale#engine#Cleanup') | call ale#engine#Cleanup(str2nr(expand('<abuf>'))) | endif
379      autocmd QuitPre * call ale#events#QuitEvent(str2nr(expand('<abuf>')))
380  
381      if exists('##VimSuspend')
382          autocmd VimSuspend * if exists('*ale#engine#CleanupEveryBuffer') | call ale#engine#CleanupEveryBuffer() | endif
383      endif
384  augroup END