diff options
Diffstat (limited to 'src/sam_edit.zig')
| -rw-r--r-- | src/sam_edit.zig | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/sam_edit.zig b/src/sam_edit.zig index 95d59a9d..604e2b31 100644 --- a/src/sam_edit.zig +++ b/src/sam_edit.zig @@ -92,6 +92,25 @@ pub fn run(arena: std.mem.Allocator, text: []const u8, dot: Range, name: []const /// Whether `command` stops inside a `{` group or an `a`, `c` or `i` text /// block still waiting for its `.` line: a writer of lines (a ctl, exec) /// hands an Edit the lines after it until it does not. +/// What an Edit command still waits for: nothing, the `.` line that ends +/// an a, c or i text block, or the `}` of a group. +pub const Wait = enum { none, text, group }; + +/// As `needsMore`, saying which: while a text block is open only a `.` +/// line can end it, so a caller need not parse the block again for every +/// line of text in it (ninep/ctl.zig, editEnd), which was quadratic. +pub fn waitsFor(arena: std.mem.Allocator, command: []const u8) Wait { + var why: Why = .{}; + const src = std.fmt.allocPrint(arena, "{s}\n", .{command}) catch return .none; + defer arena.free(src); + var ps: Parser = .{ .arena = arena, .src = src, .why = &why }; + while (true) { + const c = ps.parse(0) catch + return if (ps.open_text) .text else if (std.mem.eql(u8, why.text(), "unmatched `{'")) .group else .none; + if (c == null) return if (ps.open_text) .text else .none; + } +} + pub fn needsMore(arena: std.mem.Allocator, command: []const u8) bool { var why: Why = .{}; const src = std.fmt.allocPrint(arena, "{s}\n", .{command}) catch return false; |
