Closed diamond-lizard closed 3 years ago
I don't know how well the formatters work with partial source code (mainly with regards to indentation) but we can try it. E.g. Emacs' built-in indent-region
function can read the full source file so it can still indent correctly even if you tell it to indent only a part of it. The external formatter would only get the region and think it's the whole file. I don't recall any of them having a command line flag to only format a region.
Most of the formatters can be run manually from Emacs via C-u M-x shell-command-on-region
. For example, select a region of C/Java code, then do C-u M-x shell-command-on-region clang-format.
Please try this for the languages you are interested in to see if you think the result is sensible. A format-all-region
command would essentially do the same thing, just more convenient. I tried it on some nested C code and as expected, it loses the indentation.
swiftformat has a --fragment
switch to format partial files but that's the only one I can find that has native support.
clang-format has support:
-offset=
int
Format a range starting at this byte offset. Multiple ranges can be formatted by specifying several -offset and -length pairs. Can only be used with one input file.
-length=
int
Format a range of this length (in bytes). Multiple ranges can be formatted by specifying several -offset and -length pairs. When only a single -offset is specified without -length, clang-format will format up to the end of the file. Can only be used with one input file.
prettier has support too:
Editor options:
--cursor-offset
int
Print (to stderr) where a cursor at the given position would move to after formatting. This option cannot be used with --range-start and --range-end. Defaults to -1.
--range-end
int
Format code ending at a given character offset (exclusive). The range will extend forwards to the end of the selected statement. This option cannot be used with --cursor-offset. Defaults to Infinity.
--range-start
int
Format code starting at a given character offset. The range will extend backwards to the start of the first line containing the selected statement. This option cannot be used with --cursor-offset. Defaults to 0.
Is it able to only format the modified part, not the whole buffer? This feature is very useful when you edit other people's code, and they use different code styles, it is better to only format the code of your own.
Of course, this feature can be provided by variable and command.
Unfortunately it can't do that - the whole buffer is formatted every time. The rationale is given in the above comments: it's hard to do reliably.
As a workaround, you can create a temporary buffer that is not saved into a file (by switching into any buffer whose name does not yet exist), paste a code snippet there, switch to the mode you want (e.g. M-x c-mode
, M-x js-mode
and so on), and then do M-x format-all-buffer
and copy back the formatted text to the original file.
Actually, this problem can be workaround by executing the command narrow-to-region
to make emacs create a temporary buffer which holds the region you want to format. Then in the temporary buffer, execute format-all-buffer
. The result is that in the original buffer, only the selected region is formatted.
narrow-to-region
doesn't solve the indentation problem. If you have particular formatters that you'd like to use to format regions, please ask the maintainers of those formatters if they could add an official command line option for the job (like prettier
has done). That would solve the problem properly for all editor plugins, not only format-all.
I'll be happy to add support for those command line options to format-all (in fact, support for the prettier, clang-format, and swift-format flags should already be added; thanks for the reminder).
Closing this since #150 now implements M-x format-all-region
for formatters that support it natively. For formatters without native support, I'll be happy to help explain to their authors what kind of command line flags are needed.
Is there any chance you could provide a
format-all-region
command?It's be nice to be able to reformat a region without having to reformat absolutely everything.