@@ -6,6 +6,11 @@ const log = std.log.scoped(.zigdoc);
66const build_runner_0_14 = @embedFile ("build_runner_0.14.zig" );
77const build_runner_0_15 = @embedFile ("build_runner_0.15.zig" );
88
9+ const template_build_zig = @embedFile ("templates/build.zig.template" );
10+ const template_main_zig = @embedFile ("templates/main.zig.template" );
11+ const template_build_zig_zon = @embedFile ("templates/build.zig.zon.template" );
12+ const template_agents_md = @embedFile ("templates/AGENTS.md.template" );
13+
914pub fn main () ! void {
1015 var debug_allocator : std .heap .DebugAllocator (.{}) = .init ;
1116 const gpa , const is_debug = gpa : {
@@ -42,6 +47,11 @@ pub fn main() !void {
4247 return ;
4348 }
4449
50+ if (std .mem .eql (u8 , symbol .? , "@init" )) {
51+ try initProject (arena .allocator ());
52+ return ;
53+ }
54+
4555 Walk .init (arena .allocator ());
4656 Walk .Decl .init (arena .allocator ());
4757
@@ -84,10 +94,71 @@ fn printUsage() !void {
8494 \\ -h, --help Show this help message
8595 \\ --dump-imports Dump module imports from build.zig as JSON
8696 \\
97+ \\Commands:
98+ \\ @init Initialize a new Zig project with AGENTS.md
99+ \\
87100 );
88101 try stdout_writer .interface .flush ();
89102}
90103
104+ fn initProject (allocator : std.mem.Allocator ) ! void {
105+ const cwd = std .fs .cwd ();
106+
107+ // Check if project already exists
108+ if (cwd .access ("build.zig" , .{})) | _ | {
109+ std .debug .print ("Error: build.zig already exists\n " , .{});
110+ return error .ProjectExists ;
111+ } else | _ | {}
112+
113+ // Get project name from current directory
114+ var path_buf : [std .fs .max_path_bytes ]u8 = undefined ;
115+ const cwd_path = try cwd .realpath ("." , & path_buf );
116+ const name = std .fs .path .basename (cwd_path );
117+
118+ // Create src directory
119+ try cwd .makeDir ("src" );
120+
121+ // Write files with substitutions
122+ try cwd .writeFile (.{ .sub_path = "build.zig" , .data = try substitute (allocator , template_build_zig , name ) });
123+ try cwd .writeFile (.{ .sub_path = "build.zig.zon" , .data = try substitute (allocator , template_build_zig_zon , name ) });
124+ try cwd .writeFile (.{ .sub_path = "src/main.zig" , .data = template_main_zig });
125+ try cwd .writeFile (.{ .sub_path = "AGENTS.md" , .data = template_agents_md });
126+
127+ // Run zig build to get suggested fingerprint from error message
128+ const result = std .process .Child .run (.{
129+ .allocator = allocator ,
130+ .argv = &.{ "zig" , "build" },
131+ }) catch {
132+ std .debug .print ("Initialized Zig project '{s}' (run 'zig build' to generate fingerprint)\n " , .{name });
133+ return ;
134+ };
135+
136+ // Parse fingerprint from error: "suggested value: 0x..."
137+ if (std .mem .indexOf (u8 , result .stderr , "suggested value: " )) | start | {
138+ const fp_start = start + "suggested value: " .len ;
139+ const fp_end = std .mem .indexOfPos (u8 , result .stderr , fp_start , "\n " ) orelse result .stderr .len ;
140+ const fingerprint = result .stderr [fp_start .. fp_end ];
141+
142+ // Read current build.zig.zon and insert fingerprint
143+ const zon_content = try cwd .readFileAlloc (allocator , "build.zig.zon" , 64 * 1024 );
144+ const new_zon = try std .mem .replaceOwned (
145+ u8 ,
146+ allocator ,
147+ zon_content ,
148+ ".version = \" 0.0.0\" ," ,
149+ try std .fmt .allocPrint (allocator , ".version = \" 0.0.0\" ,\n .fingerprint = {s}," , .{fingerprint }),
150+ );
151+ try cwd .writeFile (.{ .sub_path = "build.zig.zon" , .data = new_zon });
152+ }
153+
154+ std .debug .print ("Initialized Zig project '{s}'\n " , .{name });
155+ }
156+
157+ fn substitute (allocator : std.mem.Allocator , template : []const u8 , name : []const u8 ) ! []const u8 {
158+ const sanitized = try std .mem .replaceOwned (u8 , allocator , name , "-" , "_" );
159+ return std .mem .replaceOwned (u8 , allocator , template , "{{name}}" , sanitized );
160+ }
161+
91162fn dumpImports (arena : * std.heap.ArenaAllocator ) ! void {
92163 // Check if build.zig exists
93164 std .fs .cwd ().access ("build.zig" , .{}) catch {
0 commit comments