authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-27 00:26:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-27 00:27:53-07:00
log3f844cba0b601186bb20efa6090e944b9267f538
tree1fe8a2020b0bf8293bfbea43a8a6835eeac4eb8e
parent081698156141ba16a168d9448b9883c0f5a3edd0

std.zig.fmt escaped string formatting recognizes single quote style

This introduces {'} to indicate escape for a single-quoted string, and {} to indicate escape for a double quoted string. Without this, there would be unnecessary \' inside double quoted strings, and unnecessary \" inside single quoted strings. Motivated by the llvm12 branch, in the new tool I am writing for updating target CPU features.

1 files changed, 30 insertions(+), 5 deletions(-)

lib/std/zig/fmt.zig+30-5
...@@ -12,7 +12,7 @@ pub fn formatId(...@@ -12,7 +12,7 @@ pub fn formatId(
12 return writer.writeAll(bytes);12 return writer.writeAll(bytes);
13 }13 }
14 try writer.writeAll("@\"");14 try writer.writeAll("@\"");
15 try formatEscapes(bytes, fmt, options, writer);15 try formatEscapes(bytes, "", options, writer);
16 try writer.writeByte('"');16 try writer.writeByte('"');
17}17}
1818
...@@ -32,6 +32,9 @@ pub fn isValidId(bytes: []const u8) bool {...@@ -32,6 +32,9 @@ pub fn isValidId(bytes: []const u8) bool {
32 return std.zig.Token.getKeyword(bytes) == null;32 return std.zig.Token.getKeyword(bytes) == null;
33}33}
3434
35/// Print the string as escaped contents of a double quoted or single-quoted string.
36/// Format `{}` treats contents as a double-quoted string.
37/// Format `{'}` treats contents as a single-quoted string.
35pub fn formatEscapes(38pub fn formatEscapes(
36 bytes: []const u8,39 bytes: []const u8,
37 comptime fmt: []const u8,40 comptime fmt: []const u8,
...@@ -43,8 +46,24 @@ pub fn formatEscapes(...@@ -43,8 +46,24 @@ pub fn formatEscapes(
43 '\r' => try writer.writeAll("\\r"),46 '\r' => try writer.writeAll("\\r"),
44 '\t' => try writer.writeAll("\\t"),47 '\t' => try writer.writeAll("\\t"),
45 '\\' => try writer.writeAll("\\\\"),48 '\\' => try writer.writeAll("\\\\"),
46 '"' => try writer.writeAll("\\\""),49 '"' => {
47 '\'' => try writer.writeAll("\\'"),50 if (fmt.len == 1 and fmt[0] == '\'') {
51 try writer.writeByte('"');
52 } else if (fmt.len == 0) {
53 try writer.writeAll("\\\"");
54 } else {
55 @compileError("expected {} or {'}, found {" ++ fmt ++ "}");
56 }
57 },
58 '\'' => {
59 if (fmt.len == 1 and fmt[0] == '\'') {
60 try writer.writeAll("\\'");
61 } else if (fmt.len == 0) {
62 try writer.writeByte('\'');
63 } else {
64 @compileError("expected {} or {'}, found {" ++ fmt ++ "}");
65 }
66 },
48 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),67 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),
49 // Use hex escapes for rest any unprintable characters.68 // Use hex escapes for rest any unprintable characters.
50 else => {69 else => {
...@@ -54,7 +73,10 @@ pub fn formatEscapes(...@@ -54,7 +73,10 @@ pub fn formatEscapes(
54 };73 };
55}74}
5675
57/// Return a Formatter for Zig Escapes76/// Return a Formatter for Zig Escapes of a double quoted string.
77/// The format specifier must be one of:
78/// * `{}` treats contents as a double-quoted string.
79/// * `{'}` treats contents as a single-quoted string.
58pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {80pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {
59 return .{ .data = bytes };81 return .{ .data = bytes };
60}82}
...@@ -67,6 +89,9 @@ test "escape invalid identifiers" {...@@ -67,6 +89,9 @@ test "escape invalid identifiers" {
67 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});89 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
68 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});90 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
69 try expectFmt(91 try expectFmt(
70 \\" \\ hi \x07 \x11 \" derp \'"92 \\" \\ hi \x07 \x11 " derp \'"
93 , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
94 try expectFmt(
95 \\" \\ hi \x07 \x11 \" derp '"
71 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});96 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
72}97}