summaryrefslogtreecommitdiff
path: root/src/ninep/pane.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep/pane.zig')
-rw-r--r--src/ninep/pane.zig67
1 files changed, 19 insertions, 48 deletions
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index 64355e0e..1e549107 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -83,12 +83,6 @@ pub fn tagOf(p: *Pardes, pane: *Pane) []const u8 {
return tagline.tagText(p, p.scratch.allocator(), pane) catch "";
}
-pub fn dirOf(pane: *Pane) []const u8 {
- if (pane.file) |*f| return std.fs.path.dirname(f.path) orelse "/";
- const cwd = pane.cwdSlice();
- return if (cwd.len > 0) cwd else "/";
-}
-
pub fn dirtyOf(pane: *const Pane) bool {
const f = if (pane.file) |*x| x else return false;
if (!panes.Output.fileTraits(f.output).saves) return false;
@@ -111,24 +105,15 @@ pub fn kindOf(pane: *const Pane) []const u8 {
return "term";
}
-pub fn mtimeOf(p: *Pardes, pane: *const Pane) u32 {
- if (pane.file) |*f| if (f.mtime != 0) return f.mtime;
- return p.fs.started;
-}
-
pub fn clip(n: usize) u32 {
return std.math.cast(u32, n) orelse std.math.maxInt(u32);
}
-fn cellOf(row: i32, col: i32) modal.Cursor {
- return .{ .row = @intCast(@max(0, row)), .col = @intCast(@max(0, col)) };
-}
-
pub fn dotOf(pane: *Pane) State.Range {
const text = bodyOf(pane);
- const head = modal.offsetAt(text, cellOf(pane.body.cur_row, pane.body.cur_col));
+ const head = modal.offsetAt(text, .{ .row = @intCast(@max(0, pane.body.cur_row)), .col = @intCast(@max(0, pane.body.cur_col)) });
if (!pane.body.vsel.active) return .{ .q0 = clip(head), .q1 = clip(head) };
- const anchor = modal.offsetAt(text, cellOf(pane.body.vsel.row, pane.body.vsel.col));
+ const anchor = modal.offsetAt(text, .{ .row = @intCast(@max(0, pane.body.vsel.row)), .col = @intCast(@max(0, pane.body.vsel.col)) });
var hi = @max(head, anchor);
if (hi < text.len) hi = modal.nextGrapheme(text, hi);
return .{ .q0 = clip(@min(head, anchor)), .q1 = clip(hi) };
@@ -169,10 +154,6 @@ pub fn clampAddr(pf: *State, len: usize) void {
}
}
-fn shiftBy(r: State.Range, at: u32, removed: u32, inserted: u32) State.Range {
- return .{ .q0 = shiftOne(r.q0, at, removed, inserted), .q1 = shiftOne(r.q1, at, removed, inserted) };
-}
-
fn shiftOne(v: u32, at: u32, removed: u32, inserted: u32) u32 {
if (v <= at) return v;
if (v <= at +| removed) return at +| inserted;
@@ -234,30 +215,21 @@ pub fn fileSize(p: *Pardes, id: usize, f: PaneFile) u64 {
.limit => if (pf.limit == null) 0 else range_len,
.dirty, .mark, .scroll => 2,
.look, .exec => ctl.resultsLen(p),
- .event => events.pending(&pf.events),
+ // What the next read would answer, which a client can see without
+ // parking on it.
+ .event => if (pf.events.peek()) |record| record.len else 0,
.pty_status => pty.status_len,
- .pty_ctl => pty.ctlLen(pane),
- .pty_data => events.pending(&pf.pty_out),
+ .pty_ctl => pty_ctl: {
+ var buf: [32]u8 = undefined;
+ break :pty_ctl (std.fmt.bufPrint(&buf, "winsize {d} {d}\n", .{ pane.cols, pane.rows }) catch unreachable).len;
+ },
+ .pty_data => if (pf.pty_out.peek()) |chunk| chunk.len else 0,
.dir, .errors, .pty, .pty_run => 0,
};
}
-/// The qid version, which a client polls to watch a file for change. Only
-/// the pane's text can promise one: its revision counts every edit, and
-/// nothing else here changes in step with it.
-pub fn versionOf(pane: *const Pane, f: PaneFile) u32 {
- return switch (f) {
- .body, .data, .xdata => if (pane.file) |*file| file.revision else 0,
- else => 0,
- };
-}
-
// ---- the index ----
-pub fn stageIndexLine(p: *Pardes, out: *std.ArrayList(u8), pane: *Pane) void {
- out.print(p.gpa, "{d} {s} {d} {s}\n", .{ pane.serial, kindOf(pane), @intFromBool(dirtyOf(pane)), nameOf(pane) }) catch {};
-}
-
pub fn indexLen(p: *Pardes) u64 {
var n: u64 = 0;
var last: u32 = 0;
@@ -440,7 +412,10 @@ fn writeData(p: *Pardes, req: Req, pane: *Pane) Reply {
const before = dotOf(pane);
const take = spliceBody(p, pane, q0, q1, req.data) orelse
return Reply.fail(req.tag, E.NOMEM);
- setDot(pane, shiftBy(before, clip(q0), clip(q1 - q0), clip(take)));
+ setDot(pane, .{
+ .q0 = shiftOne(before.q0, clip(q0), clip(q1 - q0), clip(take)),
+ .q1 = shiftOne(before.q1, clip(q0), clip(q1 - q0), clip(take)),
+ });
pf.addr = .{ .q0 = clip(q0 + take), .q1 = clip(q0 + take) };
if (!pf.noscroll) showOffset(pane, q0 + take);
return .{ .tag = req.tag, .written = @intCast(take) };
@@ -497,15 +472,10 @@ fn writeRange(req: Req, pane: *Pane, file: PaneFile) Reply {
return .{ .tag = req.tag, .written = @intCast(req.data.len) };
}
-fn flagOf(data: []const u8) ?bool {
- const word = std.mem.trim(u8, data, " \t\r\n");
- if (std.mem.eql(u8, word, "1")) return true;
- if (std.mem.eql(u8, word, "0")) return false;
- return null;
-}
-
fn writeFlag(p: *Pardes, req: Req, pane: *Pane, file: PaneFile) Reply {
- const on = flagOf(req.data) orelse return Reply.fail(req.tag, E.INVAL);
+ const word = std.mem.trim(u8, req.data, " \t\r\n");
+ if (!std.mem.eql(u8, word, "1") and !std.mem.eql(u8, word, "0")) return Reply.fail(req.tag, E.INVAL);
+ const on = word[0] == '1';
const pf = &pane.fs;
switch (file) {
.dirty => {
@@ -577,7 +547,8 @@ pub fn nameBuffer(p: *Pardes, id: usize, full: []const u8, preserve_tag: bool) !
pub fn appendErrors(p: *Pardes, id: usize, text: []const u8) ?usize {
if (text.len == 0) return 0;
const pane = p.panes[id] orelse return null;
- const dir = dirOf(pane);
+ const cwd = pane.cwdSlice();
+ const dir = if (pane.file) |*f| std.fs.path.dirname(f.path) orelse "/" else if (cwd.len > 0) cwd else "/";
for (p.panes) |slot| {
const q = slot orelse continue;
const qf = fileOf(q) orelse continue;