diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fs-help.txt | 6 | ||||
| -rw-r--r-- | src/layout.zig | 13 | ||||
| -rw-r--r-- | src/ninep/cols.zig | 98 | ||||
| -rw-r--r-- | src/ninep/events.zig | 2 | ||||
| -rw-r--r-- | src/ninep/pane.zig | 15 | ||||
| -rw-r--r-- | src/ninep/tree.zig | 49 |
6 files changed, 104 insertions, 79 deletions
diff --git a/src/fs-help.txt b/src/fs-help.txt index 2f944c8e..50dc5d9c 100644 --- a/src/fs-help.txt +++ b/src/fs-help.txt @@ -1,7 +1,7 @@ Pardes control filesystem ========================= README this guide -index one line per pane: serial, kind (text|term|pdf|image), dirty flag, name (+New if unnamed), column +index one line per pane: serial, kind (text|term|pdf|image), dirty flag, name (+New if unnamed), column serial status pid, version and pane count look write a line: a right click on it at the active pane; read: the serials it touched exec write a line: a middle click, an editor command word or a shell line; read the same @@ -11,9 +11,9 @@ listeners the session's dial addresses focus the serial of the pane with the keyboard (empty on a column tag); write a serial to give it the keyboard ctl settings, one a line; or Newcol (an empty column), Dump, Exit (quits, asks once), Kill [w] (stops what pardes ran, w: by first word) commands every builtin: its word, arg if it takes one, and root or pane: which ctl takes it -layout one line per column: index x width current|notcurrent empty|full serials...; then active <index> +layout one line per column: serial index x width current|notcurrent empty|full pane-serials...; then active <serial> tag the workspace tag: read it, > replaces it, >> appends (one line) -col/<n>/tag a column's tag, the same way (columns count from 0, as in layout) +col/<n>/tag the tag of the column with serial n, the same way (a serial stays while the column lives) pane/new open it to make a pane (named +New) in the active column, filling it if empty; the read answers its serial pane/<n>/ name body tag ctl addr dot limit data xdata sel dirty mark scroll errors (write-only: appended to its directory's +Errors pane) event look exec, pty/ on terminals; rmdir closes diff --git a/src/layout.zig b/src/layout.zig index 25c95d30..b9b24e79 100644 --- a/src/layout.zig +++ b/src/layout.zig @@ -322,6 +322,7 @@ pub fn removePane(p: *Pardes, id: usize) void { /// it (the first column's to its right), as acme's rowclose gives it. pub fn dropColumn(p: *Pardes, c: usize) void { std.debug.assert(p.col_n[c] == 0); + const serial = columnSerial(p, c); tagline.exitHeader(p); if (p.ncol > 1) p.col_weight[if (c > 0) c - 1 else c + 1] +|= p.col_weight[c]; p.col_tags[c].deinit(p.gpa); @@ -336,14 +337,14 @@ pub fn dropColumn(p: *Pardes, c: usize) void { p.ncol -= 1; p.col_tags[p.ncol] = .{ .what = .column, .gpa = p.gpa }; p.col_serial[p.ncol] = 0; - noteColumn(p, "delcol", c); + noteColumn(p, "delcol", serial); } -/// `newcol <n>` or `delcol <n>` in the log: the index, as /layout and -/// /col number columns, the ones after it moving up or down one. -fn noteColumn(p: *Pardes, what: []const u8, c: usize) void { +/// `newcol <serial>` or `delcol <serial>` in the log: the column's serial, +/// as /layout and /col name it. +fn noteColumn(p: *Pardes, what: []const u8, serial: u32) void { var buf: [16]u8 = undefined; - pardes.ctlfs.events.notePath(p, what, std.fmt.bufPrint(&buf, "{d}", .{c}) catch return); + pardes.ctlfs.events.notePath(p, what, std.fmt.bufPrint(&buf, "{d}", .{serial}) catch return); } /// Fold column `c` into the one on its right, its panes below theirs. @@ -499,7 +500,7 @@ pub fn insertColumn(p: *Pardes, col: usize, before: bool) ?usize { p.col_serial[c] = 0; p.col_n[c] = 0; p.ncol += 1; - noteColumn(p, "newcol", c); + noteColumn(p, "newcol", columnSerial(p, c)); return c; } diff --git a/src/ninep/cols.zig b/src/ninep/cols.zig index e1688517..682c2a02 100644 --- a/src/ninep/cols.zig +++ b/src/ninep/cols.zig @@ -1,5 +1,6 @@ //! The layout and the header tags: /layout, /tag (the workspace's) and -//! /col/<n>/tag (each column's). acme serves no column files -- its columns +//! /col/<serial>/tag (each column's; a column's serial stays while it lives, +//! as a pane's does). acme serves no column files -- its columns //! are only a window's place -- so these go past it: a script can see where //! the panes are and edit the tags a person clicks in. const std = @import("std"); @@ -22,42 +23,48 @@ pub fn activeColumn(p: *const Pardes) ?usize { return at.col; } -/// One line a column: its index, x and width in cells, `current` or -/// `notcurrent` (rio's words, for the column with the keyboard), `empty` or -/// `full`, and its panes' serials, top to bottom; then `active <index>`. -pub fn writeLayout(p: *const Pardes, w: *std.Io.Writer) !void { +/// One line a column: its serial (the name /col/<serial> and the log give +/// it, which stays while it lives), its index left to right, x and width in +/// cells, `current` or `notcurrent` (rio's words, for the column with the +/// keyboard), `empty` or `full`, and its panes' serials, top to bottom; +/// then `active <serial>`. +pub fn writeLayout(p: *Pardes, w: *std.Io.Writer) !void { const active = activeColumn(p); for (0..p.ncol) |c| { - try w.print("{d} {d} {d} {s} {s}", .{ - c, p.col_x[c], p.col_w[c], + try w.print("{d} {d} {d} {d} {s} {s}", .{ + layout.columnSerial(p, c), c, p.col_x[c], p.col_w[c], if (active == c) "current" else "notcurrent", if (p.col_n[c] == 0) "empty" else "full", }); for (p.col_panes[c][0..p.col_n[c]]) |id| if (p.panes[id]) |pane| try w.print(" {d}", .{pane.serial}); try w.writeByte('\n'); } - if (active) |c| try w.print("active {d}\n", .{c}) else try w.writeAll("active -\n"); + if (active) |c| try w.print("active {d}\n", .{layout.columnSerial(p, c)}) else try w.writeAll("active -\n"); } -pub fn layoutLen(p: *const Pardes) u64 { +pub fn layoutLen(p: *Pardes) u64 { var buf: [256]u8 = undefined; var counting: std.Io.Writer.Discarding = .init(&buf); writeLayout(p, &counting.writer) catch return 0; return counting.fullCount(); } -/// The header a node names: the workspace's (`col` null) or a column's. -fn header(p: *Pardes, col: ?usize) ?*Text { - const c = col orelse return &p.global_tag; - return if (c < p.ncol) &p.col_tags[c] else null; +/// A header by its node: the workspace's (`serial` null) or the column's +/// with that serial; null when that column has closed. +const Header = struct { text: *Text, col: ?usize }; + +fn header(p: *Pardes, serial: ?u32) ?Header { + const s = serial orelse return .{ .text = &p.global_tag, .col = null }; + const c = layout.columnBySerial(p, s) orelse return null; + return .{ .text = &p.col_tags[c], .col = c }; } -pub fn headerText(p: *Pardes, col: ?usize) ?[]const u8 { - const c = col orelse return tagline.topbar(p); - return if (c < p.ncol) tagline.columnTag(p, c) else null; +pub fn headerText(p: *Pardes, serial: ?u32) ?[]const u8 { + const h = header(p, serial) orelse return null; + return if (h.col) |c| tagline.columnTag(p, c) else tagline.topbar(p); } -pub fn read(p: *Pardes, req: Req, col: ?usize) Reply { - const text = headerText(p, col) orelse return Reply.fail(req.tag, E.NOENT); +pub fn read(p: *Pardes, req: Req, serial: ?u32) Reply { + const text = headerText(p, serial) orelse return Reply.fail(req.tag, E.NOENT); const out = p.fs.stage(p.gpa); out.appendSlice(p.gpa, text) catch return Reply.fail(req.tag, E.NOMEM); out.append(p.gpa, '\n') catch return Reply.fail(req.tag, E.NOMEM); @@ -67,12 +74,12 @@ pub fn read(p: *Pardes, req: Req, col: ?usize) Reply { /// A write appends, as a pane tag's does; the tag is one line, so a newline /// in it becomes a space (tagline.flattenHeaders), but after a truncation /// the newline that ends the write is dropped, as a pane tag drops it. -pub fn write(p: *Pardes, req: Req, col: ?usize) Reply { - const t = header(p, col) orelse return Reply.fail(req.tag, E.NOENT); +pub fn write(p: *Pardes, req: Req, serial: ?u32) Reply { + const t = (header(p, serial) orelse return Reply.fail(req.tag, E.NOENT)).text; if (req.data.len == 0) return .{ .tag = req.tag, .written = 0 }; - const was = headerText(p, col).?; + const was = headerText(p, serial).?; var data = req.data; - const rewriting = p.fs.header_rewrite == rewriteKey(col); + const rewriting = p.fs.header_rewrite == rewriteKey(serial); // A newline held from the write before goes in once more text follows. const held: []const u8 = if (rewriting and p.fs.header_held) " " else ""; p.fs.header_held = false; @@ -89,27 +96,27 @@ pub fn write(p: *Pardes, req: Req, col: ?usize) Reply { /// Truncating clears it, as a pane tag's `cleartag`: its default words go /// too, and `u` in it brings them back. -pub fn truncate(p: *Pardes, col: ?usize) tree.Status { - const t = header(p, col) orelse return .err; +pub fn truncate(p: *Pardes, serial: ?u32) tree.Status { + const t = (header(p, serial) orelse return .err).text; const empty = p.gpa.alloc(u8, 0) catch return .err; t.remember(p.gpa, if (t.own) |own| .{ .text = own } else null); if (t.own) |own| p.gpa.free(own); t.own = empty; t.cur_row = 0; t.cur_col = 0; - p.fs.header_rewrite = rewriteKey(col); + p.fs.header_rewrite = rewriteKey(serial); p.fs.header_held = false; return .ok; } -/// Which header a truncation was of: the workspace's is 0, a column's its -/// index + 1. -fn rewriteKey(col: ?usize) u32 { - return if (col) |c| @intCast(c + 1) else 0; +/// Which header a truncation was of: the workspace's is 0 (no column's +/// serial is), a column's its serial. +fn rewriteKey(serial: ?u32) u32 { + return serial orelse 0; } -pub fn released(p: *Pardes, col: ?usize) void { - if (p.fs.header_rewrite != rewriteKey(col)) return; +pub fn released(p: *Pardes, serial: ?u32) void { + if (p.fs.header_rewrite != rewriteKey(serial)) return; p.fs.header_rewrite = null; p.fs.header_held = false; } @@ -125,28 +132,39 @@ test "layout lists each column's place, panes and state, and the active one" { defer p.deinit(); p.newColumn(p.active); p.sync(); + const first_serial = layout.columnSerial(p, 0); + const new_serial = layout.columnSerial(p, 1); + try testing.expect(first_serial != new_serial); const layout_node = @intFromEnum(tree.TopFile.layout); const text = th.rd(p, layout_node, 0, 4096).bytes; var want: [256]u8 = undefined; - const first = try std.fmt.bufPrint(&want, "0 {d} {d} notcurrent full {d}\n", .{ p.col_x[0], p.col_w[0], p.panes[0].?.serial }); + const first = try std.fmt.bufPrint(&want, "{d} 0 {d} {d} notcurrent full {d}\n", .{ first_serial, p.col_x[0], p.col_w[0], p.panes[0].?.serial }); try testing.expect(std.mem.startsWith(u8, text, first)); // Newcol gives the new, empty column's tag the keyboard. try testing.expect(std.mem.indexOf(u8, text, "current empty\n") != null); - try testing.expect(std.mem.endsWith(u8, text, "active 1\n")); + try testing.expect(std.mem.endsWith(u8, text, try std.fmt.bufPrint(&want, "active {d}\n", .{new_serial}))); try testing.expectEqual(@as(u64, text.len), th.call(p, .{ .tag = 1, .op = .getattr, .node = layout_node }).reply.attr.size); - // /index says which column each pane is in, last. - try testing.expect(std.mem.endsWith(u8, th.rd(p, @intFromEnum(tree.TopFile.index), 0, 4096).bytes, " 0\n")); - try testing.expect(th.logHas(p, "newcol 1\n")); + // /index says which column each pane is in, by its serial, last. + try testing.expect(std.mem.endsWith(u8, th.rd(p, @intFromEnum(tree.TopFile.index), 0, 4096).bytes, try std.fmt.bufPrint(&want, " {d}\n", .{first_serial}))); + try testing.expect(th.logHas(p, try std.fmt.bufPrint(&want, "newcol {d}\n", .{new_serial}))); + // A column that closes takes its name with it; the others keep theirs. + try p.removeColumn(1); + try testing.expect(th.logHas(p, try std.fmt.bufPrint(&want, "delcol {d}\n", .{new_serial}))); + try testing.expectEqual(E.NOENT, th.look_up(p, @intFromEnum(tree.TopFile.col), try std.fmt.bufPrint(&want, "{d}", .{new_serial})).errno()); + try testing.expectEqual(first_serial, layout.columnSerial(p, 0)); } test "a column's tag and the workspace's read, replace and append as a pane tag does, on one line" { const p = try th.withFile(testing.allocator, "x\n"); defer p.deinit(); const col_dir = @intFromEnum(tree.TopFile.col); - try testing.expectEqual(tree.Status.ok, th.look_up(p, col_dir, "0").reply.status); - try testing.expectEqual(E.NOENT, th.look_up(p, col_dir, "7").errno()); - const tag = Node.ofCol(0, .tag); - try testing.expectEqual(tree.Status.ok, th.look_up(p, Node.ofCol(0, .dir), "tag").reply.status); + const serial = layout.columnSerial(p, 0); + var name: [16]u8 = undefined; + try testing.expectEqual(tree.Status.ok, th.look_up(p, col_dir, try std.fmt.bufPrint(&name, "{d}", .{serial})).reply.status); + try testing.expectEqual(E.NOENT, th.look_up(p, col_dir, "0").errno()); + try testing.expectEqual(E.NOENT, th.look_up(p, col_dir, "777").errno()); + const tag = Node.ofCol(serial, .tag); + try testing.expectEqual(tree.Status.ok, th.look_up(p, Node.ofCol(serial, .dir), "tag").reply.status); try testing.expectEqualStrings("New Tty Find Grep Joincol Delcol\n", th.rd(p, tag, 0, 4096).bytes); // `echo Make > tag`: cleared, then the newline ending the write dropped. _ = th.call(p, .{ .tag = 1, .op = .setattr, .node = tag, .truncate = true }); diff --git a/src/ninep/events.zig b/src/ninep/events.zig index fc410d5a..e918f09a 100644 --- a/src/ninep/events.zig +++ b/src/ninep/events.zig @@ -174,7 +174,7 @@ pub fn noteError(p: *Pardes, req: Req, reply: Reply) void { .top => |f| file = f.fileName(), .col => |c| { serial = "-"; - file = std.fmt.bufPrint(&name, "col/{d}/tag", .{c.index}) catch "col"; + file = std.fmt.bufPrint(&name, "col/{d}/tag", .{c.serial}) catch "col"; }, .pane => |pt| { serial = std.fmt.bufPrint(&name, "{d}", .{pt.serial}) catch "-"; diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig index 6542d747..c594c7a3 100644 --- a/src/ninep/pane.zig +++ b/src/ninep/pane.zig @@ -265,10 +265,11 @@ pub fn fileSize(p: *Pardes, id: usize, f: PaneFile) u64 { // ---- the index ---- -/// The column a pane is in, as /layout and /col number them; the last word -/// of its /index line. -pub fn columnOf(p: *const Pardes, id: usize) usize { - return if (pardes.layout.findPane(p, id)) |at| at.col else 0; +/// The serial of the column a pane is in, as /layout and /col name it; the +/// last word of its /index line. +pub fn columnOf(p: *Pardes, id: usize) u32 { + const at = pardes.layout.findPane(p, id) orelse return 0; + return pardes.layout.columnSerial(p, at.col); } pub fn indexLen(p: *Pardes) u64 { @@ -710,7 +711,7 @@ test "index lists serial kind dirty flag and name and stat reports its length" { const a = rd(p, index, 0, 4096); try testing.expectEqual(Status.ok, a.reply.status); var want: [64]u8 = undefined; - const clean_row = try std.fmt.bufPrint(&want, "{d} text 0 /test.txt 0\n", .{pane.serial}); + const clean_row = try std.fmt.bufPrint(&want, "{d} text 0 /test.txt {d}\n", .{ pane.serial, columnOf(p, 0) }); try testing.expect(std.mem.indexOf(u8, a.bytes, clean_row) != null); const at = std.mem.indexOf(u8, a.bytes, clean_row).?; const stat = call(p, .{ .tag = 1, .op = .getattr, .node = index }); @@ -719,7 +720,7 @@ test "index lists serial kind dirty flag and name and stat reports its length" { pane.file.?.saved_revision = pane.file.?.revision -% 1; var dirty_want: [64]u8 = undefined; - const dirty_row = try std.fmt.bufPrint(&dirty_want, "{d} text 1 /test.txt 0\n", .{pane.serial}); + const dirty_row = try std.fmt.bufPrint(&dirty_want, "{d} text 1 /test.txt {d}\n", .{ pane.serial, columnOf(p, 0) }); try testing.expect(std.mem.indexOf(u8, rd(p, index, 0, 4096).bytes, dirty_row) != null); const kind = at + std.mem.indexOfScalar(u8, clean_row, ' ').? + 1; try testing.expectEqualStrings("text", rd(p, index, kind, 4).bytes); @@ -741,7 +742,7 @@ test "a terminal is listed as term with its directory as name" { try testing.expect(std.mem.indexOf( u8, rd(p, @intFromEnum(tree.TopFile.index), 0, 4096).bytes, - try std.fmt.bufPrint(&want, "{d} term 0 /work/dir 0\n", .{pane.serial}), + try std.fmt.bufPrint(&want, "{d} term 0 /work/dir {d}\n", .{ pane.serial, columnOf(p, 0) }), ) != null); try testing.expectEqualStrings("/work/dir\n", rd(p, Node.of(pane.serial, .name), 0, 4096).bytes); const refused = wr(p, Node.of(pane.serial, .name), "/elsewhere\n"); diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig index 9459be4f..3be75960 100644 --- a/src/ninep/tree.zig +++ b/src/ninep/tree.zig @@ -19,6 +19,7 @@ pub const pane = @import("pane.zig"); pub const addr = @import("addr.zig"); pub const ctl = @import("ctl.zig"); pub const cols = @import("cols.zig"); +const layout = pardes.layout; pub const pty = @import("pty.zig"); pub const sources = @import("sources.zig"); pub const screen = @import("screen.zig"); @@ -268,8 +269,9 @@ pub const PaneFile = enum(u5) { } }; -/// /col/<n> and its tag: a column is named by its index, which a serial -/// never is (serials are 32 bits; this bit is past them). +/// /col/<serial> and its tag: a column is named by its serial, which stays +/// while it lives as a pane's does; this bit, past a pane serial's 32, keeps +/// the two apart. pub const ColFile = enum(u5) { dir = 0, tag = 1 }; const col_bit: u59 = 1 << 58; @@ -282,8 +284,8 @@ pub const Node = packed struct(u64) { return @bitCast(Node{ .file = @intFromEnum(file), .serial = serial }); } - pub fn ofCol(index: usize, file: ColFile) u64 { - return @bitCast(Node{ .file = @intFromEnum(file), .serial = col_bit | @as(u59, @intCast(index)) }); + pub fn ofCol(serial: u32, file: ColFile) u64 { + return @bitCast(Node{ .file = @intFromEnum(file), .serial = col_bit | @as(u59, serial) }); } pub fn target(node: u64) ?Target { @@ -292,7 +294,7 @@ pub const Node = packed struct(u64) { return .{ .top = std.enums.fromInt(TopFile, n.file) orelse return null }; } if (n.serial & col_bit != 0) return .{ .col = .{ - .index = std.math.cast(u32, n.serial & ~col_bit) orelse return null, + .serial = std.math.cast(u32, n.serial & ~col_bit) orelse return null, .file = std.enums.fromInt(ColFile, n.file) orelse return null, } }; return .{ .pane = .{ @@ -305,7 +307,7 @@ pub const Node = packed struct(u64) { pub const Target = union(enum) { top: TopFile, pane: struct { serial: u32, file: PaneFile }, - col: struct { index: u32, file: ColFile }, + col: struct { serial: u32, file: ColFile }, }; /// Opening /pane/new makes a pane and reading the open fid answers its @@ -450,13 +452,13 @@ fn attrOf(p: *Pardes, target: Target) ?Reply.Attr { .append = f == .tag, }, .col => |c| { - if (c.index >= p.ncol) return null; + if (layout.columnBySerial(p, c.serial) == null) return null; return .{ - .name = if (c.file == .dir) (std.fmt.bufPrint(&p.fs.node_name, "{d}", .{c.index}) catch unreachable) else "tag", - .node = Node.ofCol(c.index, c.file), + .name = if (c.file == .dir) (std.fmt.bufPrint(&p.fs.node_name, "{d}", .{c.serial}) catch unreachable) else "tag", + .node = Node.ofCol(c.serial, c.file), .dir = c.file == .dir, .mode = if (c.file == .dir) 0o755 else 0o666, - .size = if (c.file == .tag) cols.headerText(p, c.index).?.len + 1 else 0, + .size = if (c.file == .tag) cols.headerText(p, c.serial).?.len + 1 else 0, .mtime = p.fs.started, .append = c.file == .tag, }; @@ -548,18 +550,20 @@ fn lookup(p: *Pardes, req: Req, target: Target) Reply { if (serial == 0) return Reply.fail(req.tag, E.NOENT); break :pane Node.of(serial, .dir); }, - // A column is its index, in decimal digits. + // A column is its serial, in decimal digits and never 0. .col => col: { - if (name.len > 4) return Reply.fail(req.tag, E.NOENT); + if (name.len > 10) return Reply.fail(req.tag, E.NOENT); for (name) |c| if (c < '0' or c > '9') return Reply.fail(req.tag, E.NOENT); - break :col Node.ofCol(std.fmt.parseInt(u32, name, 10) catch return Reply.fail(req.tag, E.NOENT), .dir); + const serial = std.fmt.parseInt(u32, name, 10) catch return Reply.fail(req.tag, E.NOENT); + if (serial == 0) return Reply.fail(req.tag, E.NOENT); + break :col Node.ofCol(serial, .dir); }, else => return Reply.fail(req.tag, E.NOTDIR), }, .col => |c| col: { if (c.file != .dir) return Reply.fail(req.tag, E.NOTDIR); if (!std.mem.eql(u8, name, "tag")) return Reply.fail(req.tag, E.NOENT); - break :col Node.ofCol(c.index, .tag); + break :col Node.ofCol(c.serial, .tag); }, .pane => |t| pane: { _ = p.paneBySerial(t.serial) orelse return Reply.fail(req.tag, E.NOENT); @@ -626,14 +630,15 @@ fn readdir(p: *Pardes, req: Req, target: Target) Reply { continue; } var buf: [16]u8 = undefined; - stageDirent(out, p.gpa, Node.ofCol(c, .dir), true, std.fmt.bufPrint(&buf, "{d}", .{c}) catch unreachable); + const serial = layout.columnSerial(p, c); + stageDirent(out, p.gpa, Node.ofCol(serial, .dir), true, std.fmt.bufPrint(&buf, "{d}", .{serial}) catch unreachable); }, else => return Reply.fail(req.tag, E.NOTDIR), }, .col => |c| { - if (c.index >= p.ncol) return Reply.fail(req.tag, E.NOENT); + if (layout.columnBySerial(p, c.serial) == null) return Reply.fail(req.tag, E.NOENT); if (c.file != .dir) return Reply.fail(req.tag, E.NOTDIR); - if (skip > 0) skip -= 1 else stageDirent(out, p.gpa, Node.ofCol(c.index, .tag), false, "tag"); + if (skip > 0) skip -= 1 else stageDirent(out, p.gpa, Node.ofCol(c.serial, .tag), false, "tag"); }, .pane => |t| { const id = p.paneBySerial(t.serial) orelse return Reply.fail(req.tag, E.NOENT); @@ -668,7 +673,7 @@ fn open(p: *Pardes, req: Req, target: Target) Reply { .log => .{ .log = .{} }, else => return .{ .tag = req.tag }, }, - .col => |c| return if (c.index < p.ncol) .{ .tag = req.tag } else Reply.fail(req.tag, E.NOENT), + .col => |c| return if (layout.columnBySerial(p, c.serial) != null) .{ .tag = req.tag } else Reply.fail(req.tag, E.NOENT), .pane => |t| what: { const pn = p.panes[p.paneBySerial(t.serial) orelse return Reply.fail(req.tag, E.NOENT)].?; if (t.file.inPty() and !pn.isTerminal()) return Reply.fail(req.tag, E.NOENT); @@ -749,7 +754,7 @@ fn releaseHandle(p: *Pardes, req: Req) void { p.panes[id].?.fs.tag_rewrite = false; p.panes[id].?.fs.tag_held_newline = false; }; - if (t == .col and t.col.file == .tag) cols.released(p, t.col.index); + if (t == .col and t.col.file == .tag) cols.released(p, t.col.serial); if (t == .top and t.top == .tag) cols.released(p, null); const o = openOf(p, req) orelse return; const of: ?*Pane = if (t == .pane) (if (p.paneBySerial(t.pane.serial)) |id| p.panes[id] else null) else null; @@ -786,7 +791,7 @@ fn setattr(p: *Pardes, req: Req, target: Target) Reply { return failText(req.tag, E.INVAL, pane.e_addr_failed); if (pane.truncate(p, p.panes[id].?, t.file) != .ok) return Reply.fail(req.tag, E.NOMEM); }, - .col => |c| if (c.file == .tag and cols.truncate(p, c.index) != .ok) return Reply.fail(req.tag, E.NOENT), + .col => |c| if (c.file == .tag and cols.truncate(p, c.serial) != .ok) return Reply.fail(req.tag, E.NOENT), .top => |f| if (f == .tag and cols.truncate(p, null) != .ok) return Reply.fail(req.tag, E.NOMEM), }; return .{ .tag = req.tag, .attr = attrOf(p, target) orelse return Reply.fail(req.tag, E.NOENT) }; @@ -877,7 +882,7 @@ fn readFile(p: *Pardes, req: Req, target: Target) Reply { if (t.file.inPty() and !pn.isTerminal()) return Reply.fail(req.tag, E.NOENT); return pane.read(p, req, id, pn, t.file); }, - .col => |c| return if (c.file == .tag) cols.read(p, req, c.index) else Reply.fail(req.tag, E.PERM), + .col => |c| return if (c.file == .tag) cols.read(p, req, c.serial) else Reply.fail(req.tag, E.PERM), } } @@ -897,7 +902,7 @@ fn write(p: *Pardes, req: Req, target: Target) Reply { if (t.file.inPty() and !pn.isTerminal()) return Reply.fail(req.tag, E.NOENT); return pane.write(p, req, id, pn, t.file); }, - .col => |c| return if (c.file == .tag) cols.write(p, req, c.index) else Reply.fail(req.tag, E.PERM), + .col => |c| return if (c.file == .tag) cols.write(p, req, c.serial) else Reply.fail(req.tag, E.PERM), } } |
