diff --git a/README.md b/README.md index 2fbc7e8..f3fea41 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/autoload/codefmt/ruff.vim b/autoload/codefmt/ruff.vim new file mode 100644 index 0000000..f9aa6df --- /dev/null +++ b/autoload/codefmt/ruff.vim @@ -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 diff --git a/doc/codefmt.txt b/doc/codefmt.txt index 70a8246..90482bd 100644 --- a/doc/codefmt.txt +++ b/doc/codefmt.txt @@ -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 @@ -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' ` diff --git a/instant/flags.vim b/instant/flags.vim index cb9da01..ab636a9 100644 --- a/instant/flags.vim +++ b/instant/flags.vim @@ -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') diff --git a/plugin/register.vim b/plugin/register.vim index ec2ac49..1964111 100644 --- a/plugin/register.vim +++ b/plugin/register.vim @@ -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 @@ -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()) diff --git a/vroom/ruff.vroom b/vroom/ruff.vroom new file mode 100644 index 0000000..0a2548b --- /dev/null +++ b/vroom/ruff.vroom @@ -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(...) + | call add(g:repeat_calls, a:000) + :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' ); + |if bar : bar+=1; bar=bar* bar + |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