Skip to content

Commit 999c069

Browse files
committed
Elixir formatter: mix format
Fixes google/vim-codefmt #200
1 parent 406686d commit 999c069

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

autoload/codefmt/mixformat.vim

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
" Copyright 2022 Google Inc. All rights reserved.
2+
"
3+
" Licensed under the Apache License, Version 2.0 (the "License");
4+
" you may not use this file except in compliance with the License.
5+
" You may obtain a copy of the License at
6+
"
7+
" http://www.apache.org/licenses/LICENSE-2.0
8+
"
9+
" Unless required by applicable law or agreed to in writing, software
10+
" distributed under the License is distributed on an "AS IS" BASIS,
11+
" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
" See the License for the specific language governing permissions and
13+
" limitations under the License.
14+
15+
let s:plugin = maktaba#plugin#Get('codefmt')
16+
let s:cmdAvailable = {}
17+
18+
""
19+
" @private
20+
" Formatter: mixformat
21+
function! codefmt#mixformat#GetFormatter() abort
22+
let l:formatter = {
23+
\ 'name': 'mixformat',
24+
\ 'setup_instructions': 'mix is usually installed with Elixir' .
25+
\ '(https://elixir-lang.org/install.html). ' .
26+
\ "If mix is not in your path, configure it in .vimrc:\n" .
27+
\ 'Glaive codefmt mix_executable=/path/to/mix' }
28+
29+
function l:formatter.IsAvailable() abort
30+
let l:cmd = codefmt#formatterhelpers#ResolveFlagToArray('mix_executable')
31+
if codefmt#ShouldPerformIsAvailableChecks() && !executable(l:cmd[0])
32+
return 0
33+
endif
34+
return 1
35+
endfunction
36+
37+
function l:formatter.AppliesToBuffer() abort
38+
return &filetype is# 'elixir' || &filetype is# 'eelixir'
39+
\ || &filetype is# 'heex'
40+
endfunction
41+
42+
""
43+
" Reformat the current buffer using ktfmt, only targeting {ranges}.
44+
function l:formatter.FormatRange(startline, endline) abort
45+
let l:filename = expand('%:t')
46+
if empty(l:filename)
47+
let l:filename = 'stdin.exs'
48+
endif
49+
" mix format docs: https://hexdocs.pm/mix/main/Mix.Tasks.Format.html
50+
let l:cmd = codefmt#formatterhelpers#ResolveFlagToArray('mix_executable')
51+
" Specify stdin as the file
52+
let l:cmd = l:cmd + ['format', '--stdin-filename=' . l:filename, '-']
53+
try
54+
" mix format doesn't have a line-range option, but does a reasonable job
55+
" (except for leading indent) when given a full valid expression
56+
call codefmt#formatterhelpers#AttemptFakeRangeFormatting(
57+
\ a:startline, a:endline, l:cmd)
58+
catch /ERROR(ShellError):/
59+
" Parse all the errors and stick them in the quickfix list.
60+
let l:errors = []
61+
for l:line in split(v:exception, "\n")
62+
" Example output:
63+
" ** (SyntaxError) foo.exs:57:28: unexpected reserved word: end
64+
" (blank line)
65+
" HINT: it looks like the "end" on line 56 does not have a matching "do" defined before it
66+
" (blank line), (stack trace with 4-space indent)
67+
" TODO gather additional details between error message and stack trace
68+
let l:tokens = matchlist(l:line,
69+
\ printf('\v^\*\* (\(.*\)) %s:(\d+):(\d+):\s*(.*)', l:filename))
70+
if !empty(l:tokens)
71+
call add(l:errors, {
72+
\ 'filename': @%,
73+
\ 'lnum': l:tokens[1] + a:startline - 1,
74+
\ 'col': l:tokens[2],
75+
\ 'text': l:tokens[3]})
76+
endif
77+
endfor
78+
if empty(l:errors)
79+
" Couldn't parse mix error format; display it all.
80+
call maktaba#error#Shout('Error formatting range: %s', v:exception)
81+
else
82+
call setqflist(l:errors, 'r')
83+
cc 1
84+
endif
85+
endtry
86+
endfunction
87+
88+
return l:formatter
89+
endfunction

doc/codefmt.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The current list of defaults by filetype is:
3737
* clojure: cljstyle, zprint
3838
* dart: dartfmt
3939
* fish: fish_indent
40+
* elixir: mixformat
4041
* gn: gn
4142
* go: gofmt
4243
* java: google-java-format
@@ -86,6 +87,10 @@ Default: 'dartfmt' `
8687
The path to the js-beautify executable.
8788
Default: 'js-beautify' `
8889

90+
*codefmt:mix_executable*
91+
The path to the mix executable for Elixir.
92+
Default: 'mix' `
93+
8994
*codefmt:yapf_executable*
9095
The path to the yapf executable.
9196
Default: 'yapf' `

instant/flags.vim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ call s:plugin.Flag('dartfmt_executable', 'dartfmt')
8080
" The path to the js-beautify executable.
8181
call s:plugin.Flag('js_beautify_executable', 'js-beautify')
8282

83+
""
84+
" The path to the mix executable for Elixir.
85+
call s:plugin.Flag('mix_executable', 'mix')
86+
8387
""
8488
" The path to the yapf executable.
8589
call s:plugin.Flag('yapf_executable', 'yapf')

plugin/register.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
" * clojure: cljstyle, zprint
3232
" * dart: dartfmt
3333
" * fish: fish_indent
34+
" * elixir: mixformat
3435
" * gn: gn
3536
" * go: gofmt
3637
" * java: google-java-format
@@ -61,6 +62,7 @@ call s:registry.AddExtension(codefmt#clangformat#GetFormatter())
6162
call s:registry.AddExtension(codefmt#cljstyle#GetFormatter())
6263
call s:registry.AddExtension(codefmt#zprint#GetFormatter())
6364
call s:registry.AddExtension(codefmt#dartfmt#GetFormatter())
65+
call s:registry.AddExtension(codefmt#mixformat#GetFormatter())
6466
call s:registry.AddExtension(codefmt#fish_indent#GetFormatter())
6567
call s:registry.AddExtension(codefmt#gn#GetFormatter())
6668
call s:registry.AddExtension(codefmt#gofmt#GetFormatter())

0 commit comments

Comments
 (0)