Skip to content
This repository was archived by the owner on Jun 20, 2024. It is now read-only.

Commit f3a5dc7

Browse files
authored
Add ktfmt support for Kotlin (google#183)
Fixes google#176.
1 parent 793d816 commit f3a5dc7

File tree

6 files changed

+183
-0
lines changed

6 files changed

+183
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ helpfiles in the `doc/` directory. The helpfiles are also available via
2323
* Java (google-java-format or clang-format)
2424
* JavaScript (clang-format or [prettier](https://prettier.io))
2525
* JSON (js-beautify)
26+
* Kotlin ([ktfmt](https://github.com/facebookincubator/ktfmt))
2627
* Proto (clang-format)
2728
* Python (Autopep8, Black, or YAPF)
2829
* Rust ([rustfmt](https://github.com/rust-lang/rustfmt))

autoload/codefmt/ktfmt.vim

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
" Copyright 2017 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+
let s:cmdAvailable = {}
19+
20+
""
21+
" @private
22+
" Formatter: ktfmt
23+
function! codefmt#ktfmt#GetFormatter() abort
24+
let l:formatter = {
25+
\ 'name': 'ktfmt',
26+
\ 'setup_instructions': 'Install ktfmt ' .
27+
\ '(https://github.com/facebookincubator/ktfmt). ' .
28+
\ "Enable with\nGlaive codefmt ktfmt_executable=" .
29+
\ 'java,-jar,/path/to/ktfmt-<VERSION>-jar-with-dependencies.jar ' .
30+
\ "\nin your .vimrc or create a shell script named 'ktfmt'" }
31+
32+
function l:formatter.IsAvailable() abort
33+
let l:cmd = codefmt#formatterhelpers#ResolveFlagToArray('ktfmt_executable')
34+
if empty(l:cmd)
35+
return 0
36+
endif
37+
let l:joined = join(l:cmd, ' ')
38+
if has_key(s:cmdAvailable, l:joined)
39+
return s:cmdAvailable[l:joined]
40+
endif
41+
if executable(l:cmd[0])
42+
if l:cmd[0] is# 'java' || l:cmd[0] =~# '/java$'
43+
" Even if java is executable, jar path might be wrong, so run a simple
44+
" command. There's no --version flag, so format an empty file.
45+
let l:success = 0
46+
try
47+
let l:result = maktaba#syscall#Create(l:cmd + ['-']).Call()
48+
let l:success = v:shell_error != 0
49+
catch /ERROR(ShellError)/
50+
call maktaba#error#Warn(
51+
\ 'ktfmt unavailable, check jar file in `%s -`: %s',
52+
\ l:joined,
53+
\ v:exception)
54+
endtry
55+
let s:cmdAvailable[l:joined] = l:success
56+
else
57+
" command is executable and doesn't look like 'java' so assume yes
58+
let s:cmdAvailable[l:joined] = 1
59+
endif
60+
return s:cmdAvailable[l:joined]
61+
else
62+
if l:cmd[0] =~# ','
63+
call maktaba#error#Warn(
64+
\ 'ktfmt_executable is a string "%s" but looks like a list. '
65+
\ . 'Try not quoting the comma-separated value',
66+
\ l:cmd[0])
67+
endif
68+
" don't cache unavailability, in case user installs the command
69+
return 0
70+
endif
71+
endfunction
72+
73+
function l:formatter.AppliesToBuffer() abort
74+
return &filetype is# 'kotlin'
75+
endfunction
76+
77+
""
78+
" Reformat the current buffer using ktfmt, only targeting {ranges}.
79+
function l:formatter.FormatRange(startline, endline) abort
80+
" ktfmt requires '-' as a filename arg to read stdin
81+
let l:cmd = codefmt#formatterhelpers#ResolveFlagToArray('ktfmt_executable')
82+
\ + ['-']
83+
try
84+
" TODO(tstone) Switch to using --lines once that arg is added, see
85+
" https://github.com/facebookincubator/ktfmt/issues/218
86+
call codefmt#formatterhelpers#AttemptFakeRangeFormatting(
87+
\ a:startline, a:endline, l:cmd)
88+
catch /ERROR(ShellError):/
89+
" Parse all the errors and stick them in the quickfix list.
90+
let l:errors = []
91+
for l:line in split(v:exception, "\n")
92+
let l:tokens = matchlist(l:line, '\C\v^<stdin>:(\d+):(\d+):\s*(.*)')
93+
if !empty(l:tokens)
94+
call add(l:errors, {
95+
\ 'filename': @%,
96+
\ 'lnum': l:tokens[1] + a:startline - 1,
97+
\ 'col': l:tokens[2],
98+
\ 'text': l:tokens[3]})
99+
endif
100+
endfor
101+
if empty(l:errors)
102+
" Couldn't parse ktfmt error format; display it all.
103+
call maktaba#error#Shout('Error formatting range: %s', v:exception)
104+
else
105+
call setqflist(l:errors, 'r')
106+
cc 1
107+
endif
108+
endtry
109+
endfunction
110+
111+
return l:formatter
112+
endfunction
113+
114+

doc/codefmt.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The current list of defaults by filetype is:
4242
* java: google-java-format
4343
* javascript, json, html, css: js-beautify
4444
* javascript, html, css, markdown: prettier
45+
* kotlin: ktfmt
4546
* lua: luaformatterfiveone
4647
* nix: nixpkgs-fmt
4748
* python: autopep8, black, yapf
@@ -105,6 +106,18 @@ The path to the google-java executable. Generally, this should have the form:
105106
`java -jar /path/to/google-java`
106107
Default: 'google-java-format' `
107108

109+
*codefmt:ktfmt_executable*
110+
The path to the ktfmt executable with args, as a list. The default value
111+
assumes there is a wrapper script named `ktfmt`. Without such a script, this
112+
will generally have the form:
113+
`ktfmt_executable=java,-jar,/path/to/ktfmt-VERSION-jar-with-dependencies.jar`
114+
115+
Note that range formatting is not fully supported, with a feature request at
116+
https://github.com/facebookincubator/ktfmt/issues/218. ktfmt will align a
117+
formatted range to column 1, requiring a manual reindent to match the
118+
surrounding blocks.
119+
Default: ['ktfmt'] `
120+
108121
*codefmt:shfmt_options*
109122
Command line arguments to feed shfmt. Either a list or callable that takes no
110123
args and returns a list with command line arguments. By default, uses the

instant/flags.vim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ call s:plugin.Flag('buildifier_executable', 'buildifier')
102102
" `java -jar /path/to/google-java`
103103
call s:plugin.Flag('google_java_executable', 'google-java-format')
104104

105+
""
106+
" The path to the ktfmt executable with args, as a list. The default value
107+
" assumes there is a wrapper script named `ktfmt`. Without such a script, this
108+
" will generally have the form:
109+
" `ktfmt_executable=java,-jar,/path/to/ktfmt-VERSION-jar-with-dependencies.jar`
110+
"
111+
" Note that range formatting is not fully supported, with a feature request at
112+
" https://github.com/facebookincubator/ktfmt/issues/218. ktfmt will align a
113+
" formatted range to column 1, requiring a manual reindent to match the
114+
" surrounding blocks.
115+
call s:plugin.Flag('ktfmt_executable', ['ktfmt'])
116+
105117
""
106118
" Command line arguments to feed shfmt. Either a list or callable that
107119
" takes no args and returns a list with command line arguments. By default, uses

plugin/register.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
" * java: google-java-format
3737
" * javascript, json, html, css: js-beautify
3838
" * javascript, html, css, markdown: prettier
39+
" * kotlin: ktfmt
3940
" * lua: luaformatterfiveone
4041
" * nix: nixpkgs-fmt
4142
" * python: autopep8, black, yapf
@@ -65,6 +66,7 @@ call s:registry.AddExtension(codefmt#gofmt#GetFormatter())
6566
call s:registry.AddExtension(codefmt#googlejava#GetFormatter())
6667
call s:registry.AddExtension(codefmt#jsbeautify#GetFormatter())
6768
call s:registry.AddExtension(codefmt#prettier#GetFormatter())
69+
call s:registry.AddExtension(codefmt#ktfmt#GetFormatter())
6870
call s:registry.AddExtension(codefmt#luaformatterfiveone#GetFormatter())
6971
call s:registry.AddExtension(codefmt#nixpkgs_fmt#GetFormatter())
7072
call s:registry.AddExtension(codefmt#autopep8#GetFormatter())

vroom/ktfmt.vroom

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
The built-in ktfmt formatter knows how to format Java BUILD files. If you
2+
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 ktfmt formatter expects a ktfmt executable to be installed on your system,
19+
e.g. as a shell wrapper around "java -jar /path/to/ktfmt.jar"..
20+
21+
% class Foo { public bar() : String { return "bar"; } }
22+
:FormatCode ktfmt
23+
! ktfmt .*
24+
$ class Foo {
25+
$ public bar(): String {
26+
$ return "bar"
27+
$ }
28+
$ }
29+
30+
The name or path of the ktfmt executable can be configured via the
31+
ktfmt_executable flag if the default of "ktmft" doesn't work.
32+
33+
:Glaive codefmt ktfmt_executable=java,-jar,/path/to/ktfmt.jar
34+
:FormatCode ktfmt
35+
! java -jar /path/to/ktfmt.jar .*
36+
$ class Foo {
37+
$ public bar(): String {
38+
$ return "bar"
39+
$ }
40+
$ }
41+
:Glaive codefmt ktfmt_executable='ktfmt'

0 commit comments

Comments
 (0)