Skip to content

Commit 8984f61

Browse files
authored
Add ormolu formatter (Haskell) (#203)
* Add ormolu formatter (Haskell). * Add vroom test for ormolu formatter. * List Haskell formatter in the README file.
1 parent 406686d commit 8984f61

File tree

5 files changed

+204
-0
lines changed

5 files changed

+204
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ helpfiles in the `doc/` directory. The helpfiles are also available via
1919
* Fish ([fish_indent](https://fishshell.com/docs/current/commands.html#fish_indent))
2020
* Go (gofmt)
2121
* [GN](https://www.chromium.org/developers/gn-build-configuration) (gn)
22+
* Haskell ([ormolu](https://github.com/tweag/ormolu))
2223
* HTML (js-beautify)
2324
* Java (google-java-format or clang-format)
2425
* JavaScript (clang-format or [prettier](https://prettier.io))

autoload/codefmt/ormolu.vim

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
" Copyright 2021 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+
16+
let s:plugin = maktaba#plugin#Get('codefmt')
17+
18+
19+
""
20+
" @private
21+
" Formatter: ormolu
22+
function! codefmt#ormolu#GetFormatter() abort
23+
let l:formatter = {
24+
\ 'name': 'ormolu',
25+
\ 'setup_instructions': 'Install ormolu ' .
26+
\ '(https://hackage.haskell.org/package/ormolu).'}
27+
28+
function l:formatter.IsAvailable() abort
29+
return executable(s:plugin.Flag('ormolu_executable'))
30+
endfunction
31+
32+
function l:formatter.AppliesToBuffer() abort
33+
return &filetype is# 'haskell'
34+
endfunction
35+
36+
""
37+
" Reformat the current buffer with ormolu or the binary named in
38+
" @flag(ormolu_executable), only targeting the range between {startline} and
39+
" {endline}.
40+
" @throws ShellError
41+
function l:formatter.FormatRange(startline, endline) abort
42+
let l:cmd = [s:plugin.Flag('ormolu_executable')]
43+
44+
let l:lines = getline(1, line('$'))
45+
let l:input = join(l:lines, "\n")
46+
47+
call maktaba#ensure#IsNumber(a:startline)
48+
call maktaba#ensure#IsNumber(a:endline)
49+
50+
if a:startline > 1
51+
call extend(l:cmd, ['--start-line', string(a:startline)])
52+
endif
53+
call extend(l:cmd, ['--end-line', string(a:endline)])
54+
55+
try
56+
let l:syscall = maktaba#syscall#Create(l:cmd).WithStdin(l:input)
57+
let l:result = l:syscall.Call()
58+
let l:formatted = split(l:result.stdout, "\n")
59+
call maktaba#buffer#Overwrite(1, line('$'), l:formatted)
60+
catch /ERROR(ShellError):/
61+
call maktaba#error#Shout('Error formatting file: %s', v:exception)
62+
endtry
63+
endfunction
64+
65+
return l:formatter
66+
endfunction

instant/flags.vim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,7 @@ call s:plugin.Flag('luaformatterfiveone_executable', 'luaformatterfiveone')
227227
""
228228
" The path to the cljstyle executable.
229229
call s:plugin.Flag('cljstyle_executable', 'cljstyle')
230+
231+
""
232+
" The path to the ormolu executable.
233+
call s:plugin.Flag('ormolu_executable', 'ormolu')

plugin/register.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
" * fish: fish_indent
3434
" * gn: gn
3535
" * go: gofmt
36+
" * haskell: ormolu
3637
" * java: google-java-format
3738
" * javascript, json, html, css: js-beautify
3839
" * javascript, html, css, markdown: prettier
@@ -77,3 +78,4 @@ call s:registry.AddExtension(codefmt#yapf#GetFormatter())
7778
call s:registry.AddExtension(codefmt#rustfmt#GetFormatter())
7879
call s:registry.AddExtension(codefmt#shfmt#GetFormatter())
7980
call s:registry.AddExtension(codefmt#swiftformat#GetFormatter())
81+
call s:registry.AddExtension(codefmt#ormolu#GetFormatter())

vroom/ormolu.vroom

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
The ormolu formatter knows how to format Haskell.
2+
If you aren't familiar with basic codefmt usage yet, see main.vroom first.
3+
4+
We'll set up codefmt and configure the vroom environment, then jump into some
5+
examples.
6+
7+
:source $VROOMDIR/setupvroom.vim
8+
9+
:let g:repeat_calls = []
10+
:function FakeRepeat(...)<CR>
11+
| call add(g:repeat_calls, a:000)<CR>
12+
:endfunction
13+
:call maktaba#test#Override('repeat#set', 'FakeRepeat')
14+
15+
:call codefmt#SetWhetherToPerformIsAvailableChecksForTesting(0)
16+
17+
18+
The ormolu formatter expects the ormolu executable to be installed
19+
on your system.
20+
21+
% f()
22+
:FormatCode ormolu
23+
! ormolu .*
24+
$ f()
25+
26+
The name or path of the ormolu executable can be configured via the
27+
ormolu_executable flag if the default of "ormolu" doesn't work.
28+
29+
:Glaive codefmt ormolu_executable='myormolu'
30+
:FormatCode ormolu
31+
! myormolu .*
32+
$ f()
33+
:Glaive codefmt ormolu_executable='ormolu'
34+
35+
You can format any buffer with ormolu specifying the formatter explicitly.
36+
37+
@clear
38+
% module Main<CR>
39+
|<CR>
40+
| where<CR>
41+
|<CR>
42+
|main:: IO ()<CR>
43+
|<CR>
44+
|<CR>
45+
|{- this is just a comment -}<CR>
46+
|main =pure ()<CR>
47+
|<CR>
48+
|foo :: Int<CR>
49+
|foo =<CR>
50+
| 5<CR>
51+
| + 5<CR>
52+
|<CR>
53+
|bar :: Int<CR>
54+
| bar = 7
55+
56+
:FormatCode ormolu
57+
! ormolu .*2>.*
58+
$ module Main where
59+
$
60+
$ main :: IO ()
61+
$ {- this is just a comment -}
62+
$ main = pure ()
63+
$
64+
$ foo :: Int
65+
$ foo =
66+
$ 5
67+
$ + 5
68+
$
69+
$ bar :: Int
70+
$ bar = 7
71+
module Main where
72+
73+
main :: IO ()
74+
{- this is just a comment -}
75+
main = pure ()
76+
77+
foo :: Int
78+
foo =
79+
5
80+
+ 5
81+
82+
bar :: Int
83+
bar = 7
84+
@end
85+
86+
It can format specific line ranges of code using :FormatLines.
87+
88+
@clear
89+
% module Main (main) where<CR>
90+
|<CR>
91+
|main :: IO ()<CR>
92+
|{- this is just a comment -}<CR>
93+
|main = pure ()<CR>
94+
|<CR>
95+
|foo :: Int<CR>
96+
|foo =<CR>
97+
| 5<CR>
98+
| + 5<CR>
99+
|<CR>
100+
|bar :: Int<CR>
101+
| bar = 7
102+
103+
:1,5FormatLines ormolu
104+
! ormolu .*2>.*
105+
$ module Main (main) where
106+
$
107+
$ main :: IO ()
108+
$ {- this is just a comment -}
109+
$ main = pure ()
110+
$
111+
$ foo :: Int
112+
$ foo =
113+
$ 5
114+
$ + 5
115+
$
116+
$ bar :: Int
117+
$ bar = 7
118+
module Main (main) where
119+
120+
main :: IO ()
121+
{- this is just a comment -}
122+
main = pure ()
123+
124+
foo :: Int
125+
foo =
126+
5
127+
+ 5
128+
129+
bar :: Int
130+
bar = 7
131+
@end

0 commit comments

Comments
 (0)