summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth <me@liz.coffee>2025-05-28 23:02:02 -0700
committerElizabeth <me@liz.coffee>2025-05-28 23:02:02 -0700
commitea02ee5f0c6a977ba18d457175c23774690cfc38 (patch)
tree82f9ba7b52d8ed121897035958915f80ffb3b231
parent2a0f7892fd3d00daa62a24359d2bae186092916f (diff)
downloaddotfiles-ea02ee5f0c6a977ba18d457175c23774690cfc38.tar.gz
dotfiles-ea02ee5f0c6a977ba18d457175c23774690cfc38.zip
Working dotfiles!
-rw-r--r--.gitignore1
-rw-r--r--context.json68
-rw-r--r--contexts.json61
-rwxr-xr-xdots.py223
-rw-r--r--home/.pubkey.j21
-rwxr-xr-xhome/scripts/system_name.sh6
-rw-r--r--kawaii_logger.py68
-rwxr-xr-xzsh/.config/zsh/setup/gpg.zsh.j2 (renamed from zsh/.config/zsh/setup/gpg.zsh)4
8 files changed, 252 insertions, 180 deletions
diff --git a/.gitignore b/.gitignore
index 042f81c..d6ab7c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.compiled_dotfiles/
.venv
+__pycache__
diff --git a/context.json b/context.json
new file mode 100644
index 0000000..949ca69
--- /dev/null
+++ b/context.json
@@ -0,0 +1,68 @@
+{
+ "osx": {
+ "work": {
+ "user": {
+ "name": "Elizabeth Hunt",
+ "email": "lizhunt@amazon.com",
+ "work_email": "lizhunt@amazon.com",
+ "personal_email": "me@liz.coffee"
+ },
+ "paths": {
+ "homebrew": "/opt/homebrew",
+ "toolbox": "$HOME/.toolbox/bin"
+ },
+ "features": {
+ "work_mode": true,
+ "gpg": true,
+ "amazon_tools": true
+ },
+ "settings": {
+ "pinentry": "mac",
+ "theme": "work"
+ }
+ },
+ "armin": {
+ "user": {
+ "name": "Elizabeth Alexander Hunt",
+ "email": "me@liz.coffee",
+ "personal_email": "me@liz.coffee"
+ },
+ "paths": {
+ "homebrew": "/opt/homebrew"
+ },
+ "features": {
+ "work_mode": false,
+ "gpg": true
+ },
+ "settings": {
+ "pinentry": "mac",
+ "theme": "personal"
+ }
+ }
+ },
+ "linux": {
+ "default": {
+ "user": {
+ "name": "Elizabeth Alexander Hunt",
+ "email": "me@liz.coffee",
+ "personal_email": "me@liz.coffee"
+ },
+ "features": {
+ "work_mode": false,
+ "gpg": true,
+ "amazon_tools": false
+ },
+ "settings": {
+ "pinentry": "qt",
+ "theme": "dark"
+ }
+ }
+ },
+ "_global": {
+ "pgp": {
+ "signing": "7BB52F7036FA7C18",
+ "id": "DC4323D1738F27358793D6E87BB52F7036FA7C18",
+ "asc": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nComment: Hostname: \nVersion: Hockeypuck 2.2\n\n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\nLP/ND52wrv48gGe2pagTew==\n=mxMg\n-----END PGP PUBLIC KEY BLOCK-----"
+ }
+ }
+}
diff --git a/contexts.json b/contexts.json
deleted file mode 100644
index 36788f3..0000000
--- a/contexts.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "osx": {
- "work": {
- "user": {
- "name": "Elizabeth Hunt",
- "email": "lizhunt@amazon.com",
- "work_email": "lizhunt@amazon.com",
- "personal_email": "me@liz.coffee"
- },
- "paths": {
- "homebrew": "/opt/homebrew",
- "toolbox": "$HOME/.toolbox/bin"
- },
- "features": {
- "work_mode": true,
- "gpg": true,
- "amazon_tools": true
- },
- "settings": {
- "pinentry": "mac",
- "theme": "work"
- }
- },
- "armin": {
- "user": {
- "name": "Elizabeth Alexander Hunt",
- "email": "me@liz.coffee",
- "personal_email": "me@liz.coffee"
- },
- "paths": {
- "homebrew": "/opt/homebrew"
- },
- "features": {
- "work_mode": false,
- "gpg": true
- },
- "settings": {
- "pinentry": "mac",
- "theme": "personal"
- }
- }
- },
- "linux": {
- "default": {
- "user": {
- "name": "Elizabeth Alexander Hunt",
- "email": "me@liz.coffee",
- "personal_email": "me@liz.coffee"
- },
- "features": {
- "work_mode": false,
- "gpg": true,
- "amazon_tools": false
- },
- "settings": {
- "pinentry": "qt",
- "theme": "dark"
- }
- }
- }
-}
diff --git a/dots.py b/dots.py
index 7dec208..f94bcfe 100755
--- a/dots.py
+++ b/dots.py
@@ -2,7 +2,7 @@
from dataclasses import dataclass
from pathlib import Path
-from typing import Dict, List, Optional
+from typing import Dict, List, Optional, Any
import argparse
import json
import logging
@@ -11,24 +11,26 @@ import subprocess
import sys
import shutil
from concurrent.futures import Executor, ThreadPoolExecutor, as_completed
+from functools import reduce
import jinja2
+from kawaii_logger import setup_logger
@dataclass(frozen=True)
class Config:
- SCRIPT_DIR: Path = Path(__file__).parent / "home/scripts"
- COMPILED_DIR: Path = Path(".compiled_dotfiles")
- CONTEXTS: Path = Path("context.json")
- DEFAULT_TARGET_DIR: Path = Path.home()
- DEFAULT_SOURCE_DIR: Path = Path(".")
- MAX_WORKERS: int = (os.cpu_count() or 1) * 2
+ script_dir: Path = Path(__file__).parent / "home/scripts"
+ compiled_dir: Path = Path(".compiled_dotfiles")
+ contexts: Path = Path("context.json")
+ default_target_dir: Path = Path.home()
+ default_source_dir: Path = Path(".")
+ max_workers: int = (os.cpu_count() or 1) * 2
@dataclass(frozen=True)
class Environment:
platform: str
- device_name: str
- context: Dict
+ system_name: str
+ context: Dict[str, Any]
verbose: bool
logger: logging.Logger
@@ -38,134 +40,129 @@ def main() -> None:
env = initialize_environment(args.verbose)
if not (args.compile or args.stow or args.clean):
- env.logger.error("At least one of --compile, --stow, or --clean must be specified")
+ env.logger.error("you gotta specify at least one action nya~ (⁎⁍̴̆‾⁍̴̆⁎)")
sys.exit(1)
if args.compile:
- env.logger.debug(f"Compiling {args.source} -> {args.comp}")
- if not compile_dotfiles(args.source, args.comp, env):
- env.logger.error("Failed to compile dotfiles")
+ env.logger.info(f"compiling {args.source} to {args.comp} ✨✧˖°")
+ if not compile_dotfiles(Path(args.source), Path(args.comp), env):
+ env.logger.error("uh oh! failed to compile dotfiles (ɐ•゚́•̀ɐ)")
sys.exit(1)
if args.stow:
- env.logger.debug(f"Stowing {(args.target)}")
- if not stow_dotfiles(args.comp, args.target, env, clean=False):
- env.logger.error("Failed to stow dotfiles")
+ if not stow_dotfiles(Path(args.comp), Path(args.target), env, clean=False):
+ env.logger.error("failed to stow dotfiles... nyaaa (╥゚╥)")
sys.exit(1)
if args.clean:
- env.logger.debug(f"Cleaning dotfiles from {(args.target)}")
- if not stow_dotfiles(args.comp, args.target, env, clean=True):
- env.logger.error("Failed to clean dotfiles")
+ env.logger.info(f"cleaning dotfiles from {args.target} (⌟‾╥ ‾╥)°")
+ if not stow_dotfiles(Path(args.comp), Path(args.target), env, clean=True):
+ env.logger.error("couldn’t clean dotfiles... sobs (ɐ•゚́•̀ɐ)")
sys.exit(1)
- env.logger.info("Done!")
+ env.logger.info("yay~ all done!! ₕᵒ. .ᵒₕ♡")
sys.exit(0)
def initialize_environment(verbose: bool) -> Environment:
- logger = setup_logging(verbose)
+ logger = setup_logger(verbose)
platform = get_platform()
- device_name = get_device_name()
+ system_name = get_system_name()
context = {
- **load_context(platform, device_name, Config.CONTEXTS),
- "platform": platform,
- "device_name": device_name,
+ **merge_dicts(
+ load_context(platform, system_name, Config.contexts, logger),
+ {"platform": platform, "system_name": system_name},
+ )
}
-
- return Environment(platform, device_name, context, verbose, logger)
+ return Environment(platform, system_name, context, verbose, logger)
-def copy_with_templates_rendered(executor: Executor, source: Path, destination: Path, env: Environment) -> bool:
+def copy_with_templates_rendered(
+ executor: Executor, source: Path, destination: Path, env: Environment
+) -> bool:
shutil.copytree(source, destination, dirs_exist_ok=True)
- env.logger.debug(f"copytree {source} -> {destination}")
+ env.logger.debug(f"copied {source} to {destination} ₰˜⋉♡")
templates = [t for t in destination.glob("**/*.j2") if t.is_file()]
if not templates:
- env.logger.debug(f"{source} has no templates")
+ env.logger.debug(f"no templates to render in {source} (•ᴗ•)⁎")
return True
for template in templates:
- env.logger.debug(f"submitting work to render {source} . {templates}")
+ env.logger.debug(f"submitting template render for {template} ₰˜൨൨")
executor.submit(replace_with_rendered_template, template, env)
return True
+
def replace_with_rendered_template(template: Path, env: Environment) -> bool:
- env.logger.debug(f"rendering {template}")
+ env.logger.debug(f"rendering template {template} ✧*ฺ")
jinja_env = jinja2.Environment(
- undefined=jinja2.StrictUndefined, trim_blocks=True, lstrip_blocks=True
+ loader=jinja2.BaseLoader,
+ undefined=jinja2.StrictUndefined,
+ trim_blocks=True,
+ lstrip_blocks=True,
)
+ rendered = render(template, jinja_env, env)
with open(template, "w") as t:
- t.write(render(template, jinja_env, env) or "")
- env.logger.debug(f"stripping template suffix of {template}")
+ t.write(rendered)
+ env.logger.debug(f"removing .j2 suffix from {template.absolute()} ✧˖°")
template.rename(template.with_suffix(""))
return True
-
-def compile_dotfiles(source_dir: Path, target_dir: Path, env: Environment):
+def compile_dotfiles(source_dir: Path, target_dir: Path, env: Environment) -> bool:
target_dir.mkdir(exist_ok=True, parents=True)
- with ThreadPoolExecutor(max_workers=Config.MAX_WORKERS) as executor:
- dotfile_directories = [
- dir for dir in source_dir.iterdir() if dir.is_dir() and "." not in dir.name
- ]
- env.logger.debug(f"compiling dotfile directories {dotfile_directories}")
+ with ThreadPoolExecutor(max_workers=Config.max_workers) as executor:
+ dotfile_dirs = list_dotfiles(source_dir)
+ env.logger.debug(f"found dotfile dirs: {dotfile_dirs}")
+
futures = [
executor.submit(
- copy_with_templates_rendered, executor, dotfiles, target_dir / dotfiles.name, env
+ copy_with_templates_rendered,
+ executor,
+ d,
+ target_dir / d.name,
+ env,
)
- for dotfiles in dotfile_directories
+ for d in dotfile_dirs
]
- env.logger.debug(f"constructed {len(futures)} tasks")
- return sum(1 for future in as_completed(futures) if future.result()) == len(
- futures
- )
- return False
+ env.logger.info(f"submitted {len(futures)} tasks to executor ₰˜.༄")
+
+ return sum(1 for f in as_completed(futures) if f.result()) == len(futures)
-def render(
- source: Path,
- jinja_env: jinja2.Environment,
- env: Environment,
-) -> Optional[str]:
+def render(source: Path, jinja_env: jinja2.Environment, env: Environment) -> Optional[str]:
try:
- env.logger.debug(f"Reading {source}")
with open(source, "r") as f:
- template_content = f.read()
- env.logger.debug(f"Compiling template {source}")
- template = jinja_env.from_string(template_content)
+ content = f.read()
+ env.logger.debug(f"reading template {source} ✿.。.:・")
+ template = jinja_env.from_string(content)
+ env.logger.debug(f"rendered template from {source} ~ nyaaa :3")
return template.render(**env.context)
except Exception as e:
- env.logger.error(f"Error rendering template {source}: {e}")
+ env.logger.error(f"couldn’t render {source}: {e} (;⌓̀_⌓́)")
return None
-def stow_package_task(
- stow_dir: Path, package: Path, target_dir: Path, env: Environment
-) -> bool:
- try:
- return True
- except subprocess.SubprocessError as e:
- env.logger.error(f"Error stowing package {package.name}: {e}")
- return False
-
-
def stow_dotfiles(source_dir: Path, target_dir: Path, env: Environment, clean: bool = False) -> bool:
if not stow_installed():
+ env.logger.error("stow not installed (╥゚╥)")
return False
- packages = [d for d in source_dir.iterdir() if d.is_dir()]
- stow_op = ["-D"] if clean else ["--no-folding"]
+ packages = list_dotfiles(source_dir)
+ stow_cmd = ["-D"] if clean else ["--no-folding"]
for pkg in packages:
- run_shell_command(["stow", *stow_op, pkg.name])
+ env.logger.info(f"running stow for {pkg.name} ₰˜݆༿")
+ run_shell_command(["stow", "-d", source_dir, "-t", target_dir, *stow_cmd, pkg.name])
+
return True
def stow_installed() -> bool:
- return "" != run_shell_command(["stow", "--version"])
+ return run_shell_command(["stow", "--version"]) != ""
def run_shell_command(cmd: List[str]) -> str:
@@ -174,61 +171,59 @@ def run_shell_command(cmd: List[str]) -> str:
def get_platform() -> str:
- return run_shell_command([str(Config.SCRIPT_DIR / "platform.sh")])
+ return run_shell_command([str(Config.script_dir / "platform.sh")])
-def get_device_name() -> str:
- return run_shell_command([str(Config.SCRIPT_DIR / "system_name.sh")])
+def get_system_name() -> str:
+ os.environ["PLATFORM"] = get_platform()
+ return run_shell_command([str(Config.script_dir / "system_name.sh")])
+def list_dotfiles(p: Path) -> list[Path]:
+ denylist = [".", "__"]
+ return [d for d in p.iterdir() if d.is_dir() and all(y not in d.name for y in denylist)]
-def load_context(platform: str, device_name: str, context_file: Path) -> Dict:
+def load_context(platform: str, system_name: str, context_file: Path, logger: logging.Logger) -> Dict[str, Any]:
try:
+ logger.info(f"reading context file: {context_file} ✧*:。゚✧")
with open(context_file) as f:
contexts = json.load(f)
- if platform not in contexts:
- return {}
+ global_config = contexts.get("_global", {})
+ platform_defaults = contexts.get(platform, {}).get("_default", {})
+ defaults = merge_dicts(global_config, platform_defaults)
- return contexts[platform].get(
- device_name, contexts[platform].get("default", {})
- )
- except (FileNotFoundError, json.JSONDecodeError):
+ system_config = contexts.get(platform, {}).get(system_name, {})
+ if not system_config:
+ logger.warning(f"couldn’t find system-specific config for {platform}.{system_name} (ɐ•゚́•̀ɐ)")
+
+ return merge_dicts(defaults, system_config)
+ except (FileNotFoundError, json.JSONDecodeError) as e:
+ logger.error(f"error loading context: {e} ⋆ฺ°☁。⋆ฺ °★ °。")
return {}
-def parse_arguments() -> argparse.Namespace:
- parser = argparse.ArgumentParser(description="Dotfiles manager")
- parser.add_argument("--compile", action="store_true", help="Compile dotfiles")
- parser.add_argument("--stow", action="store_true", help="Stow compiled dotfiles")
- parser.add_argument("--clean", action="store_true", help="Clean (remove) stowed dotfiles")
- parser.add_argument(
- "--source",
- help=f"Target directory for dotfiles (default: {Config.DEFAULT_SOURCE_DIR})",
- default=Config.DEFAULT_SOURCE_DIR,
- )
- parser.add_argument(
- "--comp",
- help=f"Target directory for compiled templates (default: {Config.COMPILED_DIR})",
- default=Config.COMPILED_DIR,
- )
- parser.add_argument(
- "--target",
- help=f"Target directory for stow (default: {Config.DEFAULT_TARGET_DIR})",
- default=Config.DEFAULT_TARGET_DIR,
- )
- parser.add_argument(
- "--verbose", "-v", action="store_true", help="Enable verbose logging"
- )
- return parser.parse_args()
+def merge_dicts(*dicts: Dict[str, Any]) -> Dict[str, Any]:
+ def merge(a: Dict[str, Any], b: Dict[str, Any]) -> Dict[str, Any]:
+ out = dict(a)
+ for k, v in b.items():
+ if k in out and isinstance(out[k], dict) and isinstance(v, dict):
+ out[k] = merge(out[k], v)
+ else:
+ out[k] = v
+ return out
+ return reduce(merge, dicts, {})
-def setup_logging(verbose: bool) -> logging.Logger:
- logging.basicConfig(
- level=logging.DEBUG if verbose else logging.INFO,
- format="%(asctime)s - %(levelname)s - %(message)s",
- datefmt="%Y-%m-%d %H:%M:%S",
- )
- return logging.getLogger("dotfiles")
+def parse_arguments() -> argparse.Namespace:
+ parser = argparse.ArgumentParser(description="cute dotfiles manager ✧˖°")
+ parser.add_argument("--compile", action="store_true", help="compile dotfiles ✨")
+ parser.add_argument("--stow", action="store_true", help="stow compiled dotfiles ♡")
+ parser.add_argument("--clean", action="store_true", help="clean stowed dotfiles ˚°")
+ parser.add_argument("--source", default=Config.default_source_dir, help="source dir for dotfiles")
+ parser.add_argument("--comp", default=Config.compiled_dir, help="compiled template output dir")
+ parser.add_argument("--target", default=Config.default_target_dir, help="stow target directory")
+ parser.add_argument("--verbose", "-v", action="store_true", help="enable verbose logging ✧*ฺ", default=False)
+ return parser.parse_args()
if __name__ == "__main__":
diff --git a/home/.pubkey.j2 b/home/.pubkey.j2
new file mode 100644
index 0000000..e4e3602
--- /dev/null
+++ b/home/.pubkey.j2
@@ -0,0 +1 @@
+{{ pgp.asc }}
diff --git a/home/scripts/system_name.sh b/home/scripts/system_name.sh
index 92b714a..2625293 100755
--- a/home/scripts/system_name.sh
+++ b/home/scripts/system_name.sh
@@ -1,11 +1,11 @@
#!/bin/sh
-platform="$(platform.sh)"
+PLATFORM="${PLATFORM:-`platform.sh`}"
MACHINE="$HOST"
-if [ "$platform" = "osx" ]; then
+if [ "$PLATFORM" = "osx" ]; then
MACHINE="$(scutil --get ComputerName)"
-elif [ "$platform" = "linux" ]; then
+elif [ "$PLATFORM" = "linux" ]; then
MACHINE="$(cat /proc/sys/kernel/hostname)"
fi
diff --git a/kawaii_logger.py b/kawaii_logger.py
new file mode 100644
index 0000000..9ef3491
--- /dev/null
+++ b/kawaii_logger.py
@@ -0,0 +1,68 @@
+import logging
+import sys
+import random
+
+MOOD_EMOTICONS = {
+ "debug": ["(=^・^=)", "(=・ェ・=)", "(=^-ω-^=)", "(=^‥^=)"],
+ "info": ["(^• ω •^)", "(=^・ω・^)y=", "(≚ᄌ≚)", "(。♥‿♥。)"],
+ "warning": ["(; ̄Д ̄)", "(¬_¬;)", "(・ัω・ั)", "(・_・ヾ"],
+ "error": ["(╥﹏╥)", "(≧Д≦)", "(;′⌒`)", "(T▽T)"],
+}
+
+MOOD_SUFFIXES = {
+ "_happy": ["(ノ◕ヮ◕)ノ*:・゚✧", "(๑˃ᴗ˂)ﻭ", "(^▽^)", "( ˘⌣˘)♡(˘⌣˘ )"],
+ "_sad": ["(。•́︿•̀。)", "(╯︵╰,)", "(ಥ﹏ಥ)", "(︶︹︺)"],
+ "_anxious": ["(ノдヽ)", "(◎_◎;)", "(・_・;)", "(゚Д゚;)"],
+}
+
+LEVEL_COLORS = {
+ logging.DEBUG: "\033[95m", # light magenta
+ logging.INFO: "\033[96m", # light cyan
+ logging.WARNING: "\033[93m", # light yellow
+ logging.ERROR: "\033[91m", # light red
+ logging.CRITICAL: "\033[35m", # magenta
+}
+
+RESET_COLOR = "\033[0m"
+
+class KawaiiFormatter(logging.Formatter):
+ def format(self, record):
+ level = record.levelname.lower()
+ color = LEVEL_COLORS.get(record.levelno, "")
+ base_emotes = MOOD_EMOTICONS.get(level, [])
+ mood_emotes = []
+
+ msg_lower = record.msg.lower()
+ for suffix, emotes in MOOD_SUFFIXES.items():
+ if suffix in msg_lower:
+ mood_emotes = emotes
+ record.msg = record.msg.replace(suffix, "")
+ break
+
+ emote_pool = mood_emotes if mood_emotes else base_emotes
+ emote = random.choice(emote_pool) if emote_pool else "(・ω・)"
+
+ message = record.msg.lower().strip()
+ ts = self.formatTime(record, "%Y-%m-%d %H:%M:%S")
+ lvl = record.levelname
+ filename = record.filename
+ lineno = str(record.lineno)
+
+ formatted = f"[{ts}] {color}[{lvl}]{RESET_COLOR} [{filename}:{lineno}] {color}{message}{RESET_COLOR} {emote}"
+ return f"{formatted}{RESET_COLOR}"
+
+
+def setup_logger(verbose: bool = False) -> logging.Logger:
+ """sets up a super cute logger with sparkles and cat faces ✨"""
+ logger = logging.getLogger("dotfiles")
+ logger.setLevel(logging.DEBUG if verbose else logging.INFO)
+
+ handler = logging.StreamHandler(sys.stdout)
+ handler.setFormatter(KawaiiFormatter())
+
+ logger.handlers.clear()
+ logger.addHandler(handler)
+ logger.propagate = False
+
+ return logger
+
diff --git a/zsh/.config/zsh/setup/gpg.zsh b/zsh/.config/zsh/setup/gpg.zsh.j2
index 171b9d8..4ffb38f 100755
--- a/zsh/.config/zsh/setup/gpg.zsh
+++ b/zsh/.config/zsh/setup/gpg.zsh.j2
@@ -2,8 +2,8 @@
# -- <gpg> --
-KEY_ID="DC4323D1738F27358793D6E87BB52F7036FA7C18"
-gpg -k "$KEY_ID" >/dev/null 2>&1 || gpg --import "$HOME/Documents/pubkey"
+KEY_ID="{{ pgp.id }}"
+gpg -k "$KEY_ID" >/dev/null 2>&1 || gpg --import "$HOME/.pubkey"
cp $HOME/scripts/pinentry.sh /tmp/pinentry