gitignore

Pure Zig .gitignore pattern matching — no libc dependency

Features

  • Full .gitignore spec support: *, ?, [abc], **/, negation (!)
  • Recursive .gitignore filtering via GitignoreStack (per-directory layers)
  • Pure Zig implementation — no libc fnmatch dependency
  • Last-match-wins semantics across all layers

API

Gitignore

Parse a single .gitignore file and match paths against it.

1
2
3
4
5
6
7
8
9
const zigcli = @import("zigcli");
const gitignore = zigcli.gitignore;

var gi = try gitignore.Gitignore.init(allocator, content);
defer gi.deinit();

if (gi.shouldIgnore("build/output.o", false)) {
    // path is ignored
}

GitignoreStack

Manage a stack of .gitignore layers for recursive directory walks. Each layer is anchored to its directory, and patterns are evaluated with correct relative paths.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const zigcli = @import("zigcli");
const gitignore = zigcli.gitignore;

var stack = gitignore.GitignoreStack.init();
defer stack.deinit(allocator);

// Push a layer when entering a directory.
const pushed = try stack.tryPushDir(dir, rel_dir, allocator);

if (stack.shouldIgnore(rel_path, is_dir)) {
    // path is ignored
}

// Pop when leaving the directory.
if (pushed) stack.pop(allocator);

Used by

  • tree: Respects .gitignore when listing directory trees.
  • loc: Skips ignored files when counting lines of code.
Last modified March 22, 2026: chore: bump to 0.5.0 (8c7d27e)