Skip to content

Commit 4dc61ef

Browse files
committed
fix: preserve backslash in single-row aligned and do not pad the last cell
1 parent 8cddf11 commit 4dc61ef

File tree

14 files changed

+248
-74
lines changed

14 files changed

+248
-74
lines changed

crates/typstyle-core/src/pretty/math_align.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ impl<'a> PrettyPrinter<'a> {
2222
let raw_aligned = collect_aligned(math, &self.attr_store);
2323
let aligned = self.render_aligned(ctx, raw_aligned.rows)?;
2424

25-
let doc = self.print_aligned(
26-
aligned,
27-
ctx.align_mode == AlignMode::Outer && raw_aligned.has_trailing_linebreak,
28-
);
25+
let doc = self.print_aligned(aligned, raw_aligned.has_trailing_backslash);
2926
Some(doc)
3027
}
3128

@@ -115,7 +112,7 @@ impl<'a> PrettyPrinter<'a> {
115112
}
116113

117114
/// Combine aligned cells together, inserting '&', spaces, and linebreaks.
118-
fn print_aligned(&'a self, aligned: Aligned<'a>, add_trailing_linebreak: bool) -> ArenaDoc<'a> {
115+
fn print_aligned(&'a self, aligned: Aligned<'a>, add_trailing_backslash: bool) -> ArenaDoc<'a> {
119116
let rows = aligned.rows;
120117
let col_widths = aligned.col_widths;
121118
let num_rows = rows.len();
@@ -138,28 +135,31 @@ impl<'a> PrettyPrinter<'a> {
138135
(self.arena).concat(rows.into_iter().enumerate().map(|(i, row)| match row {
139136
Row::Comment(cmt) => {
140137
// Emit a full‑line comment followed by a hard linebreak
138+
// NOTE: this should not be the last row.
141139
self.arena.text(cmt) + self.arena.hardline()
142140
}
143141
Row::Cells(cells) => {
144142
let mut row_doc = self.arena.nil();
145143

146144
// For each cell: pad to column width and insert separators
145+
let is_last_row = i + 1 == num_rows;
146+
let needs_backslash = !is_last_row || add_trailing_backslash;
147147
let num_cells = cells.len();
148148
let mut is_prev_empty = false;
149149
for (j, cell) in cells.into_iter().enumerate() {
150+
let is_last_cell_in_row = j + 1 == num_cells;
150151
let alignment = if j % 2 == 1 || num_cols == 1 {
151152
Alignment::Left
152153
} else {
153154
Alignment::Right
154155
};
155156
let col_width = col_widths[j];
156157

157-
let pad = |cell_doc: ArenaDoc<'a>, width: usize| {
158-
let pad_spaces = self.arena.spaces(col_width - width);
159-
match alignment {
160-
Alignment::Left => cell_doc + pad_spaces,
161-
Alignment::Right => pad_spaces + cell_doc,
162-
}
158+
let need_pad_right = !is_last_cell_in_row || needs_backslash;
159+
let pad = |cell_doc: ArenaDoc<'a>, width: usize| match alignment {
160+
Alignment::Left if !need_pad_right => cell_doc,
161+
Alignment::Left => cell_doc + self.arena.spaces(col_width - width),
162+
Alignment::Right => self.arena.spaces(col_width - width) + cell_doc,
163163
};
164164

165165
let cell_width = cell.max_width();
@@ -179,8 +179,11 @@ impl<'a> PrettyPrinter<'a> {
179179
indent
180180
};
181181

182-
let trailing_padding =
183-
col_width - padding_left - lines[lines.len() - 1].1;
182+
let trailing_padding = if need_pad_right {
183+
col_width - padding_left - lines[lines.len() - 1].1
184+
} else {
185+
0 // do not pad the last cell
186+
};
184187
let doc = self.arena.spaces(padding_left)
185188
+ self.arena.intersperse(
186189
lines.into_iter().map(|(line, _)| line),
@@ -211,22 +214,19 @@ impl<'a> PrettyPrinter<'a> {
211214
}
212215

213216
// If row has fewer cells than columns, add trailing spaces
214-
if num_cells < num_cols {
217+
// Do not add trailing spaces when no trailing backslash.
218+
let is_last_row = i + 1 == num_rows;
219+
if num_cells < num_cols && needs_backslash {
215220
let mut padding = grid_width - num_cells - col_widths_sum[num_cells];
216221
if !is_prev_empty {
217222
padding += 1;
218223
}
219224
row_doc += self.arena.spaces(padding);
220225
}
221-
// Append trailing backslashes and linebreaks when multiple rows
222-
if num_rows > 1 {
223-
row_doc += if add_trailing_linebreak || i + 1 != num_rows {
224-
self.arena.text(" \\")
225-
} else {
226-
self.arena.text(" ")
227-
};
226+
if needs_backslash {
227+
row_doc += self.arena.text(" \\");
228228
}
229-
if i + 1 != num_rows {
229+
if !is_last_row {
230230
row_doc += self.arena.hardline();
231231
}
232232
row_doc
@@ -279,7 +279,7 @@ impl Cell {
279279

280280
struct RawAligned<'a> {
281281
rows: Vec<RawRow<'a>>,
282-
has_trailing_linebreak: bool,
282+
has_trailing_backslash: bool,
283283
}
284284

285285
/// A raw row before rendering, coming from syntax nodes.
@@ -333,7 +333,7 @@ fn collect_aligned<'a>(math: Math<'a>, attrs: &AttrStore) -> RawAligned<'a> {
333333
};
334334

335335
// First pass: split all children into lines (split at Linebreak)
336-
let (lines, has_trailing_linebreak) = {
336+
let (lines, has_trailing_backslash) = {
337337
let mut lines = flat
338338
.split(|n| n.kind() == SyntaxKind::Linebreak)
339339
.collect_vec();
@@ -372,6 +372,6 @@ fn collect_aligned<'a>(math: Math<'a>, attrs: &AttrStore) -> RawAligned<'a> {
372372
}
373373
RawAligned {
374374
rows,
375-
has_trailing_linebreak,
375+
has_trailing_backslash,
376376
}
377377
}

tests/fixtures/unit/math/aligned/empty.typ

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,38 @@ $ & & $
1010
$ && & $
1111

1212
6
13+
$& \ $
1314
$ & \ $
1415
7
16+
$&\ & $
1517
$ &\ & $
1618
8
19+
$&\ &\ $
1720
$ &\ &\ $
1821
9
1922
$ \ &\ \ $
2023
10
2124
$ &&\ &\ \ $
2225

26+
11
27+
$ & x && \
28+
& \
29+
y&z& $
30+
12
31+
$
32+
(
33+
&11111 \
34+
& )
35+
$
36+
$
37+
text(
38+
&11111 \
39+
& )
40+
$
41+
2342
$
2443
Re \
2544
Im
2645
$
46+
47+
#repr(math.equation($ 1 & 2 \ $.body + $ & 4 \ $.body))

tests/fixtures/unit/math/aligned/nested.typ

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,12 @@ $
8484
mid(|) d + & e )
8585
) + f
8686
$
87+
88+
$
89+
sin(
90+
b
91+
+ & c
92+
mid(|) \
93+
mid(|) d + & e
94+
* f )
95+
$

tests/fixtures/unit/math/aligned/snap/commented.typ-120.snap

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $
1515
// Block comments between alignment markers
1616
$
1717
f(x) /* pre */ & = /* mid */ y /* post */ \
18-
/* before */ & = /* between */ z /* after */
18+
/* before */ & = /* between */ z /* after */
1919
$
2020

2121
// Block comments in single line
@@ -25,7 +25,7 @@ $ p /* c1 */ & = /* c2 */ q /* c3 */ & = /* c4 */ r /* c5 */ $
2525
$
2626
m & = n /**/ \
2727
& = p /* */ \
28-
& = q /* */
28+
& = q /* */
2929
$
3030

3131
// Comments mixed with aligned equations
@@ -40,7 +40,7 @@ $
4040
& = v // Comment 1
4141
// Comment 2
4242
\
43-
& = u /* Nested /* comments */ here */
43+
& = u /* Nested /* comments */ here */
4444
$
4545

4646
// Comments in matrix
@@ -64,23 +64,23 @@ $
6464
// Line comment between rows
6565
& = product y /* Block
6666
comment */ \
67-
& = z // Final result
67+
& = z // Final result
6868
$
6969

7070
// Mixed Unicode and comments
7171
$
7272
α & = β // Greek variables
7373
\
7474
& = γ /* Mixed شرح explanation */ \
75-
& = θ // 说明
75+
& = θ // 说明
7676
$
7777

7878
// Comments with decorators
7979
$
8080
arrow(
8181
x & = y // Inside arrow
8282
\
83-
& = z /* Still inside */
83+
& = z /* Still inside */
8484
)
8585
$
8686

@@ -114,7 +114,7 @@ $
114114
\
115115
& =
116116
// comment before next line
117-
z // end comment
117+
z // end comment
118118
$
119119

120120
// Comments in multi-column alignment
@@ -124,5 +124,5 @@ $
124124
& = p x & q // another comment
125125
// comment between rows
126126
\
127-
& = r & s // final row
127+
& = r & s // final row
128128
$

tests/fixtures/unit/math/aligned/snap/commented.typ-40.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ $
2727
$
2828
m & = n /**/ \
2929
& = p /* */ \
30-
& = q /* */
30+
& = q /* */
3131
$
3232

3333
// Comments mixed with aligned equations
@@ -66,23 +66,23 @@ $
6666
// Line comment between rows
6767
& = product y /* Block
6868
comment */ \
69-
& = z // Final result
69+
& = z // Final result
7070
$
7171

7272
// Mixed Unicode and comments
7373
$
7474
α & = β // Greek variables
7575
\
7676
& = γ /* Mixed شرح explanation */ \
77-
& = θ // 说明
77+
& = θ // 说明
7878
$
7979

8080
// Comments with decorators
8181
$
8282
arrow(
8383
x & = y // Inside arrow
8484
\
85-
& = z /* Still inside */
85+
& = z /* Still inside */
8686
)
8787
$
8888

@@ -116,7 +116,7 @@ $
116116
\
117117
& =
118118
// comment before next line
119-
z // end comment
119+
z // end comment
120120
$
121121

122122
// Comments in multi-column alignment
@@ -126,5 +126,5 @@ $
126126
& = p x & q // another comment
127127
// comment between rows
128128
\
129-
& = r & s // final row
129+
& = r & s // final row
130130
$

tests/fixtures/unit/math/aligned/snap/commented.typ-80.snap

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $
1515
// Block comments between alignment markers
1616
$
1717
f(x) /* pre */ & = /* mid */ y /* post */ \
18-
/* before */ & = /* between */ z /* after */
18+
/* before */ & = /* between */ z /* after */
1919
$
2020

2121
// Block comments in single line
@@ -25,7 +25,7 @@ $ p /* c1 */ & = /* c2 */ q /* c3 */ & = /* c4 */ r /* c5 */ $
2525
$
2626
m & = n /**/ \
2727
& = p /* */ \
28-
& = q /* */
28+
& = q /* */
2929
$
3030

3131
// Comments mixed with aligned equations
@@ -40,7 +40,7 @@ $
4040
& = v // Comment 1
4141
// Comment 2
4242
\
43-
& = u /* Nested /* comments */ here */
43+
& = u /* Nested /* comments */ here */
4444
$
4545

4646
// Comments in matrix
@@ -64,23 +64,23 @@ $
6464
// Line comment between rows
6565
& = product y /* Block
6666
comment */ \
67-
& = z // Final result
67+
& = z // Final result
6868
$
6969

7070
// Mixed Unicode and comments
7171
$
7272
α & = β // Greek variables
7373
\
7474
& = γ /* Mixed شرح explanation */ \
75-
& = θ // 说明
75+
& = θ // 说明
7676
$
7777

7878
// Comments with decorators
7979
$
8080
arrow(
8181
x & = y // Inside arrow
8282
\
83-
& = z /* Still inside */
83+
& = z /* Still inside */
8484
)
8585
$
8686

@@ -114,7 +114,7 @@ $
114114
\
115115
& =
116116
// comment before next line
117-
z // end comment
117+
z // end comment
118118
$
119119

120120
// Comments in multi-column alignment
@@ -124,5 +124,5 @@ $
124124
& = p x & q // another comment
125125
// comment between rows
126126
\
127-
& = r & s // final row
127+
& = r & s // final row
128128
$

0 commit comments

Comments
 (0)