mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-13 19:15:48 +00:00
core: parse cmdline and cmdline_url semantic prompt options (#11046)
This commit is contained in:
@@ -1,35 +1,30 @@
|
||||
const std = @import("std");
|
||||
|
||||
/// Do an in-place decode of a string that has been encoded in the same way
|
||||
/// that `bash`'s `printf %q` encodes a string. This is safe because a string
|
||||
/// can only get shorter after decoding. This destructively modifies the buffer
|
||||
/// given to it. If an error is returned the buffer may be in an unusable state.
|
||||
pub fn printfQDecode(buf: [:0]u8) error{DecodeError}![:0]const u8 {
|
||||
const data: [:0]u8 = data: {
|
||||
/// Decode date from the buffer that has been encoded in the same way that
|
||||
/// `bash`'s `printf %q` encodes a string and write it to the writer. If an
|
||||
/// error is returned garbage may have been written to the buffer.
|
||||
pub fn printfQDecode(writer: *std.Io.Writer, buf: []const u8) (std.Io.Writer.Error || error{DecodeError})!void {
|
||||
const data: []const u8 = data: {
|
||||
// Strip off `$''` quoting.
|
||||
if (std.mem.startsWith(u8, buf, "$'")) {
|
||||
if (buf.len < 3 or !std.mem.endsWith(u8, buf, "'")) return error.DecodeError;
|
||||
buf[buf.len - 1] = 0;
|
||||
break :data buf[2 .. buf.len - 1 :0];
|
||||
break :data buf[2 .. buf.len - 1];
|
||||
}
|
||||
// Strip off `''` quoting.
|
||||
if (std.mem.startsWith(u8, buf, "'")) {
|
||||
if (buf.len < 2 or !std.mem.endsWith(u8, buf, "'")) return error.DecodeError;
|
||||
buf[buf.len - 1] = 0;
|
||||
break :data buf[1 .. buf.len - 1 :0];
|
||||
break :data buf[1 .. buf.len - 1];
|
||||
}
|
||||
break :data buf;
|
||||
};
|
||||
|
||||
var src: usize = 0;
|
||||
var dst: usize = 0;
|
||||
|
||||
while (src < data.len) {
|
||||
switch (data[src]) {
|
||||
else => {
|
||||
data[dst] = data[src];
|
||||
try writer.writeByte(data[src]);
|
||||
src += 1;
|
||||
dst += 1;
|
||||
},
|
||||
'\\' => {
|
||||
if (src + 1 >= data.len) return error.DecodeError;
|
||||
@@ -40,132 +35,141 @@ pub fn printfQDecode(buf: [:0]u8) error{DecodeError}![:0]const u8 {
|
||||
'\'',
|
||||
'$',
|
||||
=> |c| {
|
||||
data[dst] = c;
|
||||
try writer.writeByte(c);
|
||||
src += 2;
|
||||
dst += 1;
|
||||
},
|
||||
'e' => {
|
||||
data[dst] = std.ascii.control_code.esc;
|
||||
try writer.writeByte(std.ascii.control_code.esc);
|
||||
src += 2;
|
||||
dst += 1;
|
||||
},
|
||||
'n' => {
|
||||
data[dst] = std.ascii.control_code.lf;
|
||||
try writer.writeByte(std.ascii.control_code.lf);
|
||||
src += 2;
|
||||
dst += 1;
|
||||
},
|
||||
'r' => {
|
||||
data[dst] = std.ascii.control_code.cr;
|
||||
try writer.writeByte(std.ascii.control_code.cr);
|
||||
src += 2;
|
||||
dst += 1;
|
||||
},
|
||||
't' => {
|
||||
data[dst] = std.ascii.control_code.ht;
|
||||
try writer.writeByte(std.ascii.control_code.ht);
|
||||
src += 2;
|
||||
dst += 1;
|
||||
},
|
||||
'v' => {
|
||||
data[dst] = std.ascii.control_code.vt;
|
||||
try writer.writeByte(std.ascii.control_code.vt);
|
||||
src += 2;
|
||||
dst += 1;
|
||||
},
|
||||
else => return error.DecodeError,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
data[dst] = 0;
|
||||
return data[0..dst :0];
|
||||
}
|
||||
|
||||
test "printf_q 1" {
|
||||
const s: [:0]const u8 = "bobr\\ kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
const dst = try printfQDecode(&src);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", dst);
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr\\ kurwa";
|
||||
|
||||
try printfQDecode(&w.writer, s);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "printf_q 2" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "bobr\\nkurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
const dst = try printfQDecode(&src);
|
||||
try std.testing.expectEqualStrings("bobr\nkurwa", dst);
|
||||
|
||||
try printfQDecode(&w.writer, s);
|
||||
try std.testing.expectEqualStrings("bobr\nkurwa", w.written());
|
||||
}
|
||||
|
||||
test "printf_q 3" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "bobr\\dkurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&src));
|
||||
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "printf_q 4" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "bobr kurwa\\";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&src));
|
||||
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "printf_q 5" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "$'bobr kurwa'";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
const dst = try printfQDecode(&src);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", dst);
|
||||
|
||||
try printfQDecode(&w.writer, s);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "printf_q 6" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "'bobr kurwa'";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
const dst = try printfQDecode(&src);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", dst);
|
||||
|
||||
try printfQDecode(&w.writer, s);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "printf_q 7" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "$'bobr kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&src));
|
||||
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "printf_q 8" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
const s: [:0]const u8 = "$'";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&src));
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "printf_q 9" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
const s: [:0]const u8 = "'bobr kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&src));
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "printf_q 10" {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: [:0]const u8 = "'";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&src));
|
||||
try std.testing.expectError(error.DecodeError, printfQDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
/// Do an in-place decode of a string that has been URL percent encoded.
|
||||
/// This is safe because a string can only get shorter after decoding. This
|
||||
/// destructively modifies the buffer given to it. If an error is returned the
|
||||
/// buffer may be in an unusable state.
|
||||
pub fn urlPercentDecode(buf: [:0]u8) error{DecodeError}![:0]const u8 {
|
||||
/// Decode data from the buffer that has been URL percent encoded and write
|
||||
/// it to the given buffer. If an error is returned the garbage may have been
|
||||
/// written to the writer.
|
||||
pub fn urlPercentDecode(writer: *std.Io.Writer, buf: []const u8) (std.Io.Writer.Error || error{DecodeError})!void {
|
||||
var src: usize = 0;
|
||||
var dst: usize = 0;
|
||||
while (src < buf.len) {
|
||||
switch (buf[src]) {
|
||||
else => {
|
||||
buf[dst] = buf[src];
|
||||
try writer.writeByte(buf[src]);
|
||||
src += 1;
|
||||
dst += 1;
|
||||
},
|
||||
'%' => {
|
||||
if (src + 2 >= buf.len) return error.DecodeError;
|
||||
@@ -173,9 +177,8 @@ pub fn urlPercentDecode(buf: [:0]u8) error{DecodeError}![:0]const u8 {
|
||||
'0'...'9', 'a'...'f', 'A'...'F' => {
|
||||
switch (buf[src + 2]) {
|
||||
'0'...'9', 'a'...'f', 'A'...'F' => {
|
||||
buf[dst] = std.math.shl(u8, hex(buf[src + 1]), 4) | hex(buf[src + 2]);
|
||||
try writer.writeByte(std.math.shl(u8, hex(buf[src + 1]), 4) | hex(buf[src + 2]));
|
||||
src += 3;
|
||||
dst += 1;
|
||||
},
|
||||
else => return error.DecodeError,
|
||||
}
|
||||
@@ -185,8 +188,6 @@ pub fn urlPercentDecode(buf: [:0]u8) error{DecodeError}![:0]const u8 {
|
||||
},
|
||||
}
|
||||
}
|
||||
buf[dst] = 0;
|
||||
return buf[0..dst :0];
|
||||
}
|
||||
|
||||
inline fn hex(c: u8) u4 {
|
||||
@@ -200,70 +201,96 @@ inline fn hex(c: u8) u4 {
|
||||
|
||||
test "singles percent" {
|
||||
for (0..255) |c| {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var buf_: [4]u8 = undefined;
|
||||
const buf = try std.fmt.bufPrintZ(&buf_, "%{x:0>2}", .{c});
|
||||
const decoded = try urlPercentDecode(buf);
|
||||
|
||||
try urlPercentDecode(&w.writer, buf);
|
||||
const decoded = w.written();
|
||||
|
||||
try std.testing.expectEqual(1, decoded.len);
|
||||
try std.testing.expectEqual(c, decoded[0]);
|
||||
}
|
||||
for (0..255) |c| {
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var buf_: [4]u8 = undefined;
|
||||
const buf = try std.fmt.bufPrintZ(&buf_, "%{X:0>2}", .{c});
|
||||
const decoded = try urlPercentDecode(buf);
|
||||
|
||||
try urlPercentDecode(&w.writer, buf);
|
||||
const decoded = w.written();
|
||||
|
||||
try std.testing.expectEqual(1, decoded.len);
|
||||
try std.testing.expectEqual(c, decoded[0]);
|
||||
}
|
||||
}
|
||||
|
||||
test "percent 1" {
|
||||
const s: [:0]const u8 = "bobr%20kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
const dst = try urlPercentDecode(&src);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", dst);
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%20kurwa";
|
||||
|
||||
try urlPercentDecode(&w.writer, s);
|
||||
try std.testing.expectEqualStrings("bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "percent 2" {
|
||||
const s: [:0]const u8 = "bobr%2kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&src));
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%2kurwa";
|
||||
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "percent 3" {
|
||||
const s: [:0]const u8 = "bobr%kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&src));
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%kurwa";
|
||||
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "percent 4" {
|
||||
const s: [:0]const u8 = "bobr%%kurwa";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&src));
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%%kurwa";
|
||||
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "percent 5" {
|
||||
const s: [:0]const u8 = "bobr%20kurwa%20";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
const dst = try urlPercentDecode(&src);
|
||||
try std.testing.expectEqualStrings("bobr kurwa ", dst);
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%20kurwa%20";
|
||||
|
||||
try urlPercentDecode(&w.writer, s);
|
||||
try std.testing.expectEqualStrings("bobr kurwa ", w.written());
|
||||
}
|
||||
|
||||
test "percent 6" {
|
||||
const s: [:0]const u8 = "bobr%20kurwa%2";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&src));
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%20kurwa%2";
|
||||
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
test "percent 7" {
|
||||
const s: [:0]const u8 = "bobr%20kurwa%";
|
||||
var src: [s.len:0]u8 = undefined;
|
||||
@memcpy(&src, s);
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&src));
|
||||
var w: std.Io.Writer.Allocating = .init(std.testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
const s: []const u8 = "bobr%20kurwa%";
|
||||
|
||||
try std.testing.expectError(error.DecodeError, urlPercentDecode(&w.writer, s));
|
||||
}
|
||||
|
||||
/// Is the given character valid in URI percent encoding?
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//! https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md
|
||||
const std = @import("std");
|
||||
|
||||
const Parser = @import("../../osc.zig").Parser;
|
||||
const OSCCommand = @import("../../osc.zig").Command;
|
||||
const string_encoding = @import("../../../os/string_encoding.zig");
|
||||
|
||||
const log = std.log.scoped(.osc_semantic_prompt);
|
||||
|
||||
@@ -40,6 +42,20 @@ pub const Command = struct {
|
||||
) ?option.Type() {
|
||||
return option.read(self.options_unvalidated);
|
||||
}
|
||||
|
||||
/// Write the decoded command line (if any) to the writer. If an error
|
||||
/// occurs garbage may have been written to the writer.
|
||||
pub fn writeCommandLine(self: Command, writer: *std.Io.Writer) (std.Io.Writer.Error || error{DecodeError})!void {
|
||||
if (self.readOption(.cmdline)) |command_line| {
|
||||
try string_encoding.printfQDecode(writer, command_line);
|
||||
return;
|
||||
}
|
||||
if (self.readOption(.cmdline_url)) |command_line| {
|
||||
try string_encoding.urlPercentDecode(writer, command_line);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Option = enum {
|
||||
@@ -47,6 +63,8 @@ pub const Option = enum {
|
||||
cl,
|
||||
prompt_kind,
|
||||
err,
|
||||
cmdline,
|
||||
cmdline_url,
|
||||
|
||||
// https://sw.kovidgoyal.net/kitty/shell-integration/#notes-for-shell-developers
|
||||
// Kitty supports a "redraw" option for prompt_start. This is extended
|
||||
@@ -83,6 +101,8 @@ pub const Option = enum {
|
||||
.redraw => Redraw,
|
||||
.special_key => bool,
|
||||
.click_events => bool,
|
||||
.cmdline => []const u8,
|
||||
.cmdline_url => []const u8,
|
||||
.exit_code => i32,
|
||||
};
|
||||
}
|
||||
@@ -96,6 +116,8 @@ pub const Option = enum {
|
||||
.redraw => "redraw",
|
||||
.special_key => "special_key",
|
||||
.click_events => "click_events",
|
||||
.cmdline => "cmdline",
|
||||
.cmdline_url => "cmdline_url",
|
||||
|
||||
// special case, handled before ever calling key
|
||||
.exit_code => unreachable,
|
||||
@@ -181,6 +203,8 @@ pub const Option = enum {
|
||||
'1' => true,
|
||||
else => null,
|
||||
} else null,
|
||||
.cmdline => value,
|
||||
.cmdline_url => value,
|
||||
// Handled above
|
||||
.exit_code => unreachable,
|
||||
};
|
||||
@@ -389,6 +413,280 @@ test "OSC 133: end_input_start_output with options" {
|
||||
try testing.expectEqualStrings("foo", cmd.semantic_prompt.readOption(.aid).?);
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline=echo bobr kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 3" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline=echo bobr\\nkurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr\nkurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 4" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline=$'echo bobr kurwa'";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 5" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline='echo bobr kurwa'";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 6" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline='echo bobr kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 7" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline=$'echo bobr kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 8" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline=$'";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline 9" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline=";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 1" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 2" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr%20kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr kurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 3" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr%3bkurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr;kurwa", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 4" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr%3kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 5" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr%kurwa";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 6" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr kurwa%20";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
|
||||
try cmd.semantic_prompt.writeCommandLine(&w.writer);
|
||||
try testing.expectEqualStrings("echo bobr kurwa ", w.written());
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 7" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr kurwa%2";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: end_input_start_output with cmdline_url 8" {
|
||||
const testing = std.testing;
|
||||
|
||||
var w: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer w.deinit();
|
||||
|
||||
var p: Parser = .init(null);
|
||||
const input = "133;C;cmdline_url=echo bobr kurwa%";
|
||||
for (input) |ch| p.next(ch);
|
||||
|
||||
const cmd = p.end(null).?.*;
|
||||
try testing.expect(cmd == .semantic_prompt);
|
||||
try testing.expect(cmd.semantic_prompt.action == .end_input_start_output);
|
||||
try testing.expectError(error.DecodeError, cmd.semantic_prompt.writeCommandLine(&w.writer));
|
||||
}
|
||||
|
||||
test "OSC 133: fresh_line" {
|
||||
const testing = std.testing;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user