Skip to content

Commit cf9683d

Browse files
authored
Add ocamlformat formatter (#205)
1 parent 2b9dd2f commit cf9683d

File tree

6 files changed

+151
-0
lines changed

6 files changed

+151
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ helpfiles in the `doc/` directory. The helpfiles are also available via
2525
* JavaScript (clang-format or [prettier](https://prettier.io))
2626
* JSON (js-beautify)
2727
* Kotlin ([ktfmt](https://github.com/facebookincubator/ktfmt))
28+
* OCaml ([ocamlformat](https://github.com/ocaml-ppx/ocamlformat))
2829
* Proto (clang-format)
2930
* Python (Autopep8, Black, or YAPF)
3031
* Rust ([rustfmt](https://github.com/rust-lang/rustfmt))

autoload/codefmt/ocamlformat.vim

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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: ocamlformat
22+
function! codefmt#ocamlformat#GetFormatter() abort
23+
let l:formatter = {
24+
\ 'name': 'ocamlformat',
25+
\ 'setup_instructions': 'Install ocamlformat ' .
26+
\ '(https://github.com/ocaml-ppx/ocamlformat#installation).'}
27+
28+
function l:formatter.IsAvailable() abort
29+
return executable(s:plugin.Flag('ocamlformat_executable'))
30+
endfunction
31+
32+
function l:formatter.AppliesToBuffer() abort
33+
return &filetype is# 'ocaml'
34+
endfunction
35+
36+
""
37+
" Reformat the current buffer with ocamlformat or the binary named in
38+
" @flag(ocamlformat_executable)
39+
" @throws ShellError
40+
"
41+
" We implement Format(), and not FormatRange{,s}(), because black doesn't
42+
" provide a hook for formatting a range
43+
function l:formatter.Format() abort
44+
let l:executable = s:plugin.Flag('ocamlformat_executable')
45+
46+
" ocamlformat requires --name, --impl, or --intf when reading from
47+
" stdin.
48+
let l:inputflags = ['--name', @%]
49+
if len(@%) == 0
50+
" Assume we're formatting an implementation file.
51+
let l:inputflags = ['--impl']
52+
endif
53+
" TODO(dimitrije): Catch and handle formatting errors more nicely. See how
54+
" it's dome in gofmt.vim.
55+
" For now, an ugly ShellError will be thrown if anything fails here.
56+
call codefmt#formatterhelpers#Format(
57+
\ [l:executable]
58+
\ + l:inputflags
59+
\ + ['-'])
60+
endfunction
61+
62+
return l:formatter
63+
endfunction

doc/codefmt.txt

+5
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ The current list of defaults by filetype is:
4646
* kotlin: ktfmt
4747
* lua: luaformatterfiveone
4848
* nix: nixpkgs-fmt
49+
* ocaml: ocamlformat
4950
* python: autopep8, black, yapf
5051
* rust: rustfmt
5152
* sh: shfmt
@@ -219,6 +220,10 @@ Default: 'cljstyle' `
219220
The path to the ormolu executable.
220221
Default: 'ormolu' `
221222

223+
*codefmt:ocamlformat_executable*
224+
The path to the ocamlformat executable.
225+
Default: 'ocamlformat' `
226+
222227
*codefmt:plugin[autocmds]*
223228
Configures whether plugin/autocmds.vim should be loaded.
224229
Default: 1 `

instant/flags.vim

+4
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,7 @@ call s:plugin.Flag('cljstyle_executable', 'cljstyle')
231231
""
232232
" The path to the ormolu executable.
233233
call s:plugin.Flag('ormolu_executable', 'ormolu')
234+
235+
""
236+
" The path to the ocamlformat executable.
237+
call s:plugin.Flag('ocamlformat_executable', 'ocamlformat')

plugin/register.vim

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
" * kotlin: ktfmt
4141
" * lua: luaformatterfiveone
4242
" * nix: nixpkgs-fmt
43+
" * ocaml: ocamlformat
4344
" * python: autopep8, black, yapf
4445
" * rust: rustfmt
4546
" * sh: shfmt
@@ -79,3 +80,4 @@ call s:registry.AddExtension(codefmt#rustfmt#GetFormatter())
7980
call s:registry.AddExtension(codefmt#shfmt#GetFormatter())
8081
call s:registry.AddExtension(codefmt#swiftformat#GetFormatter())
8182
call s:registry.AddExtension(codefmt#ormolu#GetFormatter())
83+
call s:registry.AddExtension(codefmt#ocamlformat#GetFormatter())

vroom/ocamlformat.vroom

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
The ocamlformat formatter knows how to format OCaml.
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 ocamlformat formatter expects the ocamlformat executable to be installed
19+
on your system.
20+
21+
% f()
22+
:FormatCode ocamlformat
23+
! ocamlformat --impl - .*2>.*
24+
$ f()
25+
26+
The name or path of the ocamlformat executable can be configured via the
27+
ocamlformat_executable flag if the default of "ocamlformat" doesn't work.
28+
29+
:Glaive codefmt ocamlformat_executable='myocamlformat'
30+
:FormatCode ocamlformat
31+
! myocamlformat --impl - .*2>.*
32+
$ f()
33+
:Glaive codefmt ocamlformat_executable='ocamlformat'
34+
35+
You can format any buffer with ocamlformat specifying the formatter explicitly.
36+
37+
@clear
38+
% open Base<CR>
39+
|<CR>
40+
| open Stdio<CR>
41+
|<CR>
42+
| let build_count chan=In_channel.fold_lines chan<CR>
43+
| ~init:[]<CR>
44+
| ~f:<CR>
45+
| (fun counts line -><CR>
46+
| let count = match List.Assoc.find ~equal:String.equal counts line with<CR>
47+
| | None -> 0<CR>
48+
| | Some x -> x<CR>
49+
| in List.Assoc.add ~equal:String.equal counts line ( count + 1 )<CR>
50+
| )
51+
52+
:FormatCode ocamlformat
53+
! ocamlformat --impl - .*2>.*
54+
$ open Base
55+
$ open Stdio
56+
$
57+
$ let build_count chan =
58+
$ In_channel.fold_lines chan ~init:[] ~f:(fun counts line ->
59+
$ let count =
60+
$ match List.Assoc.find ~equal:String.equal counts line with
61+
$ | None -> 0
62+
$ | Some x -> x
63+
$ in
64+
$ List.Assoc.add ~equal:String.equal counts line (count + 1))
65+
open Base
66+
open Stdio
67+
68+
let build_count chan =
69+
In_channel.fold_lines chan ~init:[] ~f:(fun counts line ->
70+
let count =
71+
match List.Assoc.find ~equal:String.equal counts line with
72+
| None -> 0
73+
| Some x -> x
74+
in
75+
List.Assoc.add ~equal:String.equal counts line (count + 1))
76+
@end

0 commit comments

Comments
 (0)