diff options
Diffstat (limited to 'src/fs.zig')
| -rw-r--r-- | src/fs.zig | 51 |
1 files changed, 33 insertions, 18 deletions
@@ -2911,6 +2911,36 @@ fn writeCtl(p: *Pardes, req: Req, serial: u32) Reply { return .{ .tag = req.tag, .written = @intCast(req.data.len) }; } +/// Change a buffer's absolute name without writing or renaming a disk file. +/// Tag editing preserves user commands; the 9P name operation resets its tail. +pub fn nameBuffer(p: *Pardes, id: usize, full: []const u8, preserve_tag: bool) !void { + const pane = p.panes[id] orelse return error.NoPane; + const f = fileOf(pane) orelse return error.NotFile; + if (!std.fs.path.isAbsolute(full) or full.len == 0 or full.len >= 4096) + return error.InvalidName; + for (full) |c| if (c < ' ') return error.InvalidName; + if (std.mem.eql(u8, f.path, full)) return; + const copy = try p.gpa.dupe(u8, full); + p.gpa.free(f.path); + f.path = copy; + if (panes.Output.fileTraits(f.output).saves) { + f.output = null; + pane.clearCwd(); + if (!preserve_tag) { + pane.tag_init = false; + pane.tag_tail_len = 0; + } + f.saved_revision = f.revision -% 1; + f.watch_after_save = localPath(full) != null; + } + if (f.highlights.len > 0) p.tree_sitter_gpa.free(f.highlights); + f.highlights = &.{}; + f.highlight_start = 0; + f.syntax_dirty = true; + p.invalidateLookHover(id); + p.emit(.{ .watch = .{ .pane = @intCast(id), .on = false } }); +} + fn ctlVerb(p: *Pardes, id: usize, line: []const u8, apply: bool, dirty: *bool) u16 { const pane = p.panes[id] orelse return E.INVAL; const pf = &p.fs.panes[id]; @@ -2935,23 +2965,7 @@ fn ctlVerb(p: *Pardes, id: usize, line: []const u8, apply: bool, dirty: *bool) u if (std.mem.eql(u8, f.path, full)) return 0; if (panes.Output.fileTraits(f.output).saves) dirty.* = true; if (!apply) return 0; - const copy = p.gpa.dupe(u8, full) catch return E.NOMEM; - p.gpa.free(f.path); - f.path = copy; - if (panes.Output.fileTraits(f.output).saves) { - f.output = null; - pane.clearCwd(); - pane.tag_init = false; - pane.tag_tail_len = 0; - f.saved_revision = f.revision -% 1; - f.watch_after_save = localPath(full) != null; - } - if (f.highlights.len > 0) p.tree_sitter_gpa.free(f.highlights); - f.highlights = &.{}; - f.highlight_start = 0; - f.syntax_dirty = true; - p.invalidateLookHover(id); - p.emit(.{ .watch = .{ .pane = @intCast(id), .on = false } }); + nameBuffer(p, id, full, false) catch return E.NOMEM; return 0; } for (refused_verbs) |w| if (verbIs(line, w)) return E.INVAL; @@ -3711,7 +3725,8 @@ test "index prints winctlprint's five fields then the tag" { @memcpy(got[0..a.bytes.len], a.bytes); const line = got[0..a.bytes.len]; - const tag = tagOf(p, pane); + const tag = try gpa.dupe(u8, tagOf(p, pane)); + defer gpa.free(tag); var want: std.ArrayList(u8) = .empty; defer want.deinit(gpa); try want.print(gpa, "{d:>11} {d:>11} {d:>11} {d:>11} {d:>11} {s}\n", .{ |
