consolidate watchlist loading/use srf

This commit is contained in:
Emil Lerch 2026-03-19 13:00:57 -07:00
parent 46bf34fd1c
commit e29fb5b743
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 46 additions and 54 deletions

View file

@ -123,6 +123,41 @@ pub const LoadProgress = struct {
} }
}; };
// Watchlist loading
/// Load a watchlist file using the library's SRF deserializer.
/// Returns owned symbol strings. Returns null if file missing or empty.
pub fn loadWatchlist(allocator: std.mem.Allocator, path: []const u8) ?[][]const u8 {
const file_data = std.fs.cwd().readFileAlloc(allocator, path, 1024 * 1024) catch return null;
defer allocator.free(file_data);
var portfolio = zfin.cache.deserializePortfolio(allocator, file_data) catch return null;
defer portfolio.deinit();
if (portfolio.lots.len == 0) return null;
var syms: std.ArrayList([]const u8) = .empty;
for (portfolio.lots) |lot| {
const duped = allocator.dupe(u8, lot.symbol) catch continue;
syms.append(allocator, duped) catch {
allocator.free(duped);
continue;
};
}
if (syms.items.len == 0) {
syms.deinit(allocator);
return null;
}
return syms.toOwnedSlice(allocator) catch null;
}
pub fn freeWatchlist(allocator: std.mem.Allocator, watchlist: ?[][]const u8) void {
if (watchlist) |wl| {
for (wl) |sym| allocator.free(sym);
allocator.free(wl);
}
}
// Tests // Tests
test "setFg emits ANSI when color enabled" { test "setFg emits ANSI when color enabled" {

View file

@ -161,25 +161,15 @@ pub fn run(allocator: std.mem.Allocator, config: zfin.Config, svc: *zfin.DataSer
// Separate watchlist file (backward compat) // Separate watchlist file (backward compat)
if (watchlist_path) |wl_path| { if (watchlist_path) |wl_path| {
const wl_data = std.fs.cwd().readFileAlloc(allocator, wl_path, 1024 * 1024) catch null; const wl_syms = cli.loadWatchlist(allocator, wl_path);
if (wl_data) |wd| { defer cli.freeWatchlist(allocator, wl_syms);
defer allocator.free(wd); if (wl_syms) |syms_list| {
var wl_lines = std.mem.splitScalar(u8, wd, '\n'); for (syms_list) |sym| {
while (wl_lines.next()) |line| { if (watch_seen.contains(sym)) continue;
const trimmed = std.mem.trim(u8, line, &std.ascii.whitespace); try watch_seen.put(sym, {});
if (trimmed.len == 0 or trimmed[0] == '#') continue; try watch_list.append(allocator, sym);
if (std.mem.indexOf(u8, trimmed, "symbol::")) |idx| { if (svc.getCachedLastClose(sym)) |close| {
const rest = trimmed[idx + "symbol::".len ..]; try watch_prices.put(sym, close);
const end = std.mem.indexOfScalar(u8, rest, ',') orelse rest.len;
const sym = std.mem.trim(u8, rest[0..end], &std.ascii.whitespace);
if (sym.len > 0 and sym.len <= 10) {
if (watch_seen.contains(sym)) continue;
try watch_seen.put(sym, {});
try watch_list.append(allocator, sym);
if (svc.getCachedLastClose(sym)) |close| {
try watch_prices.put(sym, close);
}
}
} }
} }
} }

View file

@ -1670,41 +1670,8 @@ pub fn renderBrailleToStyledLines(arena: std.mem.Allocator, lines: *std.ArrayLis
} }
} }
pub fn loadWatchlist(allocator: std.mem.Allocator, path: []const u8) ?[][]const u8 { pub const loadWatchlist = cli.loadWatchlist;
const file_data = std.fs.cwd().readFileAlloc(allocator, path, 1024 * 1024) catch return null; pub const freeWatchlist = cli.freeWatchlist;
defer allocator.free(file_data);
var syms: std.ArrayList([]const u8) = .empty;
var file_lines = std.mem.splitScalar(u8, file_data, '\n');
while (file_lines.next()) |line| {
const trimmed = std.mem.trim(u8, line, &std.ascii.whitespace);
if (trimmed.len == 0 or trimmed[0] == '#') continue;
if (std.mem.indexOf(u8, trimmed, "symbol::")) |idx| {
const rest = trimmed[idx + "symbol::".len ..];
const end = std.mem.indexOfScalar(u8, rest, ',') orelse rest.len;
const sym = std.mem.trim(u8, rest[0..end], &std.ascii.whitespace);
if (sym.len > 0 and sym.len <= 10) {
const duped = allocator.dupe(u8, sym) catch continue;
syms.append(allocator, duped) catch {
allocator.free(duped);
continue;
};
}
}
}
if (syms.items.len == 0) {
syms.deinit(allocator);
return null;
}
return syms.toOwnedSlice(allocator) catch null;
}
pub fn freeWatchlist(allocator: std.mem.Allocator, watchlist: ?[][]const u8) void {
if (watchlist) |wl| {
for (wl) |sym| allocator.free(sym);
allocator.free(wl);
}
}
// Force test discovery for imported TUI sub-modules // Force test discovery for imported TUI sub-modules
comptime { comptime {