diff --git a/ale_linters/ansible/ansible_lint.vim b/ale_linters/ansible/ansible_lint.vim index e15008c8..80fb9871 100644 --- a/ale_linters/ansible/ansible_lint.vim +++ b/ale_linters/ansible/ansible_lint.vim @@ -2,11 +2,44 @@ " Description: ansible-lint for ansible-yaml files call ale#Set('ansible_ansible_lint_executable', 'ansible-lint') +call ale#Set('ansible_ansible_lint_auto_pipenv', 0) +call ale#Set('ansible_ansible_lint_auto_poetry', 0) +call ale#Set('ansible_ansible_lint_auto_uv', 0) +call ale#Set('ansible_ansible_lint_change_directory', 1) function! ale_linters#ansible#ansible_lint#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') + \ || ale#Var(a:buffer, 'ansible_ansible_lint_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + + if (ale#Var(a:buffer, 'python_auto_poetry') + \ || ale#Var(a:buffer, 'ansible_ansible_lint_auto_poetry')) + \ && ale#python#PoetryPresent(a:buffer) + return 'poetry' + endif + + if (ale#Var(a:buffer, 'python_auto_uv') + \ || ale#Var(a:buffer, 'ansible_ansible_lint_auto_uv')) + \ && ale#python#UvPresent(a:buffer) + return 'uv' + endif + return ale#Var(a:buffer, 'ansible_ansible_lint_executable') endfunction +function! ale_linters#ansible#ansible_lint#GetCwd(buffer) abort + if ale#Var(a:buffer, 'ansible_ansible_lint_change_directory') + " Run from project root if found, else from buffer dir. + let l:project_root = ale#python#FindProjectRoot(a:buffer) + + return !empty(l:project_root) ? l:project_root : '%s:h' + endif + + return '' +endfunction + function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort for l:line in a:lines[:10] if match(l:line, '^Traceback') >= 0 @@ -103,28 +136,50 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort endfunction function! ale_linters#ansible#ansible_lint#GetCommand(buffer, version) abort - let l:commands = { - \ '>=6.0.0': '%e --nocolor -f json -x yaml %s', - \ '>=5.0.0': '%e --nocolor --parseable-severity -x yaml %s', - \ '<5.0.0': '%e --nocolor -p %t' + let l:executable = ale_linters#ansible#ansible_lint#GetExecutable(a:buffer) + + let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$' + \ ? ' run ansible-lint' + \ : '' + + let l:opts_map = { + \ '>=6.0.0': ' --nocolor -f json -x yaml %s', + \ '>=5.0.0': ' --nocolor --parseable-severity -x yaml %s', + \ '<5.0.0': ' --nocolor -p %t' \} - let l:command = ale#semver#GTE(a:version, [6, 0]) ? l:commands['>=6.0.0'] : - \ ale#semver#GTE(a:version, [5, 0]) ? l:commands['>=5.0.0'] : - \ l:commands['<5.0.0'] + + let l:cmd_opts = ale#semver#GTE(a:version, [6, 0]) ? l:opts_map['>=6.0.0'] : + \ ale#semver#GTE(a:version, [5, 0]) ? l:opts_map['>=5.0.0'] : + \ l:opts_map['<5.0.0'] + + let l:command = ale#Escape(l:executable) . l:exec_args . l:cmd_opts return l:command endfunction +function! ale_linters#ansible#ansible_lint#RunWithVersionCheck(buffer) abort + let l:executable = ale_linters#ansible#ansible_lint#GetExecutable(a:buffer) + + let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$' + \ ? ' run ansible-lint' + \ : '' + + let l:command = ale#Escape(l:executable) . l:exec_args . ' --version' + + return ale#semver#RunWithVersionCheck( + \ a:buffer, + \ l:executable, + \ l:command, + \ function('ale_linters#ansible#ansible_lint#GetCommand'), + \) +endfunction + call ale#linter#Define('ansible', { \ 'name': 'ansible_lint', \ 'aliases': ['ansible', 'ansible-lint'], \ 'executable': function('ale_linters#ansible#ansible_lint#GetExecutable'), -\ 'command': {buffer -> ale#semver#RunWithVersionCheck( -\ buffer, -\ ale_linters#ansible#ansible_lint#GetExecutable(buffer), -\ '%e --version', -\ function('ale_linters#ansible#ansible_lint#GetCommand'), -\ )}, +\ 'cwd': function('ale_linters#ansible#ansible_lint#GetCwd'), +\ 'command': function('ale_linters#ansible#ansible_lint#RunWithVersionCheck'), \ 'lint_file': 1, \ 'callback': {buffer, lines -> ale#semver#RunWithVersionCheck( \ buffer, diff --git a/doc/ale-ansible.txt b/doc/ale-ansible.txt index 01554bcc..2fb4e2d3 100644 --- a/doc/ale-ansible.txt +++ b/doc/ale-ansible.txt @@ -44,5 +44,39 @@ g:ale_ansible_ansible_lint_executable This variable can be changed to modify the executable used for ansible-lint. + *ale-options.ansible_ansible_lint_auto_pipenv* + *g:ale_ansible_ansible_lint_auto_pipenv* + *b:ale_ansible_ansible_lint_auto_pipenv* +ansible_ansible_lint_auto_pipenv +g:ale_ansible_ansible_lint_auto_pipenv + Type: |Number| + Default: `0` + + Detect whether the file is inside a pipenv, and set the executable to `pipenv` + if true. This is overridden by a manually-set executable. + + *ale-options.ansible_ansible_lint_auto_poetry* + *g:ale_ansible_ansible_lint_auto_poetry* + *b:ale_ansible_ansible_lint_auto_poetry* +ansible_ansible_lint_auto_poetry +g:ale_ansible_ansible_lint_auto_poetry + Type: |Number| + Default: `0` + + Detect whether the file is inside a poetry, and set the executable to `poetry` + if true. This is overridden by a manually-set executable. + + *ale-options.ansible_ansible_lint_auto_uv* + *g:ale_ansible_ansible_lint_auto_uv* + *b:ale_ansible_ansible_lint_auto_uv* +ansible_ansible_lint_auto_uv +g:ale_ansible_ansible_lint_auto_uv + Type: |Number| + Default: `0` + + Set the executable to `uv` if true. This is overridden by a manually-set + executable. + + =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/test/linter/test_ansible_lint.vader b/test/linter/test_ansible_lint.vader index 3191fa7b..3f102d17 100644 --- a/test/linter/test_ansible_lint.vader +++ b/test/linter/test_ansible_lint.vader @@ -24,3 +24,28 @@ Execute(The ansible_lint executable should be configurable): GivenCommandOutput ['v4.1.2'] AssertLinter '~/.local/bin/ansible-lint', \ ale#Escape('~/.local/bin/ansible-lint') . ' --nocolor -p %t' + +Execute(pipenv is detected when ansible_ansible_lint_auto_pipenv is set): + let g:ale_ansible_ansible_lint_auto_pipenv = 1 + call ale#test#SetFilename('../test-files/ansible/pipenv/script.yml') + + GivenCommandOutput ['v25.6.1'] + AssertLinterCwd expand('%:p:h') + AssertLinter 'pipenv', ale#Escape('pipenv') . ' run ansible-lint --nocolor -f json -x yaml %s' + +Execute(poetry is detected when ansible_ansible_lint_auto_poetry is set): + let g:ale_ansible_ansible_lint_auto_poetry = 1 + call ale#test#SetFilename('../test-files/ansible/poetry/script.yml') + + GivenCommandOutput ['v25.6.1'] + AssertLinterCwd expand('%:p:h') + AssertLinter 'poetry', ale#Escape('poetry') . ' run ansible-lint --nocolor -f json -x yaml %s' + +Execute(uv is detected when ansible_ansible_lint_auto_uv is set): + let g:ale_ansible_ansible_lint_auto_uv = 1 + call ale#test#SetFilename('../test-files/ansible/uv/script.yml') + + GivenCommandOutput ['v25.6.1'] + AssertLinterCwd expand('%:p:h') + AssertLinter 'uv', ale#Escape('uv') . ' run ansible-lint --nocolor -f json -x yaml %s' + diff --git a/test/test-files/ansible/pipenv/Pipfile.lock b/test/test-files/ansible/pipenv/Pipfile.lock new file mode 100644 index 00000000..e69de29b diff --git a/test/test-files/ansible/poetry/poetry.lock b/test/test-files/ansible/poetry/poetry.lock new file mode 100644 index 00000000..e69de29b diff --git a/test/test-files/ansible/uv/uv.lock b/test/test-files/ansible/uv/uv.lock new file mode 100644 index 00000000..e69de29b