Add Entity formatting

main
copygirl 2 months ago
parent b20caf4e36
commit 96e511bfc1
  1. 55
      src/entity.zig
  2. 19
      src/path.zig

@ -340,6 +340,35 @@ pub fn Entity(comptime ctx: anytype) type {
const id = Context.anyToId(T);
_ = c.ecs_set_id(self.world.raw, self.raw, id, @sizeOf(@TypeOf(value)), &value);
}
/// The `fmt` parameter can be one of:
/// - `d`, `x` or `X`: Output entity ID as decimal or hexadecimal.
/// - `s`: Output entity name, if any, otherwise falls back to `d`.
/// - `any`: Output full entity path with `Path.FormatOptions.default`.
/// - Other `Path.FormatOptions` are also supported (such as `flecs_c`).
pub fn format(
self: Self,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
if (fmt.len == 1 and (fmt[0] == 'd' or fmt[0] == 'x' or fmt[0] == 'X')) {
try std.fmt.formatIntValue(self.entityId(), fmt, options, writer);
} else if (fmt.len == 1 and fmt[0] == 's') {
if (self.name()) |n|
try writer.writeAll(n)
else
try self.format("d", options, writer);
} else {
const opt = Path.fmtToFormatOptions(fmt);
if (self.parent()) |p| {
try p.format(fmt, .{}, writer);
try writer.writeAll(opt.sep);
} else if (opt.root_sep) |sep|
try writer.writeAll(sep);
try self.format("s", .{}, writer);
}
}
};
}
@ -418,3 +447,29 @@ test "Entity set and get with pair type" {
try expect.equal(.{ .value = 9001 }, entity.get(.{ Rank, Position }));
try expect.equal(.{ .x = 60, .y = 80 }, entity.get(.{ Copy, Position }));
}
test "Entity format" {
flecszigble.init(std.testing.allocator);
var world = try flecszigble.World(void).initMinimal();
defer world.deinit();
const grandparent = try world.entity(.{ .name = "grandparent" }, .{});
const parent = try world.entity(.{ .name = "parent", .parent = grandparent }, .{});
const child = try world.entity(.{ .name = "child", .parent = parent }, .{});
try expect.fmt("410", "{d}", .{grandparent});
try expect.fmt("411", "{d}", .{parent});
try expect.fmt("412", "{d}", .{child});
try expect.fmt("grandparent", "{s}", .{grandparent});
try expect.fmt("parent", "{s}", .{parent});
try expect.fmt("child", "{s}", .{child});
try expect.fmt("grandparent", "{}", .{grandparent});
try expect.fmt("grandparent.parent", "{}", .{parent});
try expect.fmt("grandparent.parent.child", "{}", .{child});
try expect.fmt("/grandparent", "{unix}", .{grandparent});
try expect.fmt("/grandparent/parent", "{unix}", .{parent});
try expect.fmt("/grandparent/parent/child", "{unix}", .{child});
}

@ -250,15 +250,17 @@ pub fn format(
writer: anytype,
) !void {
_ = options; // TODO: Actually make use of this.
const opt = fmtToFormatOptions(fmt);
try self.write(opt, writer);
}
const opt = if (fmt.len == 0)
pub fn fmtToFormatOptions(comptime fmt: []const u8) FormatOptions {
return if (fmt.len == 0)
FormatOptions.default
else if (@hasDecl(FormatOptions, fmt) and @TypeOf(@field(FormatOptions, fmt)) == FormatOptions)
@field(FormatOptions, fmt)
else
std.fmt.invalidFmtError(fmt, self);
try self.write(opt, writer);
@compileError("invalid format string '" ++ fmt ++ "'");
}
/// Returns whether the contents of the specified `Path`s are equivalent.
@ -295,15 +297,16 @@ fn calculateLength(self: Path, opt: FormatOptions) usize {
fn write(self: Path, opt: FormatOptions, writer: anytype) !void {
// Write root separator (if applicable).
if (self.absolute) {
if (opt.root_sep) |p|
try writer.writeAll(p);
}
if (self.absolute)
if (opt.root_sep) |sep|
try writer.writeAll(sep);
// Write the first part.
switch (self.parts[0]) {
.id => |id| try writer.writeInt(u32, id, native_endian),
.name => |name| try writer.writeAll(name),
}
// Write the remaining parts, each preceeded bu separator.
for (self.parts[1..]) |part| {
try writer.writeAll(opt.sep);

Loading…
Cancel
Save