summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/config.md2
-rw-r--r--src/config.zig49
-rw-r--r--src/ninep/ctl.zig23
3 files changed, 55 insertions, 19 deletions
diff --git a/docs/config.md b/docs/config.md
index 1967a158..23355b06 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -36,7 +36,7 @@ it is open. With no file there yet, the pane is named for it, empty, and
Save writes it, making its directory first. `DumpConfig` opens a
`+DumpConfig` pane with every live setting, each line the word that sets
it and its value (`Shell /bin/bash`, `PanelSlide off`, `LocationsConfig …`)
-and `unsupported` for one the frontend cannot show. After a blank line
+and a `# Lift unsupported` comment for one the frontend cannot show. After a blank line
come what is in effect but set by no word, such as the last shell spawned
and the font in use, and the startup path (a right click opens it), each a
`#` line. A line starting with `#` is a comment wherever a line runs (the
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;