import { AT_FIELD, READ_FIELD, TO_FIELD } from "../formatters/board.formatter.ts"; import { alreadyMarked, itemNotFound, marked, notAddressed } from "../strings/mark.strings.ts"; import { readFileSync, writeFileSync } from "node:fs"; import { itemSpans } from "../resolvers/sweep.resolver.ts"; export interface MarkRequest { readonly target: string; readonly absolute: string; readonly item: string; readonly agent: string; } export interface MarkOutcome { readonly code: number; readonly message: string; } export const markedReaders = function markedReaders(marker: string): string[] { const at = marker.indexOf(READ_FIELD); if (at === -1) { return []; } const rest = marker.slice(at + READ_FIELD.length); let value = ""; for (const character of rest) { if (character === " ") { break; } value += character; } return value.length === 0 ? [] : value.split(","); }; const withReader = function withReader(marker: string, agent: string): string { const readers = markedReaders(marker); if (readers.includes(agent)) { return marker; } const joined = [...readers, agent].join(","); const at = marker.indexOf(READ_FIELD); if (at === -1) { return `${marker} ${READ_FIELD}${joined}`; } const tail = marker.slice(at + READ_FIELD.length); let width = 0; while (width < tail.length && tail.charAt(width) !== " ") { width += 1; } return `${marker.slice(0, at)}${READ_FIELD}${joined}${tail.slice(width)}`; }; export const runMark = function runMark(request: MarkRequest): MarkOutcome { const source = readFileSync(request.absolute, "utf8"); const span = itemSpans(source).find((entry) => entry.key === request.item); if (span === undefined) { return { code: 2, message: itemNotFound(request.item, request.target) }; } if (span.to.length > 0 && !span.to.includes(request.agent)) { return { code: 2, message: notAddressed(request.item, request.agent) }; } const lines = source.split("\n"); const marker = lines[span.from] ?? ""; if (markedReaders(marker).includes(request.agent)) { return { code: 0, message: alreadyMarked(request.agent, request.item) }; } lines[span.from] = withReader(marker, request.agent); writeFileSync(request.absolute, lines.join("\n"), "utf8"); return { code: 0, message: marked(request.agent, request.item) }; }; export const healRequested = function healRequested(argv: readonly string[], flag: string): boolean { return !argv.includes(flag); }; export const authorOf = function authorOf(item: string): string { const cut = item.indexOf("-"); return cut <= 0 ? item : item.slice(0, cut); }; export const unmarkedReaders = function unmarkedReaders( marker: string, addressed: readonly string[], active: readonly string[], author = "", ): string[] { const readers = markedReaders(marker); const named = addressed.length === 0 ? active : addressed; return named.filter((letter) => letter !== author && active.includes(letter) && !readers.includes(letter)); }; export const carriesLedger = function carriesLedger(marker: string): boolean { return marker.includes(READ_FIELD) || marker.includes(TO_FIELD) || marker.includes(AT_FIELD); };