84 lines
3.2 KiB
Zig
84 lines
3.2 KiB
Zig
const std = @import("std");
|
|
const zfin = @import("../root.zig");
|
|
const cli = @import("common.zig");
|
|
const fmt = cli.fmt;
|
|
|
|
pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, symbol: []const u8, color: bool, out: *std.Io.Writer) !void {
|
|
const result = svc.getSplits(symbol) catch |err| switch (err) {
|
|
zfin.DataError.NoApiKey => {
|
|
try cli.stderrPrint("Error: POLYGON_API_KEY not set. Get a free key at https://polygon.io\n");
|
|
return;
|
|
},
|
|
else => {
|
|
try cli.stderrPrint("Error fetching split data.\n");
|
|
return;
|
|
},
|
|
};
|
|
defer allocator.free(result.data);
|
|
|
|
if (result.source == .cached) try cli.stderrPrint("(using cached split data)\n");
|
|
|
|
try display(result.data, symbol, color, out);
|
|
}
|
|
|
|
pub fn display(splits: []const zfin.Split, symbol: []const u8, color: bool, out: *std.Io.Writer) !void {
|
|
try cli.setBold(out, color);
|
|
try out.print("\nSplit History for {s}\n", .{symbol});
|
|
try cli.reset(out, color);
|
|
try out.print("========================================\n", .{});
|
|
|
|
if (splits.len == 0) {
|
|
try cli.setFg(out, color, cli.CLR_MUTED);
|
|
try out.print(" No splits found.\n\n", .{});
|
|
try cli.reset(out, color);
|
|
return;
|
|
}
|
|
|
|
try cli.setFg(out, color, cli.CLR_MUTED);
|
|
try out.print("{s:>12} {s:>10}\n", .{ "Date", "Ratio" });
|
|
try out.print("{s:->12} {s:->10}\n", .{ "", "" });
|
|
try cli.reset(out, color);
|
|
|
|
for (splits) |s| {
|
|
var db: [10]u8 = undefined;
|
|
try out.print("{s:>12} {d:.0}:{d:.0}\n", .{ s.date.format(&db), s.numerator, s.denominator });
|
|
}
|
|
try out.print("\n{d} split(s)\n\n", .{splits.len});
|
|
}
|
|
|
|
// ── Tests ────────────────────────────────────────────────────
|
|
|
|
test "display shows split data" {
|
|
var buf: [4096]u8 = undefined;
|
|
var w: std.Io.Writer = .fixed(&buf);
|
|
const splits = [_]zfin.Split{
|
|
.{ .date = .{ .days = 18000 }, .numerator = 4, .denominator = 1 },
|
|
.{ .date = .{ .days = 15000 }, .numerator = 7, .denominator = 1 },
|
|
};
|
|
try display(&splits, "AAPL", false, &w);
|
|
const out = w.buffered();
|
|
try std.testing.expect(std.mem.indexOf(u8, out, "AAPL") != null);
|
|
try std.testing.expect(std.mem.indexOf(u8, out, "4:1") != null);
|
|
try std.testing.expect(std.mem.indexOf(u8, out, "7:1") != null);
|
|
try std.testing.expect(std.mem.indexOf(u8, out, "2 split(s)") != null);
|
|
}
|
|
|
|
test "display shows empty message" {
|
|
var buf: [4096]u8 = undefined;
|
|
var w: std.Io.Writer = .fixed(&buf);
|
|
const splits = [_]zfin.Split{};
|
|
try display(&splits, "BRK.A", false, &w);
|
|
const out = w.buffered();
|
|
try std.testing.expect(std.mem.indexOf(u8, out, "No splits found") != null);
|
|
}
|
|
|
|
test "display no ANSI without color" {
|
|
var buf: [4096]u8 = undefined;
|
|
var w: std.Io.Writer = .fixed(&buf);
|
|
const splits = [_]zfin.Split{
|
|
.{ .date = .{ .days = 18000 }, .numerator = 2, .denominator = 1 },
|
|
};
|
|
try display(&splits, "GOOG", false, &w);
|
|
const out = w.buffered();
|
|
try std.testing.expect(std.mem.indexOf(u8, out, "\x1b[") == null);
|
|
}
|