-
Notifications
You must be signed in to change notification settings - Fork 105
Add ruby formatting support using Rubocop. #220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
4d55200
Add ruby formatting support using Rubocop.
akveritas 4a4ddcd
Add parameters to AttemptFakeRangeFormatting to allow code reuse
akveritas f8213de
Use varargs to pass parameters to our helper function
akveritas c887423
Use default values instead of varargs for optional arguments
akveritas 6e1c9fe
Fix stale reference to vararg0
akveritas 1fe6fb3
Revert to using varargs instead of defaults to ensure compatiblity wi…
akveritas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,6 +75,7 @@ endfunction | |
|
||
"" | ||
" @public | ||
" @usage startline endline cmd \[ignoreerrors] \[skipfirstnlines] | ||
" Attempt to format a range of lines from {startline} to {endline} in the | ||
" current buffer via a formatter that doesn't natively support range | ||
" formatting, which is invoked via {cmd} (a system call represented by either | ||
|
@@ -87,21 +88,35 @@ endfunction | |
" the tool for range formatting and post a URL for that feature request above | ||
" code that calls it. | ||
" | ||
" @throws ShellError if the {cmd} system call fails | ||
" If [ignoreerrors] is nonzero, the syscall ignores errors. This can be helpful | ||
" for formatters that return nonzero results for reasons unrelated to | ||
" formatting. If [skipfirstnlines] is set to a nonzero number N, the first | ||
" N lines of the formatter output are trimmed. This can be used to trim | ||
" always-present headers. | ||
" | ||
" @throws ShellError if the {cmd} system call fails (and [ignoreerrors] is 0) | ||
" @throws WrongType | ||
function! codefmt#formatterhelpers#AttemptFakeRangeFormatting( | ||
\ startline, endline, cmd) abort | ||
\ startline, endline, cmd, ...) abort | ||
call maktaba#ensure#IsNumber(a:startline) | ||
call maktaba#ensure#IsNumber(a:endline) | ||
|
||
let l:ignoreerrors = a:0 >= 1 ? a:1 : 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fun fact: You can also do Either way works fine here though, and I'm focused on getting this PR merged quickly after all the delays. =) |
||
let l:skipfirstnlines = a:0 >= 2 ? a:2 : 0 | ||
|
||
call maktaba#ensure#IsNumber(l:ignoreerrors) | ||
call maktaba#ensure#IsNumber(l:skipfirstnlines) | ||
|
||
let l:lines = getline(1, line('$')) | ||
let l:input = join(l:lines[a:startline - 1 : a:endline - 1], "\n") | ||
|
||
let l:result = maktaba#syscall#Create(a:cmd).WithStdin(l:input).Call() | ||
let l:result = | ||
\ maktaba#syscall#Create(a:cmd).WithStdin(l:input).Call(!l:ignoreerrors) | ||
let l:formatted = split(l:result.stdout, "\n") | ||
" Special case empty slice: neither l:lines[:0] nor l:lines[:-1] is right. | ||
let l:before = a:startline > 1 ? l:lines[ : a:startline - 2] : [] | ||
let l:full_formatted = l:before + l:formatted + l:lines[a:endline :] | ||
let l:full_formatted = l:before + l:formatted[l:skipfirstnlines :] | ||
\ + l:lines[a:endline :] | ||
|
||
call maktaba#buffer#Overwrite(1, line('$'), l:full_formatted) | ||
endfunction | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
" Copyright 2023 Google Inc. All rights reserved. | ||
" | ||
" Licensed under the Apache License, Version 2.0 (the "License"); | ||
" you may not use this file except in compliance with the License. | ||
" You may obtain a copy of the License at | ||
" | ||
" http://www.apache.org/licenses/LICENSE-2.0 | ||
" | ||
" Unless required by applicable law or agreed to in writing, software | ||
" distributed under the License is distributed on an "AS IS" BASIS, | ||
" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
" See the License for the specific language governing permissions and | ||
" limitations under the License. | ||
|
||
let s:plugin = maktaba#plugin#Get('codefmt') | ||
|
||
|
||
"" | ||
" @private | ||
" Formatter: rubocop | ||
function! codefmt#rubocop#GetFormatter() abort | ||
let l:formatter = { | ||
\ 'name': 'rubocop', | ||
\ 'setup_instructions': 'Install rubocop ' . | ||
\ '(https://rubygems.org/gems/rubocop).'} | ||
|
||
function l:formatter.IsAvailable() abort | ||
return executable(s:plugin.Flag('rubocop_executable')) | ||
endfunction | ||
|
||
function l:formatter.AppliesToBuffer() abort | ||
return &filetype is# 'eruby' || &filetype is# 'ruby' | ||
endfunction | ||
|
||
"" | ||
" Reformat the current buffer with rubocop or the binary named in | ||
" @flag(rubocop_executable), only targeting the range between {startline} and | ||
" {endline}. | ||
" | ||
" @throws ShellError | ||
function l:formatter.FormatRange(startline, endline) abort | ||
" See flag explanations at: | ||
" https://docs.rubocop.org/rubocop/1.51/usage/basic_usage.html | ||
let l:cmd = [s:plugin.Flag('rubocop_executable'), '--stdin', @%, '-a', '--no-color', '-fq', '-o', '/dev/null'] | ||
|
||
" Rubocop exits with an error condition if there are lint errors, even | ||
" after successfully formatting. This is annoying for our purpuoses, | ||
" because we have no way to distinguish lint errors from a 'real' falure. | ||
" Use Call(0) to suppress maktaba's error handling. | ||
let l:ignoreerrors = 1 | ||
" Rubocop is primarily a linter, and by default it outputs lint errors | ||
" first, followed by a dividing line, and then the formatted result. | ||
" '-o /dev/null' in the command line suppresses any lint errors, but the | ||
" divider is always printed. | ||
let l:skipfirstnlines = 1 | ||
|
||
" Rubocop does not support range formatting; see bug: | ||
" https://github.com/Shopify/ruby-lsp/issues/203 | ||
call codefmt#formatterhelpers#AttemptFakeRangeFormatting( | ||
\ a:startline, a:endline, l:cmd, l:ignoreerrors, l:skipfirstnlines) | ||
endfunction | ||
|
||
return l:formatter | ||
endfunction |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
Rubocop is a linter and formatter for ruby. | ||
If you aren't familiar with basic codefmt usage yet, see main.vroom first. | ||
|
||
First, set up the vroom environment. | ||
|
||
:source $VROOMDIR/setupvroom.vim | ||
|
||
:let g:repeat_calls = [] | ||
:function FakeRepeat(...)<CR> | ||
| call add(g:repeat_calls, a:000)<CR> | ||
:endfunction | ||
:call maktaba#test#Override('repeat#set', 'FakeRepeat') | ||
|
||
:call codefmt#SetWhetherToPerformIsAvailableChecksForTesting(0) | ||
|
||
By default, the rubocop executable is called. To use this plugin, rubocop | ||
must be installed on your system. (But not for testing; vroom intercepts | ||
system calls.) | ||
:FormatCode rubocop | ||
! rubocop .* | ||
dbarnett marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
|
||
The name and path of the Rubocop executable can be configured with a flag: | ||
:Glaive codefmt rubocop_executable=some_other_program | ||
:FormatCode rubocop | ||
! some_other_program .*-fq.* | ||
:Glaive codefmt rubocop_executable=rubocop | ||
|
||
|
||
|
||
Rubocop does basic whitespace management. Though because it's primarily a | ||
linter, it outputs lint errors first, then a separator. Even with the lint | ||
errors disabled (-fq), you still get the separator. | ||
|
||
% def SomeClass <CR> <CR> end | ||
:FormatCode rubocop | ||
! rubocop .*-fq.* | ||
$ ========= | ||
$ def SomeClass | ||
$ end | ||
def SomeClass | ||
end | ||
|
||
|
||
|
||
Being a linter, Rubocop cares about style as well as formatting. | ||
When a buffer is stylistically fine, it returns 0, and everything is OK. | ||
But sometimes it will return 1 even though things have gone well; | ||
we should still use the output when that happens. | ||
|
||
% def SomeClass <CR> <CR> end | ||
:FormatCode rubocop | ||
! rubocop .* | ||
$ ========= | ||
$ def SomeClass | ||
$ end | ||
$ 1 (status) | ||
def SomeClass | ||
end |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.