import type { CommandOptions } from '../types'; /** * Shared helpers for `head`/`tail`: resolve the line count from the usual flag forms and gather * inputs (named files, or stdin when none). Kept separate so both commands stay DRY. */ /** Resolve a line count from `-n N`, `-n=N`, or `-N` flags. Returns the count + remaining file args. */ export function resolveCount( flags: Record | undefined, args: string[], def = 10, ): { count: number; files: string[] } { let count = def; let files = [...args]; for (const k of Object.keys(flags ?? {})) if (/^\d+$/.test(k)) count = parseInt(k, 10); // -50 if (typeof flags?.n === 'string' && /^\d+$/.test(flags.n)) { count = parseInt(flags.n, 10); // -n=50 } else if (flags?.n === true && files.length && /^\d+$/.test(files[0])) { count = parseInt(files[0], 10); // -n 50 files = files.slice(1); } return { count: Math.max(0, count), files }; } /** Read each file's content (or stdin when no files). Throws a CLI-style message on a bad path. */ export async function gatherInputs( files: string[], options: CommandOptions, ): Promise> { const { fs, cwd, stdin } = options; if (files.length === 0) return [{ name: '', content: await stdin.readAll() }]; const out: Array<{ name: string; content: string }> = []; for (const file of files) { const p = fs.resolvePath(file, cwd); if (!(await fs.exists(p))) throw new Error(`${file}: No such file or directory`); if (!(await fs.isFile(p))) throw new Error(`${file}: Is a directory`); out.push({ name: file, content: await fs.readFile(p) }); } return out; } /** Split into lines, dropping the single empty element a trailing newline produces (so counts match coreutils). */ export function toLines(content: string): string[] { const lines = content.split('\n'); if (lines.length && lines[lines.length - 1] === '') lines.pop(); return lines; }