@sebastienrousseau/dotfiles 0.2.520 → 0.2.522
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/LICENSE-APACHE +190 -0
- package/LICENSE-MIT +21 -0
- package/README.md +43 -37
- package/install.sh +76 -10
- package/package.json +7 -7
- package/tools/README.md +49 -0
- package/tools/ci/install-chezmoi-verified.sh +68 -0
- package/docs/.vitepress/reports/localization-readability-audit.md +0 -73
- package/docs/AI.md +0 -179
- package/docs/ARCHITECTURE.md +0 -117
- package/docs/CNAME +0 -1
- package/docs/CONFIG_STRATEGY.md +0 -124
- package/docs/COPYRIGHT +0 -7
- package/docs/ECOSYSTEM.md +0 -220
- package/docs/GOLD-STANDARD-AUDIT.md +0 -352
- package/docs/GOVERNANCE.md +0 -98
- package/docs/MAINTAINERS.md +0 -41
- package/docs/MINIMUM-TOOLCHAIN.md +0 -100
- package/docs/NAMING_CONVENTIONS.md +0 -102
- package/docs/OPENCODE.md +0 -127
- package/docs/README.md +0 -84
- package/docs/STRUCTURE.md +0 -102
- package/docs/adr/ADR-001-ci-cd-pipeline.md +0 -118
- package/docs/adr/ADR-002-shell-performance.md +0 -130
- package/docs/adr/ADR-003-security-first.md +0 -158
- package/docs/adr/ADR-004-cli-architecture.md +0 -171
- package/docs/adr/ADR-005-chezmoi-choice.md +0 -99
- package/docs/adr/ADR-006-shell-selection.md +0 -124
- package/docs/adr/ADR-007-multi-shell-parity.md +0 -62
- package/docs/adr/ADR-008-alias-system-architecture.md +0 -95
- package/docs/adr/ADR-009-wallpaper-driven-theming.md +0 -131
- package/docs/adr/ADR-010-starship-transient-prompt.md +0 -144
- package/docs/adr/ADR-011-nushell-tier3-keep.md +0 -144
- package/docs/adr/ADR-012-ai-fleet-local-proxy.md +0 -79
- package/docs/adr/README.md +0 -40
- package/docs/architecture/AI_COST_OPTIMIZATION.md +0 -144
- package/docs/architecture/ARCHITECTURE.md +0 -20
- package/docs/architecture/INTEROP.md +0 -44
- package/docs/architecture/REPO_LAYOUT.md +0 -241
- package/docs/architecture/WALKTHROUGH.md +0 -86
- package/docs/architecture/fleet-deployment.md +0 -77
- package/docs/archive/EUXIS_2026_REVIEW.md +0 -127
- package/docs/archive/LEGACY_ROADMAP.md +0 -6
- package/docs/archive/MILESTONE_v0.2.493.md +0 -47
- package/docs/archive/PLAN.md +0 -199
- package/docs/archive/REPO_AUDIT.md +0 -31
- package/docs/articles/.pages +0 -6
- package/docs/articles/2026-07-05-custom-mkdocs-material-dark-theme.md +0 -216
- package/docs/articles/2026-07-05-fish-startup-abbr.md +0 -153
- package/docs/articles/2026-07-05-master-to-main-rename-runbook.md +0 -128
- package/docs/articles/index.md +0 -36
- package/docs/guides/INSTALL.md +0 -144
- package/docs/guides/MACOS_ICLOUD_SYMLINKS.md +0 -121
- package/docs/guides/NEOVIM_IDE_GUIDE.md +0 -61
- package/docs/guides/THEMING.md +0 -230
- package/docs/guides/TROUBLESHOOTING.md +0 -176
- package/docs/guides/WSL2_NIX_TROUBLESHOOTING.md +0 -792
- package/docs/index.md +0 -132
- package/docs/interop/A2A.md +0 -39
- package/docs/interop/POWERSHELL.md +0 -102
- package/docs/manual/00-introduction.md +0 -89
- package/docs/manual/01-concepts/01-architecture.md +0 -138
- package/docs/manual/01-concepts/02-trust-model.md +0 -183
- package/docs/manual/01-concepts/03-theme-engine.md +0 -186
- package/docs/manual/01-concepts/04-fleet.md +0 -148
- package/docs/manual/01-concepts/05-self-healing.md +0 -204
- package/docs/manual/02-tutorials/01-first-install.md +0 -197
- package/docs/manual/02-tutorials/02-add-wallpaper.md +0 -216
- package/docs/manual/02-tutorials/03-create-profile.md +0 -244
- package/docs/manual/02-tutorials/04-encrypt-secret.md +0 -281
- package/docs/manual/02-tutorials/05-deploy-fleet.md +0 -283
- package/docs/manual/03-reference/01-dot-cli.md +0 -475
- package/docs/manual/03-reference/02-config-files.md +0 -265
- package/docs/manual/03-reference/03-environment.md +0 -124
- package/docs/manual/03-reference/04-templates.md +0 -190
- package/docs/manual/03-reference/05-feature-flags.md +0 -187
- package/docs/manual/04-cookbook/01-recipes.md +0 -285
- package/docs/manual/04-cookbook/02-troubleshooting.md +0 -351
- package/docs/manual/04-cookbook/03-faq.md +0 -175
- package/docs/manual/05-appendices/A-platform-matrix.md +0 -101
- package/docs/manual/05-appendices/B-security-checklist.md +0 -85
- package/docs/manual/05-appendices/C-glossary.md +0 -40
- package/docs/manual/05-appendices/D-bibliography.md +0 -58
- package/docs/manual/05-appendices/E-license.md +0 -38
- package/docs/manual/_toc.yml +0 -58
- package/docs/manual/command-index.md +0 -175
- package/docs/manual/concept-index.md +0 -170
- package/docs/manual/index.md +0 -66
- package/docs/migration/README.md +0 -81
- package/docs/migration/from-bare-git-repo.md +0 -156
- package/docs/migration/from-gnu-stow.md +0 -165
- package/docs/migration/from-plain-chezmoi.md +0 -148
- package/docs/migration/from-yadm.md +0 -187
- package/docs/operations/ARCHITECTURE_ROADMAP.md +0 -7
- package/docs/operations/ATTESTATION.md +0 -44
- package/docs/operations/CI_CADENCE.md +0 -107
- package/docs/operations/CI_COMPOSITES.md +0 -156
- package/docs/operations/COMPLETIONS.md +0 -123
- package/docs/operations/COVERAGE.md +0 -204
- package/docs/operations/DRIFT.md +0 -107
- package/docs/operations/HARD_AUDIT_2026.md +0 -631
- package/docs/operations/MAINTENANCE.md +0 -63
- package/docs/operations/MANIFEST.md +0 -127
- package/docs/operations/MIGRATION.md +0 -109
- package/docs/operations/OPERATIONS.md +0 -188
- package/docs/operations/PERFORMANCE.md +0 -133
- package/docs/operations/PERFORMANCE_BUDGETS.md +0 -196
- package/docs/operations/REGISTRY.md +0 -90
- package/docs/operations/RELEASE_PIPELINE.md +0 -128
- package/docs/operations/RELIABILITY.md +0 -122
- package/docs/operations/RFC_v0_2_503_reorganization.md +0 -280
- package/docs/operations/ROADMAP.md +0 -10
- package/docs/operations/ROADMAP_2026.md +0 -7
- package/docs/operations/ROADMAP_V0_2_503.md +0 -10
- package/docs/operations/TESTING.md +0 -216
- package/docs/operations/TRACEABILITY.md +0 -44
- package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +0 -65
- package/docs/operations/VERSION_SYNC.md +0 -393
- package/docs/packaging.md +0 -222
- package/docs/reference/ALIASES.md +0 -131
- package/docs/reference/ALIASES_CHEATSHEET.md +0 -32
- package/docs/reference/ALIASES_DEPRECATIONS.md +0 -13
- package/docs/reference/FEATURE-MATRIX.md +0 -646
- package/docs/reference/FEATURES.md +0 -66
- package/docs/reference/FONTS.md +0 -112
- package/docs/reference/POWERSHELL_PARITY.md +0 -82
- package/docs/reference/PROFILES.md +0 -69
- package/docs/reference/SCREENSHOTS.md +0 -121
- package/docs/reference/SCRIPTS.md +0 -71
- package/docs/reference/SUPPORT_MATRIX.md +0 -80
- package/docs/reference/THEMES.md +0 -117
- package/docs/reference/TOOLS.md +0 -110
- package/docs/reference/UTILS.md +0 -243
- package/docs/registry.json +0 -6
- package/docs/schema/dot-env-v1.json +0 -110
- package/docs/schema/dot-registry-v1.json +0 -33
- package/docs/security/AI_ACT_COMPLIANCE.md +0 -94
- package/docs/security/AUDIT_BYPASS.md +0 -103
- package/docs/security/AUTOMATION_SECRETS.md +0 -26
- package/docs/security/CI_EGRESS_ALLOWLIST.md +0 -127
- package/docs/security/CI_PINNING.md +0 -129
- package/docs/security/COMMIT_SIGNING.md +0 -138
- package/docs/security/COMPLIANCE.md +0 -458
- package/docs/security/DEPS_DEV_EXCEPTIONS.md +0 -86
- package/docs/security/DISCLOSURE.md +0 -130
- package/docs/security/ENCRYPTION.md +0 -57
- package/docs/security/FMEA.md +0 -159
- package/docs/security/FUZZING.md +0 -209
- package/docs/security/HISTORY_FILTERING.md +0 -132
- package/docs/security/INCIDENT_RESPONSE.md +0 -579
- package/docs/security/INSTALL_VERIFICATION.md +0 -122
- package/docs/security/KEYS.md +0 -49
- package/docs/security/KEY_ROTATION.md +0 -303
- package/docs/security/MCP_POLICY.md +0 -78
- package/docs/security/POLICY_RELEASES.md +0 -37
- package/docs/security/README.md +0 -28
- package/docs/security/SCORECARD.md +0 -195
- package/docs/security/SECRETS.md +0 -158
- package/docs/security/SECURITY.md +0 -45
- package/docs/security/SECURITY_CHECKLIST.md +0 -55
- package/docs/security/SHELL_EXEMPTIONS.md +0 -145
- package/docs/security/SOUP_REGISTER.md +0 -36
- package/docs/security/THREAT_MODEL.md +0 -130
- package/docs/security/VERIFICATION_VALIDATION.md +0 -228
- package/docs/security/VERIFY_RELEASE.md +0 -201
- package/docs/security/security-pubkey.asc +0 -15
- package/docs/stylesheets/extra.css +0 -444
- package/docs/themes/README.md +0 -10
- package/docs/themes/VISUAL_INTEGRITY_REPORT.md +0 -30
- package/docs/themes/hero-shot.svg +0 -78
- package/scripts/README.md +0 -123
- package/scripts/ci/check-copyright-headers.sh +0 -8
- package/scripts/ci/check-shell-preamble.sh +0 -8
- package/scripts/ci/guard-gitleaks-checkout.sh +0 -8
- package/scripts/demo/record.sh +0 -43
- package/scripts/diagnostics/a2a-conformance.sh +0 -163
- package/scripts/diagnostics/alias-governance.sh +0 -165
- package/scripts/diagnostics/aliases-cheatsheet.sh +0 -74
- package/scripts/diagnostics/aliases-manifest.sh +0 -77
- package/scripts/diagnostics/attest-verify.sh +0 -147
- package/scripts/diagnostics/benchmark.sh +0 -408
- package/scripts/diagnostics/conflicts.sh +0 -73
- package/scripts/diagnostics/doctor-unified.sh +0 -43
- package/scripts/diagnostics/doctor.sh +0 -797
- package/scripts/diagnostics/drift-dashboard.sh +0 -203
- package/scripts/diagnostics/health.sh +0 -656
- package/scripts/diagnostics/history-analysis.sh +0 -86
- package/scripts/diagnostics/mcp-doctor.sh +0 -582
- package/scripts/diagnostics/perf.sh +0 -453
- package/scripts/diagnostics/scorecard.sh +0 -120
- package/scripts/diagnostics/secret-governance.sh +0 -65
- package/scripts/diagnostics/security-score.sh +0 -467
- package/scripts/diagnostics/smoke-test.sh +0 -88
- package/scripts/diagnostics/snapshot.sh +0 -90
- package/scripts/diagnostics/verify.sh +0 -108
- package/scripts/diagnostics/verify_state.sh +0 -73
- package/scripts/diagnostics/version-locks.sh +0 -94
- package/scripts/diagnostics/workstation-attestation.sh +0 -212
- package/scripts/dot/commands/agent.sh +0 -535
- package/scripts/dot/commands/agents.sh +0 -352
- package/scripts/dot/commands/ai.sh +0 -600
- package/scripts/dot/commands/aliases.sh +0 -277
- package/scripts/dot/commands/appearance.sh +0 -110
- package/scripts/dot/commands/completion.sh +0 -171
- package/scripts/dot/commands/core.sh +0 -217
- package/scripts/dot/commands/diagnostics.sh +0 -265
- package/scripts/dot/commands/env-emit.sh +0 -203
- package/scripts/dot/commands/fleet.sh +0 -711
- package/scripts/dot/commands/init.sh +0 -185
- package/scripts/dot/commands/lint.sh +0 -208
- package/scripts/dot/commands/manual.sh +0 -169
- package/scripts/dot/commands/meta.sh +0 -438
- package/scripts/dot/commands/patterns.sh +0 -55
- package/scripts/dot/commands/registry.sh +0 -455
- package/scripts/dot/commands/restore.sh +0 -232
- package/scripts/dot/commands/secrets.sh +0 -296
- package/scripts/dot/commands/security.sh +0 -102
- package/scripts/dot/commands/tools.sh +0 -570
- package/scripts/dot/data/alias-deprecations.tsv +0 -2
- package/scripts/dot/powershell/Dot.psm1 +0 -319
- package/scripts/fonts/install-nerd-fonts.sh +0 -75
- package/scripts/fonts/patch-fonts.sh +0 -36
- package/scripts/git-hooks/install.sh +0 -12
- package/scripts/git-hooks/pre-commit +0 -12
- package/scripts/git-hooks/pre-commit-audit.sh +0 -146
- package/scripts/git-hooks/pre-push +0 -105
- package/scripts/git-hooks/prepare-commit-msg +0 -29
- package/scripts/lib/secrets_provider.sh +0 -200
- package/scripts/nvim/headless-upgrade.lua +0 -81
- package/scripts/ops/ai-setup.sh +0 -71
- package/scripts/ops/bundle.sh +0 -104
- package/scripts/ops/chaos.sh +0 -50
- package/scripts/ops/chezmoi-apply.sh +0 -333
- package/scripts/ops/chezmoi-diff.sh +0 -16
- package/scripts/ops/chezmoi-remove.sh +0 -46
- package/scripts/ops/chezmoi-update.sh +0 -67
- package/scripts/ops/heal-chezmoi.sh +0 -87
- package/scripts/ops/heal-system.sh +0 -129
- package/scripts/ops/heal-tools.sh +0 -297
- package/scripts/ops/heal.sh +0 -223
- package/scripts/ops/post-apply-repair.sh +0 -107
- package/scripts/ops/prewarm.sh +0 -128
- package/scripts/ops/release.sh +0 -262
- package/scripts/ops/rollback.sh +0 -613
- package/scripts/ops/setup.sh +0 -138
- package/scripts/ops/teleport.sh +0 -34
- package/scripts/qa/check-feature-matrix.sh +0 -296
- package/scripts/qa/check-version-consistency.sh +0 -12
- package/scripts/qa/coverage-baseline.sh +0 -61
- package/scripts/qa/docs-coverage.sh +0 -118
- package/scripts/qa/examples-coverage.sh +0 -94
- package/scripts/qa/powershell-contract.ps1 +0 -95
- package/scripts/qa/reliability-audit.sh +0 -139
- package/scripts/qa/scorecard-snapshot.sh +0 -128
- package/scripts/qa/traceability-coverage.sh +0 -124
- package/scripts/qa/validate-examples.sh +0 -90
- package/scripts/qa/wsl-contract.sh +0 -12
- package/scripts/secrets/age-init.sh +0 -82
- package/scripts/secrets/create-secrets-file.sh +0 -46
- package/scripts/secrets/encrypt-ssh-key.sh +0 -44
- package/scripts/security/backup.sh +0 -58
- package/scripts/security/check-disclosure-key-expiry.sh +0 -111
- package/scripts/security/dns-doh.sh +0 -52
- package/scripts/security/encryption-check.sh +0 -55
- package/scripts/security/enforce-policies.sh +0 -552
- package/scripts/security/firewall.sh +0 -91
- package/scripts/security/lock-configs.sh +0 -67
- package/scripts/security/lock-screen.sh +0 -56
- package/scripts/security/manage-secrets.sh +0 -429
- package/scripts/security/ssh-cert.sh +0 -204
- package/scripts/security/telemetry-kill.sh +0 -51
- package/scripts/security/usb-safety.sh +0 -52
- package/scripts/theme/apply-gnome-theme.sh +0 -333
- package/scripts/theme/extract-heic-frames.sh +0 -115
- package/scripts/theme/extract-theme.py +0 -1020
- package/scripts/theme/install-boot-logo.sh +0 -63
- package/scripts/theme/install-catppuccin-themes.sh +0 -371
- package/scripts/theme/install-cursors.sh +0 -26
- package/scripts/theme/install-file-icons.sh +0 -27
- package/scripts/theme/install-grub-theme.sh +0 -62
- package/scripts/theme/install-lock-icon.sh +0 -31
- package/scripts/theme/merge-wallpaper.sh +0 -146
- package/scripts/theme/rebuild-themes.sh +0 -603
- package/scripts/theme/switch.sh +0 -476
- package/scripts/theme/wallpaper-rotate.sh +0 -137
- package/scripts/theme/wallpaper-sync.sh +0 -690
- package/scripts/tools/cmatrix.sh +0 -22
- package/scripts/tools/detect-collisions.py +0 -103
- package/scripts/tools/emoji-picker.sh +0 -49
- package/scripts/tools/figlet-banner.sh +0 -19
- package/scripts/tools/log-rotate.sh +0 -31
- package/scripts/tools/lolcat-wrap.sh +0 -20
- package/scripts/tools/pipes.sh +0 -49
- package/scripts/tuning/linux.sh +0 -186
- package/scripts/tuning/macos.sh +0 -56
- package/scripts/uninstall.sh +0 -86
- package/scripts/verify-release-versions +0 -156
- package/scripts/version-sync.sh +0 -714
- package/templates/chezmoi-data/geekom-a9.toml.example +0 -21
- package/templates/chezmoi-data/mac-m1.toml.example +0 -16
- package/templates/chezmoi-data/mac-t2-linux.toml.example +0 -21
- package/templates/chezmoi-data/surface-pro-7p.toml.example +0 -21
- package/templates/projects/go/.github/workflows/ci.yml +0 -31
- package/templates/projects/go/README.md +0 -7
- package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +0 -8
- package/templates/projects/go/go.mod +0 -3
- package/templates/projects/go/go.sum +0 -0
- package/templates/projects/molecule/README.md +0 -7
- package/templates/projects/molecule/converge.yml +0 -7
- package/templates/projects/molecule/molecule.yml +0 -16
- package/templates/projects/node/.github/workflows/ci.yml +0 -30
- package/templates/projects/node/README.md +0 -7
- package/templates/projects/node/package-lock.json +0 -12
- package/templates/projects/node/package.json +0 -10
- package/templates/projects/node/src/index.js +0 -3
- package/templates/projects/packer/README.md +0 -15
- package/templates/projects/packer/main.pkr.hcl +0 -15
- package/templates/projects/python/.github/workflows/ci.yml +0 -34
- package/templates/projects/python/README.md +0 -7
- package/templates/projects/python/pyproject.toml +0 -25
- package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +0 -2
- package/templates/projects/python/tests/test_basic.py +0 -3
package/scripts/theme/switch.sh
DELETED
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
3
|
-
# Copyright (c) 2015-2026 Sebastien Rousseau
|
|
4
|
-
## Theme Switcher — Switch between theme families and light/dark modes.
|
|
5
|
-
##
|
|
6
|
-
## Supports Tokyo Night, Catppuccin, Rose Pine, Kanagawa, and other
|
|
7
|
-
## popular theme families. Updates chezmoi data and applies changes.
|
|
8
|
-
##
|
|
9
|
-
## # Requirements
|
|
10
|
-
## - chezmoi: Dotfiles manager
|
|
11
|
-
## - sed: For updating theme configuration
|
|
12
|
-
##
|
|
13
|
-
## # Usage
|
|
14
|
-
## dot theme list # Show all available themes
|
|
15
|
-
## dot theme set NAME # Set theme to NAME
|
|
16
|
-
## dot theme toggle # Toggle light/dark within family
|
|
17
|
-
## dot theme family # Switch between theme families
|
|
18
|
-
## dot theme current # Show current theme info
|
|
19
|
-
##
|
|
20
|
-
## # Platform Notes
|
|
21
|
-
## - All platforms: Updates chezmoi configuration
|
|
22
|
-
|
|
23
|
-
set -euo pipefail
|
|
24
|
-
|
|
25
|
-
# Cleanup function for temp files
|
|
26
|
-
cleanup() {
|
|
27
|
-
if [[ -n "${tmp_file:-}" ]] && [[ -f "$tmp_file" ]]; then
|
|
28
|
-
rm -f "$tmp_file"
|
|
29
|
-
fi
|
|
30
|
-
}
|
|
31
|
-
trap cleanup EXIT
|
|
32
|
-
|
|
33
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
34
|
-
# shellcheck source=../../lib/dot/ui.sh
|
|
35
|
-
# shellcheck disable=SC1091
|
|
36
|
-
source "$SCRIPT_DIR/../../lib/dot/ui.sh"
|
|
37
|
-
|
|
38
|
-
ui_init
|
|
39
|
-
|
|
40
|
-
resolve_source_dir() {
|
|
41
|
-
if [ -n "${CHEZMOI_SOURCE_DIR:-}" ] && [ -d "$CHEZMOI_SOURCE_DIR" ]; then
|
|
42
|
-
echo "$CHEZMOI_SOURCE_DIR"
|
|
43
|
-
return
|
|
44
|
-
fi
|
|
45
|
-
if [ -d "$HOME/.dotfiles" ]; then
|
|
46
|
-
echo "$HOME/.dotfiles"
|
|
47
|
-
return
|
|
48
|
-
fi
|
|
49
|
-
if [ -d "$HOME/.local/share/chezmoi" ]; then
|
|
50
|
-
echo "$HOME/.local/share/chezmoi"
|
|
51
|
-
return
|
|
52
|
-
fi
|
|
53
|
-
echo ""
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
SRC_DIR="$(resolve_source_dir)"
|
|
57
|
-
if [ -z "$SRC_DIR" ]; then
|
|
58
|
-
ui_err "Dotfiles source" "not found"
|
|
59
|
-
exit 1
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
# Descend into the chezmoi source subdir when .chezmoiroot is present (post-reorg, chezmoi files under defaults/)
|
|
63
|
-
CHEZMOI_SRC="$SRC_DIR"
|
|
64
|
-
if [[ -f "$SRC_DIR/.chezmoiroot" ]]; then
|
|
65
|
-
_sub="$(head -1 "$SRC_DIR/.chezmoiroot" | tr -d '[:space:]')"
|
|
66
|
-
[[ -n "$_sub" && -d "$SRC_DIR/$_sub" ]] && CHEZMOI_SRC="$SRC_DIR/$_sub"
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
DATA_FILE="$CHEZMOI_SRC/.chezmoidata.toml"
|
|
70
|
-
THEMES_FILE="$CHEZMOI_SRC/.chezmoidata/themes.toml"
|
|
71
|
-
WALLPAPER_DIR="${DOTFILES_WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
|
|
72
|
-
if [ ! -f "$DATA_FILE" ]; then
|
|
73
|
-
ui_err "Missing" "$DATA_FILE"
|
|
74
|
-
exit 1
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
# =============================================================================
|
|
78
|
-
# Theme Database
|
|
79
|
-
# =============================================================================
|
|
80
|
-
|
|
81
|
-
# Default preferences (must be present keys in themes.toml — the theme
|
|
82
|
-
# regeneration removed the old macos-monterey-* names; bloom is the current
|
|
83
|
-
# default family and always ships a dark+light pair).
|
|
84
|
-
DEFAULT_DARK="bloom-dark"
|
|
85
|
-
DEFAULT_LIGHT="bloom-light"
|
|
86
|
-
|
|
87
|
-
# Machine-local chezmoi override (chezmoi.toml [data] theme) takes precedence
|
|
88
|
-
# over .chezmoidata.toml when rendering, so it is the authoritative "current"
|
|
89
|
-
# value. Kept in sync by dot-theme-sync's write_theme().
|
|
90
|
-
CHEZMOI_CFG="${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.toml"
|
|
91
|
-
|
|
92
|
-
# =============================================================================
|
|
93
|
-
# Theme Functions
|
|
94
|
-
# =============================================================================
|
|
95
|
-
|
|
96
|
-
current_theme() {
|
|
97
|
-
# Prefer the machine-local override (what chezmoi actually renders), so
|
|
98
|
-
# `dot theme current` never disagrees with the deployed configs. Fall back
|
|
99
|
-
# to the repo default in .chezmoidata.toml when no override is set.
|
|
100
|
-
if [[ -f "$CHEZMOI_CFG" ]]; then
|
|
101
|
-
local override
|
|
102
|
-
override="$(awk -F'"' '/^theme =/ {print $2}' "$CHEZMOI_CFG" | head -n 1)"
|
|
103
|
-
if [[ -n "$override" ]]; then
|
|
104
|
-
echo "$override"
|
|
105
|
-
return 0
|
|
106
|
-
fi
|
|
107
|
-
fi
|
|
108
|
-
awk -F'"' '/^theme =/ {print $2}' "$DATA_FILE" | head -n 1
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
theme_mode() {
|
|
112
|
-
local name="${1:-}"
|
|
113
|
-
awk -v n="$name" '
|
|
114
|
-
$0 == "[themes." n "]" { found=1; next }
|
|
115
|
-
/^\[/ { found=0 }
|
|
116
|
-
found && /^mode/ { sub(/.*= *"/, ""); sub(/".*/, ""); print; exit }
|
|
117
|
-
' "$THEMES_FILE"
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
theme_exists() {
|
|
121
|
-
local name="${1:-}"
|
|
122
|
-
grep -q "^\[themes\.${name}\]$" "$THEMES_FILE" 2>/dev/null
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
all_theme_names() {
|
|
126
|
-
sed -n 's/^\[themes\.\([a-zA-Z0-9-]*\)\]$/\1/p' "$THEMES_FILE" | sort -u
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
# List wallpaper families that have BOTH dark and light variants in themes.toml.
|
|
130
|
-
# Only these are presented to users — unpaired wallpapers are hidden.
|
|
131
|
-
#
|
|
132
|
-
# This was two associative arrays. Those are bash 4 only, and macOS still
|
|
133
|
-
# ships 3.2 as /bin/bash, where `local -A` fails outright ("local: -A:
|
|
134
|
-
# invalid option"). Both arrays then stayed empty, so this function printed
|
|
135
|
-
# nothing and `dot theme list`, `dot theme family` and the interactive picker
|
|
136
|
-
# silently offered no themes at all on a stock macOS shell.
|
|
137
|
-
#
|
|
138
|
-
# Two newline-separated lists plus `comm` behave identically on 3.2 and 4+.
|
|
139
|
-
paired_families() {
|
|
140
|
-
local darks="" lights="" name family
|
|
141
|
-
while IFS= read -r name; do
|
|
142
|
-
case "$name" in
|
|
143
|
-
*-dark) darks="${darks}${name%-dark}"$'\n' ;;
|
|
144
|
-
*-light) lights="${lights}${name%-light}"$'\n' ;;
|
|
145
|
-
esac
|
|
146
|
-
done < <(all_theme_names)
|
|
147
|
-
|
|
148
|
-
# `fallback` is a synthetic safety theme (see themes.toml) that templates
|
|
149
|
-
# degrade to when .theme is unset/invalid — never a user-selectable one.
|
|
150
|
-
comm -12 \
|
|
151
|
-
<(printf '%s' "$darks" | sort -u) \
|
|
152
|
-
<(printf '%s' "$lights" | sort -u) |
|
|
153
|
-
grep -vxF 'fallback' || true
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
# Determine source type (system/custom) for a wallpaper family.
|
|
157
|
-
wallpaper_source() {
|
|
158
|
-
local family="${1:-}"
|
|
159
|
-
# Check for custom wallpapers: dynamic (family.heic) or split (family-dark/light.ext)
|
|
160
|
-
for ext in heic jpg png webp; do
|
|
161
|
-
if [[ -f "$WALLPAPER_DIR/${family}.${ext}" || -f "$WALLPAPER_DIR/${family}-dark.${ext}" || -f "$WALLPAPER_DIR/${family}-light.${ext}" || -f "$WALLPAPER_DIR/${family}-0.${ext}" ]]; then
|
|
162
|
-
echo "Custom"
|
|
163
|
-
return
|
|
164
|
-
fi
|
|
165
|
-
done
|
|
166
|
-
echo "System"
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
get_theme_family() {
|
|
170
|
-
local theme="${1:-}"
|
|
171
|
-
# Read family from themes.toml if available
|
|
172
|
-
if [[ -f "$THEMES_FILE" ]]; then
|
|
173
|
-
local family
|
|
174
|
-
family="$(awk -v n="$theme" '
|
|
175
|
-
$0 == "[themes." n "]" { found=1; next }
|
|
176
|
-
/^\[/ { found=0 }
|
|
177
|
-
found && /^family/ { sub(/.*= *"/, ""); sub(/".*/, ""); print; exit }
|
|
178
|
-
' "$THEMES_FILE")"
|
|
179
|
-
if [[ -n "$family" ]]; then
|
|
180
|
-
echo "$family"
|
|
181
|
-
return
|
|
182
|
-
fi
|
|
183
|
-
fi
|
|
184
|
-
# Fallback: strip -dark/-light suffix
|
|
185
|
-
local family="${theme%-dark}"
|
|
186
|
-
[[ "$family" != "$theme" ]] || family="${theme%-light}"
|
|
187
|
-
echo "$family"
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
is_dark_theme() {
|
|
191
|
-
local theme="${1:-}"
|
|
192
|
-
case "$theme" in
|
|
193
|
-
*-dark)
|
|
194
|
-
return 0
|
|
195
|
-
;;
|
|
196
|
-
*)
|
|
197
|
-
return 1
|
|
198
|
-
;;
|
|
199
|
-
esac
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
set_theme() {
|
|
203
|
-
local new_theme="${1:-}"
|
|
204
|
-
if [ -z "$new_theme" ]; then
|
|
205
|
-
# A picker needs someone to pick. Under DOTFILES_NONINTERACTIVE the
|
|
206
|
-
# selector cannot run, and ui_pick reports "nothing selected" the same
|
|
207
|
-
# way it reports a cancel — so answering with a silent success would
|
|
208
|
-
# make a forgotten argument indistinguishable from a theme change.
|
|
209
|
-
if [ "${DOTFILES_NONINTERACTIVE:-0}" = "1" ]; then
|
|
210
|
-
ui_err "Missing theme name" "no interactive picker in a non-interactive session"
|
|
211
|
-
ui_info "Usage" "dot theme set <name> (or 'dot theme list' to see them)"
|
|
212
|
-
return 1
|
|
213
|
-
fi
|
|
214
|
-
pick_theme
|
|
215
|
-
return
|
|
216
|
-
fi
|
|
217
|
-
dot-theme-sync "$new_theme"
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
# Interactive theme picker
|
|
221
|
-
pick_theme() {
|
|
222
|
-
local current
|
|
223
|
-
current="$(current_theme)"
|
|
224
|
-
|
|
225
|
-
if [[ ! -f "$THEMES_FILE" ]]; then
|
|
226
|
-
ui_err "Missing" "$THEMES_FILE"
|
|
227
|
-
exit 1
|
|
228
|
-
fi
|
|
229
|
-
|
|
230
|
-
local current_family="${current%-dark}"
|
|
231
|
-
[[ "$current_family" != "$current" ]] || current_family="${current%-light}"
|
|
232
|
-
local current_mode="dark"
|
|
233
|
-
is_dark_theme "$current" 2>/dev/null || current_mode="light"
|
|
234
|
-
|
|
235
|
-
# Build theme list: one row per family, shows active mode
|
|
236
|
-
local theme_list=""
|
|
237
|
-
local family source marker active_mode
|
|
238
|
-
while IFS= read -r family; do
|
|
239
|
-
[[ -n "$family" ]] || continue
|
|
240
|
-
source="$(wallpaper_source "$family")"
|
|
241
|
-
marker="○"
|
|
242
|
-
active_mode=""
|
|
243
|
-
if [[ "$family" == "$current_family" ]]; then
|
|
244
|
-
marker="✓"
|
|
245
|
-
active_mode="$current_mode"
|
|
246
|
-
fi
|
|
247
|
-
theme_list+="$(printf '%s %-35s %-8s %s' "$marker" "$family" "$source" "$active_mode")"$'\n'
|
|
248
|
-
done < <(paired_families)
|
|
249
|
-
|
|
250
|
-
local selected_family
|
|
251
|
-
selected_family="$(printf '%s' "$theme_list" | ui_pick \
|
|
252
|
-
--header "Select wallpaper theme (current: $current_family [$current_mode])" \
|
|
253
|
-
--prompt "Theme >" |
|
|
254
|
-
awk '$1 !~ /^#/ && NF >= 2 {print $2}')" || return 0
|
|
255
|
-
|
|
256
|
-
if [[ -n "$selected_family" ]]; then
|
|
257
|
-
# Apply with current appearance mode (dark/light)
|
|
258
|
-
local new_theme="${selected_family}-${current_mode}"
|
|
259
|
-
if [[ "$new_theme" != "$current" ]]; then
|
|
260
|
-
dot-theme-sync "$new_theme"
|
|
261
|
-
else
|
|
262
|
-
ui_info "Theme" "already on $current"
|
|
263
|
-
fi
|
|
264
|
-
else
|
|
265
|
-
# Cancelled, or no selector could run. Either way nothing changed, and
|
|
266
|
-
# saying so beats exiting mute on a command the user asked to be
|
|
267
|
-
# interactive.
|
|
268
|
-
ui_info "Theme" "no selection — still on $current"
|
|
269
|
-
fi
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
list_themes() {
|
|
273
|
-
local current
|
|
274
|
-
current="$(current_theme)"
|
|
275
|
-
local current_family="${current%-dark}"
|
|
276
|
-
[[ "$current_family" != "$current" ]] || current_family="${current%-light}"
|
|
277
|
-
|
|
278
|
-
local count=0
|
|
279
|
-
local family source
|
|
280
|
-
|
|
281
|
-
printf ' %-35s %s\n' "WALLPAPER" "SOURCE"
|
|
282
|
-
printf ' %-35s %s\n' "---------" "------"
|
|
283
|
-
while IFS= read -r family; do
|
|
284
|
-
[[ -n "$family" ]] || continue
|
|
285
|
-
source="$(wallpaper_source "$family")"
|
|
286
|
-
if [[ "$family" == "$current_family" ]]; then
|
|
287
|
-
ui_ok "$family" "$source ◀"
|
|
288
|
-
else
|
|
289
|
-
printf ' %-35s %s\n' "$family" "$source"
|
|
290
|
-
fi
|
|
291
|
-
count=$((count + 1))
|
|
292
|
-
done < <(paired_families)
|
|
293
|
-
|
|
294
|
-
echo ""
|
|
295
|
-
ui_info "Current" "$(current_theme) ($count wallpaper themes available)"
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
# Toggle between light and dark within the same family, or switch families
|
|
299
|
-
toggle_theme() {
|
|
300
|
-
local current
|
|
301
|
-
current="$(current_theme)"
|
|
302
|
-
|
|
303
|
-
if is_dark_theme "$current"; then
|
|
304
|
-
if [[ "$current" == *-dark ]]; then
|
|
305
|
-
set_theme "${current%-dark}-light"
|
|
306
|
-
else
|
|
307
|
-
set_theme "$DEFAULT_LIGHT"
|
|
308
|
-
fi
|
|
309
|
-
else
|
|
310
|
-
if [[ "$current" == *-light ]]; then
|
|
311
|
-
set_theme "${current%-light}-dark"
|
|
312
|
-
else
|
|
313
|
-
set_theme "$DEFAULT_DARK"
|
|
314
|
-
fi
|
|
315
|
-
fi
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
# Switch to the next wallpaper family while preserving mode.
|
|
319
|
-
switch_family() {
|
|
320
|
-
local current family
|
|
321
|
-
current="$(current_theme)"
|
|
322
|
-
family="$(get_theme_family "$current")"
|
|
323
|
-
local mode="dark"
|
|
324
|
-
local families=()
|
|
325
|
-
local idx=0
|
|
326
|
-
local next_family=""
|
|
327
|
-
|
|
328
|
-
if [[ "$current" == *-light ]]; then
|
|
329
|
-
mode="light"
|
|
330
|
-
fi
|
|
331
|
-
|
|
332
|
-
while IFS= read -r name; do
|
|
333
|
-
[[ -n "$name" ]] || continue
|
|
334
|
-
families+=("$name")
|
|
335
|
-
done < <(paired_families)
|
|
336
|
-
|
|
337
|
-
if [[ ${#families[@]} -eq 0 ]]; then
|
|
338
|
-
set_theme "$DEFAULT_DARK"
|
|
339
|
-
return
|
|
340
|
-
fi
|
|
341
|
-
|
|
342
|
-
for idx in "${!families[@]}"; do
|
|
343
|
-
if [[ "${families[$idx]}" == "$family" ]]; then
|
|
344
|
-
next_family="${families[$(((idx + 1) % ${#families[@]}))]}"
|
|
345
|
-
break
|
|
346
|
-
fi
|
|
347
|
-
done
|
|
348
|
-
|
|
349
|
-
if [[ -z "$next_family" ]]; then
|
|
350
|
-
next_family="${families[0]}"
|
|
351
|
-
fi
|
|
352
|
-
|
|
353
|
-
set_theme "${next_family}-${mode}"
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
# Show current theme info
|
|
357
|
-
show_current() {
|
|
358
|
-
local current family
|
|
359
|
-
current="$(current_theme)"
|
|
360
|
-
family="$(get_theme_family "$current")"
|
|
361
|
-
local mode="dark"
|
|
362
|
-
if ! is_dark_theme "$current" 2>/dev/null; then
|
|
363
|
-
mode="light"
|
|
364
|
-
fi
|
|
365
|
-
ui_info "Current" "$current ($family, $mode)"
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
# Detect system appearance (Dark/Light) and sync dotfiles
|
|
369
|
-
sync_theme() {
|
|
370
|
-
local os_mode="dark" # Default fallback
|
|
371
|
-
case "$(uname -s)" in
|
|
372
|
-
Darwin)
|
|
373
|
-
if defaults read -g AppleInterfaceStyle >/dev/null 2>&1; then
|
|
374
|
-
os_mode="dark"
|
|
375
|
-
else
|
|
376
|
-
os_mode="light"
|
|
377
|
-
fi
|
|
378
|
-
;;
|
|
379
|
-
Linux)
|
|
380
|
-
if command -v gsettings >/dev/null 2>&1; then
|
|
381
|
-
# Check GNOME color scheme. Fixes a long-standing bug where the
|
|
382
|
-
# variable was declared as `local scheme=scheme=$(...)` — the
|
|
383
|
-
# extra `scheme=` prefix made the value always start with that
|
|
384
|
-
# literal, so the `prefer-light` test below could never match
|
|
385
|
-
# and the system always fell through to the dark branch.
|
|
386
|
-
local scheme
|
|
387
|
-
scheme=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'")
|
|
388
|
-
if [[ "$scheme" == "prefer-light" ]]; then
|
|
389
|
-
os_mode="light"
|
|
390
|
-
else
|
|
391
|
-
os_mode="dark"
|
|
392
|
-
fi
|
|
393
|
-
fi
|
|
394
|
-
;;
|
|
395
|
-
esac
|
|
396
|
-
|
|
397
|
-
local current
|
|
398
|
-
current="$(current_theme)"
|
|
399
|
-
if is_dark_theme "$current" && [[ "$os_mode" == "light" ]]; then
|
|
400
|
-
ui_info "Sync" "System is light, switching dotfiles to light..."
|
|
401
|
-
toggle_theme
|
|
402
|
-
elif ! is_dark_theme "$current" && [[ "$os_mode" == "dark" ]]; then
|
|
403
|
-
ui_info "Sync" "System is dark, switching dotfiles to dark..."
|
|
404
|
-
toggle_theme
|
|
405
|
-
else
|
|
406
|
-
ui_ok "Sync" "Dotfiles already match system ($os_mode mode)"
|
|
407
|
-
fi
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
# =============================================================================
|
|
411
|
-
# Main
|
|
412
|
-
# =============================================================================
|
|
413
|
-
|
|
414
|
-
case "${1:-}" in
|
|
415
|
-
list)
|
|
416
|
-
list_themes
|
|
417
|
-
;;
|
|
418
|
-
set)
|
|
419
|
-
shift
|
|
420
|
-
# `"${1:-}"`, not `"$1"`: with no theme name the bare positional aborts
|
|
421
|
-
# the script under `set -u` before set_theme's own empty-string check can
|
|
422
|
-
# open the picker `dot help theme` promises. Worse, the abort is silent
|
|
423
|
-
# about its status on bash 3.2 (macOS /bin/bash): when a script dies on an
|
|
424
|
-
# unbound variable with an EXIT trap installed — switch.sh installs
|
|
425
|
-
# `trap cleanup EXIT` — 3.2 exits 0, and no handler can recover the status
|
|
426
|
-
# because `$?` is already 0 when the handler runs. So on a stock Mac this
|
|
427
|
-
# one missing default turned every `dot theme set` typo into a reported
|
|
428
|
-
# success. Keep every expansion in this script guarded.
|
|
429
|
-
set_theme "${1:-}"
|
|
430
|
-
;;
|
|
431
|
-
toggle)
|
|
432
|
-
toggle_theme
|
|
433
|
-
;;
|
|
434
|
-
sync)
|
|
435
|
-
sync_theme
|
|
436
|
-
;;
|
|
437
|
-
family)
|
|
438
|
-
switch_family
|
|
439
|
-
;;
|
|
440
|
-
current)
|
|
441
|
-
show_current
|
|
442
|
-
;;
|
|
443
|
-
rebuild)
|
|
444
|
-
shift
|
|
445
|
-
bash "$SCRIPT_DIR/rebuild-themes.sh" "$@"
|
|
446
|
-
;;
|
|
447
|
-
help | --help | -h)
|
|
448
|
-
ui_header "Usage"
|
|
449
|
-
ui_info "dot theme" "[command]"
|
|
450
|
-
echo ""
|
|
451
|
-
ui_header "Commands"
|
|
452
|
-
ui_ok "(no args)" "Interactive theme picker (fzf)"
|
|
453
|
-
ui_ok "list" "Show all available themes"
|
|
454
|
-
ui_ok "set [NAME]" "Set theme (interactive if no name)"
|
|
455
|
-
ui_ok "toggle" "Toggle between light/dark within current family"
|
|
456
|
-
ui_ok "family" "Cycle between theme families"
|
|
457
|
-
ui_ok "current" "Show current theme info"
|
|
458
|
-
ui_ok "sync" "Sync dotfiles with system dark/light mode"
|
|
459
|
-
ui_ok "rebuild" "Regenerate themes from system + custom wallpapers"
|
|
460
|
-
echo ""
|
|
461
|
-
show_current
|
|
462
|
-
;;
|
|
463
|
-
"")
|
|
464
|
-
pick_theme
|
|
465
|
-
;;
|
|
466
|
-
*)
|
|
467
|
-
# Treat unknown args as theme names for quick switching: dot theme macos-sequoia-dark
|
|
468
|
-
if grep -q "^\[themes\.${1}\]" "$THEMES_FILE" 2>/dev/null; then
|
|
469
|
-
dot-theme-sync "$1"
|
|
470
|
-
else
|
|
471
|
-
ui_err "Unknown command or theme" "$1"
|
|
472
|
-
ui_info "Usage" "dot theme [list|set <name>|toggle|family|current|help]"
|
|
473
|
-
exit 1
|
|
474
|
-
fi
|
|
475
|
-
;;
|
|
476
|
-
esac
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
3
|
-
# Copyright (c) 2015-2026 Sebastien Rousseau
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
WALLPAPER_DIR="${DOTFILES_WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
|
|
7
|
-
INTERVAL="${DOTFILES_WALLPAPER_INTERVAL:-300}"
|
|
8
|
-
ONCE=0
|
|
9
|
-
|
|
10
|
-
while [[ $# -gt 0 ]]; do
|
|
11
|
-
case "$1" in
|
|
12
|
-
--interval)
|
|
13
|
-
INTERVAL="$2"
|
|
14
|
-
shift 2
|
|
15
|
-
;;
|
|
16
|
-
--once)
|
|
17
|
-
ONCE=1
|
|
18
|
-
shift
|
|
19
|
-
;;
|
|
20
|
-
--light)
|
|
21
|
-
FORCE_MODE="light"
|
|
22
|
-
shift
|
|
23
|
-
;;
|
|
24
|
-
--dark)
|
|
25
|
-
FORCE_MODE="dark"
|
|
26
|
-
shift
|
|
27
|
-
;;
|
|
28
|
-
*)
|
|
29
|
-
shift
|
|
30
|
-
;;
|
|
31
|
-
esac
|
|
32
|
-
done
|
|
33
|
-
|
|
34
|
-
if [[ ! -d "$WALLPAPER_DIR" ]]; then
|
|
35
|
-
echo "Wallpaper directory not found: $WALLPAPER_DIR" >&2
|
|
36
|
-
exit 1
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
# Detect current color scheme (light/dark)
|
|
40
|
-
detect_mode() {
|
|
41
|
-
if [[ -n "${FORCE_MODE:-}" ]]; then
|
|
42
|
-
echo "$FORCE_MODE"
|
|
43
|
-
return
|
|
44
|
-
fi
|
|
45
|
-
if command -v gsettings &>/dev/null; then
|
|
46
|
-
local scheme
|
|
47
|
-
scheme="$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null || echo "")"
|
|
48
|
-
case "$scheme" in
|
|
49
|
-
*dark*) echo "dark" ;;
|
|
50
|
-
*) echo "light" ;;
|
|
51
|
-
esac
|
|
52
|
-
else
|
|
53
|
-
echo "dark"
|
|
54
|
-
fi
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
# Pick a random wallpaper matching mode, excluding the given path
|
|
58
|
-
pick_wallpaper() {
|
|
59
|
-
local mode="$1"
|
|
60
|
-
local exclude="${2:-}"
|
|
61
|
-
local files=()
|
|
62
|
-
while IFS= read -r line; do
|
|
63
|
-
[[ "$line" == "$exclude" ]] && continue
|
|
64
|
-
files+=("$line")
|
|
65
|
-
done < <(find "$WALLPAPER_DIR" -maxdepth 1 -type f -iname "*-${mode}.jpg")
|
|
66
|
-
|
|
67
|
-
if [[ ${#files[@]} -eq 0 ]]; then
|
|
68
|
-
return 1
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
|
-
if command -v shuf &>/dev/null; then
|
|
72
|
-
printf '%s\n' "${files[@]}" | shuf -n 1
|
|
73
|
-
else
|
|
74
|
-
echo "${files[$RANDOM % ${#files[@]}]}"
|
|
75
|
-
fi
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
apply_wallpaper() {
|
|
79
|
-
local wp="$1"
|
|
80
|
-
local mode="$2"
|
|
81
|
-
|
|
82
|
-
case "$(uname -s)" in
|
|
83
|
-
Darwin)
|
|
84
|
-
osascript -e "tell application \"System Events\" to set picture of every desktop to POSIX file \"$wp\"" || true
|
|
85
|
-
;;
|
|
86
|
-
Linux)
|
|
87
|
-
if command -v gsettings &>/dev/null; then
|
|
88
|
-
local light_wp dark_wp
|
|
89
|
-
local base="${wp%-${mode}.jpg}"
|
|
90
|
-
light_wp="${base}-light.jpg"
|
|
91
|
-
dark_wp="${base}-dark.jpg"
|
|
92
|
-
|
|
93
|
-
if [[ -f "$light_wp" ]] && [[ -f "$dark_wp" ]]; then
|
|
94
|
-
gsettings set org.gnome.desktop.background picture-uri "file://${light_wp}"
|
|
95
|
-
gsettings set org.gnome.desktop.background picture-uri-dark "file://${dark_wp}"
|
|
96
|
-
gsettings set org.gnome.desktop.screensaver picture-uri "file://${light_wp}"
|
|
97
|
-
else
|
|
98
|
-
local wp_uri="file://${wp}"
|
|
99
|
-
gsettings set org.gnome.desktop.background picture-uri "$wp_uri"
|
|
100
|
-
gsettings set org.gnome.desktop.background picture-uri-dark "$wp_uri"
|
|
101
|
-
gsettings set org.gnome.desktop.screensaver picture-uri "$wp_uri"
|
|
102
|
-
fi
|
|
103
|
-
gsettings set org.gnome.desktop.background picture-options "zoom"
|
|
104
|
-
elif command -v swaybg &>/dev/null; then
|
|
105
|
-
pkill swaybg || true
|
|
106
|
-
swaybg -i "$wp" -m fill &
|
|
107
|
-
elif command -v feh &>/dev/null; then
|
|
108
|
-
feh --bg-fill "$wp"
|
|
109
|
-
else
|
|
110
|
-
echo "No supported wallpaper setter found (gsettings/swaybg/feh)." >&2
|
|
111
|
-
return 1
|
|
112
|
-
fi
|
|
113
|
-
;;
|
|
114
|
-
*)
|
|
115
|
-
echo "Wallpaper rotation not supported on this OS." >&2
|
|
116
|
-
return 1
|
|
117
|
-
;;
|
|
118
|
-
esac
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
LAST_WP=""
|
|
122
|
-
|
|
123
|
-
while true; do
|
|
124
|
-
MODE="$(detect_mode)"
|
|
125
|
-
wp="$(pick_wallpaper "$MODE" "$LAST_WP" || true)"
|
|
126
|
-
if [[ -z "$wp" ]]; then
|
|
127
|
-
echo "No ${MODE} wallpapers found in $WALLPAPER_DIR" >&2
|
|
128
|
-
exit 1
|
|
129
|
-
fi
|
|
130
|
-
apply_wallpaper "$wp" "$MODE"
|
|
131
|
-
LAST_WP="$wp"
|
|
132
|
-
echo "Wallpaper applied (${MODE}): $(basename "$wp")"
|
|
133
|
-
if [[ "$ONCE" -eq 1 ]]; then
|
|
134
|
-
break
|
|
135
|
-
fi
|
|
136
|
-
sleep "$INTERVAL"
|
|
137
|
-
done
|