return 1 on error

This commit is contained in:
Emil Lerch 2026-03-03 12:10:39 -08:00
parent 089e81df54
commit 9f4adc1ee0
Signed by: lobo
GPG key ID: A7B62D657EF764F8

View file

@ -59,7 +59,7 @@ const usage =
\\
;
pub fn main() !void {
pub fn main() !u8 {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
@ -73,9 +73,8 @@ pub fn main() !void {
const out: *std.Io.Writer = &stdout_writer.interface;
if (args.len < 2) {
try out.writeAll(usage);
try out.flush();
return;
try cli.stderrPrint(usage);
return 1;
}
// Scan for global --no-color flag
@ -92,36 +91,54 @@ pub fn main() !void {
if (std.mem.eql(u8, command, "help") or std.mem.eql(u8, command, "--help") or std.mem.eql(u8, command, "-h")) {
try out.writeAll(usage);
try out.flush();
return;
return 0;
}
// Interactive TUI -- delegates to the TUI module (owns its own DataService)
if (std.mem.eql(u8, command, "interactive") or std.mem.eql(u8, command, "i")) {
try out.flush();
try tui.run(allocator, config, args);
return;
return 0;
}
var svc = zfin.DataService.init(allocator, config);
defer svc.deinit();
if (std.mem.eql(u8, command, "perf")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'perf' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'perf' requires a symbol argument\n");
return 1;
}
try commands.perf.run(allocator, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "quote")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'quote' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'quote' requires a symbol argument\n");
return 1;
}
try commands.quote.run(allocator, config, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "history")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'history' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'history' requires a symbol argument\n");
return 1;
}
try commands.history.run(allocator, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "divs")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'divs' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'divs' requires a symbol argument\n");
return 1;
}
try commands.divs.run(allocator, &svc, config, args[2], color, out);
} else if (std.mem.eql(u8, command, "splits")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'splits' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'splits' requires a symbol argument\n");
return 1;
}
try commands.splits.run(allocator, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "options")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'options' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'options' requires a symbol argument\n");
return 1;
}
// Parse --ntm flag
var ntm: usize = 8;
var ai: usize = 3;
@ -133,10 +150,16 @@ pub fn main() !void {
}
try commands.options.run(allocator, &svc, args[2], ntm, color, out);
} else if (std.mem.eql(u8, command, "earnings")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'earnings' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'earnings' requires a symbol argument\n");
return 1;
}
try commands.earnings.run(allocator, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "etf")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'etf' requires a symbol argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'etf' requires a symbol argument\n");
return 1;
}
try commands.etf.run(allocator, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "portfolio")) {
// Parse -w/--watchlist and --refresh flags; file path is first non-flag arg (default: portfolio.srf)
@ -158,13 +181,22 @@ pub fn main() !void {
}
try commands.portfolio.run(allocator, config, &svc, file_path, watchlist_path, force_refresh, color, out);
} else if (std.mem.eql(u8, command, "lookup")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'lookup' requires a CUSIP argument\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'lookup' requires a CUSIP argument\n");
return 1;
}
try commands.lookup.run(allocator, &svc, args[2], color, out);
} else if (std.mem.eql(u8, command, "cache")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'cache' requires a subcommand (stats, clear)\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'cache' requires a subcommand (stats, clear)\n");
return 1;
}
try commands.cache.run(allocator, config, args[2], out);
} else if (std.mem.eql(u8, command, "enrich")) {
if (args.len < 3) return try cli.stderrPrint("Error: 'enrich' requires a portfolio file path or symbol\n");
if (args.len < 3) {
try cli.stderrPrint("Error: 'enrich' requires a portfolio file path or symbol\n");
return 1;
}
try commands.enrich.run(allocator, config, args[2], out);
} else if (std.mem.eql(u8, command, "analysis")) {
// File path is first non-flag arg (default: portfolio.srf)
@ -178,10 +210,12 @@ pub fn main() !void {
try commands.analysis.run(allocator, config, &svc, analysis_file, color, out);
} else {
try cli.stderrPrint("Unknown command. Run 'zfin help' for usage.\n");
return 1;
}
// Single flush for all stdout output
try out.flush();
return 0;
}
// Command modules