Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add erlang-mode fixer for Erlang files #4848

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions autoload/ale/fix/registry.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand Down
49 changes: 49 additions & 0 deletions autoload/ale/fixers/erlang_mode.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
" 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
51 changes: 51 additions & 0 deletions doc/ale-erlang.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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*

Expand Down
1 change: 1 addition & 0 deletions doc/ale-supported-languages-and-tools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ Notes:
* `SyntaxErl`
* `dialyzer`!!
* `elvis`!!
* `erlang-mode` (The Erlang mode for Emacs)
* `erlang_ls`
* `erlc`
* `erlfmt`
Expand Down
1 change: 1 addition & 0 deletions doc/ale.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand Down
1 change: 1 addition & 0 deletions supported-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
69 changes: 69 additions & 0 deletions test/fixers/test_erlang_mode_fixer_callback.vader
Original file line number Diff line number Diff line change
@@ -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\<erlang-indent-level 4\>'

Execute(erlang-indent-level should be configurable):
let b:ale_erlang_erlang_mode_indent_level = 2
Assert Fixer('command') =~# '\m\<erlang-indent-level 2\>'

Execute(erlang-icr-indent should be nil by default):
Assert Fixer('command') =~# '\m\<erlang-icr-indent nil\>'

Execute(erlang-icr-indent should be configurable):
let b:ale_erlang_erlang_mode_icr_indent = 0
Assert Fixer('command') =~# '\m\<erlang-icr-indent 0\>'

Execute(erlang-indent-guard should be 2 by default):
Assert Fixer('command') =~# '\m\<erlang-indent-guard 2\>'

Execute(erlang-indent-guard should be configurable):
let b:ale_erlang_erlang_mode_indent_guard = 0
Assert Fixer('command') =~# '\m\<erlang-indent-guard 0\>'

Execute(erlang-argument-indent should be 2 by default):
Assert Fixer('command') =~# '\m\<erlang-argument-indent 2\>'

Execute(erlang-argument-indent should be configurable):
let b:ale_erlang_erlang_mode_argument_indent = 4
Assert Fixer('command') =~# '\m\<erlang-argument-indent 4\>'

Execute(indent-tabs-mode should be nil by default):
Assert Fixer('command') =~# '\m\<indent-tabs-mode nil\>'

Execute(indent-tabs-mode should be configurable):
let b:ale_erlang_erlang_mode_indent_tabs_mode = 't'
Assert Fixer('command') =~# '\m\<indent-tabs-mode t\>'