Skip to content

Commit 2147649

Browse files
authored
Merge pull request google#108 from lhchavez/prettier
Add support for https://prettier.io
2 parents 62c09d5 + ddc5b8f commit 2147649

File tree

6 files changed

+252
-1
lines changed

6 files changed

+252
-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: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
53+
" prettier is able to automatically choose the best parser if the filepath
54+
" is provided. Otherwise, fall back to the previous default: babylon.
55+
if @% == ""
56+
call extend(l:cmd, ['--parser', 'babylon'])
57+
else
58+
call extend(l:cmd, ['--stdin-filepath', @%])
59+
endif
60+
61+
call maktaba#ensure#IsNumber(a:startline)
62+
call maktaba#ensure#IsNumber(a:endline)
63+
64+
let l:lines = getline(1, line('$'))
65+
let l:input = join(l:lines, "\n")
66+
if a:startline > 1
67+
let l:lines_start = join(l:lines[0 : a:startline - 1], "\n")
68+
call extend(l:cmd, ['--range-start', string(strchars(l:lines_start))])
69+
endif
70+
let l:lines_end = join(l:lines[0 : a:endline - 1], "\n")
71+
call extend(l:cmd, ['--range-end', string(strchars(l:lines_end))])
72+
73+
call extend(l:cmd, l:prettier_options)
74+
try
75+
let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call()
76+
let l:formatted = split(l:result.stdout, "\n")
77+
call maktaba#buffer#Overwrite(1, line('$'), l:formatted)
78+
catch /ERROR(ShellError):/
79+
" Parse all the errors and stick them in the quickfix list.
80+
let l:errors = []
81+
for l:line in split(v:exception, "\n")
82+
let l:tokens = matchlist(l:line,
83+
\ '\C\v^\[error\] stdin: (.*) \((\d+):(\d+)\).*')
84+
if !empty(l:tokens)
85+
call add(l:errors, {
86+
\ 'filename': @%,
87+
\ 'lnum': l:tokens[2],
88+
\ 'col': l:tokens[3],
89+
\ 'text': l:tokens[1]})
90+
endif
91+
endfor
92+
93+
if empty(l:errors)
94+
" Couldn't parse prettier error format; display it all.
95+
call maktaba#error#Shout('Error formatting file: %s', v:exception)
96+
else
97+
call setqflist(l:errors, 'r')
98+
cc 1
99+
endif
100+
endtry
101+
endfunction
102+
103+
return l:formatter
104+
endfunction

doc/codefmt.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,35 @@ Default: 'yapf' `
6060
The path to the gn executable.
6161
Default: 'gn' `
6262

63+
*codefmt:buildifier_executable*
64+
The path to the buildifier executable.
65+
Default: 'buildifier' `
66+
67+
*codefmt:google_java_executable*
68+
The path to the google-java executable. Generally, this should have the form:
69+
`java -jar /path/to/google-java`
70+
Default: 'google-java-format' `
71+
72+
*codefmt:shfmt_options*
73+
Command line arguments to to feed shfmt. Either a list or callable that takes
74+
no args and returns a list with command line arguments. By default, uses the
75+
Google's style. See https://github.com/mvdan/sh for details.
76+
Default: ['-i', '2', '-sr', '-ci'] `
77+
78+
*codefmt:shfmt_executable*
79+
The path to the shfmt executable.
80+
Default: 'shfmt' `
81+
82+
*codefmt:prettier_options*
83+
Command line arguments to to feed prettier. Either a list or callable that
84+
takes no args and returns a list with command line arguments.
85+
Default: [ '--single-quote', '--trailing-comma=all', '--arrow-parens=always',
86+
'--print-width=80'] `
87+
88+
*codefmt:prettier_executable*
89+
The path to the prettier executable.
90+
Default: 'prettier' `
91+
6392
*codefmt:plugin[autocmds]*
6493
Configures whether plugin/autocmds.vim should be loaded.
6594
Default: 1 `
@@ -99,6 +128,7 @@ none is explicitly supplied via an explicit arg to |:FormatCode| or the
99128
plugins are enabled or what other software is installed on your system.
100129

101130
The current list of defaults by filetype is:
131+
* bzl (Bazel): buildifier
102132
* c, cpp, proto, javascript, typescript: clang-format
103133
* go: gofmt
104134
* python: autopep8, yapf

instant/flags.vim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,14 @@ 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', [
112+
\ '--single-quote', '--trailing-comma=all',
113+
\ '--arrow-parens=always', '--print-width=80'])
114+
115+
""
116+
" The path to the prettier executable.
117+
call s:plugin.Flag('prettier_executable', 'prettier')

plugin/register.vim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ endif
2121
let s:registry = s:plugin.GetExtensionRegistry()
2222
call s:registry.SetValidator('codefmt#EnsureFormatter')
2323

24+
" Formatters that are registered later are given more priority when deciding
25+
" what the default formatter will be for a particular file type.
2426
call s:registry.AddExtension(codefmt#jsbeautify#GetFormatter())
27+
call s:registry.AddExtension(codefmt#prettier#GetFormatter())
2528
call s:registry.AddExtension(codefmt#clangformat#GetFormatter())
2629
call s:registry.AddExtension(codefmt#gofmt#GetFormatter())
2730
call s:registry.AddExtension(codefmt#dartfmt#GetFormatter())

vroom/prettier.vroom

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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+
$ 2 (status)
70+
$ echo >\1 ' (command)
71+
|[error] stdin: SyntaxError: Unexpected token (2:1)\n
72+
|[error] 1 | function foo() {\n
73+
|[error] > 2 |\n
74+
|[error] | ^'
75+
function foo() {
76+
@end
77+
:echomsg line('.') . ',' . col('.')
78+
~ 1,1
79+
:echomsg string(map(getqflist(),
80+
|'v:val.lnum . "," . v:val.col . "," . v:val.text'))
81+
~ ['2,1,SyntaxError: Unexpected token']
82+
83+
It can format specific line ranges of code using :FormatLines.
84+
85+
@clear
86+
% function HelloWorld(){if(!greeting){return null};}<CR>
87+
|function Greet(){if(!greeting){return null};}
88+
89+
:1,1FormatLines prettier
90+
! prettier .*--parser babylon --range-end 50.*2>.*
91+
$ function HelloWorld() {
92+
$ if (!greeting) {
93+
$ return null;
94+
$ }
95+
$ }
96+
$ function Greet(){if(!greeting){return null};}
97+
function HelloWorld() {
98+
if (!greeting) {
99+
return null;
100+
}
101+
}
102+
function Greet(){if(!greeting){return null};}
103+
@end

0 commit comments

Comments
 (0)