Skip to content

Commit 6bb3d21

Browse files
committed
Add support for https://prettier.io
This change adds the Prettier (https://prettier.io) JavaScript formatter. Fixes: #89
1 parent 5a198e2 commit 6bb3d21

File tree

5 files changed

+213
-1
lines changed

5 files changed

+213
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ helpfiles in the `doc/` directory. The helpfiles are also available via
1919
* [GN](https://www.chromium.org/developers/gn-build-configuration) (gn)
2020
* HTML (js-beautify)
2121
* Java (google-java-format or clang-format)
22-
* JavaScript (clang-format)
22+
* JavaScript (clang-format or [prettier](https://prettier.io))
2323
* JSON (js-beautify)
2424
* Proto (clang-format)
2525
* Python (Autopep8 or YAPF)

autoload/codefmt/prettier.vim

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
" Copyright 2018 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: prettier
22+
function! codefmt#prettier#GetFormatter() abort
23+
let l:formatter = {
24+
\ 'name': 'prettier',
25+
\ 'setup_instructions': 'Install prettier (https://prettier.io/) ' .
26+
\ 'and configure the prettier_executable flag'}
27+
28+
function l:formatter.IsAvailable() abort
29+
return executable(s:plugin.Flag('prettier_executable'))
30+
endfunction
31+
32+
function l:formatter.AppliesToBuffer() abort
33+
return &filetype is# 'javascript'
34+
endfunction
35+
36+
""
37+
" Reformat the current buffer with prettier or the binary named in
38+
" @flag(prettier_executable), only targeting the range between {startline} and
39+
" {endline}.
40+
function l:formatter.FormatRange(startline, endline) abort
41+
let l:Prettier_options = s:plugin.Flag('prettier_options')
42+
if type(l:Prettier_options) is# type([])
43+
let l:prettier_options = l:Prettier_options
44+
elseif maktaba#value#IsCallable(l:Prettier_options)
45+
let l:prettier_options = maktaba#function#Call(l:Prettier_options)
46+
else
47+
throw maktaba#error#WrongType(
48+
\ 'prettier_options flag must be list or callable. Found %s',
49+
\ string(l:Prettier_options))
50+
endif
51+
let l:cmd = [s:plugin.Flag('prettier_executable'), '--stdin', '--no-color']
52+
if @% == ""
53+
call extend(l:cmd, ['--parser', 'babylon'])
54+
else
55+
call extend(l:cmd, ['--stdin-filepath', @%])
56+
endif
57+
call maktaba#ensure#IsNumber(a:startline)
58+
call maktaba#ensure#IsNumber(a:endline)
59+
60+
let l:lines = getline(1, line('$'))
61+
let l:input = join(l:lines, "\n")
62+
if a:startline > 1
63+
let l:lines_start = join(l:lines[0 : a:startline - 1], "\n")
64+
call extend(l:cmd, ['--range-start', string(strchars(l:lines_start))])
65+
endif
66+
let l:lines_end = join(l:lines[0 : a:endline - 1], "\n")
67+
call extend(l:cmd, ['--range-end', string(strchars(l:lines_end))])
68+
69+
call extend(l:cmd, l:prettier_options)
70+
try
71+
let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call()
72+
let l:formatted = split(l:result.stdout, "\n")
73+
call maktaba#buffer#Overwrite(1, line('$'), l:formatted)
74+
catch /ERROR(ShellError):/
75+
" Parse all the errors and stick them in the quickfix list.
76+
let l:errors = []
77+
for l:line in split(v:exception, "\n")
78+
let l:tokens = matchlist(l:line,
79+
\ '\C\v^\[error\] stdin: (.*) \((\d+):(\d+)\).*')
80+
if !empty(l:tokens)
81+
call add(l:errors, {
82+
\ 'filename': @%,
83+
\ 'lnum': l:tokens[2],
84+
\ 'col': l:tokens[3],
85+
\ 'text': l:tokens[1]})
86+
endif
87+
endfor
88+
89+
if empty(l:errors)
90+
" Couldn't parse prettier error format; display it all.
91+
call maktaba#error#Shout('Error formatting file: %s', v:exception)
92+
else
93+
call setqflist(l:errors, 'r')
94+
cc 1
95+
endif
96+
endtry
97+
endfunction
98+
99+
return l:formatter
100+
endfunction

instant/flags.vim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,12 @@ call s:plugin.Flag('shfmt_options', ['-i', '2', '-sr', '-ci'])
104104
""
105105
" The path to the shfmt executable.
106106
call s:plugin.Flag('shfmt_executable', 'shfmt')
107+
108+
""
109+
" Command line arguments to to feed prettier. Either a list or callable that
110+
" takes no args and returns a list with command line arguments.
111+
call s:plugin.Flag('prettier_options', ['--single-quote', '--trailing-comma=all', '--arrow-parens=always', '--print-width=80'])
112+
113+
""
114+
" The path to the prettier executable.
115+
call s:plugin.Flag('prettier_executable', 'prettier')

plugin/register.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ let s:registry = s:plugin.GetExtensionRegistry()
2222
call s:registry.SetValidator('codefmt#EnsureFormatter')
2323

2424
call s:registry.AddExtension(codefmt#jsbeautify#GetFormatter())
25+
call s:registry.AddExtension(codefmt#prettier#GetFormatter())
2526
call s:registry.AddExtension(codefmt#clangformat#GetFormatter())
2627
call s:registry.AddExtension(codefmt#gofmt#GetFormatter())
2728
call s:registry.AddExtension(codefmt#dartfmt#GetFormatter())

vroom/prettier.vroom

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
The prettier formatter knows how to format JavaScript.
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 prettier formatter expects the prettier executable to be installed on your system.
19+
20+
% function HelloWorld(){if(!greeting){return null};}
21+
:FormatCode prettier
22+
! prettier .*
23+
$ function HelloWorld() {
24+
$ if (!greeting) {
25+
$ return null;
26+
$ }
27+
$ }
28+
29+
The name or path of the prettier executable can be configured via the
30+
prettier_executable flag if the default of "prettier" doesn't work.
31+
32+
:Glaive codefmt prettier_executable='myprettier'
33+
:FormatCode prettier
34+
! myprettier .*
35+
$ function HelloWorld() {
36+
$ if (!greeting) {
37+
$ return null;
38+
$ }
39+
$ }
40+
:Glaive codefmt prettier_executable='prettier'
41+
42+
43+
You can format any buffer with prettier specifying the formatter explicitly.
44+
45+
@clear
46+
% function HelloWorld(){if(!greeting){return null};}
47+
48+
:FormatCode prettier
49+
! prettier .*2>.*
50+
$ function HelloWorld() {
51+
$ if (!greeting) {
52+
$ return null;
53+
$ }
54+
$ }
55+
function HelloWorld() {
56+
if (!greeting) {
57+
return null;
58+
}
59+
}
60+
@end
61+
62+
Errors are reported using the quickfix list.
63+
64+
@clear
65+
% function foo() {
66+
67+
:FormatCode prettier
68+
! prettier .*2> (.*)
69+
$ echo '[error] stdin: SyntaxError: Unexpected token (2:1)' >\1 (command)
70+
$ echo '[error] 1 | function foo() {' >>\1 (command)
71+
$ echo '[error] > 2 |' >>\1 (command)
72+
$ echo '[error] | ^' >>\1 (command)
73+
$ 2 (status)
74+
function foo() {
75+
@end
76+
:echomsg line('.') . ',' . col('.')
77+
~ 1,1
78+
:echomsg string(map(getqflist(),
79+
|'v:val.lnum . "," . v:val.col . "," . v:val.text'))
80+
~ ['2,1,SyntaxError: Unexpected token']
81+
82+
It can format specific line ranges of code using :FormatLines.
83+
84+
@clear
85+
% function HelloWorld(){if(!greeting){return null};}<CR>
86+
|function Greet(){if(!greeting){return null};}
87+
88+
:1,1FormatLines prettier
89+
! prettier .*--parser babylon --range-end 50.*2>.*
90+
$ function HelloWorld() {
91+
$ if (!greeting) {
92+
$ return null;
93+
$ }
94+
$ }
95+
$ function Greet(){if(!greeting){return null};}
96+
function HelloWorld() {
97+
if (!greeting) {
98+
return null;
99+
}
100+
}
101+
function Greet(){if(!greeting){return null};}
102+
@end

0 commit comments

Comments
 (0)