aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Guzman <55927935+brockar@users.noreply.github.com>2026-01-24 19:45:52 -0300
committerGitHub <noreply@github.com>2026-01-24 19:45:52 -0300
commit6b9ef5fb2219ccbb3d42adb4b691c466991efc9f (patch)
tree74b141beda34510f7c44d5e82d2c6ed54c6bfbac
parent035724daaf362eac452a781e20144cf893ed274f (diff)
parentd2fbf319bc3b09e4345dea390b85d328eb0318c0 (diff)
Merge pull request #931 from JaKooLit/development
Development to main: Fix upgrade bug
-rw-r--r--CHANGELOG.md10
-rwxr-xr-xconfig/hypr/UserScripts/Tak0-Autodispatch.sh62
-rw-r--r--config/hypr/configs/ENVariables.conf2
-rwxr-xr-xconfig/hypr/scripts/Distro_update.sh10
-rwxr-xr-xconfig/hypr/scripts/KooLsDotsUpdate.sh8
-rwxr-xr-xconfig/hypr/scripts/Tak0-Autodispatch.sh277
-rwxr-xr-xconfig/hypr/scripts/Tak0-Per-Window-Switch.sh6
-rw-r--r--config/hypr/v2.3.20 (renamed from config/hypr/v2.3.19)0
-rw-r--r--config/nvim/init.lua16
-rw-r--r--config/nvim/init.vim.txt45
-rw-r--r--config/nvim/lazy-lock.json16
-rw-r--r--config/nvim/lua/plugins.lua2
-rw-r--r--config/nvim/lua/plugins/alpha.lua105
-rw-r--r--config/nvim/lua/plugins/catppuccin.lua13
-rw-r--r--config/nvim/lua/plugins/lsp-config.lua25
-rw-r--r--config/nvim/lua/plugins/lualine.lua10
-rw-r--r--config/nvim/lua/plugins/neo-tree.lua12
-rw-r--r--config/nvim/lua/plugins/telescope.lua13
-rw-r--r--config/nvim/lua/plugins/treesitter.lua12
-rw-r--r--config/nvim/lua/vim-options.lua15
-rwxr-xr-xcopy.sh14
-rw-r--r--scripts/lib_copy.sh299
-rw-r--r--scripts/lib_update.sh14
23 files changed, 500 insertions, 486 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3e8ca96..c733649f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog — JAK's Hyprland Dotfiles
+## v2.3.20
+
+- Bugfix release
+- Fixed issue with express-update
+ - It bypassed the code to remove duplicates in system vs. user
+ - Now checks for dups in version <= 2.3.19
+ - Improved the checking code for better matching system vs. User
+ - Merged `tak0dan` update to `Tak0-Autodispatch.sh` script
+ - Removed stale `nvim` config. It was never copied but not needed
+
## v2.3.19
- 2026-01-20
diff --git a/config/hypr/UserScripts/Tak0-Autodispatch.sh b/config/hypr/UserScripts/Tak0-Autodispatch.sh
index 114a3e8e..48c22515 100755
--- a/config/hypr/UserScripts/Tak0-Autodispatch.sh
+++ b/config/hypr/UserScripts/Tak0-Autodispatch.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# USAGE / ІНСТРУКЦІЯ:
+# USAGE:
# 1) Run from terminal:
# ./dispatch.sh <application_command> <target_workspace_number>
# Example:
@@ -14,77 +14,49 @@
# Notes:
# - Script waits about ~9 seconds (30 iterations of 0.3 sec) for window to appear.
# - Uses hyprctl and jq, so these tools must be installed.
-#
-# USAGE / ІНСТРУКЦІЯ:
-# 1) Запуск з терміналу:
-# ./dispatch.sh <application_command> <target_workspace_number>
-# Наприклад:
-# ./dispatch.sh discord 2
-#
-# 2) Виклик з конфігурації Hyprland (у файлі hyprland.conf):
-# exec-once = /path/to/dispatch.sh <application_command> <target_workspace_number>
-#
-# Логи зберігаються у файлі dispatch.log поруч зі скриптом.
-# Якщо вікно не з'явилось або неправильно диспатчилось — інформація там.
-#
-# Примітки:
-# - Скрипт чекає до ~9 секунд (30 ітерацій по 0.3 сек) поки вікно з'явиться.
-# - Використовує hyprctl і jq, тому ці інструменти мають бути встановлені.
LOGFILE="$(dirname "$0")/dispatch.log"
# Log file path located next to the script.
-# Файл логів розташований поруч зі скриптом.
APP=$1
# The application command or window class to launch or match.
-# Команда для запуску аплікації або клас вікна для пошуку.
TARGET_WORKSPACE=$2
# The target workspace number where the window should be moved.
-# Цільовий номер воркспейсу, куди потрібно перемістити вікно.
# Check if required arguments are provided.
-# Перевірка наявності необхідних параметрів.
if [[ -z "$APP" || -z "$TARGET_WORKSPACE" ]]; then
- echo "Usage: $0 <application_command> <target_workspace_number>" >> "$LOGFILE" 2>&1
- exit 1
+ echo "Usage: $0 <application_command> <target_workspace_number>" >>"$LOGFILE" 2>&1
+ exit 1
fi
-echo "Starting dispatch of '$APP' to workspace $TARGET_WORKSPACE at $(date)" >> "$LOGFILE"
+echo "Starting dispatch of '$APP' to workspace $TARGET_WORKSPACE at $(date)" >>"$LOGFILE"
# Starting the dispatch process and logging the event.
-# Початок процесу диспатчу, запис у лог.
-
# Avoid early workspace focus issues by switching workspace first.
-# Уникаємо проблем з раннім фокусом, спочатку переключаємо воркспейс.
-hyprctl dispatch workspace "$TARGET_WORKSPACE" >> "$LOGFILE" 2>&1
+hyprctl dispatch workspace "$TARGET_WORKSPACE" >>"$LOGFILE" 2>&1
sleep 0.4
# Launch the application in the background and disown it.
-# Запускаємо аплікацію у фоновому режимі та відв’язуємо від терміналу.
-$APP & disown
+$APP &
+disown
pid=$!
-echo "Launched '$APP' with PID $pid" >> "$LOGFILE"
+echo "Launched '$APP' with PID $pid" >>"$LOGFILE"
# Log the launched process ID.
-# Лог процесу запуску з PID.
-
# Wait for the application window to appear (matching window class).
-# Чекаємо появи вікна аплікації (за класом вікна).
for i in {1..30}; do
- win=$(hyprctl clients -j | jq -r --arg APP "$APP" '
+ win=$(hyprctl clients -j | jq -r --arg APP "$APP" '
.[] | select(.class | test($APP;"i")) | .address' 2>>"$LOGFILE")
- if [[ -n "$win" ]]; then
- echo "Found window $win for app '$APP', moving to workspace $TARGET_WORKSPACE" >> "$LOGFILE"
- # Move the window to the target workspace.
- # Переміщаємо вікно на цільовий воркспейс.
- hyprctl dispatch movetoworkspace "$TARGET_WORKSPACE,address:$win" >> "$LOGFILE" 2>&1
- exit 0
- fi
- sleep 0.3
+ if [[ -n "$win" ]]; then
+ echo "Found window $win for app '$APP', moving to workspace $TARGET_WORKSPACE" >>"$LOGFILE"
+ # Move the window to the target workspace.
+ hyprctl dispatch movetoworkspace "$TARGET_WORKSPACE,address:$win" >>"$LOGFILE" 2>&1
+ exit 0
+ fi
+ sleep 0.3
done
-echo "ERROR: Window for '$APP' was NOT found or dispatched properly to workspace $TARGET_WORKSPACE at $(date)" >> "$LOGFILE"
+echo "ERROR: Window for '$APP' was NOT found or dispatched properly to workspace $TARGET_WORKSPACE at $(date)" >>"$LOGFILE"
# Log error if window was not found or dispatched correctly.
-# Запис помилки, якщо вікно не знайдено або неправильно диспатчено.
exit 1
diff --git a/config/hypr/configs/ENVariables.conf b/config/hypr/configs/ENVariables.conf
index 2421199c..6be44e9b 100644
--- a/config/hypr/configs/ENVariables.conf
+++ b/config/hypr/configs/ENVariables.conf
@@ -5,7 +5,7 @@
# environment-variables
# Current Version of JakooLit Dotfiles:
-env = DOTS_VERSION,2.3.19
+env = DOTS_VERSION,2.3.20
### Toolkit Backend Variables ###
env = GDK_BACKEND,wayland,x11,*
diff --git a/config/hypr/scripts/Distro_update.sh b/config/hypr/scripts/Distro_update.sh
index 917f303b..164de7ec 100755
--- a/config/hypr/scripts/Distro_update.sh
+++ b/config/hypr/scripts/Distro_update.sh
@@ -15,23 +15,23 @@ fi
if command -v paru &> /dev/null || command -v yay &> /dev/null; then
# Arch-based
if command -v paru &> /dev/null; then
- kitty -T update paru -Syu
+ kitty -T update -e paru -Syu
notify-send -i "$iDIR/ja.png" -u low 'Arch-based system' 'has been updated.'
else
- kitty -T update yay -Syu
+ kitty -T update -e yay -Syu
notify-send -i "$iDIR/ja.png" -u low 'Arch-based system' 'has been updated.'
fi
elif command -v dnf &> /dev/null; then
# Fedora-based
- kitty -T update sudo dnf update --refresh -y
+ kitty -T update -e sudo dnf update --refresh -y
notify-send -i "$iDIR/ja.png" -u low 'Fedora system' 'has been updated.'
elif command -v apt &> /dev/null; then
# Debian-based (Debian, Ubuntu, etc.)
- kitty -T update bash -c "sudo apt update && sudo apt upgrade -y"
+ kitty -T update -e bash -c "sudo apt update && sudo apt upgrade -y"
notify-send -i "$iDIR/ja.png" -u low 'Debian/Ubuntu system' 'has been updated.'
elif command -v zypper &> /dev/null; then
# openSUSE-based
- kitty -T update sudo zypper dup -y
+ kitty -T update -e sudo zypper dup -y
notify-send -i "$iDIR/ja.png" -u low 'openSUSE system' 'has been updated.'
else
# Unsupported distro
diff --git a/config/hypr/scripts/KooLsDotsUpdate.sh b/config/hypr/scripts/KooLsDotsUpdate.sh
index a49f5430..006d66ed 100755
--- a/config/hypr/scripts/KooLsDotsUpdate.sh
+++ b/config/hypr/scripts/KooLsDotsUpdate.sh
@@ -17,12 +17,18 @@ fi
# GitHub URL - KooL's dots
branch="main"
github_url="https://github.com/JaKooLit/Hyprland-Dots/tree/$branch/config/hypr/"
+# Check for required tools (curl)
+if ! command -v curl &> /dev/null; then
+ notify-send -i "$iDIR/error.png" "Need curl:" "curl not found. Please install curl."
+ exit 1
+fi
# Fetch the version from GitHub URL - KooL's dots
-github_version=$(curl -s "$github_url" | grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V | tail -n 1 | sed 's/v//')
+github_version=$(curl -fsSL -A "Mozilla/5.0" "$github_url" | grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V | tail -n 1 | sed 's/v//')
# Cant find GitHub URL - KooL's dots version
if [ -z "$github_version" ]; then
+ notify-send -i "$iDIR/error.png" 'KooL Hyprland:' "Unable to determine GitHub version."
exit 1
fi
diff --git a/config/hypr/scripts/Tak0-Autodispatch.sh b/config/hypr/scripts/Tak0-Autodispatch.sh
index 114a3e8e..6ed7ec13 100755
--- a/config/hypr/scripts/Tak0-Autodispatch.sh
+++ b/config/hypr/scripts/Tak0-Autodispatch.sh
@@ -1,90 +1,229 @@
#!/usr/bin/env bash
-# USAGE / ІНСТРУКЦІЯ:
-# 1) Run from terminal:
-# ./dispatch.sh <application_command> <target_workspace_number>
-# Example:
-# ./dispatch.sh discord 2
-#
-# 2) Call from Hyprland config (in hyprland.conf file):
-# exec-once = /path/to/dispatch.sh <application_command> <target_workspace_number>
-#
-# Logs are saved in dispatch.log file next to the script.
-# If the window doesn't appear or is dispatched incorrectly — info will be there.
+
+# ─────────────────────────────────────────────────────────────────────────────
+# Tak0-Autodispatch.sh
+# ─────────────────────────────────────────────────────────────────────────────
+# This script is an "authoritative spawn dispatcher" for Hyprland.
#
-# Notes:
-# - Script waits about ~9 seconds (30 iterations of 0.3 sec) for window to appear.
-# - Uses hyprctl and jq, so these tools must be installed.
+# Its purpose is to FORCE all windows belonging to a single application launch
+# (main window + helpers + Electron / Steam child processes)
+# onto a specific workspace.
#
-# USAGE / ІНСТРУКЦІЯ:
-# 1) Запуск з терміналу:
-# ./dispatch.sh <application_command> <target_workspace_number>
-# Наприклад:
-# ./dispatch.sh discord 2
+# It explicitly ignores:
+# • spawn race conditions
+# • delayed window creation
+# • detached helper processes
+# • Electron / Chromium / Steam madness
#
-# 2) Виклик з конфігурації Hyprland (у файлі hyprland.conf):
-# exec-once = /path/to/dispatch.sh <application_command> <target_workspace_number>
+# Typical use cases:
+# • Launch Steam / Discord / browsers without window leakage
+# • Prevent apps from spawning on the currently focused workspace
+# • Control applications that completely ignore static windowrules
#
-# Логи зберігаються у файлі dispatch.log поруч зі скриптом.
-# Якщо вікно не з'явилось або неправильно диспатчилось — інформація там.
+# Invocation:
+# ./Tak0-Autodispatch.sh <workspace> [rule ...] -- <command>
#
-# Примітки:
-# - Скрипт чекає до ~9 секунд (30 ітерацій по 0.3 сек) поки вікно з'явиться.
-# - Використовує hyprctl і jq, тому ці інструменти мають бути встановлені.
+# Important notes:
+# • All window rules are TEMPORARY
+# • No permanent pollution of Hyprland configuration
+# ─────────────────────────────────────────────────────────────────────────────
+# REQUIREMENTS:
+# - hyprctl → runtime control of Hyprland
+# - jq → JSON client parsing
+# - pgrep/ps → process tree inspection
+
+set -u
LOGFILE="$(dirname "$0")/dispatch.log"
-# Log file path located next to the script.
-# Файл логів розташований поруч зі скриптом.
-APP=$1
-# The application command or window class to launch or match.
-# Команда для запуску аплікації або клас вікна для пошуку.
+# ─────────────────────────────────────────────────────────────────────────────
+# 0️⃣ ARGUMENT PARSING
+# ─────────────────────────────────────────────────────────────────────────────
+# $1 → target workspace
+# Next args → optional capture rules (windowrulev2 syntax)
+# "--" → argument separator
+# After "--" → command to execute (verbatim)
+
+TARGET_WS="$1"
+shift || true
-TARGET_WORKSPACE=$2
-# The target workspace number where the window should be moved.
-# Цільовий номер воркспейсу, куди потрібно перемістити вікно.
+CAPTURE_RULES=()
+while [[ "${1-}" != "--" && -n "${1-}" ]]; do
+ CAPTURE_RULES+=("$1")
+ shift || break
+done
-# Check if required arguments are provided.
-# Перевірка наявності необхідних параметрів.
-if [[ -z "$APP" || -z "$TARGET_WORKSPACE" ]]; then
- echo "Usage: $0 <application_command> <target_workspace_number>" >> "$LOGFILE" 2>&1
- exit 1
+if [[ "${1-}" == "--" ]]; then
+ shift
fi
-echo "Starting dispatch of '$APP' to workspace $TARGET_WORKSPACE at $(date)" >> "$LOGFILE"
-# Starting the dispatch process and logging the event.
-# Початок процесу диспатчу, запис у лог.
+CMD="$*"
+
+if [[ -z "$TARGET_WS" || -z "$CMD" ]]; then
+ echo "Usage: $0 <workspace> [rule rule ...] -- <command>" >>"$LOGFILE"
+ exit 1
+fi
+
+echo "=== Deploy '$CMD' → WS $TARGET_WS @ $(date) ===" >>"$LOGFILE"
+
+# ─────────────────────────────────────────────────────────────────────────────
+# 1️⃣ HYPRLAND READINESS GATE
+# ─────────────────────────────────────────────────────────────────────────────
+# Hyprland may not be fully initialized during early autostart.
+# hyprctl silently fails if called too early.
-# Avoid early workspace focus issues by switching workspace first.
-# Уникаємо проблем з раннім фокусом, спочатку переключаємо воркспейс.
-hyprctl dispatch workspace "$TARGET_WORKSPACE" >> "$LOGFILE" 2>&1
-sleep 0.4
+for _ in {1..50}; do
+ hyprctl -j monitors >/dev/null 2>&1 && break
+ sleep 0.1
+done
+
+# ─────────────────────────────────────────────────────────────────────────────
+# 2️⃣ CLEANUP GUARANTEE
+# ─────────────────────────────────────────────────────────────────────────────
+# Ensures that ALL temporary rules are removed
+# even on crash, SIGTERM, or user interruption.
+
+cleanup() {
+ echo "Cleanup: removing temporary capture rules and initialWorkspace at $(date)" >>"$LOGFILE"
+
+ hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+ for RULE in "${CAPTURE_RULES[@]}"; do
+ echo "Cleanup: removing temporary capture rule: $RULE" >>"$LOGFILE"
+ hyprctl keyword windowrulev2 "unset, $RULE" >>"$LOGFILE" 2>&1 || true
+ done
+}
+
+trap cleanup EXIT INT TERM ERR
-# Launch the application in the background and disown it.
-# Запускаємо аплікацію у фоновому режимі та відв’язуємо від терміналу.
-$APP & disown
-pid=$!
+# ─────────────────────────────────────────────────────────────────────────────
+# 3️⃣ ULTRA-EARLY GLOBAL CAPTURE (NUCLEAR OPTION)
+# ─────────────────────────────────────────────────────────────────────────────
+# Temporarily forces ALL windows (initialClass:.*)
+# onto the target workspace.
+#
+# Protects against ultra-fast helpers:
+# • gpu-process
+# • renderer
+# • steamwebhelper
+
+echo "Applying temporary initialWorkspace capture (initialClass:.*)" >>"$LOGFILE"
+hyprctl keyword windowrulev2 \
+ "initialWorkspace $TARGET_WS silent, initialClass:.*" \
+ >>"$LOGFILE" 2>&1 || true
+
+# ─────────────────────────────────────────────────────────────────────────────
+# 3️⃣.1 OPTIONAL CLASS-BASED PRE-CAPTURE
+# ─────────────────────────────────────────────────────────────────────────────
+# Additional precision rules.
+# Useful for Electron / Steam multi-process hell.
+
+for RULE in "${CAPTURE_RULES[@]}"; do
+ echo "Applying temporary capture rule: $RULE" >>"$LOGFILE"
+ hyprctl keyword windowrulev2 \
+ "initialWorkspace $TARGET_WS silent, $RULE" \
+ >>"$LOGFILE" 2>&1 || true
+done
-echo "Launched '$APP' with PID $pid" >> "$LOGFILE"
-# Log the launched process ID.
-# Лог процесу запуску з PID.
+# ─────────────────────────────────────────────────────────────────────────────
+# 4️⃣ APPLICATION LAUNCH
+# ─────────────────────────────────────────────────────────────────────────────
+# bash -c allows aliases, env vars, wrappers.
+# ROOT_PID is the root of process lineage.
-# Wait for the application window to appear (matching window class).
-# Чекаємо появи вікна аплікації (за класом вікна).
-for i in {1..30}; do
- win=$(hyprctl clients -j | jq -r --arg APP "$APP" '
- .[] | select(.class | test($APP;"i")) | .address' 2>>"$LOGFILE")
+bash -c "$CMD" &
+ROOT_PID=$!
+echo "Root PID: $ROOT_PID" >>"$LOGFILE"
- if [[ -n "$win" ]]; then
- echo "Found window $win for app '$APP', moving to workspace $TARGET_WORKSPACE" >> "$LOGFILE"
- # Move the window to the target workspace.
- # Переміщаємо вікно на цільовий воркспейс.
- hyprctl dispatch movetoworkspace "$TARGET_WORKSPACE,address:$win" >> "$LOGFILE" 2>&1
- exit 0
+# Resolve canonical process name
+APP_NAME=""
+for _ in {1..20}; do
+ if [[ -r "/proc/$ROOT_PID/comm" ]]; then
+ APP_NAME="$(tr -d '\0' </proc/$ROOT_PID/comm 2>/dev/null || true)"
+ break
+ fi
+ sleep 0.05
+done
+
+if [[ -z "$APP_NAME" ]]; then
+ read -r -a __toks <<<"$CMD"
+ APP_NAME="$(basename "${__toks[0]}")"
+fi
+
+echo "App gate name: $APP_NAME" >>"$LOGFILE"
+
+sleep 1.5
+
+#!TO-DO: Release the nuclear option ASAP
+echo "Releasing ultra-early wide capture" >>"$LOGFILE"
+hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+
+# ─────────────────────────────────────────────────────────────────────────────
+# 5️⃣ SUPERVISION LOOP (AUTHORITATIVE PHASE)
+# ─────────────────────────────────────────────────────────────────────────────
+# This loop:
+# • scans ALL Hyprland clients
+# • matches PID lineage
+# • matches detached helpers
+# • matches class rules
+
+get_descendants() {
+ local root="$1"
+ local all=("$root")
+ local changed=1
+
+ while ((changed)); do
+ changed=0
+ for p in "${all[@]}"; do
+ for c in $(pgrep -P "$p" 2>/dev/null || true); do
+ if [[ ! " ${all[*]} " =~ " $c " ]]; then
+ all+=("$c")
+ changed=1
+ fi
+ done
+ done
+ done
+
+ echo "${all[@]}"
+}
+
+pid_matches_app() {
+ local pid="$1"
+ local comm
+ comm="$(ps -p "$pid" -o comm= 2>/dev/null)" || return 1
+ [[ "$comm" == "$APP_NAME" || "$comm" == "$APP_NAME"* ]]
+}
+
+END_TIME=$((SECONDS + 20))
+declare -A SEEN
+
+while ((SECONDS < END_TIME)); do
+ PIDS="$(get_descendants "$ROOT_PID")"
+
+ while IFS=$'\t' read -r PID ADDR CLASS; do
+ MATCH=0
+
+ for TPID in $PIDS; do
+ [[ "$PID" == "$TPID" ]] && MATCH=1 && break
+ done
+
+ pid_matches_app "$PID" && MATCH=1
+
+ for RULE in "${CAPTURE_RULES[@]}"; do
+ if [[ "$RULE" =~ class:\^\((.*)\)\$ ]]; then
+ [[ "$CLASS" =~ ${BASH_REMATCH[1]} ]] && MATCH=1
+ fi
+ done
+
+ if ((MATCH)) && [[ -z "${SEEN[$ADDR]-}" ]]; then
+ echo "Placing window $ADDR (pid $PID, class $CLASS) → WS $TARGET_WS" >>"$LOGFILE"
+ hyprctl dispatch movetoworkspacesilent \
+ "$TARGET_WS,address:$ADDR" >>"$LOGFILE" 2>&1 || true
+ SEEN[$ADDR]=1
fi
- sleep 0.3
+ done < <(hyprctl clients -j | jq -r '.[] | [.pid, .address, .class] | @tsv')
+
+ sleep 0.01
done
-echo "ERROR: Window for '$APP' was NOT found or dispatched properly to workspace $TARGET_WORKSPACE at $(date)" >> "$LOGFILE"
-# Log error if window was not found or dispatched correctly.
-# Запис помилки, якщо вікно не знайдено або неправильно диспатчено.
-exit 1
+echo "=== Deploy finished: '$CMD' ===" >>"$LOGFILE"
+exit 0
diff --git a/config/hypr/scripts/Tak0-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
index 7cec89a6..d652f0f7 100755
--- a/config/hypr/scripts/Tak0-Per-Window-Switch.sh
+++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
@@ -1,16 +1,10 @@
##################################################################
-# #
-# #
# TAK_0'S Per-Window-Switch #
# #
-# #
-# #
# Just a little script that I made to switch keyboard layouts #
# per-window instead of global switching for the more #
# smooth and comfortable workflow. #
-# #
##################################################################
-
# This is for changing kb_layouts. Set kb_layouts in
MAP_FILE="$HOME/.cache/kb_layout_per_window"
diff --git a/config/hypr/v2.3.19 b/config/hypr/v2.3.20
index 31b3414d..31b3414d 100644
--- a/config/hypr/v2.3.19
+++ b/config/hypr/v2.3.20
diff --git a/config/nvim/init.lua b/config/nvim/init.lua
deleted file mode 100644
index 861f3aee..00000000
--- a/config/nvim/init.lua
+++ /dev/null
@@ -1,16 +0,0 @@
-local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
-if not (vim.uv or vim.loop).fs_stat(lazypath) then
- vim.fn.system({
- "git",
- "clone",
- "--filter=blob:none",
- "https://github.com/folke/lazy.nvim.git",
- "--branch=stable", -- latest stable release
- lazypath,
- })
-end
-vim.opt.rtp:prepend(lazypath)
-
-require("lazy").setup("plugins")
-require("vim-options")
-
diff --git a/config/nvim/init.vim.txt b/config/nvim/init.vim.txt
deleted file mode 100644
index 2388fe28..00000000
--- a/config/nvim/init.vim.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-" Basic Configurations
-" FernuDev Github - https://github.com/Fernu292
-
-set number
-set mouse=a
-syntax enable
-set showcmd
-set encoding=utf-8
-set showmatch
-set relativenumber
-
-set expandtab
-set tabstop=4
-set shiftwidth=0
-set softtabstop=0
-set autoindent
-set smarttab
-
-call plug#begin()
- Plug 'nvim-lualine/lualine.nvim'
- Plug 'nvim-tree/nvim-web-devicons'
- Plug 'navarasu/onedark.nvim'
- Plug 'catppuccin/nvim', { 'as': 'catppuccin' }
-call plug#end()
-
-" Calling the Lualine pluggin
-
-colorscheme onedark
-
-lua << END
-require('lualine').setup {
- options = {
- icons_enabled = true,
- theme = 'material'
- }
-}
-
-require('onedark').setup {
- style = "dark",
- transparent = true,
-}
-
-require('onedark').load()
-
-END
diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json
deleted file mode 100644
index b26c6d27..00000000
--- a/config/nvim/lazy-lock.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "alpha-nvim": { "branch": "main", "commit": "41283fb402713fc8b327e60907f74e46166f4cfd" },
- "catppuccin": { "branch": "main", "commit": "894efb557728e532aa98b98029d16907a214ec05" },
- "lazy.nvim": { "branch": "main", "commit": "dea1f687fe6e15eb3098557a69d44231ebcb6cf5" },
- "lualine.nvim": { "branch": "master", "commit": "0a5a66803c7407767b799067986b4dc3036e1983" },
- "mason-lspconfig.nvim": { "branch": "main", "commit": "37a336b653f8594df75c827ed589f1c91d91ff6c" },
- "mason.nvim": { "branch": "main", "commit": "2af3b574b68dc0273c7fb60369f3a48d5a16a857" },
- "neo-tree.nvim": { "branch": "v3.x", "commit": "29f7c215332ba95e470811c380ddbce2cebe2af4" },
- "nui.nvim": { "branch": "main", "commit": "a2bc1e9d0359caa5d11ad967cd1e30e8d4676226" },
- "nvim-lspconfig": { "branch": "master", "commit": "cf97d2485fc3f6d4df1b79a3ea183e24c272215e" },
- "nvim-treesitter": { "branch": "master", "commit": "d4a888ae3cff358cb239643c45b2b38bb60e29c6" },
- "nvim-web-devicons": { "branch": "master", "commit": "c0cfc1738361b5da1cd0a962dd6f774cc444f856" },
- "plenary.nvim": { "branch": "master", "commit": "a3e3bc82a3f95c5ed0d7201546d5d2c19b20d683" },
- "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" },
- "telescope.nvim": { "branch": "master", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" }
-} \ No newline at end of file
diff --git a/config/nvim/lua/plugins.lua b/config/nvim/lua/plugins.lua
deleted file mode 100644
index a2b4f84d..00000000
--- a/config/nvim/lua/plugins.lua
+++ /dev/null
@@ -1,2 +0,0 @@
-return {}
-
diff --git a/config/nvim/lua/plugins/alpha.lua b/config/nvim/lua/plugins/alpha.lua
deleted file mode 100644
index a3346f1b..00000000
--- a/config/nvim/lua/plugins/alpha.lua
+++ /dev/null
@@ -1,105 +0,0 @@
---- @type LazyPluginSpec
-return {
- "goolord/alpha-nvim",
- event = "VimEnter",
- dependencies = { "nvim-tree/nvim-web-devicons" },
- opts = function()
- local dashboard = require("alpha.themes.dashboard")
- require("alpha.term")
- local arttoggle = false
-
- local logo = {
- [[ ]],
- [[ ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ ]],
- [[ ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ ]],
- [[ ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ ]],
- [[ ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ ]],
- [[ ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ ]],
- [[ ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ ]],
- [[ ]],
- }
-
- local art = {
- -- { name, width, height }
- { "tohru", 62, 17 },
- }
-
- if arttoggle == true then
- dashboard.opts.opts.noautocmd = true
- dashboard.section.terminal.opts.redraw = true
- local path = vim.fn.stdpath("config") .. "/assets/"
- -- local random = math.random(1, #art)
- local currentart = art[1]
- dashboard.section.terminal.command = "cat " .. path .. currentart[1]
-
- dashboard.section.terminal.width = currentart[2]
- dashboard.section.terminal.height = currentart[3]
-
- dashboard.opts.layout = {
- dashboard.section.terminal,
- { type = "padding", val = 2 },
- dashboard.section.buttons,
- dashboard.section.footer,
- }
- else
- dashboard.section.header.val = logo
- end
- dashboard.section.buttons.val = {
- dashboard.button("f", " " .. "Find files", ":Telescope find_files <CR>"),
- }
- for _, button in ipairs(dashboard.section.buttons.val) do
- button.opts.hl = "AlphaButtons"
- button.opts.hl_shortcut = "AlphaShortcut"
- end
- dashboard.section.header.opts.hl = "Function"
- dashboard.section.buttons.opts.hl = "Identifier"
- dashboard.section.footer.opts.hl = "Function"
- dashboard.opts.layout[1].val = 4
- return dashboard
- end,
- config = function(_, dashboard)
- if vim.o.filetype == "lazy" then
- vim.cmd.close()
- vim.api.nvim_create_autocmd("User", {
- pattern = "AlphaReady",
- callback = function()
- require("lazy").show()
- end,
- })
- end
- require("alpha").setup(dashboard.opts)
- vim.api.nvim_create_autocmd("User", {
- pattern = "LazyVimStarted",
- callback = function()
- local v = vim.version()
- local dev = ""
- if v.prerelease == "dev" then
- dev = "-dev+" .. v.build
- else
- dev = ""
- end
- local version = v.major .. "." .. v.minor .. "." .. v.patch .. dev
- local stats = require("lazy").stats()
- local plugins_count = stats.loaded .. "/" .. stats.count
- local ms = math.floor(stats.startuptime + 0.5)
- local time = vim.fn.strftime("%H:%M:%S")
- local date = vim.fn.strftime("%d.%m.%Y")
- local line1 = " " .. plugins_count .. " plugins loaded in " .. ms .. "ms"
- local line2 = "󰃭 " .. date .. "  " .. time
- local line3 = " " .. version
-
- local line1_width = vim.fn.strdisplaywidth(line1)
- local line2Padded = string.rep(" ", (line1_width - vim.fn.strdisplaywidth(line2)) / 2) .. line2
- local line3Padded = string.rep(" ", (line1_width - vim.fn.strdisplaywidth(line3)) / 2) .. line3
-
- dashboard.section.footer.val = {
- line1,
- line2Padded,
- line3Padded,
- }
- pcall(vim.cmd.AlphaRedraw)
- end,
- })
- end,
-}
-
diff --git a/config/nvim/lua/plugins/catppuccin.lua b/config/nvim/lua/plugins/catppuccin.lua
deleted file mode 100644
index 6d05f984..00000000
--- a/config/nvim/lua/plugins/catppuccin.lua
+++ /dev/null
@@ -1,13 +0,0 @@
-return {
- "catppuccin/nvim",
- lazy = false,
- name = "catppuccin",
- priority = 1000,
- config = function()
- require("catppuccin").setup({
- transparent_background = true,
- })
- vim.cmd.colorscheme "catppuccin"
- end
-}
-
diff --git a/config/nvim/lua/plugins/lsp-config.lua b/config/nvim/lua/plugins/lsp-config.lua
deleted file mode 100644
index f41e7984..00000000
--- a/config/nvim/lua/plugins/lsp-config.lua
+++ /dev/null
@@ -1,25 +0,0 @@
-return {
- {
- "williamboman/mason.nvim",
- config = function()
- require("mason").setup()
- end
- },
- {
- "williamboman/mason-lspconfig.nvim",
- config = function()
- require("mason-lspconfig").setup({
- ensure_installed = {"lua_ls", "clangd", "cmake", "cssls", "html"}
- })
- end
- },
- {
- "neovim/nvim-lspconfig",
- config = function()
- local lspconfig = require("lspconfig")
- lspconfig.lua_ls.setup({})
- vim.keymap.set('n', 'K', vim.lsp.buf.hover, {})
- end
- }
-}
-
diff --git a/config/nvim/lua/plugins/lualine.lua b/config/nvim/lua/plugins/lualine.lua
deleted file mode 100644
index bf5923d6..00000000
--- a/config/nvim/lua/plugins/lualine.lua
+++ /dev/null
@@ -1,10 +0,0 @@
-return {
- 'nvim-lualine/lualine.nvim',
- config = function()
- require('lualine').setup({
- options = {
- theme = 'dracula'
- }
- })
- end
-}
diff --git a/config/nvim/lua/plugins/neo-tree.lua b/config/nvim/lua/plugins/neo-tree.lua
deleted file mode 100644
index da29ce40..00000000
--- a/config/nvim/lua/plugins/neo-tree.lua
+++ /dev/null
@@ -1,12 +0,0 @@
-return {
- "nvim-neo-tree/neo-tree.nvim",
- branch = "v3.x",
- dependencies = {
- "nvim-lua/plenary.nvim",
- "nvim-tree/nvim-web-devicons",
- "MunifTanjim/nui.nvim",
- },
- config = function()
- vim.keymap.set('n', '<C-n>', ':Neotree filesystem reveal left<CR>', {})
- end
-}
diff --git a/config/nvim/lua/plugins/telescope.lua b/config/nvim/lua/plugins/telescope.lua
deleted file mode 100644
index 7282f2cb..00000000
--- a/config/nvim/lua/plugins/telescope.lua
+++ /dev/null
@@ -1,13 +0,0 @@
-return {
- {
- 'nvim-telescope/telescope.nvim', tag = '0.1.8',
- dependencies = { 'nvim-lua/plenary.nvim' },
- config = function()
- local builtin = require("telescope.builtin")
- vim.keymap.set('n', '<C-p>', builtin.find_files, {})
- end
- },
- {
- "nvim-telescope/telescope-ui-select.nvim"
- }
-}
diff --git a/config/nvim/lua/plugins/treesitter.lua b/config/nvim/lua/plugins/treesitter.lua
deleted file mode 100644
index 20063418..00000000
--- a/config/nvim/lua/plugins/treesitter.lua
+++ /dev/null
@@ -1,12 +0,0 @@
-return {
- "nvim-treesitter/nvim-treesitter",
- build = ":TSUpdate",
- config = function()
- local configs = require("nvim-treesitter.configs")
- configs.setup({
- ensure_installed = {"lua", "c", "javascript"},
- highlight = { enable = true },
- indent = { enable = true }
- })
- end
-}
diff --git a/config/nvim/lua/vim-options.lua b/config/nvim/lua/vim-options.lua
deleted file mode 100644
index d28b7e8f..00000000
--- a/config/nvim/lua/vim-options.lua
+++ /dev/null
@@ -1,15 +0,0 @@
-vim.cmd("set number")
-vim.cmd("set mouse=a")
-vim.cmd("syntax enable")
-vim.cmd("set showcmd")
-vim.cmd("set encoding=utf-8")
-vim.cmd("set showmatch")
-vim.cmd("set relativenumber")
-vim.cmd("set expandtab")
-vim.cmd("set tabstop=4")
-vim.cmd("set shiftwidth=0")
-vim.cmd("set softtabstop=0")
-vim.cmd("set autoindent")
-vim.cmd("set smarttab")
-vim.keymap.set('n', '<C-h>', '<C-w>h', {})
-vim.keymap.set('n', '<C-l>', '<C-w>l',{})
diff --git a/copy.sh b/copy.sh
index b061f4ac..90dc1b83 100755
--- a/copy.sh
+++ b/copy.sh
@@ -167,6 +167,7 @@ while [[ $# -gt 0 ]]; do
esac
shift
done
+INSTALLED_VERSION=$(get_installed_dotfiles_version)
EXPRESS_SUPPORTED=0
if express_supported; then
EXPRESS_SUPPORTED=1
@@ -409,7 +410,12 @@ if command -v ags >/dev/null 2>&1; then
fi
fi
-printf "\n%.0s" {1..1}
+printf "\\n%.0s" {1..1}
+
+# Capture installed dotfiles version at the start of the workflow so we
+# can apply cleanup rules based on the pre-upgrade state, even if a newer
+# version marker is copied in later.
+INSTALLED_VERSION_AT_START="$(get_installed_dotfiles_version || true)"
# quickshell (ags alternative)
# Check if quickshell is installed
@@ -477,10 +483,10 @@ fi
printf "\n%.0s" {1..1}
restore_hypr_assets "$LOG" "$EXPRESS_MODE"
-printf "\n%.0s" {1..1}
+printf "\\n%.0s" {1..1}
-restore_user_configs "$LOG" "$EXPRESS_MODE"
-printf "\n%.0s" {1..1}
+restore_user_configs "$LOG" "$EXPRESS_MODE" "$INSTALLED_VERSION_AT_START"
+printf "\\n%.0s" {1..1}
restore_user_scripts "$LOG" "$EXPRESS_MODE"
printf "\n%.0s" {1..1}
diff --git a/scripts/lib_copy.sh b/scripts/lib_copy.sh
index fa1231c5..331c6906 100644
--- a/scripts/lib_copy.sh
+++ b/scripts/lib_copy.sh
@@ -12,25 +12,30 @@ copy_phase1() {
echo -n "${CAT:-[ACTION]} Do you want to replace ${YELLOW:-}$DIR2${RESET:-} config? (y/n): "
read DIR1_CHOICE
case "$DIR1_CHOICE" in
- [Yy]*) BACKUP_DIR=$(get_backup_dirname)
- mv "$DIRPATH" "$DIRPATH-backup-$BACKUP_DIR" 2>&1 | tee -a "$log"
- echo -e "${NOTE:-[NOTE]} - Backed up $DIR2 to $DIRPATH-backup-$BACKUP_DIR." 2>&1 | tee -a "$log"
- cp -r "config/$DIR2" "$HOME/.config/$DIR2" 2>&1 | tee -a "$log"
- echo -e "${OK:-[OK]} - Replaced $DIR2 with new configuration." 2>&1 | tee -a "$log"
- if [ "$DIR2" = "rofi" ]; then
- if [ -d "$DIRPATH-backup-$BACKUP_DIR/themes" ]; then
- for file in "$DIRPATH-backup-$BACKUP_DIR/themes"/*; do
- [ -e "$file" ] || continue
- cp -n "$file" "$HOME/.config/rofi/themes/" >>"$log" 2>&1 || true
- done || true
- fi
- if [ -f "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" ]; then
- cp "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" "$HOME/.config/rofi/0-shared-fonts.rasi" >>"$log" 2>&1
- fi
- fi
- break ;;
- [Nn]*) echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIR2${RESET:-}" 2>&1 | tee -a "$log"; break ;;
- *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;;
+ [Yy]*)
+ BACKUP_DIR=$(get_backup_dirname)
+ mv "$DIRPATH" "$DIRPATH-backup-$BACKUP_DIR" 2>&1 | tee -a "$log"
+ echo -e "${NOTE:-[NOTE]} - Backed up $DIR2 to $DIRPATH-backup-$BACKUP_DIR." 2>&1 | tee -a "$log"
+ cp -r "config/$DIR2" "$HOME/.config/$DIR2" 2>&1 | tee -a "$log"
+ echo -e "${OK:-[OK]} - Replaced $DIR2 with new configuration." 2>&1 | tee -a "$log"
+ if [ "$DIR2" = "rofi" ]; then
+ if [ -d "$DIRPATH-backup-$BACKUP_DIR/themes" ]; then
+ for file in "$DIRPATH-backup-$BACKUP_DIR/themes"/*; do
+ [ -e "$file" ] || continue
+ cp -n "$file" "$HOME/.config/rofi/themes/" >>"$log" 2>&1 || true
+ done || true
+ fi
+ if [ -f "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" ]; then
+ cp "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" "$HOME/.config/rofi/0-shared-fonts.rasi" >>"$log" 2>&1
+ fi
+ fi
+ break
+ ;;
+ [Nn]*)
+ echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIR2${RESET:-}" 2>&1 | tee -a "$log"
+ break
+ ;;
+ *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;;
esac
done
else
@@ -49,47 +54,52 @@ copy_waybar() {
echo -n "${CAT:-[ACTION]} Do you want to replace ${YELLOW:-}$DIRW${RESET:-} config? (y/n): "
read DIR1_CHOICE
case "$DIR1_CHOICE" in
- [Yy]*) BACKUP_DIR=$(get_backup_dirname)
- cp -r "$DIRPATHw" "$DIRPATHw-backup-$BACKUP_DIR" 2>&1 | tee -a "$log"
- echo -e "${NOTE:-[NOTE]} - Backed up $DIRW to $DIRPATHw-backup-$BACKUP_DIR." 2>&1 | tee -a "$log"
- rm -rf "$DIRPATHw" && cp -r "config/$DIRW" "$DIRPATHw" 2>&1 | tee -a "$log"
- for file in "config" "style.css"; do
- symlink="$DIRPATHw-backup-$BACKUP_DIR/$file"
- target_file="$DIRPATHw/$file"
- if [ -L "$symlink" ]; then
- symlink_target=$(readlink "$symlink")
- if [ -f "$symlink_target" ]; then
- rm -f "$target_file" && cp -f "$symlink_target" "$target_file"
- fi
- fi
- done
- for dir in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do
- [ -e "$dir" ] || continue
- if [ -d "$dir" ]; then
- target_dir="$HOME/.config/waybar/configs/$(basename "$dir")"
- [ -d "$target_dir" ] || cp -r "$dir" "$HOME/.config/waybar/configs/"
- fi
- done
- for file in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do
- [ -e "$file" ] || continue
- target_file="$HOME/.config/waybar/configs/$(basename "$file")"
- [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/configs/"
- done || true
- for file in "$DIRPATHw-backup-$BACKUP_DIR/style"/*; do
- [ -e "$file" ] || continue
- if [ -d "$file" ]; then
- target_dir="$HOME/.config/waybar/style/$(basename "$file")"
- [ -d "$target_dir" ] || cp -r "$file" "$HOME/.config/waybar/style/"
- else
- target_file="$HOME/.config/waybar/style/$(basename "$file")"
- [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/style/"
- fi
- done || true
- BACKUP_FILEw="$DIRPATHw-backup-$BACKUP_DIR/UserModules"
- [ -f "$BACKUP_FILEw" ] && cp -f "$BACKUP_FILEw" "$DIRPATHw/UserModules"
- break ;;
- [Nn]*) echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIRW${RESET:-} config replacement." 2>&1 | tee -a "$log"; break ;;
- *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;;
+ [Yy]*)
+ BACKUP_DIR=$(get_backup_dirname)
+ cp -r "$DIRPATHw" "$DIRPATHw-backup-$BACKUP_DIR" 2>&1 | tee -a "$log"
+ echo -e "${NOTE:-[NOTE]} - Backed up $DIRW to $DIRPATHw-backup-$BACKUP_DIR." 2>&1 | tee -a "$log"
+ rm -rf "$DIRPATHw" && cp -r "config/$DIRW" "$DIRPATHw" 2>&1 | tee -a "$log"
+ for file in "config" "style.css"; do
+ symlink="$DIRPATHw-backup-$BACKUP_DIR/$file"
+ target_file="$DIRPATHw/$file"
+ if [ -L "$symlink" ]; then
+ symlink_target=$(readlink "$symlink")
+ if [ -f "$symlink_target" ]; then
+ rm -f "$target_file" && cp -f "$symlink_target" "$target_file"
+ fi
+ fi
+ done
+ for dir in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do
+ [ -e "$dir" ] || continue
+ if [ -d "$dir" ]; then
+ target_dir="$HOME/.config/waybar/configs/$(basename "$dir")"
+ [ -d "$target_dir" ] || cp -r "$dir" "$HOME/.config/waybar/configs/"
+ fi
+ done
+ for file in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do
+ [ -e "$file" ] || continue
+ target_file="$HOME/.config/waybar/configs/$(basename "$file")"
+ [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/configs/"
+ done || true
+ for file in "$DIRPATHw-backup-$BACKUP_DIR/style"/*; do
+ [ -e "$file" ] || continue
+ if [ -d "$file" ]; then
+ target_dir="$HOME/.config/waybar/style/$(basename "$file")"
+ [ -d "$target_dir" ] || cp -r "$file" "$HOME/.config/waybar/style/"
+ else
+ target_file="$HOME/.config/waybar/style/$(basename "$file")"
+ [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/style/"
+ fi
+ done || true
+ BACKUP_FILEw="$DIRPATHw-backup-$BACKUP_DIR/UserModules"
+ [ -f "$BACKUP_FILEw" ] && cp -f "$BACKUP_FILEw" "$DIRPATHw/UserModules"
+ break
+ ;;
+ [Nn]*)
+ echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIRW${RESET:-} config replacement." 2>&1 | tee -a "$log"
+ break
+ ;;
+ *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;;
esac
done
else
@@ -187,9 +197,140 @@ compose_overlay_from_backup() {
fi
}
+cleanup_duplicate_userconfigs() {
+ local current_version="$1"
+ local log="$2"
+
+ if [ -z "$current_version" ]; then
+ return
+ fi
+
+ # Run de-dupe only for existing installs up to and including v2.3.19.
+ # For v2.3.20 and newer, the underlying duplication bug is fixed and
+ # this cleanup is no longer needed (and might mask future issues).
+ if version_gte "$current_version" "2.3.20"; then
+ echo "${INFO:-[INFO]} Skipping UserConfigs duplicate cleanup for detected version v$current_version (>= 2.3.20)." 2>&1 | tee -a "$log"
+ return
+ fi
+
+ echo "${INFO:-[INFO]} Running UserConfigs duplicate cleanup for detected version v$current_version (<= 2.3.19)." 2>&1 | tee -a "$log"
+
+ local HYPR_DIR="$HOME/.config/hypr"
+ local BASE_DIR="$HYPR_DIR/configs"
+ local USER_DIR="$HYPR_DIR/UserConfigs"
+
+ local STARTUP_BASE="$BASE_DIR/Startup_Apps.conf"
+ local STARTUP_USER="$USER_DIR/Startup_Apps.conf"
+ local WINDOW_BASE="$BASE_DIR/WindowRules.conf"
+ local WINDOW_USER="$USER_DIR/WindowRules.conf"
+ local KEYBINDS_BASE="$BASE_DIR/Keybinds.conf"
+ local KEYBINDS_USER="$USER_DIR/UserKeybinds.conf"
+
+ # Startup_Apps: strip exec-once lines from UserConfigs that are exact
+ # duplicates of the base Startup_Apps.conf.
+ if [ -f "$STARTUP_BASE" ] && [ -f "$STARTUP_USER" ]; then
+ local tmp_startup
+ local backup_startup
+ backup_startup="$STARTUP_USER.backup-dupfix-$(date +%Y%m%d-%H%M%S)"
+ tmp_startup=$(mktemp)
+ awk '
+ function trim(s){ gsub(/^[ \t]+|[ \t]+$/, "", s); return s }
+ FNR==NR {
+ if ($0 ~ /^[ \t]*exec-once[ \t]*=/) {
+ line=trim($0)
+ base[line]=1
+ }
+ next
+ }
+ {
+ if ($0 ~ /^[ \t]*exec-once[ \t]*=/) {
+ line=trim($0)
+ if (line in base) next
+ }
+ print
+ }
+ ' "$STARTUP_BASE" "$STARTUP_USER" >"$tmp_startup"
+ if ! cmp -s "$STARTUP_USER" "$tmp_startup"; then
+ cp "$STARTUP_USER" "$backup_startup"
+ mv "$tmp_startup" "$STARTUP_USER"
+ echo "${NOTE:-[NOTE]} - Removed duplicate Startup_Apps entries matching base config." 2>&1 | tee -a "$log"
+ else
+ rm -f "$tmp_startup"
+ fi
+ fi
+
+ # WindowRules: strip windowrule/layerrule lines from UserConfigs that
+ # are exact duplicates of the base WindowRules.conf.
+ if [ -f "$WINDOW_BASE" ] && [ -f "$WINDOW_USER" ]; then
+ local tmp_window
+ local backup_window
+ backup_window="$WINDOW_USER.backup-dupfix-$(date +%Y%m%d-%H%M%S)"
+ tmp_window=$(mktemp)
+ awk '
+ function trim(s){ gsub(/^[ \t]+|[ \t]+$/, "", s); return s }
+ FNR==NR {
+ if ($0 ~ /^[ \t]*(windowrule|layerrule)[ \t]*=/) {
+ line=trim($0)
+ base[line]=1
+ }
+ next
+ }
+ {
+ if ($0 ~ /^[ \t]*(windowrule|layerrule)[ \t]*=/) {
+ line=trim($0)
+ if (line in base) next
+ }
+ print
+ }
+ ' "$WINDOW_BASE" "$WINDOW_USER" >"$tmp_window"
+ if ! cmp -s "$WINDOW_USER" "$tmp_window"; then
+ cp "$WINDOW_USER" "$backup_window"
+ mv "$tmp_window" "$WINDOW_USER"
+ echo "${NOTE:-[NOTE]} - Removed duplicate WindowRules entries matching base config." 2>&1 | tee -a "$log"
+ else
+ rm -f "$tmp_window"
+ fi
+ fi
+
+ # Keybinds: strip bind* lines from UserKeybinds.conf that are exact
+ # duplicates of the base Keybinds.conf. Comments and unbinds are kept.
+ if [ -f "$KEYBINDS_BASE" ] && [ -f "$KEYBINDS_USER" ]; then
+ local tmp_keybinds
+ local backup_keybinds
+ backup_keybinds="$KEYBINDS_USER.backup-dupfix-$(date +%Y%m%d-%H%M%S)"
+ tmp_keybinds=$(mktemp)
+ awk '
+ function trim(s){ gsub(/^[ \t]+|[ \t]+$/, "", s); return s }
+ FNR==NR {
+ # Match any Hyprland bind variant: bindd, bindmd, bindld, binded,
+ # bindlnd, bindeld, etc.
+ if ($0 ~ /^[ \t]*bind[a-z]*[ \t]*=/) {
+ line=trim($0)
+ base[line]=1
+ }
+ next
+ }
+ {
+ if ($0 ~ /^[ \t]*bind[a-z]*[ \t]*=/) {
+ line=trim($0)
+ if (line in base) next
+ }
+ print
+ }
+ ' "$KEYBINDS_BASE" "$KEYBINDS_USER" >"$tmp_keybinds"
+ if ! cmp -s "$KEYBINDS_USER" "$tmp_keybinds"; then
+ cp "$KEYBINDS_USER" "$backup_keybinds"
+ mv "$tmp_keybinds" "$KEYBINDS_USER"
+ echo "${NOTE:-[NOTE]} - Removed duplicate UserKeybinds entries matching base Keybinds.conf." 2>&1 | tee -a "$log"
+ else
+ rm -f "$tmp_keybinds"
+ fi
+ fi
+}
restore_user_configs() {
local log="$1"
local express_mode="$2"
+ local old_version="$3"
local DIRPATH="$HOME/.config/hypr"
local BACKUP_DIR
@@ -201,29 +342,32 @@ restore_user_configs() {
exit 1
fi
+ # In express mode we still want to run the de-dupe logic, but we skip
+ # the interactive restoration prompts so the workflow stays non-blocking.
+ local SKIP_RESTORE_PROMPTS=0
if [ -d "$BACKUP_DIR_PATH" ] && [ "$express_mode" -eq 1 ]; then
echo "${NOTE:-[NOTE]} Express mode: skipping UserConfigs restoration prompts." 2>&1 | tee -a "$log"
- return
+ SKIP_RESTORE_PROMPTS=1
fi
- if [ -d "$BACKUP_DIR_PATH" ] && [ "$express_mode" -eq 0 ]; then
+ if [ -d "$BACKUP_DIR_PATH" ] && [ "$SKIP_RESTORE_PROMPTS" -eq 0 ]; then
local VERSION_FILE
VERSION_FILE=$(find "$DIRPATH" -maxdepth 1 -name "v*.*.*" | head -n 1)
local CURRENT_VERSION="999.9.9"
- if [ -n "$VERSION_FILE" ]; then
- CURRENT_VERSION=$(basename "$VERSION_FILE" | sed 's/^v//')
+ if [ -n "$old_version" ]; then
+ CURRENT_VERSION="$old_version"
fi
local TARGET_VERSION="2.3.19"
echo -e "${NOTE:-[NOTE]} Restoring previous ${MAGENTA:-}User-Configs${RESET:-}... " 2>&1 | tee -a "$log"
- printf "${WARNING:-}\
- █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█\n\
- NOTES for RESTORING PREVIOUS CONFIGS\n\
- █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█\n\n\
- The 'UserConfigs' directory is for all your personal settings.\n\
- Files in this directory will override the default configurations,\n\
- so your customizations are not lost when you update.\n\
+ printf "${WARNING:-}\\
+ █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█\\n\\
+ NOTES for RESTORING PREVIOUS CONFIGS\\n\\
+ █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█\\n\\n\\
+ The 'UserConfigs' directory is for all your personal settings.\\n\\
+ Files in this directory will override the default configurations,\\n\\
+ so your customizations are not lost when you update.\\n\\
" >&2
if version_gte "$CURRENT_VERSION" "$TARGET_VERSION"; then
@@ -281,6 +425,19 @@ restore_user_configs() {
done
fi
fi
+
+ # Always run de-dupe based on the installed dotfiles version so that
+ # express mode and standard mode behave consistently. Prefer the
+ # pre-upgrade version (old_version) if provided so we still clean up
+ # legacy duplicates when upgrading to a newer release that no longer
+ # needs the fix.
+ local detected_version="$old_version"
+ if [ -z "$detected_version" ]; then
+ detected_version=$(get_installed_dotfiles_version)
+ fi
+ if [ -n "$detected_version" ]; then
+ cleanup_duplicate_userconfigs "$detected_version" "$log"
+ fi
}
restore_user_scripts() {
diff --git a/scripts/lib_update.sh b/scripts/lib_update.sh
index 0a70dff0..be0b8a0a 100644
--- a/scripts/lib_update.sh
+++ b/scripts/lib_update.sh
@@ -77,6 +77,20 @@ run_repo_update() {
echo " Pull status : $( [ $pull_status -eq 0 ] && echo success || echo failure )" | tee -a "$log_file"
echo "----------------------------------------" | tee -a "$log_file"
+ # Also run the UserConfigs duplicate cleanup for existing installs,
+ # using the same version gating as the main copy workflow (<= v2.3.19).
+ if declare -f get_installed_dotfiles_version >/dev/null 2>&1 \
+ && declare -f cleanup_duplicate_userconfigs >/dev/null 2>&1; then
+ local installed_version
+ installed_version=$(get_installed_dotfiles_version)
+ if [ -n "$installed_version" ]; then
+ echo "${INFO:-[INFO]} Checking for duplicate UserConfigs entries after repo update (detected v$installed_version)..." | tee -a "$log_file"
+ cleanup_duplicate_userconfigs "$installed_version" "$log_file"
+ else
+ echo "${NOTE:-[NOTE]} Skipping UserConfigs duplicate cleanup; installed version could not be detected." | tee -a "$log_file"
+ fi
+ fi
+
read -n1 -s -r -p "Press any key to return to the main menu..."
echo
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage