mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
terminal: stream/parser changes
This commit is contained in:
@ -185,7 +185,7 @@ pub const Action = union(enum) {
|
|||||||
|
|
||||||
/// Keeps track of the parameter sep used for CSI params. We allow colons
|
/// Keeps track of the parameter sep used for CSI params. We allow colons
|
||||||
/// to be used ONLY by the 'm' CSI action.
|
/// to be used ONLY by the 'm' CSI action.
|
||||||
const ParamSepState = enum(u8) {
|
pub const ParamSepState = enum(u8) {
|
||||||
none = 0,
|
none = 0,
|
||||||
semicolon = ';',
|
semicolon = ';',
|
||||||
colon = ':',
|
colon = ':',
|
||||||
@ -279,7 +279,7 @@ pub fn next(self: *Parser, c: u8) [3]?Action {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect(self: *Parser, c: u8) void {
|
pub fn collect(self: *Parser, c: u8) void {
|
||||||
if (self.intermediates_idx >= MAX_INTERMEDIATE) {
|
if (self.intermediates_idx >= MAX_INTERMEDIATE) {
|
||||||
log.warn("invalid intermediates count", .{});
|
log.warn("invalid intermediates count", .{});
|
||||||
return;
|
return;
|
||||||
|
@ -74,17 +74,14 @@ pub fn Stream(comptime Handler: type) type {
|
|||||||
if (offset >= input.len) return;
|
if (offset >= input.len) return;
|
||||||
try self.next(input[offset]);
|
try self.next(input[offset]);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
} else if (self.parser.state != .ground) {
|
|
||||||
// If we're not in the ground state then we process until
|
|
||||||
// we are. This can happen if the last chunk of input put us
|
|
||||||
// in the middle of a control sequence.
|
|
||||||
for (input[offset..]) |single| {
|
|
||||||
try self.nextNonUtf8(single);
|
|
||||||
offset += 1;
|
|
||||||
if (self.parser.state == .ground) break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're not in the ground state then we process until
|
||||||
|
// we are. This can happen if the last chunk of input put us
|
||||||
|
// in the middle of a control sequence.
|
||||||
|
offset += try self.consumeUntilGround(input[offset..]);
|
||||||
|
if (offset >= input.len) return;
|
||||||
|
|
||||||
// If we're in the ground state then we can use SIMD to process
|
// If we're in the ground state then we can use SIMD to process
|
||||||
// input until we see an ESC (0x1B), since all other characters
|
// input until we see an ESC (0x1B), since all other characters
|
||||||
// up to that point are just UTF-8.
|
// up to that point are just UTF-8.
|
||||||
@ -112,26 +109,46 @@ pub fn Stream(comptime Handler: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process our control sequence.
|
// Process our control sequence.
|
||||||
for (input[offset..]) |single| {
|
self.parser.state = .escape;
|
||||||
try self.nextNonUtf8(single);
|
offset += 1;
|
||||||
offset += 1;
|
offset += try self.consumeUntilGround(input[offset..]);
|
||||||
if (self.parser.state == .ground) break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses escape sequences until the parser reaches the ground state.
|
||||||
|
/// Returns the number of bytes consumed from the provided input.
|
||||||
|
inline fn consumeUntilGround(self: *Self, input: []const u8) !usize {
|
||||||
|
var offset: usize = 0;
|
||||||
|
while (self.parser.state != .ground) {
|
||||||
|
if (offset >= input.len) return input.len;
|
||||||
|
try self.nextNonUtf8(input[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
/// Like nextSlice but takes one byte and is necessarilly a scalar
|
/// Like nextSlice but takes one byte and is necessarilly a scalar
|
||||||
/// operation that can't use SIMD. Prefer nextSlice if you can and
|
/// operation that can't use SIMD. Prefer nextSlice if you can and
|
||||||
/// try to get multiple bytes at once.
|
/// try to get multiple bytes at once.
|
||||||
pub fn next(self: *Self, c: u8) !void {
|
pub fn next(self: *Self, c: u8) !void {
|
||||||
// The scalar path can be responsible for decoding UTF-8.
|
// The scalar path can be responsible for decoding UTF-8.
|
||||||
if (self.parser.state == .ground and c != 0x1B) {
|
if (self.parser.state == .ground and c != 0x1B) {
|
||||||
var consumed = false;
|
const res = self.utf8decoder.next(c);
|
||||||
while (!consumed) {
|
const consumed = res[1];
|
||||||
const res = self.utf8decoder.next(c);
|
if (res[0]) |codepoint| {
|
||||||
consumed = res[1];
|
if (codepoint < 0xF) {
|
||||||
if (res[0]) |codepoint| {
|
try self.execute(@intCast(codepoint));
|
||||||
if (codepoint <= 0xF) {
|
} else {
|
||||||
|
try self.print(@intCast(codepoint));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!consumed) {
|
||||||
|
const retry = self.utf8decoder.next(c);
|
||||||
|
// It should be impossible for the decoder
|
||||||
|
// to not consume the byte twice in a row.
|
||||||
|
assert(retry[1] == true);
|
||||||
|
if (retry[0]) |codepoint| {
|
||||||
|
if (codepoint < 0xF) {
|
||||||
try self.execute(@intCast(codepoint));
|
try self.execute(@intCast(codepoint));
|
||||||
} else {
|
} else {
|
||||||
try self.print(@intCast(codepoint));
|
try self.print(@intCast(codepoint));
|
||||||
|
Reference in New Issue
Block a user