mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-13 19:15:48 +00:00
terminal: stream handles new SemanticPrompt type
This commit is contained in:
@@ -42,7 +42,7 @@ pub const Command = union(Key) {
|
||||
change_window_icon: [:0]const u8,
|
||||
|
||||
/// Semantic prompt command: https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md
|
||||
semantic_prompt: parsers.semantic_prompt2.Command,
|
||||
semantic_prompt: SemanticPrompt,
|
||||
|
||||
/// First do a fresh-line. Then start a new command, and enter prompt mode:
|
||||
/// Subsequent text (until a OSC "133;B" or OSC "133;I" command) is a
|
||||
@@ -221,6 +221,8 @@ pub const Command = union(Key) {
|
||||
/// Kitty text sizing protocol (OSC 66)
|
||||
kitty_text_sizing: parsers.kitty_text_sizing.OSC,
|
||||
|
||||
pub const SemanticPrompt = parsers.semantic_prompt2.Command;
|
||||
|
||||
pub const Key = LibEnum(
|
||||
if (build_options.c_abi) .c else .zig,
|
||||
// NOTE: Order matters, see LibEnum documentation.
|
||||
|
||||
@@ -130,6 +130,7 @@ pub const Action = union(Key) {
|
||||
set_attribute: sgr.Attribute,
|
||||
kitty_color_report: kitty.color.OSC,
|
||||
color_operation: ColorOperation,
|
||||
semantic_prompt: SemanticPrompt,
|
||||
|
||||
pub const Key = lib.Enum(
|
||||
lib_target,
|
||||
@@ -231,6 +232,7 @@ pub const Action = union(Key) {
|
||||
"set_attribute",
|
||||
"kitty_color_report",
|
||||
"color_operation",
|
||||
"semantic_prompt",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -448,6 +450,8 @@ pub const Action = union(Key) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
pub const SemanticPrompt = osc.Command.SemanticPrompt;
|
||||
};
|
||||
|
||||
/// Returns a type that can process a stream of tty control characters.
|
||||
@@ -2003,8 +2007,9 @@ pub fn Stream(comptime Handler: type) type {
|
||||
// ref: https://github.com/qwerasd205/asciinema-stats
|
||||
|
||||
switch (cmd) {
|
||||
// TODO
|
||||
.semantic_prompt => {},
|
||||
.semantic_prompt => |sp| {
|
||||
try self.handler.vt(.semantic_prompt, sp);
|
||||
},
|
||||
|
||||
.change_window_title => |title| {
|
||||
@branchHint(.likely);
|
||||
|
||||
@@ -161,6 +161,7 @@ pub const Handler = struct {
|
||||
.prompt_end => self.terminal.markSemanticPrompt(.input),
|
||||
.end_of_input => self.terminal.markSemanticPrompt(.command),
|
||||
.end_of_command => self.terminal.screens.active.cursor.page_row.semantic_prompt = .input,
|
||||
.semantic_prompt => self.semanticPrompt(value),
|
||||
.mouse_shape => self.terminal.mouse_shape = value,
|
||||
.color_operation => try self.colorOperation(value.op, &value.requests),
|
||||
.kitty_color_report => try self.kittyColorOperation(value),
|
||||
@@ -216,6 +217,39 @@ pub const Handler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn semanticPrompt(
|
||||
self: *Handler,
|
||||
cmd: Action.SemanticPrompt,
|
||||
) void {
|
||||
switch (cmd.action) {
|
||||
.fresh_line => {
|
||||
if (self.terminal.screens.active.cursor.x != 0) {
|
||||
self.terminal.carriageReturn();
|
||||
self.terminal.index() catch {};
|
||||
}
|
||||
},
|
||||
.fresh_line_new_prompt => {
|
||||
if (self.terminal.screens.active.cursor.x != 0) {
|
||||
self.terminal.carriageReturn();
|
||||
self.terminal.index() catch {};
|
||||
}
|
||||
self.terminal.screens.active.cursor.page_row.semantic_prompt = .prompt;
|
||||
},
|
||||
.new_command => {},
|
||||
.prompt_start => {
|
||||
const kind = cmd.options.prompt_kind orelse .initial;
|
||||
switch (kind) {
|
||||
.initial, .right => self.terminal.screens.active.cursor.page_row.semantic_prompt = .prompt,
|
||||
.continuation, .secondary => self.terminal.screens.active.cursor.page_row.semantic_prompt = .prompt_continuation,
|
||||
}
|
||||
},
|
||||
.end_prompt_start_input => self.terminal.markSemanticPrompt(.input),
|
||||
.end_prompt_start_input_terminate_eol => self.terminal.markSemanticPrompt(.input),
|
||||
.end_input_start_output => self.terminal.markSemanticPrompt(.command),
|
||||
.end_command => self.terminal.screens.active.cursor.page_row.semantic_prompt = .input,
|
||||
}
|
||||
}
|
||||
|
||||
fn setMode(self: *Handler, mode: modes.Mode, enabled: bool) !void {
|
||||
// Set the mode on the terminal
|
||||
self.terminal.modes.set(mode, enabled);
|
||||
|
||||
@@ -325,6 +325,7 @@ pub const StreamHandler = struct {
|
||||
.prompt_start => self.promptStart(value.aid, value.redraw),
|
||||
.prompt_continuation => self.promptContinuation(value.aid),
|
||||
.end_of_command => self.endOfCommand(value.exit_code),
|
||||
.semantic_prompt => self.semanticPrompt(value),
|
||||
.mouse_shape => try self.setMouseShape(value),
|
||||
.configure_charset => self.configureCharset(value.slot, value.charset),
|
||||
.set_attribute => {
|
||||
@@ -1094,6 +1095,48 @@ pub const StreamHandler = struct {
|
||||
self.surfaceMessageWriter(.{ .stop_command = exit_code });
|
||||
}
|
||||
|
||||
fn semanticPrompt(
|
||||
self: *StreamHandler,
|
||||
cmd: Stream.Action.SemanticPrompt,
|
||||
) void {
|
||||
switch (cmd.action) {
|
||||
.fresh_line => {
|
||||
if (self.terminal.screens.active.cursor.x != 0) {
|
||||
self.terminal.carriageReturn();
|
||||
self.terminal.index() catch {};
|
||||
}
|
||||
},
|
||||
.fresh_line_new_prompt => {
|
||||
if (self.terminal.screens.active.cursor.x != 0) {
|
||||
self.terminal.carriageReturn();
|
||||
self.terminal.index() catch {};
|
||||
}
|
||||
self.promptStart(cmd.options.aid, false);
|
||||
},
|
||||
.new_command => {},
|
||||
.prompt_start => {
|
||||
const kind = cmd.options.prompt_kind orelse .initial;
|
||||
switch (kind) {
|
||||
.initial, .right => self.promptStart(cmd.options.aid, false),
|
||||
.continuation, .secondary => self.promptContinuation(cmd.options.aid),
|
||||
}
|
||||
},
|
||||
.end_prompt_start_input => self.terminal.markSemanticPrompt(.input),
|
||||
.end_prompt_start_input_terminate_eol => self.terminal.markSemanticPrompt(.input),
|
||||
.end_input_start_output => {
|
||||
self.terminal.markSemanticPrompt(.command);
|
||||
self.surfaceMessageWriter(.start_command);
|
||||
},
|
||||
.end_command => {
|
||||
const exit_code: ?u8 = if (cmd.options.exit_code) |code|
|
||||
if (code >= 0 and code <= 255) @intCast(code) else null
|
||||
else
|
||||
null;
|
||||
self.surfaceMessageWriter(.{ .stop_command = exit_code });
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn reportPwd(self: *StreamHandler, url: []const u8) !void {
|
||||
// Special handling for the empty URL. We treat the empty URL
|
||||
// as resetting the pwd as if we never saw a pwd. I can't find any
|
||||
|
||||
Reference in New Issue
Block a user