my ziglings
0

Configure Feed

Select the types of activity you want to include in your feed.

Some deprecated functions removed and a progress bar added.

Chris Boesch (Apr 15, 2026, 6:21 PM +0200) d918dbae 4746ccc1

+58 -32
+1 -1
README.md
··· 1 1 # Ziglings 2 2 3 3 Welcome to Ziglings! This project contains a series of tiny 4 - broken programs (and one nasty surprise). By fixing them, you'll 4 + broken programs (and one nasty surprise). By fixing them, you'll 5 5 learn how to read and write [Zig](https://ziglang.org/) code. 6 6 7 7 ![Ziglings](images/ziglings_dark.jpg "Ziglings")
+57 -31
build.zig
··· 15 15 // 1) Getting Started 16 16 // 2) Version Changes 17 17 comptime { 18 - const required_zig = "0.16.0"; 18 + const required_zig = "0.16.0-dev.2915"; 19 19 const current_zig = builtin.zig_version; 20 20 const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; 21 21 if (current_zig.order(min_zig) == .lt) { ··· 205 205 break :blk seed; 206 206 }); 207 207 const rnd = prng.random(); 208 - const ex = exercises[rnd.intRangeLessThan(usize, 0, exercises.len)]; 208 + const num = rnd.intRangeLessThan(usize, 0, exercises.len); 209 + const ex = exercises[num]; 209 210 210 211 print("random exercise: {s}\n", .{ex.main_file}); 211 212 ··· 270 271 271 272 const progress_file_size = try progress_file.length(io); 272 273 273 - var gpa = std.heap.DebugAllocator(.{}){}; 274 - defer _ = gpa.deinit(); 275 - const allocator = gpa.allocator(); 276 - const contents = try allocator.alloc(u8, progress_file_size); 277 - defer allocator.free(contents); 274 + var gpa = b.allocator; 275 + const contents = try gpa.alloc(u8, progress_file_size); 276 + defer gpa.free(contents); 278 277 var file_buffer: [1024]u8 = undefined; 279 278 var file_reader = progress_file.reader(io, &file_buffer); 280 279 // try file_reader.interface.readSliceAll(contents); ··· 346 345 return self; 347 346 } 348 347 348 + fn printProgress(num: usize, max: usize) void { 349 + const bar_width: u32 = 60; 350 + 351 + const filled_len_u64 = (@as(u64, num) * bar_width) / max; 352 + const filled_len = @as(u32, @intCast(filled_len_u64)); 353 + 354 + var bar_buf: [bar_width]u8 = undefined; 355 + 356 + for (0..bar_width) |n| { 357 + const ord = std.math.order(n, filled_len); 358 + bar_buf[n] = switch (ord) { 359 + .lt => '#', 360 + .eq => '>', 361 + .gt => '-', 362 + }; 363 + } 364 + 365 + std.debug.print("\rProgress: [{s}] {d}/{d}\n\n", .{ &bar_buf, num, max }); 366 + } 367 + 349 368 fn make(step: *Step, options: Step.MakeOptions) !void { 350 369 // NOTE: Using exit code 2 will prevent the Zig compiler to print the message: 351 370 // "error: the following build command failed with exit code 1:..." ··· 360 379 print("\n\n", .{}); 361 380 return; 362 381 } 382 + 383 + // Progess 384 + printProgress(self.exercise.number(), exercises.len - 1); 363 385 364 386 const exe_path = self.compile(options.progress_node) catch { 365 387 self.printErrors(); ··· 388 410 fn run(self: *ZiglingStep, exe_path: []const u8, _: std.Progress.Node) !void { 389 411 resetLine(); 390 412 const b = self.step.owner; 413 + const gpa = b.allocator; 391 414 const io = b.graph.io; 392 415 393 416 print("Checking: {s}\n", .{self.exercise.main_file}); ··· 395 418 // Allow up to 1 MB of stdout capture. 396 419 const max_output_bytes = 1 * 1024 * 1024; 397 420 398 - const result = Process.run(b.allocator, io, .{ 421 + const result = Process.run(gpa, io, .{ 399 422 .argv = &.{exe_path}, 400 423 .cwd = .{ .path = b.build_root.path.? }, 401 424 .stdout_limit = .limited(max_output_bytes), ··· 413 436 414 437 fn check_output(self: *ZiglingStep, result: Process.RunResult) !void { 415 438 const b = self.step.owner; 439 + const gpa = b.allocator; 416 440 const io = b.graph.io; 417 441 418 442 // Make sure it exited cleanly. ··· 438 462 439 463 // NOTE: exercise.output can never contain a CR character. 440 464 // See https://ziglang.org/documentation/master/#Source-Encoding. 441 - const output = trimLines(b.allocator, raw_output) catch @panic("OOM"); 465 + const output = trimLines(gpa, raw_output) catch @panic("OOM"); 442 466 443 467 // Validate the output. 444 468 var exercise_output = self.exercise.output; ··· 486 510 , .{ red, reset, exercise_output, red, reset, output, red, reset }); 487 511 } 488 512 489 - const progress = try std.fmt.allocPrint(b.allocator, "{d}", .{self.exercise.number()}); 490 - defer b.allocator.free(progress); 513 + const progress = try std.fmt.allocPrint(gpa, "{d}", .{self.exercise.number()}); 514 + defer gpa.free(progress); 491 515 492 516 const file = try std.Io.Dir.cwd().createFile( 493 517 io, ··· 526 550 print("Compiling: {s}\n", .{self.exercise.main_file}); 527 551 528 552 const b = self.step.owner; 553 + const gpa = b.allocator; 529 554 const exercise_path = self.exercise.main_file; 530 - const path = join(b.allocator, &.{ self.work_path, exercise_path }) catch 555 + const path = join(gpa, &.{ self.work_path, exercise_path }) catch 531 556 @panic("OOM"); 532 557 533 - var zig_args = std.array_list.Managed([]const u8).init(b.allocator); 534 - defer zig_args.deinit(); 558 + var zig_args = std.ArrayList([]const u8).initCapacity(gpa, 10) catch @panic("OOM"); 559 + defer zig_args.deinit(gpa); 535 560 536 - zig_args.append(b.graph.zig_exe) catch @panic("OOM"); 561 + zig_args.append(gpa, b.graph.zig_exe) catch @panic("OOM"); 537 562 538 563 const cmd = switch (self.exercise.kind) { 539 564 .exe => "build-exe", 540 565 .@"test" => "test", 541 566 }; 542 - zig_args.append(cmd) catch @panic("OOM"); 567 + zig_args.append(gpa, cmd) catch @panic("OOM"); 543 568 544 569 // Enable C support for exercises that use C functions. 545 570 if (self.exercise.link_libc) { 546 - zig_args.append("-lc") catch @panic("OOM"); 547 - zig_args.append("-fllvm") catch @panic("OOM"); 571 + zig_args.append(gpa, "-lc") catch @panic("OOM"); 572 + zig_args.append(gpa, "-fllvm") catch @panic("OOM"); 548 573 } 549 574 550 575 if (b.reference_trace) |rt| { 551 - zig_args.append(b.fmt("-freference-trace={}", .{rt})) catch @panic("OOM"); 576 + zig_args.append(gpa, b.fmt("-freference-trace={}", .{rt})) catch @panic("OOM"); 552 577 } 553 578 554 - zig_args.append(b.pathFromRoot(path)) catch @panic("OOM"); 579 + zig_args.append(gpa, b.pathFromRoot(path)) catch @panic("OOM"); 555 580 556 - zig_args.append("--cache-dir") catch @panic("OOM"); 557 - zig_args.append(b.pathFromRoot(b.cache_root.path.?)) catch @panic("OOM"); 581 + zig_args.append(gpa, "--cache-dir") catch @panic("OOM"); 582 + zig_args.append(gpa, b.pathFromRoot(b.cache_root.path.?)) catch @panic("OOM"); 558 583 559 - zig_args.append("--listen=-") catch @panic("OOM"); 584 + zig_args.append(gpa, "--listen=-") catch @panic("OOM"); 560 585 561 586 // 562 587 // NOTE: After many changes in zig build system, we need to create the cache path manually. 563 588 // See https://github.com/ziglang/zig/pull/21115 564 589 // Maybe there is a better way (in the future). 565 - const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false, null, b.allocator); 590 + const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false, null, gpa); 566 591 const exe_name = switch (self.exercise.kind) { 567 592 .exe => self.exercise.name(), 568 593 .@"test" => "test", ··· 628 653 629 654 /// Removes trailing whitespace for each line in buf, also ensuring that there 630 655 /// are no trailing LF characters at the end. 631 - pub fn trimLines(allocator: std.mem.Allocator, buf: []const u8) ![]const u8 { 632 - var list = try std.array_list.Aligned(u8, null).initCapacity(allocator, buf.len); 656 + pub fn trimLines(gpa: std.mem.Allocator, buf: []const u8) ![]const u8 { 657 + var list = try std.ArrayList(u8).initCapacity(gpa, buf.len); 658 + errdefer list.deinit(gpa); 633 659 634 660 var iter = std.mem.splitSequence(u8, buf, " \n"); 635 661 while (iter.next()) |line| { 636 662 // TODO: trimming CR characters is probably not necessary. 637 663 const data = std.mem.trimEnd(u8, line, " \r"); 638 - try list.appendSlice(allocator, data); 639 - try list.append(allocator, '\n'); 664 + try list.appendSlice(gpa, data); 665 + try list.append(gpa, '\n'); 640 666 } 641 667 642 - const result = try list.toOwnedSlice(allocator); // TODO: probably not necessary 668 + // Calls deinit() 669 + const result = try list.toOwnedSlice(gpa); 643 670 644 - // Remove the trailing LF character, that is always present in the exercise 645 - // output. 671 + // Remove the trailing LF character, that is always present in the exercise output. 646 672 return std.mem.trimEnd(u8, result, "\n"); 647 673 } 648 674