mirror of
https://github.com/zoriya/zig-wayland.git
synced 2025-12-05 22:56:13 +00:00
scanner: refactor to use new std.fmt features
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
zig-cache
|
||||
zig-out
|
||||
|
||||
286
src/scanner.zig
286
src/scanner.zig
@@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const fmtId = std.zig.fmtId;
|
||||
|
||||
const xml = @import("xml.zig");
|
||||
|
||||
@@ -298,24 +299,21 @@ const Interface = struct {
|
||||
}
|
||||
|
||||
fn emit(interface: Interface, side: Side, namespace: []const u8, writer: anytype) !void {
|
||||
var buf: [1024]u8 = undefined;
|
||||
var fbs = std.io.fixedBufferStream(&buf);
|
||||
try printIdentifier(fbs.writer(), case(.title, trimPrefix(interface.name)));
|
||||
const title_case = fbs.getWritten();
|
||||
try printIdentifier(fbs.writer(), trimPrefix(interface.name));
|
||||
const snake_case = fbs.getWritten()[title_case.len..];
|
||||
|
||||
try writer.print(
|
||||
\\pub const {s} = opaque {{
|
||||
\\ pub const getInterface = common.{s}.{s}.getInterface;
|
||||
, .{ title_case, namespace, snake_case });
|
||||
\\pub const {[type]} = opaque {{
|
||||
\\ pub const getInterface = common.{[namespace]}.{[interface]}.getInterface;
|
||||
, .{
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
.namespace = fmtId(namespace),
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
});
|
||||
|
||||
for (interface.enums.items) |e| {
|
||||
try writer.writeAll("pub const ");
|
||||
try printIdentifier(writer, case(.title, e.name));
|
||||
try writer.print(" = common.{s}.{s}.", .{ namespace, snake_case });
|
||||
try printIdentifier(writer, case(.title, e.name));
|
||||
try writer.writeAll(";\n");
|
||||
try writer.print("pub const {[type]} = common.{[namespace]}.{[interface]}.{[type]};\n", .{
|
||||
.@"type" = titleCase(e.name),
|
||||
.namespace = fmtId(namespace),
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
});
|
||||
}
|
||||
|
||||
if (side == .client) {
|
||||
@@ -325,16 +323,19 @@ const Interface = struct {
|
||||
try writer.writeAll("};\n");
|
||||
try writer.print(
|
||||
\\pub fn setListener(
|
||||
\\ _{s}: *{s},
|
||||
\\ _{[interface]}: *{[type]},
|
||||
\\ comptime T: type,
|
||||
\\ _listener: fn ({s}: *{s}, event: Event, data: T) void,
|
||||
\\ _listener: fn ({[interface]}: *{[type]}, event: Event, data: T) void,
|
||||
\\ _data: T,
|
||||
\\) callconv(.Inline) void {{
|
||||
\\ const _proxy = @ptrCast(*client.wl.Proxy, _{s});
|
||||
\\ const _proxy = @ptrCast(*client.wl.Proxy, _{[interface]});
|
||||
\\ const _mut_data = @intToPtr(?*c_void, @ptrToInt(_data));
|
||||
\\ _proxy.addDispatcher(common.Dispatcher({s}, T).dispatcher, _listener, _mut_data);
|
||||
\\ _proxy.addDispatcher(common.Dispatcher({[type]}, T).dispatcher, _listener, _mut_data);
|
||||
\\}}
|
||||
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case });
|
||||
, .{
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
});
|
||||
}
|
||||
|
||||
for (interface.requests.items) |request, opcode|
|
||||
@@ -344,22 +345,17 @@ const Interface = struct {
|
||||
try writer.writeAll(@embedFile("client_display_functions.zig"));
|
||||
} else {
|
||||
try writer.print(
|
||||
\\pub fn create(_client: *server.wl.Client, _version: u32, _id: u32) !*{s} {{
|
||||
\\ return @ptrCast(*{s}, try server.wl.Resource.create(_client, {s}, _version, _id));
|
||||
\\pub fn create(_client: *server.wl.Client, _version: u32, _id: u32) !*{(tc)} {{
|
||||
\\ return @ptrCast(*{[type]}, try server.wl.Resource.create(_client, {[type]}, _version, _id));
|
||||
\\}}pub fn destroy(_{[interface]}: *{[type]}) void {{
|
||||
\\ return @ptrCast(*server.wl.Resource, _{[interface]}).destroy();
|
||||
\\}}pub fn fromLink(_link: *server.wl.list.Link) *{[type]} {{
|
||||
\\ return @ptrCast(*{[type]}, server.wl.Resource.fromLink(_link));
|
||||
\\}}
|
||||
, .{ title_case, title_case, title_case });
|
||||
|
||||
try writer.print(
|
||||
\\pub fn destroy(_{s}: *{s}) void {{
|
||||
\\ return @ptrCast(*server.wl.Resource, _{s}).destroy();
|
||||
\\}}
|
||||
, .{ snake_case, title_case, snake_case });
|
||||
|
||||
try writer.print(
|
||||
\\pub fn fromLink(_link: *server.wl.list.Link) *{s} {{
|
||||
\\ return @ptrCast(*{s}, server.wl.Resource.fromLink(_link));
|
||||
\\}}
|
||||
, .{ title_case, title_case });
|
||||
, .{
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
});
|
||||
|
||||
for ([_][2][]const u8{
|
||||
.{ "getLink", "*server.wl.list.Link" },
|
||||
@@ -369,20 +365,28 @@ const Interface = struct {
|
||||
.{ "postNoMemory", "void" },
|
||||
}) |func|
|
||||
try writer.print(
|
||||
\\pub fn {s}(_{s}: *{s}) {s} {{
|
||||
\\ return @ptrCast(*server.wl.Resource, _{s}).{s}();
|
||||
\\pub fn {[function]}(_{[interface]}: *{[type]}) {[return_type]} {{
|
||||
\\ return @ptrCast(*server.wl.Resource, _{[interface]}).{[function]}();
|
||||
\\}}
|
||||
, .{ func[0], snake_case, title_case, func[1], snake_case, func[0] });
|
||||
, .{
|
||||
.function = camelCase(func[0]),
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
.return_type = camelCase(func[1]),
|
||||
});
|
||||
|
||||
const has_error = for (interface.enums.items) |e| {
|
||||
if (mem.eql(u8, e.name, "error")) break true;
|
||||
} else false;
|
||||
if (has_error) {
|
||||
try writer.print(
|
||||
\\pub fn postError({s}: *{s}, _err: Error, _message: [*:0]const u8) void {{
|
||||
\\ return @ptrCast(*server.wl.Resource, {s}).postError(@intCast(u32, @enumToInt(_err)), _message);
|
||||
\\pub fn postError({[interface]}: *{[type]}, _err: Error, _message: [*:0]const u8) void {{
|
||||
\\ return @ptrCast(*server.wl.Resource, {[interface]}).postError(@intCast(u32, @enumToInt(_err)), _message);
|
||||
\\}}
|
||||
, .{ snake_case, title_case, snake_case });
|
||||
, .{
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
});
|
||||
}
|
||||
|
||||
if (interface.requests.items.len > 0) {
|
||||
@@ -392,37 +396,40 @@ const Interface = struct {
|
||||
@setEvalBranchQuota(2500);
|
||||
try writer.print(
|
||||
\\pub fn setHandler(
|
||||
\\ _{s}: *{s},
|
||||
\\ _{[interface]}: *{[type]},
|
||||
\\ comptime T: type,
|
||||
\\ handle_request: fn ({s}: *{s}, request: Request, data: T) void,
|
||||
\\ comptime handle_destroy: ?fn ({s}: *{s}, data: T) void,
|
||||
\\ handle_request: fn ({[interface]}: *{[type]}, request: Request, data: T) void,
|
||||
\\ comptime handle_destroy: ?fn ({[interface]}: *{[type]}, data: T) void,
|
||||
\\ _data: T,
|
||||
\\) callconv(.Inline) void {{
|
||||
\\ const _resource = @ptrCast(*server.wl.Resource, _{s});
|
||||
\\ const _resource = @ptrCast(*server.wl.Resource, _{[interface]});
|
||||
\\ _resource.setDispatcher(
|
||||
\\ common.Dispatcher({s}, T).dispatcher,
|
||||
\\ common.Dispatcher({[type]}, T).dispatcher,
|
||||
\\ handle_request,
|
||||
\\ @intToPtr(?*c_void, @ptrToInt(_data)),
|
||||
\\ if (handle_destroy) |_handler| struct {{
|
||||
\\ fn _wrapper(__resource: *server.wl.Resource) callconv(.C) void {{
|
||||
\\ @call(.{{ .modifier = .always_inline }}, _handler, .{{
|
||||
\\ @ptrCast(*{s}, __resource),
|
||||
\\ @ptrCast(*{[type]}, __resource),
|
||||
\\ @intToPtr(T, @ptrToInt(__resource.getUserData())),
|
||||
\\ }});
|
||||
\\ }}
|
||||
\\ }}._wrapper else null,
|
||||
\\ );
|
||||
\\}}
|
||||
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case, snake_case, title_case, title_case });
|
||||
, .{
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
});
|
||||
} else {
|
||||
try writer.print(
|
||||
\\pub fn setHandler(
|
||||
\\ _{s}: *{s},
|
||||
\\ _{[interface]}: *{[type]},
|
||||
\\ comptime T: type,
|
||||
\\ comptime handle_destroy: ?fn ({s}: *{s}, data: T) void,
|
||||
\\ comptime handle_destroy: ?fn ({[interface]}: *{[type]}, data: T) void,
|
||||
\\ _data: T,
|
||||
\\) callconv(.Inline) void {{
|
||||
\\ const _resource = @ptrCast(*server.wl.Resource, {s});
|
||||
\\ const _resource = @ptrCast(*server.wl.Resource, {[interface]});
|
||||
\\ _resource.setDispatcher(
|
||||
\\ null,
|
||||
\\ null,
|
||||
@@ -430,14 +437,17 @@ const Interface = struct {
|
||||
\\ if (handle_destroy) |_handler| struct {{
|
||||
\\ fn _wrapper(__resource: *server.wl.Resource) callconv(.C) void {{
|
||||
\\ @call(.{{ .modifier = .always_inline }}, _handler, .{{
|
||||
\\ @ptrCast(*{s}, __resource),
|
||||
\\ @ptrCast(*{[type]}, __resource),
|
||||
\\ @intToPtr(T, @ptrToInt(__resource.getUserData())),
|
||||
\\ }});
|
||||
\\ }}
|
||||
\\ }}._wrapper else null,
|
||||
\\ );
|
||||
\\}}
|
||||
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case });
|
||||
, .{
|
||||
.interface = fmtId(trimPrefix(interface.name)),
|
||||
.@"type" = titleCaseTrim(interface.name),
|
||||
});
|
||||
}
|
||||
|
||||
for (interface.events.items) |event, opcode|
|
||||
@@ -448,8 +458,7 @@ const Interface = struct {
|
||||
}
|
||||
|
||||
fn emitCommon(interface: Interface, writer: anytype) !void {
|
||||
try writer.writeAll("pub const ");
|
||||
try printIdentifier(writer, trimPrefix(interface.name));
|
||||
try writer.print("pub const {}", .{fmtId(trimPrefix(interface.name))});
|
||||
|
||||
// TODO: stop linking libwayland generated interface structs when
|
||||
// https://github.com/ziglang/zig/issues/131 is implemented
|
||||
@@ -484,11 +493,11 @@ const Interface = struct {
|
||||
|
||||
try writer.print(
|
||||
\\ = struct {{
|
||||
\\ extern const {s}_interface: common.Interface;
|
||||
\\ extern const {[interface]s}_interface: common.Interface;
|
||||
\\ pub fn getInterface() callconv(.Inline) *const common.Interface {{
|
||||
\\ return &{s}_interface;
|
||||
\\ return &{[interface]s}_interface;
|
||||
\\ }}
|
||||
, .{ interface.name, interface.name });
|
||||
, .{ .interface = interface.name });
|
||||
|
||||
for (interface.enums.items) |e| try e.emit(writer);
|
||||
try writer.writeAll("};");
|
||||
@@ -574,7 +583,7 @@ const Message = struct {
|
||||
//}
|
||||
|
||||
fn emitField(message: Message, side: Side, writer: anytype) !void {
|
||||
try printIdentifier(writer, message.name);
|
||||
try writer.print("{s}", .{fmtId(message.name)});
|
||||
if (message.args.items.len == 0) {
|
||||
try writer.writeAll(": void,");
|
||||
return;
|
||||
@@ -582,17 +591,13 @@ const Message = struct {
|
||||
try writer.writeAll(": struct {");
|
||||
for (message.args.items) |arg| {
|
||||
if (side == .server and arg.kind == .new_id and arg.kind.new_id == null) {
|
||||
try writer.writeAll("interface_name: [*:0]const u8, version: u32,");
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.writeAll(": u32");
|
||||
try writer.print("interface_name: [*:0]const u8, version: u32,{}: u32", .{fmtId(arg.name)});
|
||||
} else if (side == .client and arg.kind == .new_id) {
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.writeAll(": *");
|
||||
try writer.print("{}: *", .{fmtId(arg.name)});
|
||||
try printAbsolute(.client, writer, arg.kind.new_id.?);
|
||||
std.debug.assert(!arg.allow_null);
|
||||
} else {
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.writeByte(':');
|
||||
try writer.print("{}:", .{fmtId(arg.name)});
|
||||
// See notes on NULL in doc comment for wl_message in wayland-util.h
|
||||
if (side == .client and arg.kind == .object and !arg.allow_null)
|
||||
try writer.writeByte('?');
|
||||
@@ -606,41 +611,34 @@ const Message = struct {
|
||||
fn emitFn(message: Message, side: Side, writer: anytype, interface: Interface, opcode: usize) !void {
|
||||
try writer.writeAll("pub fn ");
|
||||
if (side == .server) {
|
||||
try writer.writeAll("send");
|
||||
try printIdentifier(writer, case(.title, message.name));
|
||||
try writer.print("send{}", .{titleCase(message.name)});
|
||||
} else {
|
||||
try printIdentifier(writer, case(.camel, message.name));
|
||||
try writer.print("{}", .{camelCase(message.name)});
|
||||
}
|
||||
try writer.writeAll("(_");
|
||||
try printIdentifier(writer, trimPrefix(interface.name));
|
||||
try writer.writeAll(": *");
|
||||
try printIdentifier(writer, case(.title, trimPrefix(interface.name)));
|
||||
try writer.print("(_{}: *{}", .{
|
||||
fmtId(trimPrefix(interface.name)),
|
||||
titleCaseTrim(interface.name),
|
||||
});
|
||||
for (message.args.items) |arg| {
|
||||
if (side == .server and arg.kind == .new_id) {
|
||||
try writer.writeAll(", _");
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.writeByte(':');
|
||||
try writer.print(", _{s}:", .{arg.name});
|
||||
if (arg.allow_null) try writer.writeByte('?');
|
||||
try writer.writeByte('*');
|
||||
if (arg.kind.new_id) |iface|
|
||||
try printIdentifier(writer, case(.title, trimPrefix(iface)))
|
||||
try writer.print("{}", .{titleCaseTrim(iface)})
|
||||
else
|
||||
try writer.writeAll("server.wl.Resource");
|
||||
} else if (side == .client and arg.kind == .new_id) {
|
||||
if (arg.kind.new_id == null) try writer.writeAll(", comptime T: type, _version: u32");
|
||||
} else {
|
||||
try writer.writeAll(", _");
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.writeByte(':');
|
||||
try writer.print(", _{s}:", .{arg.name});
|
||||
try arg.emitType(side, writer);
|
||||
}
|
||||
}
|
||||
if (side == .server or message.kind != .constructor) {
|
||||
try writer.writeAll(") void {");
|
||||
} else if (message.kind.constructor) |new_iface| {
|
||||
try writer.writeAll(") !*");
|
||||
try printIdentifier(writer, case(.title, trimPrefix(new_iface)));
|
||||
try writer.writeAll("{");
|
||||
try writer.print(") !*{}{{", .{titleCaseTrim(new_iface)});
|
||||
} else {
|
||||
try writer.writeAll(") !*T {");
|
||||
}
|
||||
@@ -648,8 +646,7 @@ const Message = struct {
|
||||
try writer.writeAll("const _resource = @ptrCast(*server.wl.Resource,_")
|
||||
else
|
||||
try writer.writeAll("const _proxy = @ptrCast(*client.wl.Proxy,_");
|
||||
try printIdentifier(writer, trimPrefix(interface.name));
|
||||
try writer.writeAll(");");
|
||||
try writer.print("{});", .{fmtId(trimPrefix(interface.name))});
|
||||
if (message.args.items.len > 0) {
|
||||
try writer.writeAll("var _args = [_]common.Argument{");
|
||||
for (message.args.items) |arg| {
|
||||
@@ -667,14 +664,13 @@ const Message = struct {
|
||||
const c_type = if (arg.kind == .uint) "u32" else "i32";
|
||||
try writer.print(
|
||||
\\ )) {{
|
||||
\\ .Enum => @intCast({s}, @enumToInt(_{s})),
|
||||
\\ .Struct => @bitCast(u32, _{s}),
|
||||
\\ .Enum => @intCast({[ct]s}, @enumToInt(_{[an]})),
|
||||
\\ .Struct => @bitCast(u32, _{[an]}),
|
||||
\\ else => unreachable,
|
||||
\\ }}
|
||||
, .{ c_type, arg.name, arg.name });
|
||||
, .{ .ct = c_type, .an = fmtId(arg.name) });
|
||||
} else {
|
||||
try writer.writeByte('_');
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.print("_{s}", .{arg.name});
|
||||
}
|
||||
try writer.writeAll("},");
|
||||
},
|
||||
@@ -685,8 +681,7 @@ const Message = struct {
|
||||
} else {
|
||||
try writer.writeAll(".{ .o = @ptrCast(*common.Object, _");
|
||||
}
|
||||
try printIdentifier(writer, arg.name);
|
||||
try writer.writeAll(") },");
|
||||
try writer.print("{s}) }},", .{arg.name});
|
||||
} else {
|
||||
if (new_iface == null) {
|
||||
try writer.writeAll(
|
||||
@@ -711,11 +706,10 @@ const Message = struct {
|
||||
},
|
||||
.constructor => |new_iface| {
|
||||
if (new_iface) |i| {
|
||||
try writer.writeAll("return @ptrCast(*");
|
||||
try printIdentifier(writer, case(.title, trimPrefix(i)));
|
||||
try writer.print(", try _proxy.marshalConstructor({}, &_args, ", .{opcode});
|
||||
try printIdentifier(writer, case(.title, trimPrefix(i)));
|
||||
try writer.writeAll(".getInterface()));");
|
||||
try writer.print("return @ptrCast(*{[type]}, try _proxy.marshalConstructor({[opcode]}, &_args, {[type]}.getInterface()));", .{
|
||||
.@"type" = titleCaseTrim(i),
|
||||
.opcode = opcode,
|
||||
});
|
||||
} else {
|
||||
try writer.print("return @ptrCast(*T, try _proxy.marshalConstructorVersioned({}, &_args, T.getInterface(), _version));", .{opcode});
|
||||
}
|
||||
@@ -813,14 +807,14 @@ const Arg = struct {
|
||||
if (arg.enum_name) |name| {
|
||||
if (mem.indexOfScalar(u8, name, '.')) |dot_index| {
|
||||
// Turn a reference like wl_shm.format into common.wl.shm.Format
|
||||
try writer.writeAll("common.");
|
||||
const us_index = mem.indexOfScalar(u8, name, '_') orelse 0;
|
||||
try writer.writeAll(name[0..us_index]);
|
||||
try writer.writeAll(".");
|
||||
try writer.writeAll(name[us_index + 1 .. dot_index + 1]);
|
||||
try writer.writeAll(case(.title, name[dot_index + 1 ..]));
|
||||
try writer.print("common.{s}.{s}{}", .{
|
||||
name[0..us_index],
|
||||
name[us_index + 1 .. dot_index + 1],
|
||||
titleCase(name[dot_index + 1 ..]),
|
||||
});
|
||||
} else {
|
||||
try writer.writeAll(case(.title, name));
|
||||
try writer.print("{}", .{titleCase(name)});
|
||||
}
|
||||
} else if (arg.kind == .int) {
|
||||
try writer.writeAll("i32");
|
||||
@@ -895,8 +889,7 @@ const Enum = struct {
|
||||
}
|
||||
|
||||
fn emit(e: Enum, writer: anytype) !void {
|
||||
try writer.writeAll("pub const ");
|
||||
try printIdentifier(writer, case(.title, e.name));
|
||||
try writer.print("pub const {}", .{titleCase(e.name)});
|
||||
|
||||
if (e.bitfield) {
|
||||
var entries_emitted: u8 = 0;
|
||||
@@ -904,7 +897,7 @@ const Enum = struct {
|
||||
for (e.entries.items) |entry| {
|
||||
const value = entry.intValue();
|
||||
if (value != 0 and std.math.isPowerOfTwo(value)) {
|
||||
try printIdentifier(writer, entry.name);
|
||||
try writer.print("{s}", .{entry.name});
|
||||
if (entries_emitted == 0) {
|
||||
// Align the first field to ensure the entire packed
|
||||
// struct matches the alignment of a u32. This allows
|
||||
@@ -930,8 +923,7 @@ const Enum = struct {
|
||||
|
||||
try writer.writeAll(" = extern enum(c_int) {");
|
||||
for (e.entries.items) |entry| {
|
||||
try printIdentifier(writer, entry.name);
|
||||
try writer.print("= {s},", .{entry.value});
|
||||
try writer.print("{s}= {s},", .{ fmtId(entry.name), entry.value });
|
||||
}
|
||||
// Always generate non-exhaustive enums to ensure forward compatability.
|
||||
// Entries have been added to wl_shm.format without bumping the version.
|
||||
@@ -993,46 +985,52 @@ fn trimPrefix(s: []const u8) []const u8 {
|
||||
return s[mem.indexOfScalar(u8, s, '_').? + 1 ..];
|
||||
}
|
||||
|
||||
var case_buf: [512]u8 = undefined;
|
||||
fn case(out_case: enum { title, camel }, snake_case: []const u8) []const u8 {
|
||||
var i: usize = 0;
|
||||
var upper = out_case == .title;
|
||||
for (snake_case) |ch| {
|
||||
if (ch == '_') {
|
||||
upper = true;
|
||||
continue;
|
||||
const Case = enum { title, camel };
|
||||
|
||||
fn formatCaseImpl(case: Case, comptime trim: bool) type {
|
||||
return struct {
|
||||
pub fn f(
|
||||
bytes: []const u8,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) !void {
|
||||
var upper = case == .title;
|
||||
var str = if (trim) trimPrefix(bytes) else bytes;
|
||||
for (str) |c| {
|
||||
if (c == '_') {
|
||||
upper = true;
|
||||
continue;
|
||||
}
|
||||
try writer.writeByte(if (upper) std.ascii.toUpper(c) else c);
|
||||
upper = false;
|
||||
}
|
||||
}
|
||||
case_buf[i] = if (upper) std.ascii.toUpper(ch) else ch;
|
||||
i += 1;
|
||||
upper = false;
|
||||
}
|
||||
return case_buf[0..i];
|
||||
};
|
||||
}
|
||||
|
||||
fn titleCase(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.title, false).f) {
|
||||
return .{ .data = bytes };
|
||||
}
|
||||
|
||||
fn titleCaseTrim(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.title, true).f) {
|
||||
return .{ .data = bytes };
|
||||
}
|
||||
|
||||
fn camelCase(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.camel, false).f) {
|
||||
return .{ .data = bytes };
|
||||
}
|
||||
|
||||
fn camelCaseTrim(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.camel, true).f) {
|
||||
return .{ .data = bytes };
|
||||
}
|
||||
|
||||
fn printAbsolute(side: Side, writer: anytype, interface: []const u8) !void {
|
||||
try writer.writeAll(@tagName(side));
|
||||
try writer.writeByte('.');
|
||||
try printIdentifier(writer, prefix(interface) orelse return error.MissingPrefix);
|
||||
try writer.writeByte('.');
|
||||
try printIdentifier(writer, case(.title, trimPrefix(interface)));
|
||||
}
|
||||
|
||||
fn printIdentifier(writer: anytype, identifier: []const u8) !void {
|
||||
if (isValidIdentifier(identifier))
|
||||
try writer.writeAll(identifier)
|
||||
else
|
||||
try writer.print("@\"{s}\"", .{identifier});
|
||||
}
|
||||
|
||||
fn isValidIdentifier(identifier: []const u8) bool {
|
||||
// !keyword [A-Za-z_] [A-Za-z0-9_]*
|
||||
if (identifier.len == 0) return false;
|
||||
for (identifier) |ch, i| switch (ch) {
|
||||
'A'...'Z', 'a'...'z', '_' => {},
|
||||
'0'...'9' => if (i == 0) return false,
|
||||
else => return false,
|
||||
};
|
||||
return std.zig.Token.getKeyword(identifier) == null;
|
||||
try writer.print("{s}.{s}.{}", .{
|
||||
@tagName(side),
|
||||
prefix(interface) orelse return error.MissingPrefix,
|
||||
titleCaseTrim(interface),
|
||||
});
|
||||
}
|
||||
|
||||
test "parsing" {
|
||||
|
||||
Reference in New Issue
Block a user