~leon_plickat/public-inbox

zig-spoon: Add rgb and 256 colours mode support v1 NEEDS REVISION

Hugo Machet: 3
 Add rgb and 256 colours mode support
 Add a string parser to return a Colour
 Add a function to get RGB from HTML name

 8 files changed, 353 insertions(+), 9 deletions(-)
#760273 alpine.yml success
zig-spoon/patches/alpine.yml: SUCCESS in 34s

[Add rgb and 256 colours mode support][0] from [Hugo Machet][1]

[0]: https://lists.sr.ht/~leon_plickat/public-inbox/patches/32345
[1]: mailto:mail@hmachet.com

✓ #760273 SUCCESS zig-spoon/patches/alpine.yml https://builds.sr.ht/~leon_plickat/job/760273
Thanks for working on this!
Next
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~leon_plickat/public-inbox/patches/32345/mbox | git am -3
Learn more about email & git

[PATCH zig-spoon 1/3] Add rgb and 256 colours mode support Export this patch

Implements: https://todo.sr.ht/~leon_plickat/zig-spoon/4
---
 example/colours.zig |  4 ++--
 lib/Attribute.zig   | 35 ++++++++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/example/colours.zig b/example/colours.zig
index 431a3a6073fa..43a0854746ca 100644
--- a/example/colours.zig
+++ b/example/colours.zig
@@ -8,8 +8,8 @@ const spoon = @import("spoon");

const red = spoon.Attribute{ .fg = .red, .italic = true };
const green = spoon.Attribute{ .fg = .green, .blinking = true };
const blue = spoon.Attribute{ .fg = .blue, .bold = true };
const cyan = spoon.Attribute{ .fg = .cyan, .reverse = true };
const blue = spoon.Attribute{ .fg = .{ .rgb = .{ 137, 207, 240 } }, .bold = true };
const cyan = spoon.Attribute{ .fg = .{ .@"256" = 123 }, .reverse = true };
const reset = spoon.Attribute{};

pub fn main() !void {
diff --git a/lib/Attribute.zig b/lib/Attribute.zig
index 2aa3d17c2c4a..c75468de1e30 100644
--- a/lib/Attribute.zig
+++ b/lib/Attribute.zig
@@ -6,7 +6,7 @@

const Self = @This();

const Colour = enum {
const Colour = union(enum) {
    none,
    black,
    red,
@@ -24,6 +24,11 @@ const Colour = enum {
    bright_magenta,
    bright_cyan,
    bright_white,

    /// 0-255 colours
    @"256": u8,
    /// u8{<red 0-255>, <green 0-255>, <blue 0-255>}
    rgb: [3]u8,
};

fg: Colour = .white,
@@ -75,6 +80,20 @@ pub fn dump(self: Self, writer: anytype) !void {
        .bright_magenta => try writer.writeAll(";95"),
        .bright_cyan => try writer.writeAll(";96"),
        .bright_white => try writer.writeAll(";97"),
        .@"256" => {
            try writer.writeAll("m");
            try writer.writeAll("\x1b[38;5;");
            try writer.print("{d}", .{self.fg.@"256"});
        },
        .rgb => {
            try writer.writeAll("m");
            try writer.writeAll("\x1b[38;2;");
            try writer.print("{d};{d};{d}", .{
                self.fg.rgb[0],
                self.fg.rgb[1],
                self.fg.rgb[2],
            });
        },
    }
    switch (self.bg) {
        .none => {},
@@ -94,6 +113,20 @@ pub fn dump(self: Self, writer: anytype) !void {
        .bright_magenta => try writer.writeAll(";105"),
        .bright_cyan => try writer.writeAll(";106"),
        .bright_white => try writer.writeAll(";107"),
        .@"256" => {
            try writer.writeAll("m");
            try writer.writeAll("\x1b[48;5;");
            try writer.print("{d}", .{self.fg.@"256"});
        },
        .rgb => {
            try writer.writeAll("m");
            try writer.writeAll("\x1b[48;2;");
            try writer.print("{d};{d};{d}", .{
                self.fg.rgb[0],
                self.fg.rgb[1],
                self.fg.rgb[2],
            });
        },
    }
    try writer.writeAll("m");
}
-- 
2.36.1

[PATCH zig-spoon 2/3] Add a string parser to return a Colour Export this patch

Examples:
    var rgb = try parseColoursString("0x2b45a7");
    var 256 = try parseColoursString("234");
    var ansi = try parseColoursString("red");
---
 example/colours.zig |  13 +++--
 lib/Attribute.zig   | 134 ++++++++++++++++++++++++++++++++++++++++++++
 test_main.zig       |   1 +
 3 files changed, 142 insertions(+), 6 deletions(-)

diff --git a/example/colours.zig b/example/colours.zig
index 43a0854746ca..4be9e63f0aaf 100644
--- a/example/colours.zig
+++ b/example/colours.zig
@@ -6,13 +6,14 @@ const io = std.io;

const spoon = @import("spoon");

const red = spoon.Attribute{ .fg = .red, .italic = true };
const green = spoon.Attribute{ .fg = .green, .blinking = true };
const blue = spoon.Attribute{ .fg = .{ .rgb = .{ 137, 207, 240 } }, .bold = true };
const cyan = spoon.Attribute{ .fg = .{ .@"256" = 123 }, .reverse = true };
const reset = spoon.Attribute{};

pub fn main() !void {
    const red = spoon.Attribute{ .fg = .red, .italic = true };
    const green_str = try spoon.Attribute.parseColoursString("green");
    const green = spoon.Attribute{ .fg = green_str, .blinking = true };
    const blue = spoon.Attribute{ .fg = .{ .rgb = .{ 137, 207, 240 } }, .bold = true };
    const cyan = spoon.Attribute{ .fg = .{ .@"256" = 123 }, .reverse = true };
    const reset = spoon.Attribute{};

    const writer = io.getStdOut().writer();

    try red.dump(writer);
diff --git a/lib/Attribute.zig b/lib/Attribute.zig
index c75468de1e30..af4f7ff0055f 100644
--- a/lib/Attribute.zig
+++ b/lib/Attribute.zig
@@ -4,6 +4,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

const std = @import("std");
const fmt = std.fmt;
const mem = std.mem;

const Self = @This();

const Colour = union(enum) {
@@ -130,3 +134,133 @@ pub fn dump(self: Self, writer: anytype) !void {
    }
    try writer.writeAll("m");
}

/// RGB colours: "0xRRGGBB"
/// 256 colours: "154"
/// ANSI colours: a string equal to one of Colour fields (case sensitive)
/// For Example:
///     var rgb = try parseColoursString("0x2b45a7");
///     var 256 = try parseColoursString("234");
///     var ansi = try parseColoursString("red");
pub fn parseColoursString(s: []const u8) !Colour {
    var ret: Colour = .none;

    switch (s[0]) {
        '0'...'9' => {
            if (s[0] == '0' and s[1] == 'x') {
                const color = try hexToRgb(s);
                ret = .{ .rgb = color };
            } else {
                const color = fmt.parseUnsigned(u8, s, 10) catch |err| switch (err) {
                    error.Overflow => return error.BadColoursFormat,
                    else => return err,
                };
                ret = .{ .@"256" = color };
            }
        },
        'a'...'z' => {
            if (mem.eql(u8, s, "none")) {
                ret = .none;
            } else if (mem.eql(u8, s, "black")) {
                ret = .black;
            } else if (mem.eql(u8, s, "red")) {
                ret = .red;
            } else if (mem.eql(u8, s, "green")) {
                ret = .green;
            } else if (mem.eql(u8, s, "yellow")) {
                ret = .yellow;
            } else if (mem.eql(u8, s, "blue")) {
                ret = .blue;
            } else if (mem.eql(u8, s, "magenta")) {
                ret = .magenta;
            } else if (mem.eql(u8, s, "cyan")) {
                ret = .cyan;
            } else if (mem.eql(u8, s, "white")) {
                ret = .white;
            } else if (mem.eql(u8, s, "bright_black")) {
                ret = .bright_black;
            } else if (mem.eql(u8, s, "bright_red")) {
                ret = .bright_red;
            } else if (mem.eql(u8, s, "bright_green")) {
                ret = .bright_green;
            } else if (mem.eql(u8, s, "bright_yellow")) {
                ret = .bright_yellow;
            } else if (mem.eql(u8, s, "bright_blue")) {
                ret = .bright_blue;
            } else if (mem.eql(u8, s, "bright_magenta")) {
                ret = .bright_magenta;
            } else if (mem.eql(u8, s, "bright_cyan")) {
                ret = .bright_cyan;
            } else if (mem.eql(u8, s, "bright_white")) {
                ret = .bright_white;
            } else {
                return error.BadColoursFormat;
            }
        },
        else => return error.BadColoursFormat,
    }

    return ret;
}

/// Convert a string in the format "0xRRGGBB" to [3]u8.
fn hexToRgb(s: []const u8) ![3]u8 {
    if (s.len != 8) return error.BadRgbFormat;
    if (s[0] != '0' or s[1] != 'x') return error.BadRgbFormat;

    var color = try fmt.parseUnsigned(u32, s[2..], 16);
    color <<= 8;
    color |= 0xff;

    const bytes = @bitCast([4]u8, color);
    return [3]u8{
        @truncate(u8, @as(u16, bytes[3]) * 0x101),
        @truncate(u8, @as(u16, bytes[2]) * 0x101),
        @truncate(u8, @as(u16, bytes[1]) * 0x101),
    };
}

test "parse colours string (good input)" {
    const testing = std.testing;

    try testing.expectEqual(
        Colour{ .rgb = .{ 255, 255, 255 } },
        try parseColoursString("0xffffff"),
    );
    try testing.expectEqual(
        Colour{ .rgb = .{ 0, 169, 143 } },
        try parseColoursString("0x00a98f"),
    );
    try testing.expectEqual(
        Colour{ .@"256" = 54 },
        try parseColoursString("54"),
    );
    try testing.expectEqual(
        Colour{ .@"256" = 007 },
        try parseColoursString("7"),
    );
    try testing.expectEqual(
        Colour{ .@"256" = 237 },
        try parseColoursString("237"),
    );
    try testing.expectEqual(
        Colour.bright_black,
        try parseColoursString("bright_black"),
    );
    try testing.expectEqual(
        Colour.blue,
        try parseColoursString("blue"),
    );
}

test "parse colours string (bad input)" {
    const testing = std.testing;

    try testing.expectError(error.BadRgbFormat, parseColoursString("0xfff"));

    try testing.expectError(error.BadColoursFormat, parseColoursString("xffffff"));
    try testing.expectError(error.BadColoursFormat, parseColoursString("ffffff"));
    try testing.expectError(error.BadColoursFormat, parseColoursString("blu"));
    try testing.expectError(error.BadColoursFormat, parseColoursString("bLue"));
    try testing.expectError(error.BadColoursFormat, parseColoursString("256"));
}
diff --git a/test_main.zig b/test_main.zig
index 4dba7ce47076..ed8aba1a74f4 100644
--- a/test_main.zig
+++ b/test_main.zig
@@ -1,4 +1,5 @@
test {
    _ = @import("lib/input.zig");
    _ = @import("lib/input_description.zig");
    _ = @import("lib/Attribute.zig");
}
-- 
2.36.1

[PATCH zig-spoon 3/3] Add a function to get RGB from HTML name Export this patch

---
Feel free to just ignore this one if that not something that you are
interested in.

 example/colours.zig  |   4 ++
 lib/Attribute.zig    |   7 ++
 lib/colours_name.zig | 164 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 lib/colours_name.zig

diff --git a/example/colours.zig b/example/colours.zig
index 4be9e63f0aaf..8a029854cc44 100644
--- a/example/colours.zig
+++ b/example/colours.zig
@@ -11,6 +11,8 @@ pub fn main() !void {
    const green_str = try spoon.Attribute.parseColoursString("green");
    const green = spoon.Attribute{ .fg = green_str, .blinking = true };
    const blue = spoon.Attribute{ .fg = .{ .rgb = .{ 137, 207, 240 } }, .bold = true };
    const hotpink = try spoon.Attribute.rgbFromName("hotpink");
    const pink = spoon.Attribute{ .fg = .{ .rgb = hotpink } };
    const cyan = spoon.Attribute{ .fg = .{ .@"256" = 123 }, .reverse = true };
    const reset = spoon.Attribute{};

@@ -22,6 +24,8 @@ pub fn main() !void {
    try writer.writeAll("bar ");
    try blue.dump(writer);
    try writer.writeAll("baz ");
    try pink.dump(writer);
    try writer.writeAll("zig ");
    try cyan.dump(writer);
    try writer.writeAll("spoon\n");

diff --git a/lib/Attribute.zig b/lib/Attribute.zig
index af4f7ff0055f..b1c0c3b36d25 100644
--- a/lib/Attribute.zig
+++ b/lib/Attribute.zig
@@ -8,6 +8,8 @@ const std = @import("std");
const fmt = std.fmt;
const mem = std.mem;

const colours_name = @import("colours_name.zig");

const Self = @This();

const Colour = union(enum) {
@@ -135,6 +137,11 @@ pub fn dump(self: Self, writer: anytype) !void {
    try writer.writeAll("m");
}

/// Return a RGB version from a name of a HTML colour.
pub fn rgbFromName(name: []const u8) ![3]u8 {
    return colours_name.name.get(name) orelse return error.UnknowColourName;
}

/// RGB colours: "0xRRGGBB"
/// 256 colours: "154"
/// ANSI colours: a string equal to one of Colour fields (case sensitive)
diff --git a/lib/colours_name.zig b/lib/colours_name.zig
new file mode 100644
index 000000000000..7e346c73e087
--- /dev/null
+++ b/lib/colours_name.zig
@@ -0,0 +1,164 @@
// Copyright © 2022 Hugo Machet
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

const std = @import("std");

/// REF: https://www.w3.org/TR/css-color-3/#svg-color
pub const name = blk: {
    @setEvalBranchQuota(4000);
    break :blk std.ComptimeStringMap(
        [3]u8,
        .{
            .{ "aliceblue", .{ 240, 248, 255 } },
            .{ "antiquewhite", .{ 250, 235, 215 } },
            .{ "aqua", .{ 0, 255, 255 } },
            .{ "aquamarine", .{ 127, 255, 212 } },
            .{ "azure", .{ 240, 255, 255 } },
            .{ "beige", .{ 245, 245, 220 } },
            .{ "bisque", .{ 255, 228, 196 } },
            .{ "black", .{ 0, 0, 0 } },
            .{ "blanchedalmond", .{ 255, 235, 205 } },
            .{ "blue", .{ 0, 0, 255 } },
            .{ "blueviolet", .{ 138, 43, 226 } },
            .{ "brown", .{ 165, 42, 42 } },
            .{ "burlywood", .{ 222, 184, 135 } },
            .{ "cadetblue", .{ 95, 158, 160 } },
            .{ "chartreuse", .{ 127, 255, 0 } },
            .{ "chocolate", .{ 210, 105, 30 } },
            .{ "coral", .{ 255, 127, 80 } },
            .{ "cornflowerblue", .{ 100, 149, 237 } },
            .{ "cornsilk", .{ 255, 248, 220 } },
            .{ "crimson", .{ 220, 20, 60 } },
            .{ "cyan", .{ 0, 255, 255 } },
            .{ "darkblue", .{ 0, 0, 139 } },
            .{ "darkcyan", .{ 0, 139, 139 } },
            .{ "darkgoldenrod", .{ 184, 134, 11 } },
            .{ "darkgray", .{ 169, 169, 169 } },
            .{ "darkgreen", .{ 0, 100, 0 } },
            .{ "darkgrey", .{ 169, 169, 169 } },
            .{ "darkkhaki", .{ 189, 183, 107 } },
            .{ "darkmagenta", .{ 139, 0, 139 } },
            .{ "darkolivegreen", .{ 85, 107, 47 } },
            .{ "darkorange", .{ 255, 140, 0 } },
            .{ "darkorchid", .{ 153, 50, 204 } },
            .{ "darkred", .{ 139, 0, 0 } },
            .{ "darksalmon", .{ 233, 150, 122 } },
            .{ "darkseagreen", .{ 143, 188, 143 } },
            .{ "darkslateblue", .{ 72, 61, 139 } },
            .{ "darkslategray", .{ 47, 79, 79 } },
            .{ "darkslategrey", .{ 47, 79, 79 } },
            .{ "darkturquoise", .{ 0, 206, 209 } },
            .{ "darkviolet", .{ 148, 0, 211 } },
            .{ "deeppink", .{ 255, 20, 147 } },
            .{ "deepskyblue", .{ 0, 191, 255 } },
            .{ "dimgray", .{ 105, 105, 105 } },
            .{ "dimgrey", .{ 105, 105, 105 } },
            .{ "dodgerblue", .{ 30, 144, 255 } },
            .{ "firebrick", .{ 178, 34, 34 } },
            .{ "floralwhite", .{ 255, 250, 240 } },
            .{ "forestgreen", .{ 34, 139, 34 } },
            .{ "fuchsia", .{ 255, 0, 255 } },
            .{ "gainsboro", .{ 220, 220, 220 } },
            .{ "ghostwhite", .{ 248, 248, 255 } },
            .{ "gold", .{ 255, 215, 0 } },
            .{ "goldenrod", .{ 218, 165, 32 } },
            .{ "gray", .{ 128, 128, 128 } },
            .{ "green", .{ 0, 128, 0 } },
            .{ "greenyellow", .{ 173, 255, 47 } },
            .{ "grey", .{ 128, 128, 128 } },
            .{ "honeydew", .{ 240, 255, 240 } },
            .{ "hotpink", .{ 255, 105, 180 } },
            .{ "indianred", .{ 205, 92, 92 } },
            .{ "indigo", .{ 75, 0, 130 } },
            .{ "ivory", .{ 255, 255, 240 } },
            .{ "khaki", .{ 240, 230, 140 } },
            .{ "lavender", .{ 230, 230, 250 } },
            .{ "lavenderblush", .{ 255, 240, 245 } },
            .{ "lawngreen", .{ 124, 252, 0 } },
            .{ "lemonchiffon", .{ 255, 250, 205 } },
            .{ "lightblue", .{ 173, 216, 230 } },
            .{ "lightcoral", .{ 240, 128, 128 } },
            .{ "lightcyan", .{ 224, 255, 255 } },
            .{ "lightgoldenrodyellow", .{ 250, 250, 210 } },
            .{ "lightgray", .{ 211, 211, 211 } },
            .{ "lightgreen", .{ 144, 238, 144 } },
            .{ "lightgrey", .{ 211, 211, 211 } },
            .{ "lightpink", .{ 255, 182, 193 } },
            .{ "lightsalmon", .{ 255, 160, 122 } },
            .{ "lightseagreen", .{ 32, 178, 170 } },
            .{ "lightskyblue", .{ 135, 206, 250 } },
            .{ "lightslategray", .{ 119, 136, 153 } },
            .{ "lightslategrey", .{ 119, 136, 153 } },
            .{ "lightsteelblue", .{ 176, 196, 222 } },
            .{ "lightyellow", .{ 255, 255, 224 } },
            .{ "lime", .{ 0, 255, 0 } },
            .{ "limegreen", .{ 50, 205, 50 } },
            .{ "linen", .{ 250, 240, 230 } },
            .{ "magenta", .{ 255, 0, 255 } },
            .{ "maroon", .{ 128, 0, 0 } },
            .{ "mediumaquamarine", .{ 102, 205, 170 } },
            .{ "mediumblue", .{ 0, 0, 205 } },
            .{ "mediumorchid", .{ 186, 85, 211 } },
            .{ "mediumpurple", .{ 147, 112, 219 } },
            .{ "mediumseagreen", .{ 60, 179, 113 } },
            .{ "mediumslateblue", .{ 123, 104, 238 } },
            .{ "mediumspringgreen", .{ 0, 250, 154 } },
            .{ "mediumturquoise", .{ 72, 209, 204 } },
            .{ "mediumvioletred", .{ 199, 21, 133 } },
            .{ "midnightblue", .{ 25, 25, 112 } },
            .{ "mintcream", .{ 245, 255, 250 } },
            .{ "mistyrose", .{ 255, 228, 225 } },
            .{ "moccasin", .{ 255, 228, 181 } },
            .{ "navajowhite", .{ 255, 222, 173 } },
            .{ "navy", .{ 0, 0, 128 } },
            .{ "oldlace", .{ 253, 245, 230 } },
            .{ "olive", .{ 128, 128, 0 } },
            .{ "olivedrab", .{ 107, 142, 35 } },
            .{ "orange", .{ 255, 165, 0 } },
            .{ "orangered", .{ 255, 69, 0 } },
            .{ "orchid", .{ 218, 112, 214 } },
            .{ "palegoldenrod", .{ 238, 232, 170 } },
            .{ "palegreen", .{ 152, 251, 152 } },
            .{ "paleturquoise", .{ 175, 238, 238 } },
            .{ "palevioletred", .{ 219, 112, 147 } },
            .{ "papayawhip", .{ 255, 239, 213 } },
            .{ "peachpuff", .{ 255, 218, 185 } },
            .{ "peru", .{ 205, 133, 63 } },
            .{ "pink", .{ 255, 192, 203 } },
            .{ "plum", .{ 221, 160, 221 } },
            .{ "powderblue", .{ 176, 224, 230 } },
            .{ "purple", .{ 128, 0, 128 } },
            .{ "red", .{ 255, 0, 0 } },
            .{ "rosybrown", .{ 188, 143, 143 } },
            .{ "royalblue", .{ 65, 105, 225 } },
            .{ "saddlebrown", .{ 139, 69, 19 } },
            .{ "salmon", .{ 250, 128, 114 } },
            .{ "sandybrown", .{ 244, 164, 96 } },
            .{ "seagreen", .{ 46, 139, 87 } },
            .{ "seashell", .{ 255, 245, 238 } },
            .{ "sienna", .{ 160, 82, 45 } },
            .{ "silver", .{ 192, 192, 192 } },
            .{ "skyblue", .{ 135, 206, 235 } },
            .{ "slateblue", .{ 106, 90, 205 } },
            .{ "slategray", .{ 112, 128, 144 } },
            .{ "slategrey", .{ 112, 128, 144 } },
            .{ "snow", .{ 255, 250, 250 } },
            .{ "springgreen", .{ 0, 255, 127 } },
            .{ "steelblue", .{ 70, 130, 180 } },
            .{ "tan", .{ 210, 180, 140 } },
            .{ "teal", .{ 0, 128, 128 } },
            .{ "thistle", .{ 216, 191, 216 } },
            .{ "tomato", .{ 255, 99, 71 } },
            .{ "turquoise", .{ 64, 224, 208 } },
            .{ "violet", .{ 238, 130, 238 } },
            .{ "wheat", .{ 245, 222, 179 } },
            .{ "white", .{ 255, 255, 255 } },
            .{ "whitesmoke", .{ 245, 245, 245 } },
            .{ "yellow", .{ 255, 255, 0 } },
            .{ "yellowgreen", .{ 154, 205, 50 } },
        },
    );
};
-- 
2.36.1
zig-spoon/patches/alpine.yml: SUCCESS in 34s

[Add rgb and 256 colours mode support][0] from [Hugo Machet][1]

[0]: https://lists.sr.ht/~leon_plickat/public-inbox/patches/32345
[1]: mailto:mail@hmachet.com

✓ #760273 SUCCESS zig-spoon/patches/alpine.yml https://builds.sr.ht/~leon_plickat/job/760273
Thanks for working on this!