Skip to content

Commit 5ede026

Browse files
authored
Merge pull request #77 from Kashomon/master
Split out all the formatters into separate files for readability.
2 parents b97f44b + c38bd84 commit 5ede026

File tree

11 files changed

+626
-508
lines changed

11 files changed

+626
-508
lines changed

autoload/codefmt.vim

Lines changed: 2 additions & 498 deletions
Large diffs are not rendered by default.

autoload/codefmt/autopep8.vim

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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+
19+
""
20+
" @private
21+
" Invalidates the cached autopep8 version detection info.
22+
function! codefmt#autopep8#InvalidateVersion() abort
23+
unlet! s:autopep8_supports_range
24+
endfunction
25+
26+
27+
""
28+
" @private
29+
" Formatter: autopep8
30+
function! codefmt#autopep8#GetFormatter() abort
31+
let l:formatter = {
32+
\ 'name': 'autopep8',
33+
\ 'setup_instructions': 'Install autopep8 ' .
34+
\ '(https://pypi.python.org/pypi/autopep8/).'}
35+
36+
function l:formatter.IsAvailable() abort
37+
return executable(s:plugin.Flag('autopep8_executable'))
38+
endfunction
39+
40+
function l:formatter.AppliesToBuffer() abort
41+
return &filetype is# 'python'
42+
endfunction
43+
44+
""
45+
" Reformat the current buffer with autopep8 or the binary named in
46+
" @flag(autopep8_executable), only targeting the range between {startline} and
47+
" {endline}.
48+
" @throws ShellError
49+
function l:formatter.FormatRange(startline, endline) abort
50+
let l:executable = s:plugin.Flag('autopep8_executable')
51+
if !exists('s:autopep8_supports_range')
52+
let l:version_call =
53+
\ maktaba#syscall#Create([l:executable, '--version']).Call()
54+
" In some cases version is written to stderr, in some to stdout
55+
let l:version_output = empty(version_call.stderr) ?
56+
\ version_call.stdout : version_call.stderr
57+
let l:autopep8_version =
58+
\ matchlist(l:version_output, '\m\Cautopep8 \(\d\+\)\.')
59+
if empty(l:autopep8_version)
60+
throw maktaba#error#Failure(
61+
\ 'Unable to parse version from `%s --version`: %s',
62+
\ l:executable, l:version_output)
63+
else
64+
let s:autopep8_supports_range = l:autopep8_version[1] >= 1
65+
endif
66+
endif
67+
68+
call maktaba#ensure#IsNumber(a:startline)
69+
call maktaba#ensure#IsNumber(a:endline)
70+
let l:lines = getline(1, line('$'))
71+
72+
if s:autopep8_supports_range
73+
let l:cmd = [l:executable, '--range', ''.a:startline, ''.a:endline, '-']
74+
let l:input = join(l:lines, "\n")
75+
else
76+
let l:cmd = [l:executable, '-']
77+
" Hack range formatting by formatting range individually, ignoring context.
78+
let l:input = join(l:lines[a:startline - 1 : a:endline - 1], "\n")
79+
endif
80+
81+
let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call()
82+
let l:formatted = split(l:result.stdout, "\n")
83+
84+
if s:autopep8_supports_range
85+
let l:full_formatted = l:formatted
86+
else
87+
" Special case empty slice: neither l:lines[:0] nor l:lines[:-1] is right.
88+
let l:before = a:startline > 1 ? l:lines[ : a:startline - 2] : []
89+
let l:full_formatted = l:before + l:formatted + l:lines[a:endline :]
90+
endif
91+
92+
call maktaba#buffer#Overwrite(1, line('$'), l:full_formatted)
93+
endfunction
94+
95+
return l:formatter
96+
endfunction

autoload/codefmt/buildifier.vim

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515

1616
let s:plugin = maktaba#plugin#Get('codefmt')
17-
let s:registry = s:plugin.GetExtensionRegistry()
1817

1918

2019
""

autoload/codefmt/clangformat.vim

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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+
19+
function! s:ClangFormatHasAtLeastVersion(minimum_version) abort
20+
if !exists('s:clang_format_version')
21+
let l:executable = s:plugin.Flag('clang_format_executable')
22+
let l:version_output =
23+
\ maktaba#syscall#Create([l:executable, '--version']).Call().stdout
24+
let l:version_string = matchstr(l:version_output, '\v\d+(.\d+)+')
25+
let s:clang_format_version = map(split(l:version_string, '\.'), 'v:val + 0')
26+
endif
27+
let l:length = min([len(a:minimum_version), len(s:clang_format_version)])
28+
for i in range(l:length)
29+
if a:minimum_version[i] < s:clang_format_version[i]
30+
return 1
31+
elseif a:minimum_version[i] > s:clang_format_version[i]
32+
return 0
33+
endif
34+
endfor
35+
return len(a:minimum_version) <= len(s:clang_format_version)
36+
endfunction
37+
38+
39+
""
40+
" @private
41+
" Invalidates the cached clang-format version.
42+
function! codefmt#clangformat#InvalidateVersion() abort
43+
unlet! s:clang_format_version
44+
endfunction
45+
46+
47+
""
48+
" @private
49+
" Formatter: clang-format
50+
function! codefmt#clangformat#GetFormatter() abort
51+
let l:formatter = {
52+
\ 'name': 'clang-format',
53+
\ 'setup_instructions': 'Install clang-format from ' .
54+
\ 'http://clang.llvm.org/docs/ClangFormat.html and ' .
55+
\ 'configure the clang_format_executable flag'}
56+
57+
function l:formatter.IsAvailable() abort
58+
return executable(s:plugin.Flag('clang_format_executable'))
59+
endfunction
60+
61+
function l:formatter.AppliesToBuffer() abort
62+
if &filetype is# 'c' || &filetype is# 'cpp' ||
63+
\ &filetype is# 'proto' || &filetype is# 'javascript' ||
64+
\ &filetype is# 'typescript'
65+
return 1
66+
endif
67+
" Version 3.6 adds support for java
68+
" http://llvm.org/releases/3.6.0/tools/clang/docs/ReleaseNotes.html
69+
return &filetype is# 'java' && s:ClangFormatHasAtLeastVersion([3, 6])
70+
endfunction
71+
72+
""
73+
" Reformat buffer with clang-format, only targeting [ranges] if given.
74+
function l:formatter.FormatRanges(ranges) abort
75+
let l:Style_value = s:plugin.Flag('clang_format_style')
76+
if type(l:Style_value) is# type('')
77+
let l:style = l:Style_value
78+
elseif maktaba#value#IsCallable(l:Style_value)
79+
let l:style = maktaba#function#Call(l:Style_value)
80+
else
81+
throw maktaba#error#WrongType(
82+
\ 'clang_format_style flag must be string or callable. Found %s',
83+
\ string(l:Style_value))
84+
endif
85+
if empty(a:ranges)
86+
return
87+
endif
88+
89+
let l:cmd = [
90+
\ s:plugin.Flag('clang_format_executable'),
91+
\ '-style', l:style]
92+
let l:fname = expand('%:p')
93+
if !empty(l:fname)
94+
let l:cmd += ['-assume-filename', l:fname]
95+
endif
96+
97+
for [l:startline, l:endline] in a:ranges
98+
call maktaba#ensure#IsNumber(l:startline)
99+
call maktaba#ensure#IsNumber(l:endline)
100+
let l:cmd += ['-lines', l:startline . ':' . l:endline]
101+
endfor
102+
103+
" Version 3.4 introduced support for cursor tracking
104+
" http://llvm.org/releases/3.4/tools/clang/docs/ClangFormat.html
105+
let l:supports_cursor = s:ClangFormatHasAtLeastVersion([3, 4])
106+
if l:supports_cursor
107+
" line2byte counts bytes from 1, and col counts from 1, so -2
108+
let l:cursor_pos = line2byte(line('.')) + col('.') - 2
109+
let l:cmd += ['-cursor', string(l:cursor_pos)]
110+
endif
111+
112+
let l:input = join(getline(1, line('$')), "\n")
113+
let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call()
114+
let l:formatted = split(l:result.stdout, "\n")
115+
116+
if !l:supports_cursor
117+
call maktaba#buffer#Overwrite(1, line('$'), l:formatted[0:])
118+
else
119+
call maktaba#buffer#Overwrite(1, line('$'), l:formatted[1:])
120+
try
121+
let l:clang_format_output_json = maktaba#json#Parse(l:formatted[0])
122+
let l:new_cursor_pos =
123+
\ maktaba#ensure#IsNumber(l:clang_format_output_json.Cursor) + 1
124+
execute 'goto' l:new_cursor_pos
125+
catch
126+
call maktaba#error#Warn('Unable to parse clang-format cursor pos: %s',
127+
\ v:exception)
128+
endtry
129+
endif
130+
endfunction
131+
132+
return l:formatter
133+
endfunction

autoload/codefmt/dartfmt.vim

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
19+
""
20+
" @private
21+
" Formatter: dartfmt
22+
function! codefmt#dartfmt#GetFormatter() abort
23+
let l:formatter = {
24+
\ 'name': 'dartfmt',
25+
\ 'setup_instructions': 'Install the Dart SDK from ' .
26+
\ 'https://www.dartlang.org/tools/sdk/'}
27+
28+
function l:formatter.IsAvailable() abort
29+
return executable(s:plugin.Flag('dartfmt_executable'))
30+
endfunction
31+
32+
function l:formatter.AppliesToBuffer() abort
33+
return &filetype is# 'dart'
34+
endfunction
35+
36+
""
37+
" Reformat the current buffer with dartfmt or the binary named in
38+
" @flag(dartfmt_executable}, only targetting the range from {startline} to
39+
" {endline}
40+
function l:formatter.FormatRange(startline, endline) abort
41+
" Hack range formatting by formatting range individually, ignoring context.
42+
let l:cmd = [ s:plugin.Flag('dartfmt_executable') ]
43+
" TODO When https://github.com/dart-lang/dart_style/issues/92 is implemented
44+
" use those options.
45+
call maktaba#ensure#IsNumber(a:startline)
46+
call maktaba#ensure#IsNumber(a:endline)
47+
let l:lines = getline(1, line('$'))
48+
let l:input = join(l:lines[a:startline - 1 : a:endline - 1], "\n")
49+
try
50+
let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call()
51+
let l:formatted = split(l:result.stdout, "\n")
52+
" Special case empty slice: neither l:lines[:0] nor l:lines[:-1] is right.
53+
let l:before = a:startline > 1 ? l:lines[ : a:startline - 2] : []
54+
55+
let l:full_formatted = l:before + l:formatted + l:lines[a:endline :]
56+
call maktaba#buffer#Overwrite(1, line('$'), l:full_formatted)
57+
catch /ERROR(ShellError):/
58+
" Parse all the errors and stick them in the quickfix list.
59+
let l:errors = []
60+
for l:line in split(v:exception, "\n")
61+
let l:tokens = matchlist(l:line,
62+
\ '\C\v^line (\d+), column (\d+) of stdin: (.*)')
63+
if !empty(l:tokens)
64+
call add(l:errors, {
65+
\ 'filename': @%,
66+
\ 'lnum': l:tokens[1] + a:startline - 1,
67+
\ 'col': l:tokens[2],
68+
\ 'text': l:tokens[3]})
69+
endif
70+
endfor
71+
72+
if empty(l:errors)
73+
" Couldn't parse dartfmt error format; display it all.
74+
call maktaba#error#Shout('Failed to format range; showing all errors: %s', v:exception)
75+
else
76+
let l:errorHeaderLines = split(v:exception, "\n")[1 : 5]
77+
let l:errorHeader = join(l:errorHeaderLines, "\n")
78+
call maktaba#error#Shout(
79+
\ "Error formatting file:\n%s\n\nMore errors in the fixlist.",
80+
\ l:errorHeader)
81+
call setqflist(l:errors, 'r')
82+
cc 1
83+
endif
84+
endtry
85+
endfunction
86+
87+
return l:formatter
88+
endfunction
89+

0 commit comments

Comments
 (0)