feat: add MANIFEST and dotfiles-link script
This commit is contained in:
parent
52bf91a6f2
commit
0718f6d21c
4 changed files with 212 additions and 1 deletions
34
MANIFEST
Normal file
34
MANIFEST
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Dotfiles Symlink Manifest
|
||||
#
|
||||
# Format: <os>:<source>:<target>
|
||||
# os = common | linux | darwin
|
||||
# source = path relative to config/
|
||||
# target = destination path ($HOME and $XDG_CONFIG_HOME are expanded)
|
||||
#
|
||||
# Lines starting with # are comments. Empty lines are ignored.
|
||||
|
||||
# Common configs (both Linux and Darwin)
|
||||
common:direnv:${XDG_CONFIG_HOME}/direnv
|
||||
common:fish:${XDG_CONFIG_HOME}/fish
|
||||
common:ghostty:${XDG_CONFIG_HOME}/ghostty
|
||||
common:git:${XDG_CONFIG_HOME}/git
|
||||
common:kitty:${XDG_CONFIG_HOME}/kitty
|
||||
common:nvim:${XDG_CONFIG_HOME}/nvim
|
||||
common:sesh:${XDG_CONFIG_HOME}/sesh
|
||||
common:spotify-player:${XDG_CONFIG_HOME}/spotify-player
|
||||
common:tmux:${XDG_CONFIG_HOME}/tmux
|
||||
common:yazi:${XDG_CONFIG_HOME}/yazi
|
||||
common:zathura:${XDG_CONFIG_HOME}/zathura
|
||||
common:emacs:${XDG_CONFIG_HOME}/emacs
|
||||
|
||||
# Linux-only configs
|
||||
linux:autorandr:${XDG_CONFIG_HOME}/autorandr
|
||||
linux:sioyek/keys_user.config:${XDG_CONFIG_HOME}/sioyek/keys_user.config
|
||||
linux:sioyek/prefs_user.linux.config:${XDG_CONFIG_HOME}/sioyek/prefs_user.config
|
||||
|
||||
# Darwin-only configs
|
||||
darwin:aerospace:${XDG_CONFIG_HOME}/aerospace
|
||||
darwin:sketchybar:${XDG_CONFIG_HOME}/sketchybar
|
||||
darwin:yabai:${XDG_CONFIG_HOME}/yabai
|
||||
darwin:sioyek/keys_user.config:${HOME}/Library/Application Support/sioyek/keys_user.config
|
||||
darwin:sioyek/prefs_user.darwin.config:${HOME}/Library/Application Support/sioyek/prefs_user.config
|
||||
176
bin/dotfiles-link
Executable file
176
bin/dotfiles-link
Executable file
|
|
@ -0,0 +1,176 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# dotfiles-link - Symlink dotfiles without Nix
|
||||
#
|
||||
# Usage: dotfiles-link [--dry-run] [--force]
|
||||
#
|
||||
# Reads MANIFEST file from dotfiles root and creates symlinks accordingly.
|
||||
# Works on both Linux and macOS (Darwin).
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ============================================================================
|
||||
# Configuration
|
||||
# ============================================================================
|
||||
|
||||
DOTFILES_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
CONFIG_DIR="${DOTFILES_DIR}/config"
|
||||
MANIFEST="${DOTFILES_DIR}/MANIFEST"
|
||||
|
||||
# Detect OS
|
||||
case "$(uname -s)" in
|
||||
Darwin) OS="darwin" ;;
|
||||
Linux) OS="linux" ;;
|
||||
*)
|
||||
echo "Unsupported OS: $(uname -s)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# XDG config directory
|
||||
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
|
||||
# ============================================================================
|
||||
# Functions
|
||||
# ============================================================================
|
||||
|
||||
DRY_RUN=true
|
||||
FORCE=false
|
||||
|
||||
usage() {
|
||||
echo "Usage: $(basename "$0") [--apply] [--force]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --apply Actually create symlinks (dry-run is default)"
|
||||
echo " --force Remove existing files/symlinks before linking"
|
||||
echo ""
|
||||
echo "Manifest: ${MANIFEST}"
|
||||
echo "Detected OS: ${OS}"
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "[dotfiles-link] $*"
|
||||
}
|
||||
|
||||
# Expand variables in target path
|
||||
expand_path() {
|
||||
local path="$1"
|
||||
# Use eval to expand $HOME and $XDG_CONFIG_HOME
|
||||
eval echo "$path"
|
||||
}
|
||||
|
||||
create_symlink() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
local target_dir
|
||||
target_dir="$(dirname "$target")"
|
||||
|
||||
# Check if source exists
|
||||
if [[ ! -e $source ]]; then
|
||||
log "SKIP: Source does not exist: $source"
|
||||
return
|
||||
fi
|
||||
|
||||
# Create parent directory if needed
|
||||
if [[ ! -d $target_dir ]]; then
|
||||
if $DRY_RUN; then
|
||||
log "WOULD CREATE DIR: $target_dir"
|
||||
else
|
||||
log "CREATE DIR: $target_dir"
|
||||
mkdir -p "$target_dir"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Handle existing target
|
||||
if [[ -e $target || -L $target ]]; then
|
||||
if [[ -L $target ]] && [[ "$(readlink "$target")" == "$source" ]]; then
|
||||
log "OK: $target (already linked)"
|
||||
return
|
||||
fi
|
||||
|
||||
if $FORCE; then
|
||||
if $DRY_RUN; then
|
||||
log "WOULD REMOVE: $target"
|
||||
else
|
||||
log "REMOVE: $target"
|
||||
rm -rf "$target"
|
||||
fi
|
||||
else
|
||||
log "SKIP: $target exists (use --force to override)"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create symlink
|
||||
if $DRY_RUN; then
|
||||
log "WOULD LINK: $target -> $source"
|
||||
else
|
||||
log "LINK: $target -> $source"
|
||||
ln -s "$source" "$target"
|
||||
fi
|
||||
}
|
||||
|
||||
process_manifest() {
|
||||
if [[ ! -f $MANIFEST ]]; then
|
||||
log "ERROR: Manifest not found: $MANIFEST"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS= read -r line || [[ -n $line ]]; do
|
||||
# Skip comments and empty lines
|
||||
[[ -z $line || $line =~ ^[[:space:]]*# ]] && continue
|
||||
|
||||
# Parse: os:source:target
|
||||
local entry_os="${line%%:*}"
|
||||
local rest="${line#*:}"
|
||||
local source="${rest%%:*}"
|
||||
local target="${rest#*:}"
|
||||
|
||||
# Check if this entry applies to current OS
|
||||
if [[ $entry_os != "common" && $entry_os != "$OS" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Expand variables and create symlink
|
||||
target="$(expand_path "$target")"
|
||||
create_symlink "${CONFIG_DIR}/${source}" "$target"
|
||||
done <"$MANIFEST"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Main
|
||||
# ============================================================================
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--apply)
|
||||
DRY_RUN=false
|
||||
shift
|
||||
;;
|
||||
--force)
|
||||
FORCE=true
|
||||
shift
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log "Dotfiles directory: ${DOTFILES_DIR}"
|
||||
log "OS: ${OS}"
|
||||
$DRY_RUN && log "DRY RUN MODE - no changes will be made"
|
||||
echo ""
|
||||
|
||||
process_manifest
|
||||
|
||||
echo ""
|
||||
log "Done!"
|
||||
|
|
@ -50,7 +50,7 @@ zoom_inc_factor 1.2
|
|||
|
||||
# Inverse search - click PDF to jump to Neovim source
|
||||
# %1 = filename, %2 = line number
|
||||
inverse_search_command /Users/rayandrew/dotfiles/bin/nvim-vimtex-callback %2 %1
|
||||
inverse_search_command /home/rayandrew/dotfiles/bin/nvim-vimtex-callback %2 %1
|
||||
|
||||
# Control+click triggers synctex inverse search
|
||||
control_click_command synctex_under_cursor
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
hm.home.packages = with pkgs; [
|
||||
vscode
|
||||
claude-code
|
||||
codex
|
||||
];
|
||||
|
||||
# home manager
|
||||
|
|
|
|||
Loading…
Reference in a new issue