Skip to content

Lorem Ipsum Generator — Zig source

Generate placeholder Lorem Ipsum text - paragraphs and sentences with adjustable counts. Classic Latin word pool, instant copy.

This is the Zig implementation — the same logic the interactive tool runs, in a shareable, citable form.

// lorem-ipsum — Zig port: canonical Lorem Ipsum generator (sentences, paragraphs, blocks).
const std = @import("std");

// The canonical word pool — identical across every port.
const words = [_][]const u8{
    "lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
    "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et",
    "dolore", "magna", "aliqua", "enim", "ad", "minim", "veniam", "quis",
    "nostrud", "exercitation", "ullamco", "laboris", "nisi", "aliquip", "ex", "ea",
    "commodo", "consequat", "duis", "aute", "irure", "in", "reprehenderit",
    "voluptate", "velit", "esse", "cillum", "eu", "fugiat", "nulla", "pariatur",
    "excepteur", "sint", "occaecat", "cupidatat", "non", "proident", "sunt",
    "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum",
};

// DefaultPrng is non-crypto, matching the TS source's Math.random().
const Lorem = struct {
    prng: std.Random.DefaultPrng,

    fn init(seed: u64) Lorem {
        return .{ .prng = std.Random.DefaultPrng.init(seed) };
    }

    // Uniform integer in [0, n); 0 for n == 0 so callers never divide by zero.
    fn randBelow(self: *Lorem, n: usize) usize {
        return if (n == 0) 0 else self.prng.random().uintLessThan(usize, n);
    }

    // One capitalized sentence of min_words..max_words random words.
    fn sentence(self: *Lorem, a: std.mem.Allocator, min_words: usize, max_words: usize) ![]u8 {
        // Saturating subtraction collapses a reversed range to exactly
        // min_words words, matching the TS max(1, ...) guard.
        const span = @max(1, (max_words + 1) -| min_words);
        const n = min_words + self.randBelow(span);
        var buf = std.ArrayList(u8).init(a);
        const w = buf.writer();
        for (0..n) |i| {
            if (i != 0) try w.writeByte(' ');
            try w.writeAll(words[self.randBelow(words.len)]);
        }
        // Capitalize the first character only — the tail keeps its spelling.
        if (buf.items.len != 0) buf.items[0] = std.ascii.toUpper(buf.items[0]);
        try w.writeByte('.');
        return buf.toOwnedSlice();
    }

    // sentences default-length (8..16 word) sentences joined by spaces.
    fn paragraph(self: *Lorem, a: std.mem.Allocator, sentences: usize) ![]u8 {
        var buf = std.ArrayList(u8).init(a);
        const w = buf.writer();
        for (0..sentences) |i| {
            if (i != 0) try w.writeByte(' ');
            const s = try self.sentence(a, 8, 16);
            defer a.free(s);
            try w.writeAll(s);
        }
        return buf.toOwnedSlice();
    }

    fn text(self: *Lorem, a: std.mem.Allocator, paragraphs: usize, per_para: usize) ![]u8 {
        var buf = std.ArrayList(u8).init(a);
        const w = buf.writer();
        for (0..paragraphs) |i| {
            if (i != 0) try w.writeAll("\n\n");
            const p = try self.paragraph(a, per_para);
            defer a.free(p);
            try w.writeAll(p);
        }
        return buf.toOwnedSlice();
    }
};

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const a = arena.allocator();
    var generator = Lorem.init(0x5EED);
    const out = try generator.text(a, 3, 5);
    try std.io.getStdOut().writer().print("{s}\n", .{out});
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →