diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index 661fa1e109..0f9fdb5dff 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -98,6 +98,12 @@ let s:default_registry = { \ 'suggested_filetypes': ['dune'], \ 'description': 'Fix dune files with dune format', \ }, +\ 'erlang_mode': { +\ 'function': 'ale#fixers#erlang_mode#Fix', +\ 'suggested_filetypes': ['erlang'], +\ 'description': 'Indent with the Erlang mode for Emacs', +\ 'aliases': ['erlang-mode'], +\ }, \ 'fecs': { \ 'function': 'ale#fixers#fecs#Fix', \ 'suggested_filetypes': ['javascript', 'css', 'html'], diff --git a/autoload/ale/fixers/erlang_mode.vim b/autoload/ale/fixers/erlang_mode.vim new file mode 100644 index 0000000000..a89784d5c7 --- /dev/null +++ b/autoload/ale/fixers/erlang_mode.vim @@ -0,0 +1,49 @@ +" Author: Dmitri Vereshchagin +" Description: Indent with the Erlang mode for Emacs + +call ale#Set('erlang_erlang_mode_emacs_executable', 'emacs') +call ale#Set('erlang_erlang_mode_indent_level', 4) +call ale#Set('erlang_erlang_mode_icr_indent', 'nil') +call ale#Set('erlang_erlang_mode_indent_guard', 2) +call ale#Set('erlang_erlang_mode_argument_indent', 2) +call ale#Set('erlang_erlang_mode_indent_tabs_mode', 'nil') + +let s:variables = { +\ 'erlang-indent-level': 'erlang_erlang_mode_indent_level', +\ 'erlang-icr-indent': 'erlang_erlang_mode_icr_indent', +\ 'erlang-indent-guard': 'erlang_erlang_mode_indent_guard', +\ 'erlang-argument-indent': 'erlang_erlang_mode_argument_indent', +\ 'indent-tabs-mode': 'erlang_erlang_mode_indent_tabs_mode', +\} + +function! ale#fixers#erlang_mode#Fix(buffer) abort + let emacs_executable = + \ ale#Var(a:buffer, 'erlang_erlang_mode_emacs_executable') + + let l:exprs = [ + \ s:SetqDefault(a:buffer, s:variables), + \ '(erlang-mode)', + \ '(font-lock-fontify-region (point-min) (point-max))', + \ '(indent-region (point-min) (point-max))', + \ '(funcall (if indent-tabs-mode ''tabify ''untabify)' + \ . ' (point-min) (point-max))', + \ '(save-buffer 0)', + \] + + let l:command = ale#Escape(l:emacs_executable) + \ . ' --batch' + \ . ' --find-file=%t' + \ . join(map(l:exprs, '" --eval=" . ale#Escape(v:val)'), '') + + return {'command': l:command, 'read_temporary_file': 1} +endfunction + +function! s:SetqDefault(buffer, variables) abort + let l:args = [] + + for [l:emacs_name, l:ale_name] in items(a:variables) + let l:args += [l:emacs_name, ale#Var(a:buffer, l:ale_name)] + endfor + + return '(setq-default ' . join(l:args) . ')' +endfunction diff --git a/doc/ale-erlang.txt b/doc/ale-erlang.txt index 2c6ff22a2f..601410da12 100644 --- a/doc/ale-erlang.txt +++ b/doc/ale-erlang.txt @@ -51,6 +51,57 @@ g:ale_erlang_elvis_executable *g:ale_erlang_elvis_executable* This variable can be changed to specify the elvis executable. +------------------------------------------------------------------------------- +erlang-mode *ale-erlang-erlang-mode* + +g:ale_erlang_erlang_mode_emacs_executable + *g:ale_erlang_erlang_mode_emacs_executable* + *b:ale_erlang_erlang_mode_emacs_executable* + Type: |String| + Default: `'emacs'` + + This variable can be changed to specify the Emacs executable. + +g:ale_erlang_erlang_mode_indent_level *g:ale_erlang_erlang_mode_indent_level* + *b:ale_erlang_erlang_mode_indent_level* + Type: |Number| + Default: `4` + + Indentation of Erlang calls/clauses within blocks. + +g:ale_erlang_erlang_mode_icr_indent *g:ale_erlang_erlang_mode_icr_indent* + *b:ale_erlang_erlang_mode_icr_indent* + Type: `'nil'` or |Number| + Default: `'nil'` + + Indentation of Erlang if/case/receive patterns. `'nil'` means keeping default + behavior. When non-`'nil'`, indent to the column of if/case/receive. + +g:ale_erlang_erlang_mode_indent_guard *g:ale_erlang_erlang_mode_indent_guard* + *b:ale_erlang_erlang_mode_indent_guard* + Type: |Number| + Default: `2` + + Indentation of Erlang guards. + +g:ale_erlang_erlang_mode_argument_indent + *g:ale_erlang_erlang_mode_argument_indent* + *b:ale_erlang_erlang_mode_argument_indent* + Type: `'nil'` or |Number| + Default: `2` + + Indentation of the first argument in a function call. When `'nil'`, indent + to the column after the `'('` of the function. + +g:ale_erlang_erlang_mode_indent_tabs_mode + *g:ale_erlang_erlang_mode_indent_tabs_mode* + *b:ale_erlang_erlang_mode_indent_tabs_mode* + Type: `'nil'` or `'t'` + Default: `'nil'` + + Indentation can insert tabs if this is non-`'nil'`. + + ------------------------------------------------------------------------------- erlang_ls *ale-erlang-erlang_ls* diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index ec787d22f1..fddf3d1f7c 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -191,6 +191,7 @@ Notes: * `SyntaxErl` * `dialyzer`!! * `elvis`!! + * `erlang-mode` (The Erlang mode for Emacs) * `erlang_ls` * `erlc` * `erlfmt` diff --git a/doc/ale.txt b/doc/ale.txt index 05a14b7ae9..cbfd5e2f26 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -3024,6 +3024,7 @@ documented in additional help files. erlang..................................|ale-erlang-options| dialyzer..............................|ale-erlang-dialyzer| elvis.................................|ale-erlang-elvis| + erlang-mode...........................|ale-erlang-erlang-mode| erlang_ls.............................|ale-erlang-erlang_ls| erlc..................................|ale-erlang-erlc| erlfmt................................|ale-erlang-erlfmt| diff --git a/supported-tools.md b/supported-tools.md index f49b5a02ab..a48429541b 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -200,6 +200,7 @@ formatting. * [SyntaxErl](https://github.com/ten0s/syntaxerl) * [dialyzer](http://erlang.org/doc/man/dialyzer.html) :floppy_disk: * [elvis](https://github.com/inaka/elvis) :floppy_disk: + * [erlang-mode](https://www.erlang.org/doc/apps/tools/erlang_mode_chapter.html) (The Erlang mode for Emacs) * [erlang_ls](https://github.com/erlang-ls/erlang_ls) * [erlc](http://erlang.org/doc/man/erlc.html) * [erlfmt](https://github.com/WhatsApp/erlfmt) diff --git a/test/fixers/test_erlang_mode_fixer_callback.vader b/test/fixers/test_erlang_mode_fixer_callback.vader new file mode 100644 index 0000000000..fdee586ff6 --- /dev/null +++ b/test/fixers/test_erlang_mode_fixer_callback.vader @@ -0,0 +1,69 @@ +Before: + call ale#assert#SetUpFixerTest('erlang', 'erlang_mode') + + function! Fixer(key, ...) abort + let l:name = get(a:, 1, 'erlang_mode') + + let l:func = ale#fix#registry#GetFunc(l:name) + let l:dict = call(l:func, [bufnr('')]) + + return l:dict[a:key] + endfunction + +After: + delfunction Fixer + call ale#assert#TearDownFixerTest() + +Execute(Emacs should edit temporary file in batch mode): + AssertEqual 0, stridx( + \ Fixer('command'), + \ ale#Escape('emacs') . ' --batch --find-file=%t --eval=', + \) + +Execute(The temporary file should be read): + AssertEqual 1, Fixer('read_temporary_file') + +Execute(Fixer alias erlang-mode should be provided): + AssertEqual 0, stridx( + \ Fixer('command', 'erlang-mode'), + \ ale#Escape('emacs') . ' --batch --find-file=%t --eval=', + \) + +Execute(Emacs executable should be configurable): + let b:ale_erlang_erlang_mode_emacs_executable = '/path/to/emacs' + AssertEqual 0, stridx(Fixer('command'), ale#Escape('/path/to/emacs')) + +Execute(erlang-indent-level should be 4 by default): + Assert Fixer('command') =~# '\m\' + +Execute(erlang-indent-level should be configurable): + let b:ale_erlang_erlang_mode_indent_level = 2 + Assert Fixer('command') =~# '\m\' + +Execute(erlang-icr-indent should be nil by default): + Assert Fixer('command') =~# '\m\' + +Execute(erlang-icr-indent should be configurable): + let b:ale_erlang_erlang_mode_icr_indent = 0 + Assert Fixer('command') =~# '\m\' + +Execute(erlang-indent-guard should be 2 by default): + Assert Fixer('command') =~# '\m\' + +Execute(erlang-indent-guard should be configurable): + let b:ale_erlang_erlang_mode_indent_guard = 0 + Assert Fixer('command') =~# '\m\' + +Execute(erlang-argument-indent should be 2 by default): + Assert Fixer('command') =~# '\m\' + +Execute(erlang-argument-indent should be configurable): + let b:ale_erlang_erlang_mode_argument_indent = 4 + Assert Fixer('command') =~# '\m\' + +Execute(indent-tabs-mode should be nil by default): + Assert Fixer('command') =~# '\m\' + +Execute(indent-tabs-mode should be configurable): + let b:ale_erlang_erlang_mode_indent_tabs_mode = 't' + Assert Fixer('command') =~# '\m\'