9 Commits

Author SHA1 Message Date
Fabio Scotto di Santolo
60f177f51c Add targeted Gufw compatibility for Sway sessions
- Remove the global xhost call from start-sway-session to keep Wayland startup clean
- Add a dedicated gufw wrapper and desktop override that temporarily grants Xwayland access only for gufw
2026-04-24 10:27:57 +02:00
Fabio Scotto di Santolo
dc25960f08 Replace Noctalia screenshot plugin with flameshot
- Switch Sway screenshot keybinds to flameshot and start it with the session
- Replace the Noctalia screenshot plugin with the official clipboard plugin and dedicated clipboard shortcuts
2026-04-24 10:27:13 +02:00
Fabio Scotto di Santolo
a57685d377 Desktop Sway: add xhost for polkit authentication compatibility 2026-04-24 00:26:39 +02:00
Fabio Scotto di Santolo
781f366fe7 Desktop Sway: add xorg-server-xwayland for X11 app compatibility 2026-04-24 00:07:23 +02:00
Fabio Scotto di Santolo
53b7baf52f Noctalia: add Network and Bluetooth to systray 2026-04-24 00:03:25 +02:00
Fabio Scotto di Santolo
525b0b0e42 Profile i3: remove unnecessary dunst/rofi directory creation
These directories are created automatically by the dotfiles copy task
in profile_desktop_i3, so hardcoding them in profile_desktop_common
unnecessarily creates them on Sway hosts.
2026-04-23 23:22:56 +02:00
Fabio Scotto di Santolo
57a605587a Set fixed wallpaper for Noctalia via wallpapers.json cache 2026-04-23 23:17:49 +02:00
Fabio Scotto di Santolo
8acd8204b9 Add i3 cleanup script for post-migration hosts
- Add a manual oneshot script to remove i3-only packages and configs after moving a host to SwayFX and Noctalia
- Support dry-run by default with optional apply and aggressive cleanup modes
2026-04-23 21:24:05 +02:00
Fabio Scotto di Santolo
e5b24fdf2c Align desktop theming around Noctalia Ayu
- Move Sway, GTK, Qt, Alacritty, and Emacs toward the Noctalia-generated Ayu theme
- Add shared font/cursor settings, qt5ct/qt6ct templates, and Flatpak theme integration support
- Keep browser and Telegram theming manual while preserving generated Noctalia assets where useful
2026-04-23 20:52:58 +02:00
21 changed files with 469 additions and 97 deletions

View File

@@ -91,7 +91,7 @@ Lo stato attuale del profilo desktop include, tra le altre cose:
- `tmux` con plugin gestiti da TPM al bootstrap del profilo desktop
- Flatpak con remoto Flathub
- GNOME Keyring e bootstrap della posta via script dedicato
- shell Noctalia su Sway su `nymph`, con plugin ufficiali per clipboard (`clipper`), polkit (`polkit-agent`), screenshot (`screenshot`) e gestione USB (`usb-drive-manager`); config condivisa in `dotfiles/desktop/.config/noctalia/` e `settings.json` renderizzato da template Ansible con variabili host-specifiche
- shell Noctalia su Sway su `nymph`, con plugin ufficiali per clipboard (`clipper`, `clipboard`), polkit (`polkit-agent`) e gestione USB (`usb-drive-manager`); config condivisa in `dotfiles/desktop/.config/noctalia/` e `settings.json` renderizzato da template Ansible con variabili host-specifiche
- `udiskie` come backend per automount/LUKS su Sway, senza tray; la UI dei dispositivi removibili è demandata a `usb-drive-manager`
- `kanshi` su `nymph` per il profilo monitor Wayland, con workspace Sway deterministici: in dual monitor `1` resta su `eDP-1` e `2-10` vanno su `DP-1`, mentre in laptop-only tutti tornano su `eDP-1`
- monitor Noctalia e `screenOverrides` dichiarati in inventory (`noctalia_bar_monitors`, `noctalia_screen_overrides`) per host `nymph`

View File

@@ -9,6 +9,16 @@ desktop_default_session_env: xorg
desktop_restart_emptty_automatically: false
desktop_emptty_session_error_logging: disabled
desktop_ui_font_family: Noto Sans
desktop_ui_font_size: 10
desktop_fixed_font_family: Hack Nerd Font
desktop_sway_font_size: 10
desktop_alacritty_font_size: 12
desktop_emacs_font_size: 14
desktop_cursor_theme: Yaru
desktop_cursor_size: 24
desktop_icon_theme: Yaru-orange-dark
desktop_common_packages:
- brightnessctl
- dex
@@ -47,12 +57,18 @@ desktop_i3_packages:
- xss-lock
desktop_sway_packages:
- adw-gtk-theme
- flameshot
- grim
- kanshi
- qt5ct
- qt6ct
- slurp
- swayfx
- wl-clipboard
- xhost
- xdg-desktop-portal-wlr
- xorg-server-xwayland
profile_packages:
- alacritty
@@ -231,10 +247,18 @@ desktop_common_dotfiles:
src: .local/bin/update-turnstile-env
dest: .local/bin/update-turnstile-env
mode: "0755"
- name: Gufw Sway wrapper
src: .local/bin/run-gufw
dest: .local/bin/run-gufw
mode: "0755"
- name: Udiskie password helper
src: .local/bin/udiskie-password
dest: .local/bin/udiskie-password
mode: "0755"
- name: Desktop application overrides
src: .local/share/applications/
dest: .local/share/applications/
mode: preserve
- name: SSH config
src: .ssh/config
dest: .ssh/config
@@ -277,6 +301,10 @@ desktop_sway_dotfiles:
src: .config/i3/wallpapers/
dest: .config/sway/wallpapers/
mode: preserve
- name: Noctalia wallpaper library
src: Pictures/Wallpapers/
dest: Pictures/Wallpapers/
mode: preserve
- name: Sway session wrapper
src: .local/bin/start-sway-session
dest: .local/bin/start-sway-session
@@ -299,6 +327,8 @@ noctalia_bar_monitors:
noctalia_screen_overrides: []
noctalia_wallpaper: "{{ user_home }}/Pictures/Wallpapers/star-wars-trio.jpg"
desktop_flatpak_packages:
- be.alexandervanhee.gradia
- ch.protonmail.protonmail-bridge
@@ -310,4 +340,14 @@ desktop_flatpak_packages:
- org.telegram.desktop
desktop_flatpak_extensions:
- org.gtk.Gtk3theme.Yaru-Blue-dark//stable
- org.gtk.Gtk3theme.Yaru-Orange-dark//3.22
desktop_flatpak_global_filesystems:
- xdg-config/gtk-3.0:ro
- xdg-config/gtk-4.0:ro
- xdg-config/qt5ct:ro
- xdg-config/qt6ct:ro
desktop_flatpak_global_env:
- QT_QPA_PLATFORM=wayland
- QT_QPA_PLATFORMTHEME=qt6ct

View File

@@ -18,10 +18,10 @@
loop:
- "{{ user_home }}/.config"
- "{{ user_home }}/.config/autostart"
- "{{ user_home }}/.config/dunst"
- "{{ user_home }}/.config/alacritty"
- "{{ user_home }}/.config/Thunar"
- "{{ user_home }}/.config/rofi"
- "{{ user_home }}/.local/share"
- "{{ user_home }}/.local/share/applications"
- "{{ user_home }}/.tmux"
- "{{ user_home }}/.tmux/bin"
- "{{ user_home }}/.tmux/plugins"

View File

@@ -10,6 +10,10 @@
loop:
- "{{ user_home }}/.config/sway"
- "{{ user_home }}/.config/kanshi"
- "{{ user_home }}/.config/qt5ct"
- "{{ user_home }}/.config/qt5ct/colors"
- "{{ user_home }}/.config/qt6ct"
- "{{ user_home }}/.config/qt6ct/colors"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Ensure Noctalia config directories exist
@@ -69,6 +73,26 @@
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Render qt5ct config
tags: [dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.template:
src: qt5ct.conf.j2
dest: "{{ user_home }}/.config/qt5ct/qt5ct.conf"
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Render qt6ct config
tags: [dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.template:
src: qt6ct.conf.j2
dest: "{{ user_home }}/.config/qt6ct/qt6ct.conf"
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Manage Noctalia shell plugins
tags: [dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.include_tasks: noctalia.yml
@@ -83,3 +107,37 @@
group: "{{ user_group }}"
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Allow Flatpak apps to read shared theme configs
tags: [packages, dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.command:
argv:
- flatpak
- override
- --user
- "--filesystem={{ item }}"
become_user: "{{ username }}"
environment:
HOME: "{{ user_home }}"
changed_when: false
loop: "{{ desktop_flatpak_global_filesystems | default([]) }}"
when:
- "'sway' in (desktop_sessions_enabled | default([]))"
- (desktop_flatpak_packages | default([])) | length > 0
- name: Export global Flatpak environment for theme integration
tags: [packages, dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.command:
argv:
- flatpak
- override
- --user
- "--env={{ item }}"
become_user: "{{ username }}"
environment:
HOME: "{{ user_home }}"
changed_when: false
loop: "{{ desktop_flatpak_global_env | default([]) }}"
when:
- "'sway' in (desktop_sessions_enabled | default([]))"
- (desktop_flatpak_packages | default([])) | length > 0

View File

@@ -137,6 +137,22 @@
owner: "{{ username }}"
group: "{{ user_group }}"
loop:
- clipboard
- polkit-agent
- screenshot
- usb-drive-manager
- name: Ensure Noctalia cache directory exists
ansible.builtin.file:
path: "{{ user_home }}/.cache/noctalia"
state: directory
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0755"
- name: Deploy Noctalia wallpapers cache
ansible.builtin.template:
src: wallpapers.json.j2
dest: "{{ user_home }}/.cache/noctalia/wallpapers.json"
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0644"

View File

@@ -203,6 +203,18 @@
"middleClickCommand": "pwvucontrol || pavucontrol",
"textColor": "none"
},
{
"displayMode": "onhover",
"iconColor": "none",
"id": "Network",
"textColor": "none"
},
{
"displayMode": "onhover",
"iconColor": "none",
"id": "Bluetooth",
"textColor": "none"
},
{
"applyToAllMonitors": false,
"displayMode": "onhover",
@@ -561,15 +573,17 @@
{"enabled": true, "id": "alacritty"},
{"enabled": true, "id": "gtk"},
{"enabled": true, "id": "emacs"},
{"enabled": true, "id": "telegram"}
{"enabled": true, "id": "telegram"},
{"enabled": true, "id": "qt"},
{"enabled": true, "id": "sway"}
],
"enableUserTheming": false
},
"ui": {
"boxBorderEnabled": false,
"fontDefault": "Sans Serif",
"fontDefault": "{{ desktop_ui_font_family | default('Noto Sans') }}",
"fontDefaultScale": 1,
"fontFixed": "monospace",
"fontFixed": "{{ desktop_fixed_font_family | default('Hack Nerd Font') }}",
"fontFixedScale": 1,
"panelBackgroundOpacity": 0.93,
"panelsAttachedToBar": true,

View File

@@ -0,0 +1,6 @@
[Appearance]
color_scheme_path={{ user_home }}/.config/qt5ct/colors/noctalia.conf
custom_palette=true
icon_theme={{ desktop_icon_theme | default('Yaru-orange-dark') }}
standard_dialogs=default
style=Fusion

View File

@@ -0,0 +1,6 @@
[Appearance]
color_scheme_path={{ user_home }}/.config/qt6ct/colors/noctalia.conf
custom_palette=true
icon_theme={{ desktop_icon_theme | default('Yaru-orange-dark') }}
standard_dialogs=default
style=Fusion

View File

@@ -2,9 +2,9 @@ set $menu qs -c noctalia-shell ipc call launcher toggle
set $audio_panel qs -c noctalia-shell ipc call volume openPanel
set $locker qs -c noctalia-shell ipc call lockScreen lock
set $powermenu qs -c noctalia-shell ipc call sessionMenu toggle
set $screenshot_full qs -c noctalia-shell ipc call plugin:screenshot takeScreenshot output
set $screenshot_region qs -c noctalia-shell ipc call plugin:screenshot takeScreenshot region
set $screenshot_window qs -c noctalia-shell ipc call plugin:screenshot takeScreenshot window
set $screenshot_full sh -c 'QT_QPA_PLATFORM=wayland flameshot full --clipboard'
set $screenshot_region sh -c 'QT_QPA_PLATFORM=wayland flameshot gui'
set $screenshot_window sh -c 'QT_QPA_PLATFORM=wayland flameshot gui'
set $audio_raise qs -c noctalia-shell ipc call volume increase
set $audio_lower qs -c noctalia-shell ipc call volume decrease
set $audio_mute qs -c noctalia-shell ipc call volume muteOutput
@@ -22,8 +22,11 @@ exec pipewire
exec pipewire-pulse
exec wireplumber
exec kanshi
exec flameshot
exec udiskie --no-tray
exec wl-paste --watch cliphist store
exec qs -c noctalia-shell
bindsym $mod+c exec qs -c noctalia-shell ipc call launcher clipboard
bindsym $mod+Ctrl+v exec qs -c noctalia-shell ipc call plugin:clipboard toggle
bindsym $mod+Ctrl+Shift+v exec qs -c noctalia-shell ipc call plugin:clipboard wipe

View File

@@ -0,0 +1,18 @@
{
"defaultWallpaper": "/etc/xdg/quickshell/noctalia-shell/Assets/Wallpaper/noctalia.png",
"usedRandomWallpapers": {},
"wallpapers": {
"": {
"dark": "{{ noctalia_wallpaper }}",
"light": "{{ noctalia_wallpaper }}"
},
"DP-1": {
"dark": "{{ noctalia_wallpaper }}",
"light": "{{ noctalia_wallpaper }}"
},
"eDP-1": {
"dark": "{{ noctalia_wallpaper }}",
"light": "{{ noctalia_wallpaper }}"
}
}
}

View File

@@ -1,3 +1,6 @@
[general]
import = ["~/.config/alacritty/themes/noctalia.toml"]
[window]
padding = { x = 8, y = 8 }
opacity = 1.0
@@ -13,30 +16,6 @@ multiplier = 3
[cursor]
style = { shape = "Beam", blinking = "Off" }
[colors.primary]
background = "#000000"
foreground = "#c8c8c8"
[colors.normal]
black = "#1f1f28"
red = "#c7162b"
green = "#4caf50"
yellow = "#e95420"
blue = "#4a90d9"
magenta = "#7e57c2"
cyan = "#6daeea"
white = "#eeeeee"
[colors.bright]
black = "#3a3a46"
red = "#ff5c5c"
green = "#7ad97a"
yellow = "#ff8f40"
blue = "#6daeea"
magenta = "#9575cd"
cyan = "#8bd6ff"
white = "#ffffff"
[keyboard]
bindings = [
{ key = "V", mods = "Control|Shift", action = "Paste" },

View File

@@ -7,6 +7,10 @@
}
],
"states": {
"clipboard": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
},
"clipper": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
@@ -15,10 +19,6 @@
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
},
"screenshot": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
},
"usb-drive-manager": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"

View File

@@ -38,43 +38,7 @@
"fg": "mOnError"
}
},
"customColors": {
"Text": {
"bg": "#555555",
"separator": "#000000",
"fg": "#e9e4f0"
},
"Image": {
"bg": "#e0b7c9",
"separator": "#000000",
"fg": "#20161f"
},
"Link": {
"bg": "#c7a1d8",
"separator": "#000000",
"fg": "#1a151f"
},
"Code": {
"bg": "#a984c4",
"separator": "#000000",
"fg": "#f3edf7"
},
"Color": {
"bg": "#a984c4",
"separator": "#000000",
"fg": "#f3edf7"
},
"Emoji": {
"bg": "#e0b7c9",
"separator": "#000000",
"fg": "#20161f"
},
"File": {
"bg": "#e9899d",
"separator": "#000000",
"fg": "#1e1418"
}
},
"customColors": {},
"enableTodoIntegration": true,
"autoOpenPinnedPanel": false,
"pincardsEnabled": true,

View File

@@ -6,7 +6,7 @@ set $fallback_terminal st
include ~/.config/sway/host.conf
include ~/.config/sway/shell.conf
font pango:Liberation Mono 10
font pango:Hack Nerd Font 10
# Input and output defaults
seat seat0 xcursor_theme Yaru 24
@@ -166,9 +166,4 @@ mode "resize" {
bindsym $mod+r mode "resize"
client.focused #4a90d9 #4a90d9 #ffffff #4a90d9 #4a90d9
client.focused_inactive #3a3a46 #2b2b36 #eeeeee #3a3a46 #3a3a46
client.unfocused #2b2b36 #1f1f28 #bcbcbc #2b2b36 #2b2b36
client.urgent #c7162b #c7162b #ffffff #c7162b #c7162b
client.placeholder #1f1f28 #1f1f28 #bcbcbc #1f1f28 #1f1f28
client.background #1f1f28
include ~/.config/sway/noctalia

View File

@@ -1,16 +1,14 @@
;;; core-ui.el -*- lexical-binding: t; -*-
;; Load default theme
(use-package nordic-night-theme
:ensure t)
(load-theme 'nordic-night t)
;; Load generated Noctalia theme.
(add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory))
(load-theme 'noctalia t)
;; Setting default font
(set-frame-font "Liberation Mono 14" nil t)
(set-frame-font "Hack Nerd Font 14" nil t)
(add-to-list 'default-frame-alist
'(font . "Liberation Mono-14"))
'(font . "Hack Nerd Font-14"))
;; Remove toolbar
(tool-bar-mode -1)

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env sh
set -eu
if [ -z "${DISPLAY:-}" ]; then
printf 'Error: DISPLAY is not set; cannot launch gufw under Xwayland.\n' >&2
exit 1
fi
if ! command -v xhost >/dev/null 2>&1; then
printf 'Error: xhost is required to launch gufw from a Wayland session.\n' >&2
exit 1
fi
cleanup() {
xhost -si:localuser:root >/dev/null 2>&1 || true
}
trap cleanup EXIT INT TERM HUP
xhost si:localuser:root >/dev/null
exec gufw "$@"

View File

@@ -1,15 +1,13 @@
#!/bin/sh
THEME="Yaru-blue-dark"
ICONS="Yaru-blue-dark"
ICONS="Yaru-orange-dark"
CURSOR="Yaru"
FONT_UI="Liberation Sans 10"
FONT_UI="Noto Sans 10"
mkdir -p "$HOME/.config/gtk-3.0"
mkdir -p "$HOME/.config/gtk-4.0"
cat > "$HOME/.gtkrc-2.0" <<EOF
gtk-theme-name="$THEME"
gtk-icon-theme-name="$ICONS"
gtk-cursor-theme-name="$CURSOR"
gtk-font-name="$FONT_UI"
@@ -19,7 +17,6 @@ EOF
cat > "$HOME/.config/gtk-3.0/settings.ini" <<EOF
[Settings]
gtk-theme-name=$THEME
gtk-icon-theme-name=$ICONS
gtk-cursor-theme-name=$CURSOR
gtk-font-name=$FONT_UI
@@ -32,7 +29,6 @@ EOF
cat > "$HOME/.config/gtk-4.0/settings.ini" <<EOF
[Settings]
gtk-theme-name=$THEME
gtk-icon-theme-name=$ICONS
gtk-cursor-theme-name=$CURSOR
gtk-font-name=$FONT_UI
@@ -40,8 +36,8 @@ gtk-application-prefer-dark-theme=1
EOF
if command -v gsettings >/dev/null 2>&1; then
gsettings set org.gnome.desktop.interface gtk-theme "$THEME" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface icon-theme "$ICONS" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface cursor-theme "$CURSOR" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface font-name "$FONT_UI" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface color-scheme prefer-dark >/dev/null 2>&1 || true
fi

View File

@@ -0,0 +1,13 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Firewall Configuration
Comment=An easy way to configure your firewall
Keywords=gufw;security;firewall;network;
Categories=GNOME;GTK;Settings;Security;X-GNOME-Settings-Panel;X-GNOME-SystemSettings;X-Unity-Settings-Panel;X-XFCE-SettingsDialog;X-XFCE-SystemSettings;
Exec=/home/fscotto/.local/bin/run-gufw
Icon=gufw
Terminal=false
X-GNOME-Settings-Panel=gufw
X-Unity-Settings-Panel=gufw
X-Ubuntu-Gettext-Domain=gufw

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -1,4 +1,6 @@
export LIBVA_DRIVER_NAME=iHD
export QT_QPA_PLATFORM=wayland
export QT_QPA_PLATFORMTHEME=qt6ct
export SWAY_UNSUPPORTED_GPU=1
export WLR_DRM_DEVICES=/dev/dri/card0:/dev/dri/card1
export WLR_NO_HARDWARE_CURSORS=1

View File

@@ -0,0 +1,242 @@
#!/usr/bin/env sh
set -eu
APPLY=0
AGGRESSIVE=0
SAFE_PACKAGES="
arandr
autorandr
feh
i3
i3blocks
i3blocks-blocklets
i3lock-color
i3status
scrot
setxkbmap
volumeicon
xclip
xkbutils
xorg-fonts
xorg-minimal
xss-lock
"
AGGRESSIVE_PACKAGES="
dunst
rofi
blueman
network-manager-applet
xfce-polkit
xfce4-clipman-plugin
xfce4-screenshooter
"
SAFE_PATHS="
$HOME/.config/i3
$HOME/.config/i3blocks
$HOME/.config/autorandr
$HOME/.xinitrc
"
AGGRESSIVE_PATHS="
$HOME/.config/dunst
$HOME/.config/rofi
"
usage() {
cat <<'EOF'
Usage: cleanup_i3_after_sway_migration.sh [--apply] [--aggressive]
One-shot cleanup for removing i3/X11-only packages and dotfiles after a host
has already migrated to SwayFX + Noctalia.
Options:
--apply perform the cleanup for real
--aggressive also remove extra desktop apps/configs that were mainly useful
in the old i3 setup (dunst, rofi, blueman, etc.)
-h, --help show this help
Default mode is dry-run.
EOF
}
have_command() {
command -v "$1" >/dev/null 2>&1
}
require_sway_noctalia() {
if [ ! -f "$HOME/.config/sway/config" ]; then
printf 'Error: Sway config not found at %s\n' "$HOME/.config/sway/config" >&2
exit 1
fi
if [ ! -f "$HOME/.config/noctalia/settings.json" ]; then
printf 'Error: Noctalia settings not found at %s\n' "$HOME/.config/noctalia/settings.json" >&2
exit 1
fi
}
append_lines() {
src_lines=$1
dst_var=$2
for line in $src_lines; do
line=$(printf '%s' "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$line" ] || continue
case "$dst_var" in
PACKAGES)
PACKAGES="$PACKAGES $line"
;;
PATHS)
PATHS="$PATHS $line"
;;
*)
printf 'Error: unsupported destination list: %s\n' "$dst_var" >&2
exit 1
;;
esac
done
}
filter_installed_packages() {
packages=$1
installed=''
for pkg in $packages; do
pkg=$(printf '%s' "$pkg" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$pkg" ] || continue
if xbps-query -s "$pkg" >/dev/null 2>&1; then
installed="$installed $pkg"
fi
done
printf '%s' "$installed"
}
filter_existing_paths() {
paths=$1
existing=''
for path in $paths; do
path=$(printf '%s' "$path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$path" ] || continue
if [ -e "$path" ] || [ -L "$path" ]; then
existing="$existing $path"
fi
done
printf '%s' "$existing"
}
print_section() {
title=$1
items=$2
printf '%s\n' "$title"
if [ -z "$items" ]; then
printf ' (none)\n'
return
fi
for item in $items; do
item=$(printf '%s' "$item" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$item" ] || continue
printf ' - %s\n' "$item"
done
}
confirm_apply() {
printf 'Proceed with i3 cleanup? [y/N] '
IFS= read -r answer
case "$answer" in
y|Y|yes|YES)
;;
*)
printf 'Aborted.\n'
exit 0
;;
esac
}
run_remove_packages() {
packages=$1
[ -n "$packages" ] || return 0
if [ "$(id -u)" -eq 0 ]; then
xbps-remove -R $packages
elif have_command sudo; then
sudo xbps-remove -R $packages
else
printf 'Error: package removal requires root and sudo was not found.\n' >&2
exit 1
fi
}
run_remove_paths() {
paths=$1
[ -n "$paths" ] || return 0
for path in $paths; do
path=$(printf '%s' "$path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$path" ] || continue
rm -rf "$path"
done
}
while [ $# -gt 0 ]; do
case "$1" in
--apply)
APPLY=1
;;
--aggressive)
AGGRESSIVE=1
;;
-h|--help)
usage
exit 0
;;
*)
printf 'Error: unknown argument: %s\n\n' "$1" >&2
usage >&2
exit 1
;;
esac
shift
done
require_sway_noctalia
PACKAGES=''
PATHS=''
append_lines "$SAFE_PACKAGES" PACKAGES
append_lines "$SAFE_PATHS" PATHS
if [ "$AGGRESSIVE" -eq 1 ]; then
append_lines "$AGGRESSIVE_PACKAGES" PACKAGES
append_lines "$AGGRESSIVE_PATHS" PATHS
fi
INSTALLED_PACKAGES=$(filter_installed_packages "$PACKAGES")
EXISTING_PATHS=$(filter_existing_paths "$PATHS")
printf 'Mode: %s\n' "$( [ "$APPLY" -eq 1 ] && printf 'apply' || printf 'dry-run' )"
printf 'Aggressive cleanup: %s\n\n' "$( [ "$AGGRESSIVE" -eq 1 ] && printf 'yes' || printf 'no' )"
print_section 'Packages to remove:' "$INSTALLED_PACKAGES"
printf '\n'
print_section 'Paths to remove:' "$EXISTING_PATHS"
if [ "$APPLY" -ne 1 ]; then
printf '\nDry-run only. Re-run with --apply to perform the cleanup.\n'
exit 0
fi
confirm_apply
run_remove_packages "$INSTALLED_PACKAGES"
run_remove_paths "$EXISTING_PATHS"
printf '\nCleanup complete.\n'