commit 3f844cba0b601186bb20efa6090e944b9267f538 (tree)
parent 081698156141ba16a168d9448b9883c0f5a3edd0
Author: Andrew Kelley <andrew@ziglang.org>
Date: Sat, 27 Feb 2021 00:26:25 -0700
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.
Diffstat:
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/lib/std/zig/fmt.zig b/lib/std/zig/fmt.zig
@@ -12,7 +12,7 @@ pub fn formatId(
return writer.writeAll(bytes);
}
try writer.writeAll("@\"");
- try formatEscapes(bytes, fmt, options, writer);
+ try formatEscapes(bytes, "", options, writer);
try writer.writeByte('"');
}
@@ -32,6 +32,9 @@ pub fn isValidId(bytes: []const u8) bool {
return std.zig.Token.getKeyword(bytes) == null;
}
+/// Print the string as escaped contents of a double quoted or single-quoted string.
+/// Format `{}` treats contents as a double-quoted string.
+/// Format `{'}` treats contents as a single-quoted string.
pub fn formatEscapes(
bytes: []const u8,
comptime fmt: []const u8,
@@ -43,8 +46,24 @@ pub fn formatEscapes(
'\r' => try writer.writeAll("\\r"),
'\t' => try writer.writeAll("\\t"),
'\\' => try writer.writeAll("\\\\"),
- '"' => try writer.writeAll("\\\""),
- '\'' => try writer.writeAll("\\'"),
+ '"' => {
+ if (fmt.len == 1 and fmt[0] == '\'') {
+ try writer.writeByte('"');
+ } else if (fmt.len == 0) {
+ try writer.writeAll("\\\"");
+ } else {
+ @compileError("expected {} or {'}, found {" ++ fmt ++ "}");
+ }
+ },
+ '\'' => {
+ if (fmt.len == 1 and fmt[0] == '\'') {
+ try writer.writeAll("\\'");
+ } else if (fmt.len == 0) {
+ try writer.writeByte('\'');
+ } else {
+ @compileError("expected {} or {'}, found {" ++ fmt ++ "}");
+ }
+ },
' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),
// Use hex escapes for rest any unprintable characters.
else => {
@@ -54,7 +73,10 @@ pub fn formatEscapes(
};
}
-/// Return a Formatter for Zig Escapes
+/// Return a Formatter for Zig Escapes of a double quoted string.
+/// The format specifier must be one of:
+/// * `{}` treats contents as a double-quoted string.
+/// * `{'}` treats contents as a single-quoted string.
pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {
return .{ .data = bytes };
}
@@ -67,6 +89,9 @@ test "escape invalid identifiers" {
try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
try expectFmt(
- \\" \\ hi \x07 \x11 \" derp \'"
+ \\" \\ hi \x07 \x11 " derp \'"
+ , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
+ try expectFmt(
+ \\" \\ hi \x07 \x11 \" derp '"
, "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
}