summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.zig62
-rw-r--r--src/exec.zig10
-rw-r--r--src/ninep/cols.zig2
-rw-r--r--src/ninep/ctl.zig22
4 files changed, 64 insertions, 32 deletions
diff --git a/src/config.zig b/src/config.zig
index 94b32b88..592281d3 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -1386,35 +1386,36 @@ pub const Runtime = struct {
};
if (context.locations.len > 0) try out.print("LocationsConfig {s}\n", .{context.locations});
- // In effect, and set by no word.
+ // In effect, and set by no word: each a `#` line, which runs as
+ // nothing (exec.executeFrom), so the report can be written back.
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)});
+ 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)});
+ 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)});
+ 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");
+ try out.writeAll("# Tagline size: build-time only\n");
if (context.startup_config_path) |path|
- try out.print("Startup config: {s}\n", .{path})
+ try out.print("# Startup config: {s}\n", .{path})
else
- try out.writeAll("Startup config: no per-user config path\n");
+ try out.writeAll("# Startup config: no per-user config path\n");
try out.print(
- "Platform: {s}\n" ++
- "Default shell ($SHELL, else /bin/sh): {s}\n",
+ "# Platform: {s}\n" ++
+ "# Default shell ($SHELL, else /bin/sh): {s}\n",
.{ context.platform, context.compiled_default_shell },
);
if (context.hover_delay_frames) |frames|
- try out.print("Look hover delay: {d} frames\n", .{frames})
+ try out.print("# Look hover delay: {d} frames\n", .{frames})
else
- try out.writeAll("Look hover delay: off\n");
- try out.print("Native images: {s}\n", .{onOff(context.native_images)});
+ try out.writeAll("# Look hover delay: off\n");
+ try out.print("# Native images: {s}\n", .{onOff(context.native_images)});
if (std.mem.eql(u8, context.platform, "gui"))
- try out.print("Pet: {s}\n", .{@tagName(state.pet)});
+ try out.print("# Pet: {s}\n", .{@tagName(state.pet)});
}
test "setting names are unique" {
@@ -1761,15 +1762,15 @@ pub const Runtime = struct {
"Theme acme\n",
"WindowOpacity 85\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",
+ "# 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",
- "Default shell ($SHELL, else /bin/sh): /bin/sh\n",
- "Look hover delay: 18 frames\n",
- "Native images: on\n",
+ "# Startup config: /tmp/pardes/init\n",
+ "# Platform: gui\n",
+ "# Default shell ($SHELL, else /bin/sh): /bin/sh\n",
+ "# Look hover delay: 18 frames\n",
+ "# Native images: on\n",
}) |expected| try std.testing.expect(std.mem.indexOf(u8, report, expected) != null);
var defaults: Runtime = .{};
@@ -1794,22 +1795,25 @@ pub const Runtime = struct {
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 /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, "# 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 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);
+ 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.
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);
+ // ...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, "# "));
defaults_context.platform = "web";
defaults_context.capabilities.panel_transitions = false;
@@ -1819,7 +1823,7 @@ pub const Runtime = struct {
const web_report = storage[0..out.end];
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);
+ try std.testing.expect(std.mem.indexOf(u8, web_report, "# Tagline size: build-time only\n") != null);
}
};
diff --git a/src/exec.zig b/src/exec.zig
index 6070d038..8356db75 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -643,7 +643,16 @@ pub fn execute(p: *Pardes, id: usize, txt: []const u8) ?usize {
/// `execute` for text a gesture took from `id`'s body when `from_body`:
/// such text may be a bound REPL's. Run by name (`Exec ...`, whose line
/// comes back through `execute`) or written as a command word, never.
+/// A line that starts with `#` is a comment, as in a shell: it runs as
+/// nothing, silently, wherever a line runs (exec, a ctl, the init file),
+/// so DumpConfig's report reads back as configuration whole.
+pub fn isComment(line: []const u8) bool {
+ const t = std.mem.trimStart(u8, line, " \t");
+ return t.len > 0 and t[0] == '#';
+}
+
pub fn executeFrom(p: *Pardes, id: usize, txt: []const u8, from_body: bool) ?usize {
+ if (isComment(commandText(txt))) return null;
// An empty window runs its session words, and a command line in the
// session's directory (execDir), as its workspace tag would.
const pane = p.panes[id] orelse {
@@ -841,6 +850,7 @@ pub const acme_words = [_]struct { acme: []const u8, pardes: ?[]const u8, hint:
pub fn executeBuiltinLine(p: *Pardes, id: usize, txt: []const u8) bool {
const raw = commandText(txt);
if (raw.len == 0 or p.exec_depth >= max_exec_depth) return false;
+ if (isComment(raw)) return true;
const word_end = std.mem.indexOfAny(u8, raw, " \t") orelse raw.len;
var renamed: [1024 + 16]u8 = undefined;
const cmd = for (acme_words) |w| {
diff --git a/src/ninep/cols.zig b/src/ninep/cols.zig
index f07c7f39..24fb590c 100644
--- a/src/ninep/cols.zig
+++ b/src/ninep/cols.zig
@@ -163,7 +163,7 @@ pub fn writeCtl(p: *Pardes, req: Req, serial: u32) Reply {
var lines = std.mem.splitScalar(u8, req.data, '\n');
while (lines.next()) |raw| {
const line = std.mem.trim(u8, raw, " \t\r");
- if (line.len == 0) continue;
+ if (line.len == 0 or pardes.exec.isComment(line)) continue;
const word = line[0 .. std.mem.indexOfAny(u8, line, " \t") orelse line.len];
const takes = for ([_][]const u8{ "Delcol", "Joincol", "New", "Tty" }) |w| {
if (std.mem.eql(u8, w, word)) break true;
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index f4e6bb9c..cf0b241c 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -608,7 +608,7 @@ pub fn writeRoot(p: *Pardes, req: Req) Reply {
if (apply) p.fs.results_len = 0;
var it = Messages.init(p, req.data);
while (it.next()) |line| {
- if (line.len == 0) continue;
+ if (line.len == 0 or exec_line.isComment(line)) continue;
if (std.mem.startsWith(u8, line, "size ") or std.mem.eql(u8, line, "size")) {
const size = sizeOf(line) orelse return refuse(p, req, e_size, line);
// A frontend's window is the size; only a session none is
@@ -834,7 +834,7 @@ pub fn writePane(p: *Pardes, req: Req, pane: *Pane) Reply {
var held = !other and pane.fs.lock != null;
var it = Messages.init(p, req.data);
while (it.next()) |line_in| {
- if (line_in.len == 0) continue;
+ if (line_in.len == 0 or exec_line.isComment(line_in)) continue;
// A line before this one may have closed the pane (`Del`).
if (apply and p.paneBySerial(serial) == null) return Reply.fail(req.tag, E.NOENT);
// acme's ctl words: done by the file that replaces each, or the
@@ -2504,6 +2504,24 @@ test "with no pane at all, the root look opens its file and the root exec runs i
try testing.expectEqualStrings(session, made.cwdSlice());
}
+test "a line starting with # runs as nothing at an exec or a ctl, silently" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ const serial = serialOf(p);
+ // The setup's own announcements are made by the first write's update.
+ _ = wr(p, @intFromEnum(tree.TopFile.ctl), "# settle\n");
+ const before = p.next_serial;
+ const log_before = try pardes.ctlfs.events.freezeLog(p);
+ defer p.gpa.free(log_before.bytes);
+ for ([_]u64{ @intFromEnum(tree.TopFile.exec), Node.of(serial, .exec), @intFromEnum(tree.TopFile.ctl), Node.of(serial, .ctl), Node.ofCol(layout.columnSerial(p, 0), .ctl) }) |node| {
+ try testing.expectEqual(Status.ok, wr(p, node, "# Platform: tty\n # indented too\n").reply.status);
+ }
+ try testing.expectEqual(before, p.next_serial);
+ const log_after = try pardes.ctlfs.events.freezeLog(p);
+ defer p.gpa.free(log_after.bytes);
+ try testing.expectEqualStrings(log_before.bytes, log_after.bytes);
+}
+
test "the ctl word name refuses a leading blank, as the name file does" {
const p = try withFile(testing.allocator, "x\n");
defer p.deinit();