Something went wrong. Try again.
My version of https://github.com/vercel-labs/fx
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233const std = @import("std");const runtime_profile = @import("../hosts/runtime_profile.zig");const app_lifecycle = @import("app_lifecycle.zig");const app_render_runtime = @import("app_render_runtime.zig");const debug_trace = @import("../shared/debug_trace.zig");const input_action = @import("../input/input_action.zig");const transcript_presentation = @import("../output/transcript_presentation.zig");const types = @import("../shared/types.zig");const interaction_state = @import("../../ui/footer/interaction_state.zig");const approval_prompt = @import("../permissions/approval_prompt.zig");const shell_runtime = @import("../../ui/shell_runtime.zig");const transcript_runtime = @import("../../ui/transcript/runtime.zig");
pub fn Runtime(comptime App: type) type { return struct { const FullTranscriptKey = union(enum) { toggle, navigate: transcript_presentation.Event, close, interrupt, redraw, wheel_scroll: input_action.MouseWheel, page_scroll: input_action.MouseWheel, };
fn requestActiveSurfaceFrame(app: *App) void { app_render_runtime.Runtime(App).requestActiveSurfaceFrame(app, .modal); }
fn screenOwnsInput(app: *App) bool { if (comptime !@hasField(App, "terminal")) return false; if (approvalOwnsCurrentSurface(app)) return false; return app.terminal.fullTranscriptScreenActive(); }
fn approvalOwnsCurrentSurface(app: *const App) bool { return app.approval_prompt.isActive(); }
pub fn routeByte(app: *App, byte: u8) !bool { const key = keyForByte(byte) orelse return false; if (!screenOwnsInput(app)) return false; try routeKey(app, key); return true; }
pub fn routeAction(app: *App, resolved: input_action.Action) !bool { const key = keyForAction(resolved) orelse return false; if (!screenOwnsInput(app)) return false; try routeKey(app, key); return true; }
pub fn routeComposerAction(app: *App, resolved: input_action.Action) !bool { return switch (keyForAction(resolved) orelse return false) { .toggle => { try transitionScreen(app, .toggle); return true; }, .close => { if (comptime @hasDecl( @TypeOf(app.shell), "cancelPendingFullTranscriptOpen", )) { if (app.shell.cancelPendingFullTranscriptOpen()) return true; } return false; }, else => false, }; }
pub fn cancelPendingOpenForInput(app: *App) bool { if (comptime @hasDecl( @TypeOf(app.shell), "cancelPendingFullTranscriptOpen", )) { return app.shell.cancelPendingFullTranscriptOpen(); } return false; }
fn transitionScreen( app: *App, event: transcript_presentation.Event, ) !void { if (comptime !@hasField(App, "terminal")) { _ = try app.transitionFullTranscriptProjection(event); return; }
const from = app.shell.transcriptPresentationDepth(); const to = from.transition(event); if (from == to) return; if (from == .inline_mode) { std.debug.assert(to == .full); if (app.terminal.alternate_screen_owner != .none) return; if (app.approval_prompt.isActive()) return; if (comptime @hasDecl( @TypeOf(app.shell), "requestFullTranscriptOpen", )) { if (!app.shell.requestFullTranscriptOpen()) return; } try app_lifecycle.openFullTranscript( app.alloc, &app.terminal, &app.shell, &app.metrics, ); requestActiveSurfaceFrame(app); } else { std.debug.assert(to == .inline_mode); try app_lifecycle.closeFullTranscript( app.alloc, &app.terminal, &app.shell, &app.metrics, ); } logDepthTransition( from, app.shell.transcriptPresentationDepth(), .root, triggerForEvent(event), ); }
fn closeScreen(app: *App, trigger: TransitionTrigger) !void { debug_trace.logf( "full_transcript", "close_screen trigger={s}", .{@tagName(trigger)}, ); if (comptime !@hasField(App, "terminal")) return; const from = app.shell.transcriptPresentationDepth(); if (!from.active()) return; try app_lifecycle.closeFullTranscript( app.alloc, &app.terminal, &app.shell, &app.metrics, ); logDepthTransition(from, .inline_mode, .root, trigger); }
fn keyForByte(byte: u8) ?FullTranscriptKey { return switch (byte) { 3 => .interrupt, 12 => .redraw, 24 => null, else => null, }; }
fn keyForAction(resolved: input_action.Action) ?FullTranscriptKey { return switch (resolved) { .toggle_full_transcript => .toggle, .cursor_left => .{ .navigate = .left }, .cursor_right => .{ .navigate = .right }, .cursor_up => .{ .wheel_scroll = .up }, .cursor_down => .{ .wheel_scroll = .down }, .escape => .close, .mouse_wheel => |direction| .{ .wheel_scroll = direction }, .page_up => .{ .page_scroll = .up }, .page_down => .{ .page_scroll = .down }, .composer_shortcut => |shortcut| switch (shortcut) { .redraw => .redraw, else => null, }, .remapped_byte => |byte| switch (byte) { 3 => .interrupt, 12 => .redraw, 24 => null, else => null, }, else => null, }; }
fn routeKey(app: *App, key: FullTranscriptKey) !void { switch (key) { .toggle => try transitionScreen(app, .toggle), .navigate => |event| try transitionScreen(app, event), .close => try closeScreen(app, .escape), .interrupt => try closeScreen(app, .ctrl_c), .redraw => {}, .wheel_scroll => |direction| { app.shell.scrollFullTranscript(direction, .wheel); requestActiveSurfaceFrame(app); }, .page_scroll => |direction| { app.shell.scrollFullTranscript(direction, .page); requestActiveSurfaceFrame(app); }, } }
const TransitionRoute = enum { root }; const TransitionTrigger = enum { ctrl_o, left, right, escape, ctrl_c };
fn triggerForEvent( event: transcript_presentation.Event, ) TransitionTrigger { return switch (event) { .toggle => .ctrl_o, .left => .left, .right => .right, }; }
fn logDepthTransition( from: transcript_presentation.Depth, to: transcript_presentation.Depth, route: TransitionRoute, trigger: TransitionTrigger, ) void { debug_trace.logf( "full_transcript", "depth_transition from={s} to={s} route={s} trigger={s}", .{ depthName(from), depthName(to), @tagName(route), @tagName(trigger) }, ); }
fn depthName(depth: transcript_presentation.Depth) []const u8 { return switch (depth) { .inline_mode => "inline", .full => "full", }; } };}