a73x

499daca1

Remove spacer boundary normalization

a73x   2026-04-09 18:14

Commit message
Remove spacer boundary normalization

src/main.zig
Old New
@@ -583,40 +583,13 @@ fn appendSelectedRowText(
583 span: SelectionSpan, 583 span: SelectionSpan,
584 row_idx: usize, 584 row_idx: usize,
585 ) !void { 585 ) !void {
586 const bounds = canonicalizeSelectedRowBounds(row_cells, span, row_idx) orelse return; 586 if (row_cells.len == 0) return;
587 587
588 var end_col = bounds.end_col; 588 const start_col: usize = if (row_idx == span.start.row)
589 while (end_col >= bounds.start_col) {
590 const cell = row_cells.get(end_col);
591 if (!isTrailingBlankCell(cell)) break;
592 if (end_col == 0) return;
593 end_col -= 1;
594 }
595
596 var col = bounds.start_col;
597 while (col <= end_col) : (col += 1) {
598 const cell = row_cells.get(col);
599 try appendSelectedCellText(alloc, out, cell);
600 }
601 }
602
603 const SelectedRowBounds = struct {
604 start_col: usize,
605 end_col: usize,
606 };
607
608 fn canonicalizeSelectedRowBounds(
609 row_cells: anytype,
610 span: SelectionSpan,
611 row_idx: usize,
612 ) ?SelectedRowBounds {
613 if (row_cells.len == 0) return null;
614
615 var start_col: usize = if (row_idx == span.start.row)
616 @intCast(span.start.col) 589 @intCast(span.start.col)
617 else 590 else
618 0; 591 0;
619 if (start_col >= row_cells.len) return null; 592 if (start_col >= row_cells.len) return;
620 593
621 var end_col: usize = if (row_idx == span.end.row) 594 var end_col: usize = if (row_idx == span.end.row)
622 @intCast(span.end.col) 595 @intCast(span.end.col)
@@ -624,26 +597,18 @@ fn canonicalizeSelectedRowBounds(
624 row_cells.len - 1; 597 row_cells.len - 1;
625 if (end_col >= row_cells.len) end_col = row_cells.len - 1; 598 if (end_col >= row_cells.len) end_col = row_cells.len - 1;
626 599
627 start_col = canonicalizeSpacerBoundary(row_cells, start_col) orelse return null; 600 while (end_col >= start_col) {
628 end_col = canonicalizeSpacerBoundary(row_cells, end_col) orelse return null; 601 const cell = row_cells.get(end_col);
629 if (end_col < start_col) return null; 602 if (!isTrailingBlankCell(cell)) break;
630 603 if (end_col == 0) return;
631 return .{ 604 end_col -= 1;
632 .start_col = start_col,
633 .end_col = end_col,
634 };
635 }
636
637 fn canonicalizeSpacerBoundary(row_cells: anytype, col: usize) ?usize {
638 if (col >= row_cells.len) return null;
639
640 const cell = row_cells.get(col);
641 if (cell.raw.wide == .spacer_tail or cell.raw.wide == .spacer_head) {
642 if (col == 0) return null;
643 return col - 1;
644 } 605 }
645 606
646 return col; 607 var col = start_col;
608 while (col <= end_col) : (col += 1) {
609 const cell = row_cells.get(col);
610 try appendSelectedCellText(alloc, out, cell);
611 }
647 } 612 }
648 613
649 fn isTrailingBlankCell(cell: anytype) bool { 614 fn isTrailingBlankCell(cell: anytype) bool {
@@ -2490,7 +2455,7 @@ test "extractSelectedText preserves interior spaces while trimming trailing blan
2490 try std.testing.expectEqualStrings("a b c ", text); 2455 try std.testing.expectEqualStrings("a b c ", text);
2491 } 2456 }
2492 2457
2493 test "extractSelectedText copies a wide glyph when selection lands on its spacer cell" { 2458 test "extractSelectedText emits a wide glyph once when its spacer cell is selected too" {
2494 var term = try vt.Terminal.init(std.testing.allocator, .{ 2459 var term = try vt.Terminal.init(std.testing.allocator, .{
2495 .cols = 4, 2460 .cols = 4,
2496 .rows = 1, 2461 .rows = 1,
@@ -2505,7 +2470,7 @@ test "extractSelectedText copies a wide glyph when selection lands on its spacer
2505 try std.testing.expectEqual(.spacer_tail, row_cells.get(1).raw.wide); 2470 try std.testing.expectEqual(.spacer_tail, row_cells.get(1).raw.wide);
2506 2471
2507 const span = SelectionSpan{ 2472 const span = SelectionSpan{
2508 .start = .{ .col = 1, .row = 0 }, 2473 .start = .{ .col = 0, .row = 0 },
2509 .end = .{ .col = 1, .row = 0 }, 2474 .end = .{ .col = 1, .row = 0 },
2510 }; 2475 };
2511 const text = try extractSelectedText(std.testing.allocator, term.render_state.row_data.items(.cells), span); 2476 const text = try extractSelectedText(std.testing.allocator, term.render_state.row_data.items(.cells), span);