config: add delta config and enhance lazygit with Dracula theme

- Extract delta configuration to dedicated managed config file
- Update lazygit with full Dracula theme and quality-of-life improvements
- Remove banner comments from config files for cleaner format
- Update git-related tool scripts (install-fonts, share utility)
This commit is contained in:
2026-01-03 19:26:36 -06:00
parent ce9afed824
commit 91e58db0d9
6 changed files with 626 additions and 402 deletions
+25 -57
View File
@@ -18,10 +18,6 @@ import { join, basename } from "node:path";
import { parseArgs } from "node:util";
import { $ } from "bun";
// ============================================================================
// Types
// ============================================================================
interface GoogleFont {
id: string;
family: string;
@@ -65,13 +61,16 @@ interface FuseResult<T> {
score?: number;
}
// ============================================================================
// Constants
// ============================================================================
const FONTS_DIR = join(homedir(), ".local", "share", "fonts");
// Meta-config location: chezmoi source dir, not deployed to filesystem
const CONFIG_PATH = join(homedir(), ".local", "share", "chezmoi", "meta", "fonts.toml");
const CONFIG_PATH = join(
homedir(),
".local",
"share",
"chezmoi",
"meta",
"fonts.toml",
);
const API_BASE = "https://gwfh.mranftl.com/api";
const CACHE_FILE = join(homedir(), ".cache", "font-catalog.json");
const CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
@@ -124,10 +123,6 @@ const CYAN = "\x1b[36m";
const RESET = "\x1b[0m";
const BOLD = "\x1b[1m";
// ============================================================================
// Logging
// ============================================================================
const log = {
info: (msg: string) => console.log(`${BLUE}[info]${RESET} ${msg}`),
success: (msg: string) => console.log(`${GREEN}[ok]${RESET} ${msg}`),
@@ -136,10 +131,6 @@ const log = {
step: (msg: string) => console.log(`${CYAN}>>>${RESET} ${msg}`),
};
// ============================================================================
// Simple Fuzzy Matching (no external deps)
// ============================================================================
function fuzzyScore(needle: string, haystack: string): number {
const n = needle.toLowerCase();
const h = haystack.toLowerCase();
@@ -181,7 +172,7 @@ function fuzzySearch<T>(
query: string,
getKey: (item: T) => string,
threshold = 0.3,
limit = 5
limit = 5,
): FuseResult<T>[] {
const results: FuseResult<T>[] = [];
@@ -197,13 +188,9 @@ function fuzzySearch<T>(
.slice(0, limit);
}
// ============================================================================
// API Functions
// ============================================================================
async function fetchWithRetry(
url: string,
retries = 3
retries = 3,
): Promise<Response | null> {
for (let i = 0; i < retries; i++) {
try {
@@ -267,14 +254,7 @@ async function fetchFontDetails(fontId: string): Promise<FontDetails | null> {
return response.json();
}
// ============================================================================
// Font Installation
// ============================================================================
async function downloadFont(
url: string,
destPath: string
): Promise<boolean> {
async function downloadFont(url: string, destPath: string): Promise<boolean> {
try {
const response = await fetchWithRetry(url);
if (!response) return false;
@@ -288,10 +268,6 @@ async function downloadFont(
}
}
// ============================================================================
// GitHub Font Installation (Iosevka, etc.)
// ============================================================================
interface GitHubRelease {
tag_name: string;
assets: Array<{
@@ -330,7 +306,9 @@ async function installGitHubFont(fontName: string): Promise<boolean> {
if (!asset) {
log.error(`No matching asset found for ${fontName} in ${release.tag_name}`);
log.info(`Available assets: ${release.assets.map((a) => a.name).join(", ")}`);
log.info(
`Available assets: ${release.assets.map((a) => a.name).join(", ")}`,
);
return false;
}
@@ -364,7 +342,9 @@ async function installGitHubFont(fontName: string): Promise<boolean> {
rmSync(zipPath, { force: true });
const files = readdirSync(fontDir).filter((f) => f.endsWith(".ttf"));
log.success(`Installed ${fontName}: ${files.length} files (${release.tag_name})`);
log.success(
`Installed ${fontName}: ${files.length} files (${release.tag_name})`,
);
return true;
}
@@ -398,7 +378,7 @@ function weightToName(weight: number): string {
async function installFont(
fontName: string,
catalog: GoogleFont[]
catalog: GoogleFont[],
): Promise<boolean> {
// Fuzzy search for the font
const results = fuzzySearch(catalog, fontName, (f) => f.family, 0.3, 5);
@@ -413,7 +393,7 @@ async function installFont(
fontName,
(name) => name,
0.3,
3
3,
);
if (githubMatches.length > 0) {
const suggestions = githubMatches.map((r) => r.item).join(", ");
@@ -427,7 +407,7 @@ async function installFont(
fontName,
(f) => f.family,
0.2,
5
5,
);
if (looseSuggestions.length > 0) {
const suggestions = looseSuggestions.map((r) => r.item.family).join(", ");
@@ -442,7 +422,7 @@ async function installFont(
// Warn if not an exact match
if (font.family.toLowerCase() !== fontName.toLowerCase()) {
log.warn(
`"${fontName}" matched to "${font.family}" (score: ${(bestMatch.score ?? 0).toFixed(2)})`
`"${fontName}" matched to "${font.family}" (score: ${(bestMatch.score ?? 0).toFixed(2)})`,
);
}
@@ -500,7 +480,7 @@ async function installFont(
if (successCount > 0) {
log.success(
`Installed ${font.family}: ${successCount} files` +
(failCount > 0 ? ` (${failCount} failed)` : "")
(failCount > 0 ? ` (${failCount} failed)` : ""),
);
return true;
} else {
@@ -513,10 +493,6 @@ async function installFont(
}
}
// ============================================================================
// Configuration
// ============================================================================
async function loadConfig(): Promise<FontConfig> {
if (!existsSync(CONFIG_PATH)) {
throw new Error(`Config not found: ${CONFIG_PATH}`);
@@ -572,10 +548,6 @@ async function loadConfig(): Promise<FontConfig> {
return config;
}
// ============================================================================
// Main Commands
// ============================================================================
async function listFonts(): Promise<void> {
const catalog = await fetchFontCatalog();
@@ -612,7 +584,7 @@ async function searchFonts(query: string): Promise<void> {
query,
(name) => name,
0.2,
10
10,
);
if (results.length === 0 && githubResults.length === 0) {
@@ -627,7 +599,7 @@ async function searchFonts(query: string): Promise<void> {
const fontName = result.item;
const score = ((result.score ?? 0) * 100).toFixed(0);
console.log(
` ${GREEN}${fontName}${RESET} (monospace) - via GitHub [${score}% match]`
` ${GREEN}${fontName}${RESET} (monospace) - via GitHub [${score}% match]`,
);
}
@@ -637,7 +609,7 @@ async function searchFonts(query: string): Promise<void> {
const score = ((result.score ?? 0) * 100).toFixed(0);
const variants = Array.isArray(font.variants) ? font.variants.length : "?";
console.log(
` ${GREEN}${font.family}${RESET} (${font.category}) - ${variants} variants [${score}% match]`
` ${GREEN}${font.family}${RESET} (${font.category}) - ${variants} variants [${score}% match]`,
);
}
console.log();
@@ -711,10 +683,6 @@ async function installFromConfig(): Promise<void> {
}
}
// ============================================================================
// Entry Point
// ============================================================================
async function main(): Promise<void> {
const { values, positionals } = parseArgs({
args: Bun.argv.slice(2),