Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283#!/usr/bin/env node// hand-meter — measure a file against the "hand" metrics from// papers/arxiv-hand-and-loop. turns "feels bloated" into numbers, and// shows where ceremony ends and real surface begins. see HAND.md.//// usage:// hand-meter <file> metrics for the working-tree file// hand-meter <file> <rev|date> [...] also measure at each rev/date, in columns//// a date (YYYY-MM-DD) resolves to the last commit on/before it touching <file>.//// hand-meter system/public/aesthetic.computer/lib/disk.mjs 2023-12-31// hand-meter system/.../disk.mjs 2023-12-31 2025-06-30 HEAD
import { execSync } from "child_process";import { readFileSync } from "fs";
const [path, ...revs] = process.argv.slice(2);if (!path) { console.error("usage: hand-meter <file> [rev|date ...]"); process.exit(1);}
const isDate = (s) => /^\d{4}-\d{2}-\d{2}$/.test(s);
// source text for a column: the working tree, a date-resolved commit, or a rev.function source(ref) { if (!ref) return { label: "working", text: readFileSync(path, "utf8") }; if (isDate(ref)) { const rev = git(`log -1 --until=${ref}T23:59:59 --format=%h -- "${path}"`); if (!rev) return { label: `${ref} (none)`, text: "" }; return { label: `${ref} @${rev}`, text: git(`show ${rev}:"${path}"`) }; } return { label: ref, text: git(`show ${ref}:"${path}"`) };}
function git(args) { try { return execSync(`git ${args}`, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim(); } catch { return ""; }}
const count = (re, s) => (s.match(re) || []).length;
function measure(text) { const lines = text ? text.split("\n") : []; const loc = lines.length; const comment = lines.filter((l) => /^\s*(\/\/|\/\*|\*)/.test(l)).length; const log = lines.filter((l) => /console\.(log|warn|error|info)/.test(l)); const emojiRe = /\p{Extended_Pictographic}/u; const fns = count(/\bfunction\b/g, text) + count(/=>\s*\{/g, text); return { "lines": loc, "comment lines": comment, "comment density": loc ? `${((comment / loc) * 100).toFixed(0)}%` : "—", "try/catch": count(/\btry\s*\{/g, text), "null guards (?. ?? ==null)": count(/\?\./g, text) + count(/\?\?/g, text) + count(/[!=]==\s*null/g, text) + count(/[!=]==\s*undefined/g, text), "banner comments (// ===)": count(/\/\/\s*=+/g, text), "emoji console logs": log.filter((l) => emojiRe.test(l)).length, "functions (approx)": fns, "avg fn length (loc/fn)": fns ? Math.round(loc / fns) : "—", };}
const cols = [source(undefined), ...revs.map(source)];const data = cols.map((c) => ({ ...c, m: measure(c.text) }));const rows = Object.keys(data[0].m);
// width-aware tableconst labelW = Math.max(...rows.map((r) => r.length));const colW = data.map((c) => Math.max(c.label.length, 12));const pad = (s, w, left = false) => (left ? String(s).padEnd(w) : String(s).padStart(w));
console.log(`\n ${path}\n`);console.log(" " + pad("metric", labelW, true) + " " + data.map((c, i) => pad(c.label, colW[i])).join(" "));console.log(" " + "─".repeat(labelW) + " " + data.map((_, i) => "─".repeat(colW[i])).join(" "));for (const r of rows) { console.log(" " + pad(r, labelW, true) + " " + data.map((c, i) => pad(c.m[r], colW[i])).join(" "));}console.log("");