summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/config.md7
-rw-r--r--src/Output.zig4
-rw-r--r--src/builtins.zig3
-rw-r--r--src/config.zig165
-rw-r--r--test/appearance_gallery.py2
-rw-r--r--test/font_size.py6
-rw-r--r--test/output.zig26
7 files changed, 97 insertions, 116 deletions
diff --git a/docs/config.md b/docs/config.md
index bc4acf12..35f0b6e7 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -34,8 +34,11 @@ not stop later ones. Text that is no builtin is not run as a shell command
`Config` (`SPC f c`) opens `init` itself in a pane, or goes to its pane when
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 the startup path (a right click opens it) and every
-live setting; a setting the frontend cannot show reads `unsupported`. The
+`+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
+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). The
root `ctl` file reads the settings back in the words a write takes
([fs.md](fs.md#the-root-ctl)).
diff --git a/src/Output.zig b/src/Output.zig
index 0581be41..65f6bfe4 100644
--- a/src/Output.zig
+++ b/src/Output.zig
@@ -815,7 +815,11 @@ pub fn openConfig(p: *Pardes, id: usize) !void {
errdefer out.deinit();
var dir_buf: [1024]u8 = undefined;
const host_fs = comptime (pardes.platform != .web and pardes.platform != .esp32p4);
+ var located: std.Io.Writer.Allocating = .init(p.gpa);
+ defer located.deinit();
+ try p.locations_config.write(&located.writer);
try config.Runtime.writeReport(&out.writer, .{
+ .locations = located.written(),
.default_dump_dir = if (host_fs) (pardes.dump.defaultDirectory(&dir_buf) orelse "") else "",
.startup_config_path = p.opts.startup_config_path,
.platform = @tagName(pardes.platform),
diff --git a/src/builtins.zig b/src/builtins.zig
index c40b2e00..8fe49649 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -458,7 +458,8 @@ test "Ligatures is a setting only in the shell that shapes text" {
.state = &p.settings,
});
try std.testing.expectEqual(exists, std.mem.indexOf(u8, storage[0..out.end], "Ligatures off\n") != null);
- try std.testing.expectEqual(exists, std.mem.indexOf(u8, storage[0..out.end], "Ligatures") != null);
+ // A GUI-only setting reads so elsewhere, as every one the shell lacks.
+ try std.testing.expectEqual(!exists, std.mem.indexOf(u8, storage[0..out.end], "Ligatures unsupported\n") != null);
}
comptime {
diff --git a/src/config.zig b/src/config.zig
index a70ae708..94b32b88 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -1275,6 +1275,8 @@ pub const Runtime = struct {
native_images: bool,
capabilities: Capabilities,
state: *const Runtime,
+ /// The `LocationsConfig` argument in effect, as it would be typed.
+ locations: []const u8 = "",
};
fn onOff(value: bool) []const u8 {
@@ -1285,23 +1287,19 @@ pub const Runtime = struct {
return if (text.len == 0) "(none)" else text;
}
- fn transitionSettingName(transition: animation.Transition) []const u8 {
- if (transition == .off) return "off";
- return findAction(.{ .transition = transition }).?.word;
- }
-
- /// Each line reads as the command that would set it: the word, then the
- /// value you would type after it. No colons, no units — `WindowOpacity 70`
- /// is both what DumpConfig prints and what you write back.
+ /// 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`
+ /// 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 {
const state = context.state;
- var wrote_transition = false;
for (settings) |setting| switch (setting.action) {
.toggle => |field| {
- // A toggle for what this shell does not draw (Ligatures in a
- // terminal, whose text its emulator draws) is no setting here:
- // it is not a builtin, so the report does not list it either.
- if (!setting.enabled(context.capabilities)) continue;
+ if (!setting.enabled(context.capabilities)) {
+ try out.print("{s} unsupported\n", .{setting.word});
+ continue;
+ }
const value = switch (field) {
inline else => |f| @field(state, @tagName(f)),
};
@@ -1310,11 +1308,7 @@ pub const Runtime = struct {
.theme => try out.print("{s} {s}\n", .{ setting.word, context.theme_name }),
.window_opacity => {
if (setting.enabled(context.capabilities))
- try out.print("{s} {d}{s}\n", .{
- setting.word,
- state.window_opacity,
- if (state.window_opacity_pending) " (pending)" else "",
- })
+ try out.print("{s} {d}\n", .{ setting.word, state.window_opacity })
else
try out.print("{s} unsupported\n", .{setting.word});
},
@@ -1333,64 +1327,28 @@ pub const Runtime = struct {
} }),
.shell => {
const chosen = state.shell.requested.get();
- try out.print(
- "{s} requested (new panes) {s}{s}\n" ++
- "{s} effective (last spawn) {s}\n" ++
- "{s} pending {s}\n",
- .{
- setting.word,
- if (chosen.len == 0) context.compiled_default_shell else chosen,
- if (chosen.len == 0) " (default)" else "",
- setting.word,
- shown(state.shell.effective.get()),
- setting.word,
- onOff(state.shell.pending),
- },
- );
+ 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})
else {
- if (state.font.requested_size_hundredths == 0)
- try out.print("{s} requested size unchanged\n", .{setting.word})
- else
- try out.print("{s} requested size {d}.{d:0>2}\n", .{ setting.word, state.font.requested_size_hundredths / 100, state.font.requested_size_hundredths % 100 });
- try out.print(
- "{s} requested {s}\n" ++
- "{s} requested path {s}\n" ++
- "{s} effective {s}\n" ++
- "{s} pending {s}\n" ++
- "{s} effective size {d}.{d:0>2} {s}\n",
- .{
- setting.word,
- shown(state.font.requested_name.get()),
- setting.word,
- shown(state.font.requested_path.get()),
- setting.word,
- shown(state.font.effective_name.get()),
- setting.word,
- onOff(state.font.pending),
- setting.word,
- state.font.effective_size_hundredths / 100,
- state.font.effective_size_hundredths % 100,
- @tagName(state.font.effective_size_unit),
- },
- );
+ // 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();
+ 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})
- else if (!setting.enabled(context.capabilities))
- try out.print("{s} {d} (build-time only)\n", .{ setting.word, state.font.tagline_percent })
else
try out.print("{s} {d}\n", .{ setting.word, state.font.tagline_percent }),
- .transition => {
- if (wrote_transition) continue;
- wrote_transition = true;
- if (!setting.enabled(context.capabilities))
- try out.writeAll("Panel transition unsupported\n")
- else
- try out.print("Panel transition {s}\n", .{transitionSettingName(state.panel_transition)});
- },
+ // 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})
+ 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});
@@ -1426,7 +1384,21 @@ pub const Runtime = struct {
.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 }),
};
+ if (context.locations.len > 0) try out.print("LocationsConfig {s}\n", .{context.locations});
+ // In effect, and set by no word.
+ try out.writeByte('\n');
+ try out.print("Last shell spawned: {s}\n", .{shown(state.shell.effective.get())});
+ try out.print("Shell change pending: {s}\n", .{onOff(state.shell.pending)});
+ if (find("Font").?.enabled(context.capabilities)) {
+ const f = &state.font;
+ try out.print("Font in use: {s} {d}.{d:0>2} {s}\n", .{ shown(f.effective_name.get()), f.effective_size_hundredths / 100, f.effective_size_hundredths % 100, @tagName(f.effective_size_unit) });
+ try out.print("Font change pending: {s}\n", .{onOff(f.pending)});
+ }
+ if (find("WindowOpacity").?.enabled(context.capabilities))
+ try out.print("Window opacity change pending: {s}\n", .{onOff(state.window_opacity_pending)});
+ if (context.capabilities.tagline_font_size and !find("TaglineSize").?.enabled(context.capabilities))
+ try out.writeAll("Tagline size: build-time only\n");
if (context.startup_config_path) |path|
try out.print("Startup config: {s}\n", .{path})
else
@@ -1726,9 +1698,9 @@ pub const Runtime = struct {
.chip_shadow => "ChipShadow on\n",
.thumb_flash => "ThumbFlash on\n",
},
- .shell => "Shell requested (new panes) fish\n",
+ .shell => "Shell fish\n",
.tagline_size => "TaglineSize 73\n",
- .window_opacity => "WindowOpacity 85 (pending)\n",
+ .window_opacity => "WindowOpacity 85\n",
.window_blur => "WindowBlur 40\n",
.dump_dir => "DumpDir ~/dumps\n",
.message_ms => |which| switch (which) {
@@ -1738,17 +1710,17 @@ pub const Runtime = struct {
},
.transition => |transition| switch (transition) {
.off => unreachable,
- .slide => "Panel transition PanelSlide\n",
- .zoom => "Panel transition PanelZoom\n",
- .dissolve => "Panel transition PanelDissolve\n",
- .ascii => "Panel transition PanelAscii\n",
- .vertical => "Panel transition PanelVertical\n",
- .edges => "Panel transition PanelEdges\n",
- .fall => "Panel transition PanelFall\n",
- .wave => "Panel transition PanelWave\n",
- .curtain => "Panel transition PanelCurtain\n",
- .scramble => "Panel transition PanelScramble\n",
- .typewriter => "Panel transition PanelType\n",
+ .slide => "PanelSlide on\n",
+ .zoom => "PanelZoom on\n",
+ .dissolve => "PanelDissolve on\n",
+ .ascii => "PanelAscii on\n",
+ .vertical => "PanelVertical on\n",
+ .edges => "PanelEdges on\n",
+ .fall => "PanelFall on\n",
+ .wave => "PanelWave on\n",
+ .curtain => "PanelCurtain on\n",
+ .scramble => "PanelScramble on\n",
+ .typewriter => "PanelType on\n",
},
.scene => |effect| switch (effect) {
.crt => "Crt 2\n",
@@ -1788,12 +1760,10 @@ pub const Runtime = struct {
for ([_][]const u8{
"Theme acme\n",
"WindowOpacity 85\n",
- "Font requested size 18.50\n",
- "Font requested Wanted Mono\n",
- "Font requested path /fonts/wanted.ttf\n",
- "Font effective Effective Mono\n",
- "Font pending on\n",
- "Font effective size 13.75 points\n",
+ "Font /fonts/wanted.ttf:18.50\n",
+ "Font in use: Effective Mono 13.75 points\n",
+ "Font change pending: on\n",
+ "Window opacity change pending: off\n",
"TaglineSize 82\n",
"Startup config: /tmp/pardes/init\n",
"Platform: gui\n",
@@ -1823,19 +1793,23 @@ pub const Runtime = struct {
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "WindowBlur unsupported\n") != null);
try std.testing.expect(!find("WindowBlur").?.enabled(defaults_context.capabilities));
try std.testing.expect(find("WindowOpacity").?.enabled(context.capabilities));
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell requested (new panes) /bin/sh (default)\n") != null);
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell effective (last spawn) (none)\n") != null);
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell pending on\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell /bin/sh\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Last shell spawned: (none)\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell change pending: on\n") != null);
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Startup config: no per-user config path\n") != null);
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Font unsupported\n") != null);
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Font requested") == null);
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Panel transition off\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Font in use") == null);
+ try std.testing.expect(std.mem.indexOf(u8, defaults_report, "PanelSlide off\n") != null);
try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Crt unsupported\n") != null);
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 shell that does not shape text has no Ligatures setting to report.
- try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Ligatures") == 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.
+ 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);
defaults_context.platform = "web";
defaults_context.capabilities.panel_transitions = false;
@@ -1843,8 +1817,9 @@ pub const Runtime = struct {
out = .fixed(&storage);
try writeReport(&out, defaults_context);
const web_report = storage[0..out.end];
- try std.testing.expect(std.mem.indexOf(u8, web_report, "Panel transition unsupported\n") != null);
- try std.testing.expect(std.mem.indexOf(u8, web_report, "TaglineSize 100 (build-time only)\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, web_report, "PanelSlide unsupported\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, web_report, "TaglineSize 100\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, web_report, "Tagline size: build-time only\n") != null);
}
};
diff --git a/test/appearance_gallery.py b/test/appearance_gallery.py
index c321c7c0..98420a15 100644
--- a/test/appearance_gallery.py
+++ b/test/appearance_gallery.py
@@ -98,7 +98,7 @@ def run(args):
return text
settings = config_report()
- require('Font effective size 18.00 pixels' in settings, 'configured font size not applied: ' + settings)
+ require(' 18.00 pixels\n' in settings, 'configured font size not applied: ' + settings)
require('TaglineSize 80' in settings, 'configured tag size missing')
(root / 'effective-config.txt').write_text(settings)
report['font_effective_pixels'] = 18
diff --git a/test/font_size.py b/test/font_size.py
index ef685a9e..878d6472 100644
--- a/test/font_size.py
+++ b/test/font_size.py
@@ -30,16 +30,16 @@ def run(args):
for serial, tag in panes(client).items():
if '/+DumpConfig ' in tag:
body = client.read(f'/pane/{serial}/body').decode()
- if f'Font effective size {size:.2f} pixels' in body:
+ if f' {size:.2f} pixels\n' in body and 'Font in use: ' in body:
return body
return None
return require(wait_for(ready), f'Font did not become {size} pixels')
initial = report(18)
- require('Font requested size 18.00' in initial, 'startup size suffix ignored')
+ require(':18.00\n' in initial, 'startup size suffix ignored')
require(args.font in initial, 'requested font missing')
execute(client, control, f'Font {args.font}:20.5')
- require('Font requested size 20.50' in report(20.5), 'fractional size ignored')
+ require(':20.50\n' in report(20.5), 'fractional size ignored')
execute(client, control, f'Font {args.font}')
report(20.5) # no suffix preserves current size
execute(client, control, f'Font {args.font}:900')
diff --git a/test/output.zig b/test/output.zig
index c67c021e..51d620c0 100644
--- a/test/output.zig
+++ b/test/output.zig
@@ -544,11 +544,12 @@ test "DumpConfig prints the startup path and refreshes its one output" {
for ([_][]const u8{
"Startup config: " ++ path ++ "\n",
"Theme orchard\n",
- "Shell effective (last spawn) (none)\n",
- "Shell pending on\n",
+ "Last shell spawned: (none)\n",
+ "Shell change pending: on\n",
+ "LocationsConfig ",
}) |line| try std.testing.expect(std.mem.indexOf(u8, out.content, line) != null);
var default_line: [256]u8 = undefined;
- try std.testing.expect(std.mem.indexOf(u8, out.content, try std.fmt.bufPrint(&default_line, "Shell requested (new panes) {s} (default)\n", .{config.defaultShell()})) != null);
+ try std.testing.expect(std.mem.indexOf(u8, out.content, try std.fmt.bufPrint(&default_line, "Shell {s}\n", .{config.defaultShell()})) != null);
try std.testing.expectEqualStrings(config.dump_config_buffer, std.fs.path.basename(out.path));
try std.testing.expectEqual(panes.Output.Origin{ .cmd = .DumpConfig }, out.output.?.from);
@@ -734,14 +735,14 @@ test "every enabled setting builtin mutates the State Config reports" {
"Tagbottom on\n",
"Debug on\n",
"Theme acme\n",
- "Shell requested (new panes) fish\n",
+ "Shell fish\n",
}) |line| try std.testing.expect(std.mem.indexOf(u8, report, line) != null);
- const transition = if (builtins.capabilities.panel_transitions)
- try std.fmt.bufPrint(&buf, "Panel transition {s}\n", .{
- config.Runtime.findAction(.{ .transition = p.settings.panel_transition }).?.word,
- })
+ const transition = if (!builtins.capabilities.panel_transitions)
+ "PanelSlide unsupported\n"
+ else if (p.settings.panel_transition == .off)
+ "PanelSlide off\n"
else
- "Panel transition unsupported\n";
+ try std.fmt.bufPrint(&buf, "{s} on\n", .{config.Runtime.findAction(.{ .transition = p.settings.panel_transition }).?.word});
try std.testing.expect(std.mem.indexOf(u8, report, transition) != null);
// A bare word turns a bundled pass on at its default level.
const scene_status = if (builtins.capabilities.scene_shaders) "2" else "unsupported";
@@ -752,14 +753,11 @@ test "every enabled setting builtin mutates the State Config reports" {
const tagline = if (!builtins.capabilities.tagline_font_size)
"TaglineSize unsupported\n"
else
- try std.fmt.bufPrint(&buf, "TaglineSize {d}{s}\n", .{
- p.settings.font.tagline_percent,
- if (builtins.capabilities.font_picker) "" else " (build-time only)",
- });
+ try std.fmt.bufPrint(&buf, "TaglineSize {d}\n", .{p.settings.font.tagline_percent});
try std.testing.expect(std.mem.indexOf(u8, report, tagline) != null);
if (chosen_font) |name| {
try std.testing.expect(std.mem.indexOf(u8, report, name) != null);
- try std.testing.expect(std.mem.indexOf(u8, report, "Font pending on\n") != null);
+ try std.testing.expect(std.mem.indexOf(u8, report, "Font change pending: on\n") != null);
}
}