My problem is that sometimes I'm editing some code in a project that doesn't use Black (heresy, I know). Sometimes I'll type some code, or paste into the source something like a generated dict literal, and I want to run Black on just the edited section of code.
I set up a Vim binding to do that, passing just the code from the visual selection to Black, and using the output to update the code in Vim. The result is:
1) If I select lines of module-level code, this works really well! Hooray!
2) If I select a few lines in the middle of a function, or select a whole class method, this fails, because Black (understandably) does not like that the initial line of code is indented.
3) Trivially, it also fails if the selected code is not an entire valid expression or statement. That's fine and I don't propose trying to "fix" that.
What I'd like to see:
The alternative I'm currently considering is writing my own wrapper script to do the un-indenting and re-indenting. Not a biggie, but I thought other people might appreciate this mode of operation being supported out of the box.
For reference, Vim binding to call Black on the visual selection:
" Black(Python) format the visual selection
xnoremap <Leader>k :!black -q -<CR>
If indentation seems to be the only problem here not allowing to perform black as intended, then a wrapper script using textwrap (the indent/dedent functions) seems like a crude/quick way of doing that.
This can obviously be integrated in black through some argument (or maybe natively!) using the same logic.
I wrote a wrapper script to do the dedenting/reindenting: https://github.com/tartley/dotfiles/blob/master/other/bin/enblacken
(I don't think textwrap is any use for this particular task. We could use the .dedent() there, but then we'd have to go and manually count how many spaces it dedented by, so that we know how much to reindent by later. The reindenting is just line = " " * indent + line. So I just do it all manually.)
It's rough and ready, and in particular doesn't handle errors from Black (e.g. what if the fragment you pass to Black has a syntax error) but works for me thus far.
For emac users, there is https://github.com/wbolster/emacs-python-black (according to https://github.com/psf/black/issues/1076#issuecomment-544117991)
See also https://github.com/wbolster/black-macchiato (according to https://github.com/psf/black/issues/987#issuecomment-521635701 and https://github.com/psf/black/issues/1076#issuecomment-544117991)
I haven't verified that either of these options actually work.
I don't understand @ichard26, you just closed all issues that asked for "Format Selection" including mine! All of them were saying the same thing but in different situations: one asked for a cli option, for me (#987) I asked for running it against some visualized lines in vim, other one asked for running in vscode, All of them are the same.
Is it going somewhere anysoon? Can I help to achieve this functionality?
Most helpful comment
I wrote a wrapper script to do the dedenting/reindenting: https://github.com/tartley/dotfiles/blob/master/other/bin/enblacken
(I don't think
textwrapis any use for this particular task. We could use the.dedent()there, but then we'd have to go and manually count how many spaces it dedented by, so that we know how much to reindent by later. The reindenting is justline = " " * indent + line. So I just do it all manually.)It's rough and ready,
and in particular doesn't handle errors from Black (e.g. what if the fragment you pass to Black has a syntax error)but works for me thus far.