diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.zig | 49 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 23 |
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; |
