Skip to content
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

Add ruff as formatter for Python #238

Merged
merged 1 commit into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ codefmt` if codefmt is installed (and helptags have been generated).
* Nix (nixpkgs-fmt)
* OCaml ([ocamlformat](https://github.com/ocaml-ppx/ocamlformat))
* Protocol Buffers (clang-format)
* Python (Autopep8, Black, isort, or YAPF)
* Python (Autopep8, Black, isort, Ruff, or YAPF)
* Ruby ([rubocop](https://rubocop.org))
* Rust ([rustfmt](https://github.com/rust-lang/rustfmt))
* Shell (shfmt)
Expand Down
71 changes: 71 additions & 0 deletions autoload/codefmt/ruff.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
" Copyright 2017 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')


function! s:FormatWithArgs(args) abort
let l:executable = s:plugin.Flag('ruff_executable')
let l:lines = getline(1, line('$'))
let l:cmd = [l:executable, 'format'] + a:args
if !empty(@%)
let l:cmd += ['--stdin-filename=' . @%]
endif
let l:input = join(l:lines, "\n")
let l:result = maktaba#syscall#Create(l:cmd).WithStdin(l:input).Call(0)
if v:shell_error
call maktaba#error#Shout('Error formatting file: %s', l:result.stderr)
return
endif
let l:formatted = split(l:result.stdout, "\n")

call maktaba#buffer#Overwrite(1, line('$'), l:formatted)
endfunction


""
" @private
" Formatter: ruff
function! codefmt#ruff#GetFormatter() abort
let l:formatter = {
\ 'name': 'ruff',
\ 'setup_instructions': 'Install ruff ' .
\ '(https://docs.astral.sh/ruff/).'}

function l:formatter.IsAvailable() abort
return executable(s:plugin.Flag('ruff_executable'))
endfunction

function l:formatter.AppliesToBuffer() abort
return codefmt#formatterhelpers#FiletypeMatches(&filetype, 'python')
endfunction

function l:formatter.Format() abort
call s:FormatWithArgs([])
endfunction

""
" Reformat the current buffer with ruff or the binary named in
" @flag(ruff_executable), only targeting the range between {startline} and
" {endline}.
" @throws ShellError
function l:formatter.FormatRange(startline, endline) abort
call maktaba#ensure#IsNumber(a:startline)
call maktaba#ensure#IsNumber(a:endline)
call s:FormatWithArgs(['--range=' . a:startline . ':' . a:endline])
endfunction

return l:formatter
endfunction
6 changes: 5 additions & 1 deletion doc/codefmt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ The current list of defaults by filetype is:
* lua: luaformatterfiveone
* nix: nixpkgs-fmt
* ocaml: ocamlformat
* python: autopep8, black, yapf
* python: autopep8, black, ruff, yapf
* ruby: rubocop
* rust: rustfmt
* sh: shfmt
Expand Down Expand Up @@ -98,6 +98,10 @@ The path to the mix executable for Elixir. String, list, or callable that
takes no args and returns a string or a list with command line arguments.
Default: 'mix' `

*codefmt:ruff_executable*
The path to the ruff executable.
Default: 'ruff' `

*codefmt:yapf_executable*
The path to the yapf executable.
Default: 'yapf' `
Expand Down
4 changes: 4 additions & 0 deletions instant/flags.vim
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ call s:plugin.Flag('js_beautify_executable', 'js-beautify')
" takes no args and returns a string or a list with command line arguments.
call s:plugin.Flag('mix_executable', 'mix')

""
" The path to the ruff executable.
call s:plugin.Flag('ruff_executable', 'ruff')

""
" The path to the yapf executable.
call s:plugin.Flag('yapf_executable', 'yapf')
Expand Down
3 changes: 2 additions & 1 deletion plugin/register.vim
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
" * lua: luaformatterfiveone
" * nix: nixpkgs-fmt
" * ocaml: ocamlformat
" * python: autopep8, black, yapf
" * python: autopep8, black, ruff, yapf
" * ruby: rubocop
" * rust: rustfmt
" * sh: shfmt
Expand Down Expand Up @@ -82,6 +82,7 @@ call s:registry.AddExtension(codefmt#nixpkgs_fmt#GetFormatter())
call s:registry.AddExtension(codefmt#autopep8#GetFormatter())
call s:registry.AddExtension(codefmt#isort#GetFormatter())
call s:registry.AddExtension(codefmt#black#GetFormatter())
call s:registry.AddExtension(codefmt#ruff#GetFormatter())
call s:registry.AddExtension(codefmt#yapf#GetFormatter())
call s:registry.AddExtension(codefmt#rubocop#GetFormatter())
call s:registry.AddExtension(codefmt#rustfmt#GetFormatter())
Expand Down
71 changes: 71 additions & 0 deletions vroom/ruff.vroom
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
The built-in ruff formatter knows how to format python code.
If you aren't familiar with basic codefmt usage yet, see main.vroom first.

We'll set up codefmt and configure the vroom environment, then jump into some
examples.

: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)


The ruff formatter expects the ruff executable to be installed on your
system.

:silent file somefile.py
% f()
:FormatCode ruff
! ruff format --stdin-filename=somefile.py.*
$ f()

The name or path of the ruff executable can be configured via the
ruff_executable flag if the default of "ruff" doesn't work.

:Glaive codefmt ruff_executable='/somepath/ruff'
:FormatCode ruff
! /somepath/ruff format.*
$ f()
:Glaive codefmt ruff_executable='ruff'


You can format any buffer with ruff specifying the formatter explicitly.

@clear
% if True: pass

:FormatCode ruff
! ruff format.*
$ if True:
$ pass
if True:
pass
@end

It can format specific line ranges of code using :FormatLines.

@clear
% some_tuple=( 1,2, 3,'a' );<CR>
|if bar : bar+=1; bar=bar* bar<CR>
|else: bar-=1;

:2,3FormatLines ruff
! ruff format .*--range=2:3.*
$ some_tuple=( 1,2, 3,'a' );
$ if bar:
$ bar += 1
$ bar = bar * bar
$ else:
$ bar -= 1
some_tuple=( 1,2, 3,'a' );
if bar:
bar += 1
bar = bar * bar
else:
bar -= 1
@end
Loading