From 2db0f29196999907991deea3d21be2501cb3d309 Mon Sep 17 00:00:00 2001 From: m1ngsama Date: Tue, 17 Mar 2026 18:31:16 +0800 Subject: [PATCH] chore(ranger): add installer for tracked config --- README.md | 6 ++ ranger/README.md | 13 +++ scripts/install-ranger.sh | 169 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100755 scripts/install-ranger.sh diff --git a/README.md b/README.md index f458a90..da32a36 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,9 @@ - [ranger](https://github.com/ranger/ranger) - Custom keymap files + +## Quick start + +```bash +./scripts/install-ranger.sh +``` diff --git a/ranger/README.md b/ranger/README.md index 5130987..4840739 100644 --- a/ranger/README.md +++ b/ranger/README.md @@ -16,8 +16,21 @@ sudo pacman -S --needed \ perl-image-exiftool w3m mpv trash-cli unrar poppler imagemagick bat jq file ``` +## Install + +```bash +./scripts/install-ranger.sh +``` + +Useful options: + +- `./scripts/install-ranger.sh --dry-run` +- `./scripts/install-ranger.sh --copy` +- `./scripts/install-ranger.sh --target-dir ~/.config/ranger` + ## Notes - `preview_images_method ueberzug` works well in X11 terminals such as Alacritty. - `chafa` provides a readable fallback when graphical image previews are unavailable. - `trash-cli` powers the `dt` and `dT` key bindings in `rc.conf`. +- Existing `rc.conf` and `scope.sh` files are backed up under `~/.local/state/dotfiles-backups/ranger/`. diff --git a/scripts/install-ranger.sh b/scripts/install-ranger.sh new file mode 100755 index 0000000..94f9fe2 --- /dev/null +++ b/scripts/install-ranger.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +repo_root="$(cd -- "${script_dir}/.." && pwd)" +source_dir="${repo_root}/ranger" + +target_dir="${XDG_CONFIG_HOME:-${HOME}/.config}/ranger" +state_dir="${XDG_STATE_HOME:-${HOME}/.local/state}/dotfiles-backups/ranger" +backup_dir="" +mode="link" +dry_run="false" + +files=( + "rc.conf" + "scope.sh" +) + +usage() { + cat <<'EOF' +Usage: install-ranger.sh [options] + +Install the tracked ranger configuration into ~/.config/ranger. + +Options: + --copy Copy files instead of creating symlinks + --link Create symlinks (default) + --dry-run Print the planned actions without changing anything + --target-dir Override the install target directory + -h, --help Show this help message +EOF +} + +log() { + printf '%s\n' "$*" +} + +run() { + if [[ "${dry_run}" == "true" ]]; then + printf '[dry-run] %s\n' "$*" + return 0 + fi + + "$@" +} + +ensure_backup_dir() { + if [[ -n "${backup_dir}" ]]; then + return 0 + fi + + backup_dir="${state_dir}/$(date +%Y%m%d-%H%M%S)-$$" + run mkdir -p -- "${backup_dir}" +} + +backup_target() { + local target="${1}" + + if [[ ! -e "${target}" && ! -L "${target}" ]]; then + return 0 + fi + + if [[ -d "${target}" && ! -L "${target}" ]]; then + printf 'Refusing to replace directory target: %s\n' "${target}" >&2 + exit 1 + fi + + ensure_backup_dir + log "Backing up ${target} -> ${backup_dir}/$(basename -- "${target}")" + run mv -- "${target}" "${backup_dir}/$(basename -- "${target}")" +} + +install_one() { + local name="${1}" + local src="${source_dir}/${name}" + local dst="${target_dir}/${name}" + + if [[ ! -f "${src}" ]]; then + printf 'Missing source file: %s\n' "${src}" >&2 + exit 1 + fi + + if [[ "${mode}" == "link" && -L "${dst}" ]]; then + local current + current="$(readlink -- "${dst}" || true)" + if [[ "${current}" == "${src}" ]]; then + log "Already linked: ${dst}" + return 0 + fi + fi + + if [[ "${mode}" == "copy" && -f "${dst}" && ! -L "${dst}" ]] && cmp -s -- "${src}" "${dst}"; then + log "Already up to date: ${dst}" + return 0 + fi + + backup_target "${dst}" + + case "${mode}" in + link) + log "Linking ${dst} -> ${src}" + run ln -s -- "${src}" "${dst}" + ;; + copy) + local install_mode="644" + if [[ -x "${src}" ]]; then + install_mode="755" + fi + log "Copying ${src} -> ${dst}" + run install -m "${install_mode}" -- "${src}" "${dst}" + ;; + *) + printf 'Unsupported mode: %s\n' "${mode}" >&2 + exit 1 + ;; + esac +} + +while [[ $# -gt 0 ]]; do + case "${1}" in + --copy) + mode="copy" + shift + ;; + --link) + mode="link" + shift + ;; + --dry-run) + dry_run="true" + shift + ;; + --target-dir) + if [[ $# -lt 2 ]]; then + printf 'Missing value for %s\n' "${1}" >&2 + exit 1 + fi + target_dir="${2}" + shift 2 + ;; + -h | --help) + usage + exit 0 + ;; + *) + printf 'Unknown argument: %s\n' "${1}" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ ! -d "${source_dir}" ]]; then + printf 'Missing ranger source directory: %s\n' "${source_dir}" >&2 + exit 1 +fi + +run mkdir -p -- "${target_dir}" + +for name in "${files[@]}"; do + install_one "${name}" +done + +if [[ -n "${backup_dir}" ]]; then + log "Backups stored in ${backup_dir}" +fi + +log "ranger config installed into ${target_dir}"