15890 lines · 603.1 KB · Zig
RawDownload
const std = @import("std");const io_mod = @import("../../core/shared/io.zig");const types = @import("../../core/shared/types.zig");const command_output_content = @import("../../core/tooling/command_output_content.zig");const full_transcript_screen = @import("../full_transcript_screen.zig");const input_visual_layout = @import("../input/visual_layout.zig");const render_engine = @import("../render_engine.zig");const command_output_runtime = @import("command_output_runtime.zig");const transcript_painter = @import("painter.zig");const transcript_runtime = @import("runtime.zig");const transcript_store = @import("store.zig");const transcript_writer = @import("writer.zig");const ui_render = @import("../render.zig");const user_message_card = @import("../assistant/user_message_card.zig");const vt_emulator = @import("../../core/terminal/engine.zig"); const Allocator = std.mem.Allocator;const Layout = types.Layout;const Metrics = types.Metrics;const transcript_blocks = render_engine.transcript_blocks;const viewport_selection = render_engine.viewport_selection; const RawEntryClass = transcript_blocks.RawEntryClass;const Styles = transcript_blocks.Styles;const ToolDetailRecord = transcript_blocks.ToolDetailRecord;const TranscriptPreparationSource = transcript_runtime.TranscriptPreparationSource;const TranscriptRuntime = transcript_runtime.TranscriptRuntime;const HardLineStarts = viewport_selection.HardLineStarts;const TranscriptBuffer = viewport_selection.TranscriptBuffer;const VisibleTranscriptLine = viewport_selection.VisibleTranscriptLine;fn renderEntriesToBytes(alloc: Allocator, entries: []const transcript_blocks.TranscriptEntry, cols: u16) ![]u8 {    return transcript_runtime.renderEntriesToBytes(alloc, entries, cols, .{});}const visualRowsForLine = transcript_blocks.visualRowsForLine; fn resolveAndSealTranscriptTransitionForTest(    runtime: *TranscriptRuntime,    alloc: Allocator,    source: *TranscriptPreparationSource,    prepared: *transcript_painter.PreparedTranscriptSurfacePaint,    target_layout: render_engine.frame_layout.CommittedLayoutSnapshot,    plan: *render_engine.paint_plan.PaintPlan,    scroll_plan: render_engine.frame_scroll_plan.FrameScrollPlan,) !transcript_runtime.TranscriptTransition {    const scroll_facts = try runtime.prepareTranscriptScrollFactsForFrame(        alloc,        source,        prepared,        false,        false,    );    const destructive_invalidation = render_engine.frame_retention.transcriptAreaHasDestructiveInvalidation(        runtime.committed_frame_layout.transcript_area,        plan.invalidation,    );    const resolved = try runtime.resolveTranscriptTransitionTargetForFrame(        alloc,        source,        prepared,        target_layout,        scroll_plan,        scroll_facts,        destructive_invalidation,        plan.activity == .overlay_entry,    );    resolved.applyToPaintPlan(plan);    return runtime.sealTranscriptTransition(        alloc,        source,        prepared,        plan,        resolved,    );} fn resolveVisibleLineForTest(line: VisibleTranscriptLine, buf: TranscriptBuffer) []const u8 {    return switch (line) {        .transcript => |t| t.ref.resolve(buf),        .folded_line => |f| f.text,    };} fn commandOutputTestRuntime(sink: std.Io.File) TranscriptRuntime {    return .{        .stdout_file = sink,        .maxxing_mode = .legacy,        .layout = .{            .rows = 24,            .cols = 80,            .content_bottom = 21,            .divider_top_row = 22,            .input_row = 23,            .divider_bottom_row = 24,            .hint_row = 22,        },    };} fn testSelection(start_line: usize) viewport_selection.ViewportSelection {    return .{        .top_row = 1,        .bottom_row = 4,        .start_line = start_line,        .partial_skip_rows = 0,        .line_count = 16,    };} fn transcriptTestLayout(cols: u16, rows: u16, content_bottom: u16) Layout {    return .{        .rows = rows,        .cols = cols,        .content_bottom = content_bottom,        .divider_top_row = content_bottom + 1,        .input_row = content_bottom + 2,        .divider_bottom_row = content_bottom + 3,        .hint_row = rows,    };} fn makeLongPastePrompt(alloc: Allocator, line_count: usize) ![]u8 {    var out: std.Io.Writer.Allocating = .init(alloc);    defer out.deinit();     try out.writer.writeAll("LONG_PASTE_FIRST_MARKER\n");    var index: usize = 0;    while (index < line_count) : (index += 1) {        try out.writer.print("long-paste-line-{d}\n", .{index});    }    try out.writer.writeAll("LONG_PASTE_LAST_MARKER\n");    return out.toOwnedSlice();} fn installStableAnchorWithOriginForTest(    runtime: *TranscriptRuntime,    alloc: Allocator,    flow: []const u8,    selection: viewport_selection.ViewportSelection,    visual_offset: u32,    cursor_row: u16,    cursor_col: u16,    layout_id: u64,    measured_history_origin: ?transcript_painter.MeasuredHistoryOrigin,) !void {    var target_cache: std.ArrayList(u8) = .empty;    errdefer target_cache.deinit(alloc);    try target_cache.appendSlice(alloc, flow);    var transition = transcript_runtime.TranscriptTransition{        .scroll_plan = render_engine.frame_scroll_plan.FrameScrollPlan.none(            runtime.layout.rows,            runtime.owned_top_row,        ),        .document_append = .{},        .materialized_without_append = .{},        .target_flow = try alloc.dupe(u8, flow),        .target_cache = target_cache,        .target_cache_origin_untrimmed = runtime.transcript_cache_origin_untrimmed,        .folded_summary_indices = &.{},        .target_layout = .{            .layout_id = layout_id,            .owned_top = runtime.owned_top_row,            .owned_band = .{ .top = runtime.owned_top_row, .bottom = runtime.layout.rows },            .body_area = .{ .top = runtime.owned_top_row, .bottom = runtime.layout.content_bottom },            .transcript_area = .{ .top = runtime.owned_top_row, .bottom = runtime.layout.content_bottom },            .footer_area = .{ .top = runtime.layout.content_bottom + 1, .bottom = runtime.layout.rows },            .solved_frame_height = runtime.layout.rows - runtime.owned_top_row + 1,            .terminal_rows = runtime.layout.rows,            .terminal_cols = runtime.layout.cols,        },        .selection = selection,        .visual_offset = visual_offset,        .history_visual_offset = visual_offset,        .total_visual_rows = visual_offset + 64,        .cursor_row = cursor_row,        .cursor_col = cursor_col,        .replaceable_last_line = false,        .replaceable_start = 0,        .replaceable_row = cursor_row,        .trace_transcript_frame = false,        .trace_visible_rows = selection.bottom_row - selection.top_row + 1,        .measured_history_origin = measured_history_origin,    };    defer transition.deinit(alloc);    runtime.consumeTranscriptTransition(alloc, &transition, .{        .bytes_written = 0,        .changed_cells = 0,        .full_repaint = false,        .terminal_scroll_rows_committed = 0,        .document_append_committed = false,        .committed_cursor_row = cursor_row,        .committed_cursor_col = cursor_col,        .shadow_state = .committed,        .next_invalidation = render_engine.paint_plan.FrameInvalidationSet.empty(),    });} fn installStableAnchorForTest(    runtime: *TranscriptRuntime,    alloc: Allocator,    flow: []const u8,    selection: viewport_selection.ViewportSelection,    visual_offset: u32,    cursor_row: u16,    cursor_col: u16,    layout_id: u64,) !void {    return installStableAnchorWithOriginForTest(        runtime,        alloc,        flow,        selection,        visual_offset,        cursor_row,        cursor_col,        layout_id,        null,    );} fn testPaintPlan(    runtime: *const TranscriptRuntime,    selection: viewport_selection.ViewportSelection,) render_engine.paint_plan.PaintPlan {    const footer_top = runtime.layout.content_bottom + 1;    return .{        .layout = runtime.layout,        .viewport = selection,        .footer = .{            .top = footer_top,            .top_divider = footer_top,            .banner = footer_top,            .banner_active = false,            .input_base = @min(footer_top + 1, runtime.layout.rows),            .picker_divider = @min(footer_top + 2, runtime.layout.rows),            .picker_start = runtime.layout.rows,            .bottom_divider = @min(footer_top + 2, runtime.layout.rows),            .hint = runtime.layout.rows,            .total_rows = runtime.layout.rows - footer_top + 1,        },        .activity = .none,        .preserved_band = if (runtime.owned_top_row > 1)            .{ .top = 1, .bottom = runtime.owned_top_row - 1, .owner = .preserved_shell }        else            render_engine.paint_plan.FrameBand.empty(.preserved_shell),        .transcript_band = .{            .top = runtime.owned_top_row,            .bottom = runtime.layout.content_bottom,            .owner = .transcript,        },        .activity_band = render_engine.paint_plan.FrameBand.empty(.activity),        .footer_band = .{            .top = footer_top,            .bottom = runtime.layout.rows,            .owner = .footer,        },        .invalidation = render_engine.paint_plan.FrameInvalidationSet.empty(),        .footer_clean_allowed = true,        .synchronized_update = true,        .cursor_target = .{ .row = selection.bottom_row, .col = 1, .visible = true },        .footer_reservation_source = .none,        .bottom_reserved_rows = 0,        .preserve_scrollback = true,    };} const TestTranscriptFixedPointFrame = struct {    layout: render_engine.frame_layout.FrameLayout,    scroll_plan: render_engine.frame_scroll_plan.FrameScrollPlan,}; fn solveTestTranscriptFixedPointFrame(    runtime: *TranscriptRuntime,    alloc: Allocator,    metrics: *Metrics,    source: *const TranscriptPreparationSource,    footer_rows: u16,    prepared: *?transcript_painter.PreparedTranscriptSurfacePaint,) !TestTranscriptFixedPointFrame {    var release_floor_rows: u16 = 0;    var previous_candidate_owned_top: ?u16 = null;     while (true) {        const release = render_engine.frame_layout.solveWithPreservedRowRelease(.{            .terminal = runtime.layout,            .owned_top = runtime.owned_top_row,            .footer = .{                .natural_rows = footer_rows,                .min_rows = footer_rows,                .max_rows = footer_rows,            },            .transcript = source.preview,            .prior = runtime.committed_frame_layout,        }, release_floor_rows);        const candidate = release.layout;        if (previous_candidate_owned_top) |previous| {            if (candidate.owned_top >= previous) return error.InvalidFrameScrollPlan;        }         if (prepared.*) |*paint| {            paint.deinit(alloc);            prepared.* = null;        }        var inline_advance_rows: u16 = 0;        if (!candidate.transcript_area.isEmpty()) {            prepared.* = try runtime.prepareTranscriptSurfacePaintFromSourceForArea(                alloc,                metrics,                source,                candidate.transcript_area,            );            inline_advance_rows = runtime.planTranscriptScroll(&prepared.*.?).planned_rows;        }        const scroll_plan = render_engine.frame_scroll_plan.merge(            runtime.layout.rows,            runtime.owned_top_row,            release.released_rows,            inline_advance_rows,        );        if (candidate.owned_top == scroll_plan.post_scroll_owned_top) {            return .{                .layout = candidate,                .scroll_plan = scroll_plan,            };        }        previous_candidate_owned_top = candidate.owned_top;        release_floor_rows = scroll_plan.preserved_release_rows;    }} fn testPaintPlanForFrame(    layout: render_engine.frame_layout.FrameLayout,    selection: viewport_selection.ViewportSelection,    cursor_row: u16,    cursor_col: u16,) render_engine.paint_plan.PaintPlan {    const footer_rows = render_engine.footer_layout.resolve(.{        .footer_top_for_extra = layout.footer_area.top,        .terminal_rows = layout.terminal.rows,        .activity_offset = 0,        .extra_input_rows = 0,        .input_extra = 0,        .picker_rows = 0,        .banner_active = false,        .allocated_rows = layout.footer_area.height(),    });    return layout.toPaintPlan(.{        .footer_rows = footer_rows,        .viewport = selection,        .cursor_target = .{            .row = cursor_row,            .col = cursor_col,            .visible = true,        },    });} fn testSource(    alloc: Allocator,    bytes: []const u8,    cols: u16,) !TranscriptPreparationSource {    return .{        .bytes = try alloc.dupe(u8, bytes),        .folded_summary_indices = &.{},        .preview = .{ .natural_visual_rows = 4 },        .tail_kind = null,        .tracked_entry_id = null,        .tracked_entry_start_line = null,        .replaceable_last_line = false,        .replaceable_start = 0,        .replaceable_row = 1,        .welcome_cut_line = null,        .welcome_boundary = null,        .cols = cols,    };} fn testFoldedSource(    alloc: Allocator,    bytes: []const u8,    cols: u16,    summary_transcript_index: usize,) !TranscriptPreparationSource {    var source = try testSource(alloc, bytes, cols);    errdefer source.deinit(alloc);    source.folded_summary_indices = try alloc.dupe(        usize,        &.{summary_transcript_index},    );    return source;} fn testSourceWithReplaceableTail(    alloc: Allocator,    bytes: []const u8,    cols: u16,    replaceable_start: usize,) !TranscriptPreparationSource {    var source = try testSource(alloc, bytes, cols);    source.replaceable_last_line = true;    source.replaceable_start = replaceable_start;    return source;} fn appendFoldedLineForTest(    runtime: *TranscriptRuntime,    alloc: Allocator,    block_index: usize,    text: []const u8,) !void {    const owned = try alloc.dupe(u8, text);    errdefer alloc.free(owned);    try runtime.folded_command_blocks.items[block_index].lines.append(alloc, .{        .stream = .stdout,        .text = owned,    });} fn prepareTestSourceForCurrentArea(    runtime: *TranscriptRuntime,    alloc: Allocator,    source: *const TranscriptPreparationSource,) !transcript_painter.PreparedTranscriptSurfacePaint {    var metrics: Metrics = .{};    return runtime.prepareTranscriptSurfacePaintFromSourceForArea(        alloc,        &metrics,        source,        .{            .top = runtime.owned_top_row,            .bottom = runtime.layout.content_bottom,        },    );} fn preparedVisualOffsetForTest(    prepared: *const transcript_painter.PreparedTranscriptSurfacePaint,) u32 {    var offset: u32 = 0;    const end = @min(        prepared.selection.start_line,        prepared.sourceVisualRows().len,    );    for (prepared.sourceVisualRows()[0..end]) |rows| offset += rows;    return offset + prepared.selection.partial_skip_rows;} test "unchanged transcript keeps stable projection during footer reflow" {    const alloc = std.testing.allocator;    const flow =        "line 00\n" ++        "line 01\n" ++        "line 02\n" ++        "line 03\n" ++        "line 04\n" ++        "line 05\n";    var runtime = TranscriptRuntime{        .layout = transcriptTestLayout(60, 12, 8),        .owned_top_row = 1,    };    defer runtime.deinit(alloc);    var metrics = Metrics{};     var source = try testSource(alloc, flow, runtime.layout.cols);    defer source.deinit(alloc);    var compact = try runtime.prepareTranscriptSurfacePaintFromSourceForFrame(        alloc,        &metrics,        &source,        .{ .top = 1, .bottom = 4 },        false,    );    defer compact.deinit(alloc);    try std.testing.expectEqual(@as(usize, 2), compact.selection.start_line);    try installStableAnchorWithOriginForTest(        &runtime,        alloc,        flow,        compact.selection,        preparedVisualOffsetForTest(&compact),        compact.cursor.cursor_row,        compact.cursor.cursor_col,        800,        .{            .source_cols = runtime.layout.cols,            .source_visual_offset = preparedVisualOffsetForTest(&compact),        },    );     var expanded = try runtime.prepareTranscriptSurfacePaintFromSourceForFrame(        alloc,        &metrics,        &source,        .{ .top = 1, .bottom = 6 },        true,    );    defer expanded.deinit(alloc);     try std.testing.expectEqual(compact.selection.start_line, expanded.selection.start_line);    try std.testing.expectEqual(compact.selection.last_visible_row, expanded.selection.last_visible_row);

Lines 1–500 of 15890.