summaryrefslogtreecommitdiff
path: root/src/ninep/ctl.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep/ctl.zig')
-rw-r--r--src/ninep/ctl.zig23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 549aa265..66fa22ab 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -110,6 +110,9 @@ const Messages = struct {
p: *Pardes,
data: []const u8,
at: usize = 0,
+ /// A look's line is its text, leading blanks and all (` return x`,
+ /// a diff's context line ` ` alone): only its `\r` goes.
+ keep_blanks: bool = false,
fn init(p: *Pardes, data: []const u8) Messages {
return .{ .p = p, .data = data };
@@ -120,6 +123,7 @@ const Messages = struct {
const start = m.at;
var end = std.mem.indexOfScalarPos(u8, m.data, start, '\n') orelse m.data.len;
m.at = end + 1;
+ if (m.keep_blanks) return std.mem.trimEnd(u8, m.data[start..end], "\r");
const first = std.mem.trim(u8, m.data[start..end], " \t\r");
const edit = "Edit";
if (!std.mem.startsWith(u8, first, edit) or (first.len > edit.len and first[edit.len] != ' ' and first[edit.len] != '\t'))
@@ -186,6 +190,7 @@ pub fn command(p: *Pardes, req: Req, serial: ?u32, exec: bool, in_tag: bool) Rep
for ([2]bool{ false, true }) |apply| {
if (apply) p.fs.results_len = 0;
var it = Messages.init(p, req.data);
+ it.keep_blanks = !exec;
while (it.next()) |text| {
if (text.len == 0) continue;
// Only an Edit block holds newlines (Messages).
@@ -2540,6 +2545,24 @@ test "a restored pane whose file is gone from disk comes back dirty, and Del ask
try testing.expect(std.mem.indexOf(u8, r.reply.ename, "Modified") != null);
}
+test "a 9P look keeps its leading blanks, a blank-only look included, and exec still trims" {
+ const p = try withFile(testing.allocator, "a indented\nb\n indented\n \n");
+ defer p.deinit();
+ const serial = serialOf(p);
+ const pane = p.panes[p.paneBySerial(serial).?].?;
+ pane_files.setDot(pane, .{ .q0 = 0, .q1 = 0 });
+ // The indented line, not the `indented` after `a `.
+ try testing.expectEqual(Status.ok, wr(p, Node.of(serial, .look), " indented\n").reply.status);
+ try testing.expectEqual(pane_files.State.Range{ .q0 = 13, .q1 = 25 }, pane_files.dotOf(pane));
+ // Blanks alone are text to find too.
+ pane_files.setDot(pane, .{ .q0 = 26, .q1 = 26 });
+ try testing.expectEqual(Status.ok, wr(p, Node.of(serial, .look), " \n").reply.status);
+ try testing.expectEqual(pane_files.State.Range{ .q0 = 26, .q1 = 30 }, pane_files.dotOf(pane));
+ // exec's line is still trimmed: ` Msg hi` runs Msg.
+ try testing.expectEqual(Status.ok, wr(p, Node.of(serial, .exec), " Msg blanks trimmed\n").reply.status);
+ try testing.expect(th.logHas(p, "blanks trimmed"));
+}
+
test "a line starting with # runs as nothing at an exec or a ctl, silently" {
const p = try withFile(testing.allocator, "x\n");
defer p.deinit();