You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Support line-range formatting (lines kwarg and jlfmt --lines) (#1100)
Add a way to restrict formatting to specific line ranges, emitting all
other lines verbatim. This is useful for formatting only the lines
touched by a PR/diff, enforcing "newly-changed code must be formatted"
in CI without churning unrelated lines, and backing the LSP 3.18
`textDocument/rangesFormatting` capability (multiple ranges per
request).
- Core API: a `lines` keyword on `format_text` accepting a collection of
inclusive, 1-based `(start, stop)` tuples and/or ranges, e.g.
`format_text(text; lines = [(1, 10), (42, 47)])`. Overlapping and
adjacent ranges are merged.
- CLI: a repeatable `--lines=<start>:<stop>` flag forwarding to the
`lines` kwarg. Limited to a single input file (or stdin); it can not be
combined with multiple inputs/directories or Markdown.
Rather than teaching the formatting pipeline about line ranges, the
feature is kept orthogonal to it (the approach Runic.jl takes): marker
comments are inserted around the requested ranges, the whole text is
formatted as usual so in-range code reflows in its real context, and the
result is spliced back together line by line -- formatted lines between
markers, original source verbatim elsewhere, markers dropped. Line
comments are used as markers so they reliably survive on their own line.
- Closes#191
- Closes#1099
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Penelope Yong <penelopeysm@gmail.com>
Copy file name to clipboardExpand all lines: HISTORY_v2.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,8 @@
2
2
3
3
Improved usage messages for the `jlfmt` command-line tool. (#1098)
4
4
5
+
Added the ability to format only specific lines of a file, either via the `--lines` option to `jlfmt`, or the `lines` keyword argument to `format_text()`. (#191, #1099, #1100)
6
+
5
7
# v2.6.15
6
8
7
9
Fixed a bug where the combination of `always_use_return` and `short_circuit_to_if` would silently change the meaning of a programme. (#887, #1096)
Copy file name to clipboardExpand all lines: docs/src/cli.md
+1-4Lines changed: 1 addition & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,10 +25,7 @@ julia -m JuliaFormatter [<options>] <path>...
25
25
```
26
26
27
27
!!! note "Runic Compatibility"
28
-
The CLI interface is designed to be compatible with [Runic.jl](https://github.com/fredrikekre/Runic.jl)'s CLI where possible, making it easier to switch between formatters.
29
-
30
-
!!! warning "Missing features"
31
-
Note that the `--lines` option is not yet implemented.
28
+
The CLI interface is designed to be compatible with [Runic.jl](https://github.com/fredrikekre/Runic.jl)'s CLI where possible, making it easier to switch between formatters. This includes the repeatable `--lines=<start>:<stop>` option for formatting only specific line ranges (e.g. `jlfmt --lines=1:10 --lines=42:47 src/file.jl`).
Copy file name to clipboardExpand all lines: docs/src/skipping_formatting.md
+59-1Lines changed: 59 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,7 +30,7 @@ Note that the formatter expects `#! format: on` and `#! format: off` to be on it
30
30
!!! note "Ignoring files"
31
31
You can also ignore entire files and directories by supplying [the `ignore` option](@ref options-ignore) in `.JuliaFormatter.toml`.
32
32
33
-
###Preventing indentation
33
+
## Preventing indentation
34
34
35
35
Sometimes you may wish for a block of code to not be indented.
36
36
You can achieve this with a more targeted approach of `#! format: noindent`.
@@ -89,3 +89,61 @@ end
89
89
```
90
90
91
91
`#! format: noindent` can also be nested.
92
+
93
+
## One-off range formatting
94
+
95
+
Sometimes it is quite useful to only format specific ranges of a file.
96
+
This situation can occur e.g. when highlighting a block of code in an editor and formatting only that block.
97
+
(Indeed, both LanguageServer.jl and JETLS.jl support this feature.)
98
+
99
+
It is also useful for minimising diffs: by formatting only the lines that have been newly changed, you can avoid introducing formatting-only diffs in other parts of a file.
100
+
101
+
Since version 2.7, JuliaFormatter allows you to do this with the `lines` keyword argument in `format_text(...; lines=[(start_line, end_line)], ...)`.
102
+
Multiple ranges can be specified; each range must be a tuple of two (1-indexed) integers representing the start and end line of the range to format.
103
+
104
+
```@example lines
105
+
s = """
106
+
f(a , g(b ,
107
+
h( 12 ),
108
+
))"""
109
+
110
+
# Format only line 2.
111
+
using JuliaFormatter
112
+
format_text(s; lines=[(2, 2)]) |> println
113
+
```
114
+
115
+
The second line (`h(12)`) is now formatted, but the extra spaces in the first line have not been collapsed.
116
+
117
+
With the `jlfmt` CLI, you can specify `--lines=2:2` to achieve the same effect.
118
+
119
+
Note, however, that this works best when the lines to be formatted are a self-contained block of code.
120
+
This is because formatting is context-sensitive: it's not possible to format a single line in isolation without considering where it occurs!
121
+
122
+
This can sometimes lead to odd results, and indeed the example above was chosen to showcase this.
123
+
**In general, formatting of partial expressions is performed only on a best-effort basis.**
Here, the formatter decided to indent the call `h(12)` by eight spaces, even though based on its position in the file it should have been indented by only four spaces.
132
+
Furthermore, as a result of this increased indentation, the formatter also decided to break up `h(12)` into multiple lines, even though `h(12),` with a four-space indent would have fit within the margin.
133
+
134
+
To understand why, we need to look at what would happen if *all* the text were to be formatted:
135
+
136
+
```@example lines
137
+
format_text(s; margin=10) |> println
138
+
```
139
+
140
+
Because of the small margin, JuliaFormatter decided to break the calls to `f` and `g`, meaning that `h(12)` would now get two levels of indentation.
141
+
When formatting only line 2, however, you don't see the changes to the surrounding code: the only visible change is that of `h(12)`.
142
+
143
+
## A note about other special comments
144
+
145
+
Note that any comment that begins with `#! __JuliaFormatter` is reserved for internal use.
146
+
For example, the option to format only specific lines of a file uses such marker comments.
147
+
If you have one of these in your source code, unexpected results may occur.
148
+
149
+
It is very unlikely that your source code will inadvertently include such a comment, but this is documented here for completeness!
0 commit comments