summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.zig49
-rw-r--r--src/ninep/ctl.zig23
2 files changed, 54 insertions, 18 deletions
diff --git a/src/config.zig b/src/config.zig
index a17e2fd2..6bb4d6e4 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -1307,8 +1307,8 @@ pub const Runtime = struct {
}
/// Each setting line reads as the command that would set it: the word,
- /// then the value you would type after it (`unsupported` where this
- /// shell has no such setting). No colons, no units: `WindowOpacity 70`
+ /// then the value you would type after it (a `# Word unsupported`
+ /// comment where this shell has no such setting). No colons, no units: `WindowOpacity 70`
/// is both what DumpConfig prints and what you write back. What is in
/// effect but set by no word follows, after a blank line.
pub fn writeReport(out: *std.Io.Writer, context: ReportContext) !void {
@@ -1316,7 +1316,7 @@ pub const Runtime = struct {
for (settings) |setting| switch (setting.action) {
.toggle => |field| {
if (!setting.enabled(context.capabilities)) {
- try out.print("{s} unsupported\n", .{setting.word});
+ try out.print("# {s} unsupported\n", .{setting.word});
continue;
}
const value = switch (field) {
@@ -1332,17 +1332,17 @@ pub const Runtime = struct {
if (setting.enabled(context.capabilities))
try out.print("{s} {d}\n", .{ setting.word, state.window_opacity })
else
- try out.print("{s} unsupported\n", .{setting.word});
+ try out.print("# {s} unsupported\n", .{setting.word});
},
.window_blur => {
if (setting.enabled(context.capabilities))
try out.print("{s} {d}\n", .{ setting.word, state.window_blur })
else
- try out.print("{s} unsupported\n", .{setting.word});
+ try out.print("# {s} unsupported\n", .{setting.word});
},
.dump_dir => {
const dir = if (state.dump_dir.len > 0) state.dump_dir.get() else context.default_dump_dir;
- try out.print("{s} {s}\n", .{ setting.word, if (dir.len > 0) dir else "(none)" });
+ if (dir.len > 0) try out.print("{s} {s}\n", .{ setting.word, dir }) else try out.print("# {s} (none)\n", .{setting.word});
},
.message_ms => |which| try out.print("{s} {d}\n", .{ setting.word, switch (which) {
inline else => |w| @field(state, "message_" ++ @tagName(w) ++ "_ms"),
@@ -1352,28 +1352,34 @@ pub const Runtime = struct {
try out.print("{s} {s}\n", .{ setting.word, if (chosen.len == 0) context.compiled_default_shell else chosen });
},
.font => if (!setting.enabled(context.capabilities))
- try out.print("{s} unsupported\n", .{setting.word})
+ try out.print("# {s} unsupported\n", .{setting.word})
else {
// As `Font` takes it, `name:size`: the one asked for, else
// the one in use.
const f = &state.font;
const name = if (f.requested_path.get().len > 0) f.requested_path.get() else if (f.requested_name.get().len > 0) f.requested_name.get() else f.effective_name.get();
+ // None known yet (no font loaded): a comment, as `Font`
+ // alone is no line a ctl takes.
+ if (name.len == 0) {
+ try out.print("# {s} (none yet)\n", .{setting.word});
+ continue;
+ }
try out.print("{s} {s}", .{ setting.word, name });
if (f.requested_size_hundredths != 0) try out.print(":{d}.{d:0>2}", .{ f.requested_size_hundredths / 100, f.requested_size_hundredths % 100 });
try out.writeByte('\n');
},
.tagline_size => if (!context.capabilities.tagline_font_size)
- try out.print("{s} unsupported\n", .{setting.word})
+ try out.print("# {s} unsupported\n", .{setting.word})
else
try out.print("{s} {d}\n", .{ setting.word, state.font.tagline_percent }),
// Each a switch of its own, the one in use on.
.transition => |transition| if (!setting.enabled(context.capabilities))
- try out.print("{s} unsupported\n", .{setting.word})
+ try out.print("# {s} unsupported\n", .{setting.word})
else
try out.print("{s} {s}\n", .{ setting.word, onOff(state.panel_transition == transition) }),
.scene => |effect| {
if (!setting.enabled(context.capabilities)) {
- try out.print("{s} unsupported\n", .{setting.word});
+ try out.print("# {s} unsupported\n", .{setting.word});
continue;
}
const level = state.post.level(effect);
@@ -1381,7 +1387,7 @@ pub const Runtime = struct {
},
.shader => {
if (!setting.enabled(context.capabilities)) {
- try out.print("{s} unsupported\n", .{setting.word});
+ try out.print("# {s} unsupported\n", .{setting.word});
continue;
}
var files: usize = 0;
@@ -1394,17 +1400,20 @@ pub const Runtime = struct {
.shader_animation => if (setting.enabled(context.capabilities))
try out.print("{s} {s}\n", .{ setting.word, @tagName(state.shader_animation) })
else
- try out.print("{s} unsupported\n", .{setting.word}),
+ try out.print("# {s} unsupported\n", .{setting.word}),
.choice => |which| switch (which) {
inline else => |field| try out.print("{s} {s}\n", .{ setting.word, @tagName(@field(state, @tagName(field))) }),
},
.lift => if (setting.enabled(context.capabilities))
try out.print("{s} {s}\n", .{ setting.word, @tagName(state.lift) })
else
- try out.print("{s} unsupported\n", .{setting.word}),
+ try out.print("# {s} unsupported\n", .{setting.word}),
.motion => try out.print("{s} {s}\n", .{ setting.word, @tagName(state.motion) }),
.inactive_dim => try out.print("{s} {d}\n", .{ setting.word, state.inactive_dim }),
- .grip_width => try out.print("{s} {d}\n", .{ setting.word, state.grip_width }),
+ .grip_width => if (setting.enabled(context.capabilities))
+ try out.print("{s} {d}\n", .{ setting.word, state.grip_width })
+ else
+ try out.print("# {s} unsupported\n", .{setting.word}),
};
if (context.locations.len > 0) try out.print("LocationsConfig {s}\n", .{context.locations});
@@ -1827,12 +1836,16 @@ pub const Runtime = struct {
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "TaglineSize unsupported\n") != null);
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "# Look hover delay: off\n") != null);
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "# Native images: off\n") != null);
- // A setting this shell does not have reads so, as a line to write.
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Ligatures unsupported\n") != null);
- // Every line before the blank one is a ctl word and its value.
+ // A setting this shell does not have reads so, as a comment.
+ try std.testing.expect(std.mem.indexOf(u8, defaults_report, "# Ligatures unsupported\n") != null);
+ // Every line before the blank one is a ctl word and its value, or a
+ // comment naming one.
const words = defaults_report[0..std.mem.indexOf(u8, defaults_report, "\n\n").?];
var lines = std.mem.splitScalar(u8, words, '\n');
- while (lines.next()) |line| try std.testing.expect(find(line[0..std.mem.indexOfScalar(u8, line, ' ').?]) != null);
+ while (lines.next()) |line| {
+ const word = if (std.mem.startsWith(u8, line, "# ")) line[2..] else line;
+ try std.testing.expect(find(word[0..std.mem.indexOfScalar(u8, word, ' ').?]) != null);
+ }
// ...and every one after it a `#` line, which runs as nothing.
var info = std.mem.splitScalar(u8, std.mem.trimEnd(u8, defaults_report[words.len + 2 ..], "\n"), '\n');
while (info.next()) |line| try std.testing.expect(std.mem.startsWith(u8, line, "# "));
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 2cd865de..eff8003b 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -1836,6 +1836,29 @@ test "an error's words give the errno a mount reads: EINVAL for what is malforme
}
}
+test "DumpConfig's whole report writes back to the root ctl, line by line, with no error" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ const root_ctl = @intFromEnum(tree.TopFile.ctl);
+ try testing.expectEqual(Status.ok, wr(p, root_ctl, "DumpConfig\n").reply.status);
+ const report = for (p.panes) |slot| {
+ const pane = slot orelse continue;
+ const f = pane.file orelse continue;
+ const o = f.output orelse continue;
+ if (std.meta.eql(o.from, panes.Output.Origin{ .cmd = .DumpConfig })) break try testing.allocator.dupe(u8, f.content);
+ } else return error.NoDumpConfigPane;
+ defer testing.allocator.free(report);
+ // What this shell cannot show is a comment, never a value it refuses.
+ if (pardes.platform == .tty) try testing.expect(std.mem.indexOf(u8, report, "# GripWidth unsupported\n") != null);
+ var lines = std.mem.splitScalar(u8, report, '\n');
+ while (lines.next()) |line| {
+ if (line.len == 0) continue;
+ const r = wr(p, root_ctl, line);
+ if (r.reply.status != .ok) std.debug.print("refused: {s}: {s}\n", .{ line, r.reply.ename });
+ try testing.expectEqual(Status.ok, r.reply.status);
+ }
+}
+
test "after a ThemeFile the root ctl and DumpConfig say ThemeFile and its path, which writes back" {
if (comptime !pardes.hosted) return;
const gpa = testing.allocator;