From 5200b48ee76a3b0173d2647fd99bec2297decd92 Mon Sep 17 00:00:00 2001 From: bgk- Date: Sun, 19 May 2024 06:43:39 -0700 Subject: [PATCH] Update cli --- build.zig.zon | 2 +- docs/cli.md | 15 ++++++++++----- docs/syntax.md | 14 ++++++++++++++ src/class.zig | 2 +- src/cli.zig | 37 ++++++++++++++++++++++++++----------- src/vm.zig | 14 ++++++++------ 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index ab760ad..e24cf78 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = "topiary", - .version = "0.12.1", + .version = "0.12.2", .paths = .{""}, .dependencies = .{}, } diff --git a/docs/cli.md b/docs/cli.md index bac58e1..b74ef75 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -9,16 +9,21 @@ To run the CLI: ```shell topi - command line topiary processor Usage: - topi [-v | --version] [-h | --help] [flags] + topi [flags] Commands: - topi run [start_bough] [--verbose] - topi auto [--verbose] - topi compile [--verbose] + topi version + topi run [start_bough] [--auto|-a] [--lang language_key] [--verbose] + topi test [--verbose] + topi compile [--loc] [--verbose] + topi loc validate [--verbose] + topi loc export [--verbose] Flags: - --version, -v: Output current version --verbose: Output debug logs + --auto, -a: Automatically continue to next line + --lang: Localization language key + --loc: Include localization in compiled bytecode --dry, -d: Compile only ``` diff --git a/docs/syntax.md b/docs/syntax.md index 960cad2..f6a8e2f 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -549,6 +549,20 @@ john.increaseAge(2) print(john.age) // 27 ``` +Fields can also be indexed as well with `[]` notation. +This can be especially useful for extern function calls. +As an example with the above class: + +```topi +const changeField = |instance, fieldName, newValue| { + instance[fieldName] = newValue +} + +changeField(john, "firstName", "Johnny") +changeField(john, "age", 28) +print(john.fullName()) // "Johnny Doe" +``` + ## Multiple Files Multiple files can be joined together to create a single story using `include "[PATH]"`. diff --git a/src/class.zig b/src/class.zig index d0421ae..a2fc504 100644 --- a/src/class.zig +++ b/src/class.zig @@ -26,7 +26,7 @@ pub const Class = struct { pub fn getIndex(self: *const Class, field_name: []const u8) ?usize { var i: usize = 0; while (i < self.fields.len) : (i += 1) { - if (!std.mem.eql(u8, self.fields[i].name, field_name)) continue; + if (!std.mem.eql(u8, self.fields[i].name, std.mem.trim(u8, field_name, &[_]u8{0}))) continue; return i; } return null; diff --git a/src/cli.zig b/src/cli.zig index 08efb6b..7a7b99f 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -26,14 +26,17 @@ fn usage(comptime msg: []const u8) !void { try out.print("\n", .{}); try out.print("Commands:\n", .{}); try out.print(" topi version\n", .{}); - try out.print(" topi run [start_bough] [--loc language_key] [--verbose]\n", .{}); - try out.print(" topi auto [--verbose]\n", .{}); - try out.print(" topi compile [--loc | --verbose]\n", .{}); + try out.print(" topi run [start_bough] [--auto|-a] [--lang language_key] [--verbose]\n", .{}); + try out.print(" topi test [--verbose]\n", .{}); + try out.print(" topi compile [--loc] [--verbose]\n", .{}); try out.print(" topi loc validate [--verbose]\n", .{}); try out.print(" topi loc export [--verbose]\n", .{}); try out.print("\n", .{}); try out.print("Flags:\n", .{}); try out.print(" --verbose: Output debug logs\n", .{}); + try out.print(" --auto, -a: Automatically continue to next line\n", .{}); + try out.print(" --lang: Localization language key\n", .{}); + try out.print(" --loc: Include localization in compiled bytecode\n", .{}); try out.print(" --dry, -d: Dry-run only\n", .{}); } @@ -72,10 +75,10 @@ pub fn main() !void { } const is_run = std.mem.eql(u8, cmd, "run"); - const is_auto = std.mem.eql(u8, cmd, "auto"); + const is_test = std.mem.eql(u8, cmd, "auto"); const is_compile = std.mem.eql(u8, cmd, "compile"); const is_loc = std.mem.eql(u8, cmd, "loc"); - if (!is_run and !is_auto and !is_compile and !is_loc) return usage("Unknown command"); + if (!is_run and !is_test and !is_compile and !is_loc) return usage("Unknown command"); var bough_path: ?[]const u8 = null; var out_path: ?[]const u8 = null; @@ -83,6 +86,7 @@ pub fn main() !void { var is_dry = false; var is_export = false; var is_validate = false; + var is_auto = false; if (is_loc) { const maybe_sub = args.next(); @@ -111,7 +115,11 @@ pub fn main() !void { if (is_run) { while (args.next()) |arg| { if (std.mem.eql(u8, arg, "--verbose")) continue; - if (std.mem.eql(u8, arg, "--loc")) { + if (std.mem.eql(u8, arg, "--auto") or std.mem.eql(u8, arg, "-a")) { + is_auto = true; + continue; + } + if (std.mem.eql(u8, arg, "--lang")) { loc_key = args.next(); continue; } @@ -193,7 +201,7 @@ pub fn main() !void { } const vm_alloc = arena.allocator(); - if (is_auto) { + if (is_test) { const maybe_count = args.next(); if (maybe_count == null) return usage("Auto requires a play count."); auto_count = std.fmt.parseInt(u64, maybe_count.?, 10) catch { @@ -228,7 +236,7 @@ pub fn main() !void { } if (is_run) { - var cli_runner = CliRunner.init(); + var cli_runner = CliRunner.init(is_auto); var vm = Vm.init(vm_alloc, bytecode, &cli_runner.runner) catch |err| { try std.io.getStdErr().writeAll("Could not initialize Vm"); return checkVerbose(err); @@ -254,9 +262,11 @@ fn getFilePath(allocator: std.mem.Allocator) !?[]const u8 { const CliRunner = struct { runner: Runner, + is_auto: bool, - pub fn init() CliRunner { + pub fn init(is_auto: bool) CliRunner { return .{ + .is_auto = is_auto, .runner = .{ .onLineFn = onLine, .onChoicesFn = onChoices, @@ -280,9 +290,14 @@ const CliRunner = struct { } self.print(": ", .{}); self.print("{s}", .{dialogue.content}); - var buf: [2]u8 = undefined; - if (stdin.readUntilDelimiterOrEof(&buf, '\n') catch &buf) |_| { + if (self.is_auto) { + self.print("\n", .{}); vm.selectContinue(); + } else { + var buf: [2]u8 = undefined; + if (stdin.readUntilDelimiterOrEof(&buf, '\n') catch &buf) |_| { + vm.selectContinue(); + } } } diff --git a/src/vm.zig b/src/vm.zig index 553a9e6..fb4471e 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -505,10 +505,12 @@ pub const Vm = struct { const field_name = field_value.obj.data.string; if (inst.base.data.class.getIndex(field_name)) |idx| { inst.fields[idx] = new_value; - } else return self.fail("Instance of {s} does not contain {s}", .{ inst.base.data.class.name, field_name }); + } else { + return self.fail("Instance of {s} does not contain field '{s}'", .{ inst.base.data.class.name, field_name }); + } }, // todo add string indexing - else => return self.fail("Cannot index {s} into type {s}", .{ @tagName(field_value), @tagName(instance_value.obj.data) }), + else => return self.fail("Cannot index '{s}' into type {s}", .{ @tagName(field_value), @tagName(instance_value.obj.data) }), } }, .get_builtin => { @@ -566,11 +568,11 @@ pub const Vm = struct { switch (o.data) { // remove final 0 .string => try writer.writeAll(o.data.string[0..(o.data.string.len - 1)]), - else => return self.fail("Unsupported interpolated type {s} for {s}", .{ val.typeName(), str }), + else => return self.fail("Unsupported interpolated type '{s}' for '{s}'", .{ val.typeName(), str }), } }, .visit => |v| try std.fmt.formatIntValue(v, "", .{}, list.writer()), - else => return self.fail("Unsupported interpolated type {s} for {s}", .{ val.typeName(), str }), + else => return self.fail("Unsupported interpolated type '{s}' for '{s}'", .{ val.typeName(), str }), } s = i; } @@ -773,9 +775,9 @@ pub const Vm = struct { }, .instance => |i| { if (index != .obj) - return self.fail("Can only query instance fields by string name, not {s}", .{@tagName(index)}); + return self.fail("Can only query instance fields by string name, not '{s}'", .{@tagName(index)}); if (index.obj.data != .string) - return self.fail("Can only query instance fields by string name, not {s}", .{@tagName(index.obj.data)}); + return self.fail("Can only query instance fields by string name, not '{s}'", .{@tagName(index.obj.data)}); if (i.base.data.class.getIndex(index.obj.data.string)) |idx| { const field = i.fields[idx]; try self.push(field);