mirror of
https://github.com/Xevion/dotfiles.git
synced 2026-01-31 06:24:13 -06:00
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:
@@ -0,0 +1,57 @@
|
||||
# Delta Configuration - Dracula Theme
|
||||
[delta]
|
||||
# Core Settings
|
||||
navigate = true # n/N to jump between files
|
||||
side-by-side = false # Unified diff (better for small changes)
|
||||
line-numbers = true # Show line numbers
|
||||
syntax-theme = Dracula # Match Dracula theme
|
||||
paging = never # Let lazygit handle paging
|
||||
|
||||
# Display Quality
|
||||
true-color = always
|
||||
hyperlinks = true
|
||||
hyperlinks-file-link-format = "file://{path}"
|
||||
|
||||
# Line Number Styling (clearer format)
|
||||
line-numbers-left-format = "{nm:>4} ⋮" # Old file line
|
||||
line-numbers-right-format = "{np:>4} │" # New file line
|
||||
line-numbers-left-style = "#6272a4" # Dracula comment
|
||||
line-numbers-right-style = "#6272a4"
|
||||
line-numbers-minus-style = "#ff5555" # Red for removed
|
||||
line-numbers-plus-style = "#50fa7b" # Green for added
|
||||
line-numbers-zero-style = "#6272a4" # Comment for unchanged
|
||||
|
||||
# Hunk Headers (the @@ lines)
|
||||
hunk-header-style = file line-number syntax
|
||||
hunk-header-decoration-style = "#bd93f9" box # Purple box
|
||||
hunk-header-line-number-style = "#f1fa8c" # Yellow line numbers
|
||||
|
||||
# File Headers
|
||||
file-style = "#ff79c6" bold # Pink filename
|
||||
file-decoration-style = "#ff79c6" ul # Underline
|
||||
|
||||
# Diff Styling (subtle backgrounds)
|
||||
minus-style = syntax "#3f2d3d" # Subtle red bg for deletions
|
||||
minus-emph-style = syntax "#5f3746" # Stronger red for changed parts
|
||||
minus-non-emph-style = syntax auto
|
||||
plus-style = syntax "#273a2e" # Subtle green bg for additions
|
||||
plus-emph-style = syntax "#2f4f39" # Stronger green for changed parts
|
||||
plus-non-emph-style = syntax auto
|
||||
|
||||
# Whitespace Handling
|
||||
whitespace-error-style = "#ff5555" reverse # Highlight trailing whitespace
|
||||
|
||||
# Merge Conflict Styling
|
||||
merge-conflict-begin-symbol = "⌃"
|
||||
merge-conflict-end-symbol = "⌄"
|
||||
merge-conflict-ours-diff-header-style = "#f1fa8c" bold
|
||||
merge-conflict-theirs-diff-header-style = "#f1fa8c" bold italic
|
||||
|
||||
[interactive]
|
||||
diffFilter = delta --color-only --features=interactive
|
||||
|
||||
[delta "interactive"]
|
||||
keep-plus-minus-markers = false
|
||||
|
||||
[diff]
|
||||
colorMoved = default
|
||||
@@ -1,23 +1,137 @@
|
||||
gui:
|
||||
# Dracula Theme - Official Colors
|
||||
theme:
|
||||
activeBorderColor:
|
||||
- "#E97387"
|
||||
- "#ff79c6" # Pink
|
||||
- bold
|
||||
inactiveBorderColor:
|
||||
- "#a5adce"
|
||||
optionsTextColor:
|
||||
- "#8caaee"
|
||||
selectedLineBgColor:
|
||||
- "#ECCFD3"
|
||||
cherryPickedCommitBgColor:
|
||||
- "#51576d"
|
||||
cherryPickedCommitFgColor:
|
||||
- "#CFF2E2"
|
||||
unstagedChangesColor:
|
||||
- "#E97387"
|
||||
defaultFgColor:
|
||||
- "#6B6B6B"
|
||||
- "#6272a4" # Comment
|
||||
searchingActiveBorderColor:
|
||||
- "#e5c890"
|
||||
- "#8be9fd" # Cyan
|
||||
- bold
|
||||
optionsTextColor:
|
||||
- "#bd93f9" # Purple
|
||||
selectedLineBgColor:
|
||||
- "#44475a" # Current Line
|
||||
inactiveViewSelectedLineBgColor:
|
||||
- bold
|
||||
cherryPickedCommitFgColor:
|
||||
- "#8be9fd" # Cyan
|
||||
cherryPickedCommitBgColor:
|
||||
- "#44475a" # Current Line
|
||||
markedBaseCommitFgColor:
|
||||
- "#f1fa8c" # Yellow
|
||||
markedBaseCommitBgColor:
|
||||
- "#44475a" # Current Line
|
||||
unstagedChangesColor:
|
||||
- "#ff5555" # Red
|
||||
defaultFgColor:
|
||||
- "#f8f8f2" # Foreground
|
||||
authorColors:
|
||||
"*": "#babbf1"
|
||||
"*": "#bd93f9" # Unified purple for all authors
|
||||
# Nerd Fonts
|
||||
nerdFontsVersion: "3"
|
||||
showFileIcons: true
|
||||
# Visual Preferences
|
||||
border: "rounded"
|
||||
animateExplosion: true
|
||||
# Info Density (Balanced)
|
||||
showListFooter: true
|
||||
showFileTree: true
|
||||
showCommandLog: true
|
||||
showBottomLine: true
|
||||
showPanelJumps: true
|
||||
commitHashLength: 8
|
||||
showBranchCommitHash: false
|
||||
showDivergenceFromBaseBranch: "arrowAndNumber"
|
||||
# Disable Annoying Popups
|
||||
skipDiscardChangeWarning: true
|
||||
skipStashWarning: true
|
||||
skipRewordInEditorWarning: true
|
||||
showRandomTip: false
|
||||
# Window Sizing
|
||||
scrollHeight: 8
|
||||
sidePanelWidth: 0.3333
|
||||
expandFocusedSidePanel: false
|
||||
# Commit Display
|
||||
commitAuthorShortLength: 2
|
||||
commitAuthorLongLength: 17
|
||||
git:
|
||||
# Paging (use delta)
|
||||
pagers:
|
||||
- colorArg: always
|
||||
pager: delta
|
||||
# Auto-behaviors
|
||||
autoFetch: true
|
||||
autoRefresh: true
|
||||
fetchAll: true
|
||||
autoStageResolvedConflicts: true
|
||||
# Commit Settings
|
||||
commit:
|
||||
signOff: false
|
||||
autoWrapCommitMessage: true
|
||||
autoWrapWidth: 72
|
||||
# Log Display
|
||||
log:
|
||||
order: "topo-order"
|
||||
showGraph: "always"
|
||||
showWholeGraph: false
|
||||
# Parsing
|
||||
parseEmoji: true
|
||||
# Copy Behavior
|
||||
truncateCopiedCommitHashesTo: 12
|
||||
os:
|
||||
edit: "micro {{filename}}"
|
||||
editAtLine: "micro {{filename}}:{{line}}"
|
||||
editAtLineAndWait: "micro {{filename}}:{{line}}"
|
||||
editInTerminal: true
|
||||
update:
|
||||
method: "never"
|
||||
confirmOnQuit: false
|
||||
quitOnTopLevelReturn: false
|
||||
disableStartupPopups: true
|
||||
promptToReturnFromSubprocess: false
|
||||
refresher:
|
||||
refreshInterval: 2 # Fast refresh for file changes
|
||||
fetchInterval: 60 # Fetch from remote every 60s
|
||||
customCommands:
|
||||
- key: "a"
|
||||
context: "commits"
|
||||
description: "Show CI status for commit"
|
||||
command: 'bash -c "gh run list --commit {{.SelectedCommit.Sha}} --json conclusion,status,name,updatedAt --jq ''if length == 0 then \"No CI runs found\" else .[] | \"\\(.name): \\(if .conclusion == \"success\" then \"✓\" elif .conclusion == \"failure\" then \"✗\" elif .status == \"in_progress\" then \"⏳\" else \"?\" end) \\(.conclusion // .status)\" end''"'
|
||||
loadingText: "Checking CI status..."
|
||||
- key: "A"
|
||||
context: "commits"
|
||||
description: "View CI logs for commit"
|
||||
command: 'bash -c "RUN_ID=$(gh run list --commit {{.SelectedCommit.Sha}} --json databaseId -q ''.[0].databaseId''); if [ -n \"$RUN_ID\" ]; then gh run view $RUN_ID --log; else echo \"No CI runs found for this commit\"; fi"'
|
||||
loadingText: "Loading CI logs..."
|
||||
- key: "a"
|
||||
context: "localBranches"
|
||||
description: "Show CI status for branch"
|
||||
command: 'bash -c "gh run list --branch {{.SelectedLocalBranch.Name}} -L 1 --json conclusion,status,name,updatedAt --jq ''if length == 0 then \"No CI runs for this branch\" else .[0] | \"Latest: \\(.name) - \\(if .conclusion == \"success\" then \"✓ Passed\" elif .conclusion == \"failure\" then \"✗ Failed\" elif .status == \"in_progress\" then \"⏳ Running\" else .status end) (\\(.updatedAt))\" end''"'
|
||||
loadingText: "Checking CI status..."
|
||||
- key: "A"
|
||||
context: "localBranches"
|
||||
description: "View latest CI run for branch"
|
||||
command: 'bash -c "RUN_ID=$(gh run list --branch {{.SelectedLocalBranch.Name}} -L 1 --json databaseId -q ''.[0].databaseId''); if [ -n \"$RUN_ID\" ]; then gh run view $RUN_ID --log; else echo \"No CI runs found for this branch\"; fi"'
|
||||
loadingText: "Loading CI logs..."
|
||||
- key: "w"
|
||||
context: "files"
|
||||
description: "Commit staged changes without pre-commit hooks"
|
||||
prompts:
|
||||
- type: "input"
|
||||
title: "Commit message"
|
||||
key: "message"
|
||||
command: 'git commit --no-verify -m "{{.Form.message}}"'
|
||||
- key: "o"
|
||||
context: "commits"
|
||||
description: "Open commit in GitHub"
|
||||
command: "gh browse {{.SelectedCommit.Sha}}"
|
||||
- key: "o"
|
||||
context: "files"
|
||||
description: "Open file in GitHub"
|
||||
command: "gh browse {{.SelectedFile.Name}}"
|
||||
- key: "<c-r>"
|
||||
context: "localBranches"
|
||||
description: "Create PR for branch"
|
||||
command: "gh pr create --fill --web"
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
-->
|
||||
<fontconfig>
|
||||
|
||||
<!-- ============================================================
|
||||
Global Rendering Settings
|
||||
============================================================ -->
|
||||
|
||||
<!-- Enable antialiasing for smooth edges -->
|
||||
<match target="font">
|
||||
<edit name="antialias" mode="assign">
|
||||
@@ -87,10 +83,6 @@
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!-- ============================================================
|
||||
Default Font Aliases
|
||||
============================================================ -->
|
||||
|
||||
<!-- Sans-serif: Inter with Noto Sans fallback -->
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
@@ -194,10 +186,6 @@
|
||||
</prefer>
|
||||
</alias>
|
||||
|
||||
<!-- ============================================================
|
||||
Font-Specific Tweaks
|
||||
============================================================ -->
|
||||
|
||||
<!--
|
||||
Geist Mono: Use slight hinting for clean rendering
|
||||
Geist Mono has good weight distribution
|
||||
|
||||
@@ -59,11 +59,9 @@
|
||||
editor = micro
|
||||
pager = delta
|
||||
|
||||
[interactive]
|
||||
diffFilter = delta --color-only
|
||||
|
||||
[delta]
|
||||
navigate = true # use n and N to move between diff sections
|
||||
# Delta configuration
|
||||
[include]
|
||||
path = {{ .chezmoi.sourceDir }}/.managed/git/delta-config
|
||||
|
||||
[merge]
|
||||
conflictStyle = zdiff3
|
||||
|
||||
@@ -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),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user