forked from Shinonome/dots-hyprland
Rearrange for tidier structure (#2212)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
This folder mainly contains data for install scripts.
|
||||
@@ -0,0 +1,86 @@
|
||||
## Status: WIP
|
||||
This file was generated by AI (see [#2102](https://github.com/end-4/dots-hyprland/issues/2102)).
|
||||
It still needs manual correction.
|
||||
|
||||
## Information
|
||||
Meta-packages (from sdist/arch/install-deps.sh)
|
||||
- illogical-impulse-basic
|
||||
- Purpose: Core shell tooling used by scripts (general CLI utilities, build helpers, JSON processing, etc.).
|
||||
- illogical-impulse-audio
|
||||
- Purpose: Audio stack (e.g., PipeWire/WirePlumber, mixers, control UIs) used by widgets and desktop integrations.
|
||||
- illogical-impulse-backlight
|
||||
- Purpose: Screen brightness control utilities (e.g., brightnessctl).
|
||||
- illogical-impulse-fonts-themes
|
||||
- Purpose: Fonts and themes used across the shell/widgets (Noto, emoji fonts, icon themes, GTK/Qt themes).
|
||||
- illogical-impulse-kde
|
||||
- Purpose: KDE integration bits (dialogs, theming helpers, optional browser integration).
|
||||
- illogical-impulse-portal
|
||||
- Purpose: Desktop portals (e.g., xdg-desktop-portal and Wayland compositor-specific portals).
|
||||
- illogical-impulse-python
|
||||
- Purpose: Python 3 and libs for repo Python scripts and virtualenv activation.
|
||||
- illogical-impulse-screencapture
|
||||
- Purpose: Screenshot/recording tools on Wayland (e.g., grim, slurp, wf-recorder or similar).
|
||||
- illogical-impulse-toolkit
|
||||
- Purpose: General utilities used by scripts (jq, imagemagick, bc, etc.).
|
||||
- illogical-impulse-widgets
|
||||
- Purpose: Runtime deps for Quickshell widgets and supporting tools used in the UI modules.
|
||||
- illogical-impulse-hyprland
|
||||
- Purpose: Hyprland compositor and related tools (hyprland, hyprctl, hypridle, hyprlock, hyprcursor, portals).
|
||||
- illogical-impulse-microtex-git
|
||||
- Purpose: MicroTeX-related setup used by this config (custom packaging).
|
||||
- illogical-impulse-bibata-modern-classic-bin (optional)
|
||||
- Purpose: Bibata Modern Classic mouse cursor theme (installed only if not present).
|
||||
|
||||
Concrete dependencies inferred from repository scripts
|
||||
- hyprland (provides hyprctl)
|
||||
- Purpose: Compositor
|
||||
- jq
|
||||
- Used by: switchwall.sh (JSON parsing), multiple scripts reading config.json, hyprctl -j output.
|
||||
- Purpose: JSON parsing and transformation.
|
||||
- matugen (AUR)
|
||||
- Used by: switchwall.sh to generate Material You colors from image or color input.
|
||||
- Purpose: Color extraction and scheme generation.
|
||||
- python (python3) + virtualenv (python-virtualenv)
|
||||
- Used by: switchwall.sh activates $ILLOGICAL_IMPULSE_VIRTUAL_ENV and runs generate_colors_material.py.
|
||||
- Purpose: Color processing
|
||||
- imagemagick (identify)
|
||||
- Used by: switchwall.sh to probe image width/height to suggest upscaling.
|
||||
- Purpose: Image metadata inspection.
|
||||
- bc
|
||||
- Used by: switchwall.sh for simple arithmetic on cursor coordinates.
|
||||
- Purpose: Shell-friendly math.
|
||||
- xdg-user-dirs (xdg-user-dir)
|
||||
- Used by: switchwall.sh to locate Pictures folder.
|
||||
- Purpose: XDG directories resolution.
|
||||
- libnotify (notify-send)
|
||||
- Used by: switchwall.sh to interactively prompt actions (install/open apps) via notifications.
|
||||
- Purpose: Desktop notifications with actions.
|
||||
- hyprpicker (AUR)
|
||||
- Used by: switchwall.sh for picking colors from screen when --color is passed without hex.
|
||||
- Purpose: On-screen color picker (Wayland).
|
||||
- mpvpaper (AUR)
|
||||
- Used by: switchwall.sh to set video wallpapers per monitor.
|
||||
- Purpose: Video wallpaper playback under Wayland.
|
||||
- ffmpeg
|
||||
- Used by: switchwall.sh to extract a frame from videos to derive colors and thumbnails.
|
||||
- Purpose: Video frame extraction and media handling.
|
||||
- kitty
|
||||
- Used by: switchwall.sh to run interactive installs or external tools in a terminal (kitty -1 ...).
|
||||
- Purpose: Terminal emulator integration.
|
||||
- kdialog (KDE)
|
||||
- Used by: switchwall.sh to open a file picker for choosing wallpapers.
|
||||
- Purpose: GUI file selection dialog.
|
||||
- glib2 (gsettings) + dconf
|
||||
- Used by: switchwall.sh to set GNOME interface color-scheme and GTK theme.
|
||||
- Purpose: System settings manipulation.
|
||||
- yay (or yay-bin from AUR)
|
||||
- Used by: sdist/arch/install-deps.sh to build/install local PKGBUILDs and dependencies.
|
||||
- Purpose: AUR helper used by installer.
|
||||
- base-devel, git, makepkg (core Arch tooling)
|
||||
- Used by: sdist/arch/install-deps.sh and update.sh for building AUR/PKGBUILD packages and repository management.
|
||||
- Purpose: Build toolchain and VCS for packaging.
|
||||
|
||||
|
||||
Notes
|
||||
- Some Hyprland-adjacent packages appear in a legacy removal list as -git variants (e.g., hypridle, hyprlock, xdg-desktop-portal-hyprland). This suggests the meta-packages likely standardized on stable repo versions now.
|
||||
- Exact package lists per meta-package should be verified against the PKGBUILD files in sdist/arch/*; the above is aligned with how the code uses these tools.
|
||||
@@ -0,0 +1,77 @@
|
||||
# This script is meant to be sourced.
|
||||
# It's not for directly running.
|
||||
|
||||
printf 'Hi there!\n'
|
||||
printf 'This script 1. will uninstall [end-4/dots-hyprland > illogical-impulse] dotfiles\n'
|
||||
printf ' 2. will try to revert *mostly everything* installed using install.sh, so it'\''s pretty destructive\n'
|
||||
printf ' 3. has not been tested, use at your own risk.\n'
|
||||
printf ' 4. will show all commands that it runs.\n'
|
||||
printf 'Ctrl+C to exit. Enter to continue.\n'
|
||||
read -r
|
||||
##############################################################################################################################
|
||||
|
||||
# Undo Step 3: Removing copied config and local folders
|
||||
printf "${STY_CYAN}Removing copied config and local folders...\n${STY_RESET}"
|
||||
|
||||
dirs=(
|
||||
Kvantum/
|
||||
fish/
|
||||
fontconfig/
|
||||
foot/
|
||||
fuzzel/
|
||||
hypr/
|
||||
kde-material-you-colors/
|
||||
kitty/
|
||||
matugen/
|
||||
mpv/
|
||||
qt5ct/
|
||||
qt6ct/
|
||||
quickshell/
|
||||
wlogout/
|
||||
xdg-desktop-portal/
|
||||
zshrc.d/
|
||||
chrome-flags.conf
|
||||
code-flags.conf
|
||||
darklyrc
|
||||
dolphinrc
|
||||
kdeglobals
|
||||
konsolerc
|
||||
starship.toml
|
||||
thorium-flags.conf
|
||||
)
|
||||
|
||||
for i in ${dirs[@]}
|
||||
do v rm -rf "$XDG_CONFIG_HOME/$i"
|
||||
done
|
||||
|
||||
for i in "glib-2.0/schemas/com.github.GradienceTeam.Gradience.Devel.gschema.xml" "gradience"
|
||||
do v rm -rf "$XDG_DATA_HOME/$i"
|
||||
done
|
||||
v rm -rf "$XDG_CACHE_HOME/quickshell"
|
||||
v sudo rm -rf "$XDG_STATE_HOME/quickshell"
|
||||
|
||||
##############################################################################################################################
|
||||
|
||||
# Undo Step 2: Uninstall AGS - Disabled for now, check issues
|
||||
# echo 'Uninstalling AGS...'
|
||||
# sudo meson uninstall -C ~/ags/build
|
||||
# rm -rf ~/ags
|
||||
|
||||
##############################################################################################################################
|
||||
|
||||
# Undo Step 1: Remove added user from video, i2c, and input groups and remove yay packages
|
||||
printf "${STY_CYAN}Removing user from video, i2c, and input groups and removing packages...\n${STY_RESET}"
|
||||
user=$(whoami)
|
||||
v sudo gpasswd -d "$user" video
|
||||
v sudo gpasswd -d "$user" i2c
|
||||
v sudo gpasswd -d "$user" input
|
||||
v sudo rm /etc/modules-load.d/i2c-dev.conf
|
||||
|
||||
##############################################################################################################################
|
||||
read -p "Do you want to uninstall the illogical-impulse-* meta packages (Arch Linux only)?
|
||||
Ctrl+C to exit, or press Enter to proceed" p
|
||||
|
||||
# Removing installed yay packages and dependencies
|
||||
v yay -Rns illogical-impulse-{audio,backlight,basic,bibata-modern-classic-bin,fonts-themes,hyprland,kde,microtex-git,oneui4-icons-git,portal,python,screencapture,toolkit,widgets} plasma-browser-integration
|
||||
|
||||
printf "${STY_CYAN}Uninstall Complete.\n${STY_RESET}"
|
||||
@@ -0,0 +1,860 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# update.sh - Enhanced dotfiles update script
|
||||
#
|
||||
# Features:
|
||||
# - Pull latest commits from remote
|
||||
# - Rebuild packages if PKGBUILD files changed (user choice)
|
||||
# - Handle config file conflicts with user choices
|
||||
# - Respect .updateignore file for exclusions
|
||||
#
|
||||
set -uo pipefail
|
||||
|
||||
# === Configuration ===
|
||||
FORCE_CHECK=false
|
||||
CHECK_PACKAGES=false
|
||||
REPO_DIR="$(cd $(dirname $(dirname $(dirname $0))) &>/dev/null && pwd)"
|
||||
ARCH_PACKAGES_DIR="${REPO_DIR}/sdist/arch"
|
||||
UPDATE_IGNORE_FILE="${REPO_DIR}/.updateignore"
|
||||
HOME_UPDATE_IGNORE_FILE="${HOME}/.updateignore"
|
||||
|
||||
# Directories to monitor for changes
|
||||
MONITOR_DIRS=(".config" ".local/bin")
|
||||
|
||||
# === Color Codes ===
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
PURPLE='\033[0;35m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# === Helper Functions ===
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1" >&2
|
||||
}
|
||||
|
||||
log_header() {
|
||||
echo -e "\n${PURPLE}=== $1 ===${NC}"
|
||||
}
|
||||
|
||||
die() {
|
||||
log_error "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to safely read input with terminal compatibility
|
||||
safe_read() {
|
||||
local prompt="$1"
|
||||
local varname="$2"
|
||||
local default="${3:-}"
|
||||
|
||||
# Simple approach: just use read with /dev/tty and handle errors
|
||||
local input_value=""
|
||||
|
||||
# Display prompt and read from terminal
|
||||
echo -n "$prompt"
|
||||
if read input_value </dev/tty 2>/dev/null || read input_value 2>/dev/null; then
|
||||
eval "$varname='$input_value'"
|
||||
return 0
|
||||
else
|
||||
# If read failed and we have a default, use it
|
||||
if [[ -n "$default" ]]; then
|
||||
echo
|
||||
log_warning "Using default: $default"
|
||||
eval "$varname='$default'"
|
||||
return 0
|
||||
else
|
||||
echo
|
||||
log_error "Failed to read input"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check if a file should be ignored
|
||||
should_ignore() {
|
||||
local file_path="$1"
|
||||
local relative_path="${file_path#$HOME/}"
|
||||
|
||||
# Also get path relative to repo for repo-level ignores
|
||||
local repo_relative=""
|
||||
if [[ "$file_path" == "$REPO_DIR"* ]]; then
|
||||
repo_relative="${file_path#$REPO_DIR/}"
|
||||
fi
|
||||
|
||||
# Check both repo and home ignore files
|
||||
for ignore_file in "$UPDATE_IGNORE_FILE" "$HOME_UPDATE_IGNORE_FILE"; do
|
||||
if [[ -f "$ignore_file" ]]; then
|
||||
while IFS= read -r pattern || [[ -n "$pattern" ]]; do
|
||||
# Skip empty lines and comments
|
||||
[[ -z "$pattern" || "$pattern" =~ ^[[:space:]]*# ]] && continue
|
||||
# Remove leading/trailing whitespace
|
||||
pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
[[ -z "$pattern" ]] && continue
|
||||
|
||||
# Handle different gitignore-style patterns
|
||||
local should_skip=false
|
||||
|
||||
# Exact match
|
||||
if [[ "$relative_path" == "$pattern" ]] || [[ "$repo_relative" == "$pattern" ]]; then
|
||||
should_skip=true
|
||||
fi
|
||||
|
||||
# Wildcard patterns (basic glob matching)
|
||||
if [[ "$relative_path" == $pattern ]] || [[ "$repo_relative" == $pattern ]]; then
|
||||
should_skip=true
|
||||
fi
|
||||
|
||||
# Directory patterns (ending with /)
|
||||
if [[ "$pattern" == */ ]]; then
|
||||
local dir_pattern="${pattern%/}"
|
||||
if [[ "$relative_path" == "$dir_pattern"/* ]] || [[ "$repo_relative" == "$dir_pattern"/* ]]; then
|
||||
should_skip=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Patterns starting with / (from root)
|
||||
if [[ "$pattern" == /* ]]; then
|
||||
local root_pattern="${pattern#/}"
|
||||
if [[ "$relative_path" == "$root_pattern" ]] || [[ "$relative_path" == "$root_pattern"/* ]] ||
|
||||
[[ "$repo_relative" == "$root_pattern" ]] || [[ "$repo_relative" == "$root_pattern"/* ]]; then
|
||||
should_skip=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Patterns with wildcards
|
||||
if [[ "$pattern" == *"*"* ]]; then
|
||||
if [[ "$relative_path" == $pattern ]] || [[ "$repo_relative" == $pattern ]]; then
|
||||
should_skip=true
|
||||
fi
|
||||
# Also check if any parent directory matches
|
||||
local temp_path="$relative_path"
|
||||
while [[ "$temp_path" == */* ]]; do
|
||||
temp_path="${temp_path%/*}"
|
||||
if [[ "$temp_path" == $pattern ]]; then
|
||||
should_skip=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Simple substring matching (for backward compatibility)
|
||||
if [[ ! "$should_skip" == true ]]; then
|
||||
if [[ "$file_path" == *"$pattern"* ]] || [[ "$relative_path" == *"$pattern"* ]]; then
|
||||
should_skip=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$should_skip" == true ]]; then
|
||||
return 0
|
||||
fi
|
||||
done <"$ignore_file"
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to show file diff with syntax highlighting if possible
|
||||
show_diff() {
|
||||
local file1="$1"
|
||||
local file2="$2"
|
||||
|
||||
echo -e "\n${CYAN}Showing differences:${NC}"
|
||||
echo -e "${CYAN}Old file: $file1${NC}"
|
||||
echo -e "${CYAN}New file: $file2${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
if command -v diff &>/dev/null; then
|
||||
diff -u "$file1" "$file2" || true
|
||||
else
|
||||
echo "diff command not available"
|
||||
fi
|
||||
echo "----------------------------------------"
|
||||
}
|
||||
|
||||
# Function to handle file conflicts
|
||||
handle_file_conflict() {
|
||||
local repo_file="$1"
|
||||
local home_file="$2"
|
||||
local filename=$(basename "$home_file")
|
||||
local dirname=$(dirname "$home_file")
|
||||
|
||||
echo -e "\n${YELLOW}Conflict detected:${NC} $home_file"
|
||||
echo "Repository version differs from your local version."
|
||||
echo
|
||||
echo "Choose an action:"
|
||||
echo "1) Replace local file with repository version"
|
||||
echo "2) Keep local file unchanged"
|
||||
echo "3) Backup local file as ${filename}.old, use repository version"
|
||||
echo "4) Save repository version as ${filename}.new, keep local file"
|
||||
echo "5) Show diff and decide"
|
||||
echo "6) Skip this file"
|
||||
echo "7) Add to ignore and skip"
|
||||
echo
|
||||
|
||||
while true; do
|
||||
if ! safe_read "Enter your choice (1-7): " choice "6"; then
|
||||
echo
|
||||
log_warning "Failed to read input. Skipping file."
|
||||
return
|
||||
fi
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
cp -p "$repo_file" "$home_file"
|
||||
log_success "Replaced $home_file with repository version"
|
||||
break
|
||||
;;
|
||||
2)
|
||||
log_info "Keeping local version of $home_file"
|
||||
break
|
||||
;;
|
||||
3)
|
||||
mv "$home_file" "${dirname}/${filename}.old"
|
||||
cp -p "$repo_file" "$home_file"
|
||||
log_success "Backed up local file to ${filename}.old and updated with repository version"
|
||||
break
|
||||
;;
|
||||
4)
|
||||
cp -p "$repo_file" "${dirname}/${filename}.new"
|
||||
log_success "Saved repository version as ${filename}.new, kept local file"
|
||||
break
|
||||
;;
|
||||
5)
|
||||
show_diff "$home_file" "$repo_file"
|
||||
echo
|
||||
echo "After reviewing the diff, choose:"
|
||||
echo "r) Replace with repository version"
|
||||
echo "k) Keep local version"
|
||||
echo "b) Backup local and use repository version"
|
||||
echo "n) Save repository version as .new"
|
||||
echo "s) Skip this file"
|
||||
echo "i) Add to ignore and skip"
|
||||
|
||||
if ! safe_read "Enter your choice (r/k/b/n/s/i): " subchoice "s"; then
|
||||
echo
|
||||
log_warning "Failed to read input. Skipping file."
|
||||
return
|
||||
fi
|
||||
|
||||
case $subchoice in
|
||||
r)
|
||||
cp -p "$repo_file" "$home_file"
|
||||
log_success "Replaced $home_file with repository version"
|
||||
break
|
||||
;;
|
||||
k)
|
||||
log_info "Keeping local version of $home_file"
|
||||
break
|
||||
;;
|
||||
b)
|
||||
mv "$home_file" "${dirname}/${filename}.old"
|
||||
cp -p "$repo_file" "$home_file"
|
||||
log_success "Backed up local file to ${filename}.old and updated"
|
||||
break
|
||||
;;
|
||||
n)
|
||||
cp -p "$repo_file" "${dirname}/${filename}.new"
|
||||
log_success "Saved repository version as ${filename}.new"
|
||||
break
|
||||
;;
|
||||
s)
|
||||
log_info "Skipping $home_file"
|
||||
break
|
||||
;;
|
||||
i)
|
||||
local relative_path_to_home="${home_file#$HOME/}"
|
||||
echo "$relative_path_to_home" >>"$HOME_UPDATE_IGNORE_FILE"
|
||||
log_success "Added '$relative_path_to_home' to $HOME_UPDATE_IGNORE_FILE and skipped."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Please try again."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
6)
|
||||
log_info "Skipping $home_file"
|
||||
break
|
||||
;;
|
||||
7)
|
||||
local relative_path_to_home="${home_file#$HOME/}"
|
||||
echo "$relative_path_to_home" >>"$HOME_UPDATE_IGNORE_FILE"
|
||||
log_success "Added '$relative_path_to_home' to $HOME_UPDATE_IGNORE_FILE and skipped."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Please enter 1-7."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Function to check if PKGBUILD has changed
|
||||
check_pkgbuild_changed() {
|
||||
local pkg_dir="$1"
|
||||
local pkgbuild_path="${pkg_dir}/PKGBUILD"
|
||||
|
||||
[[ ! -f "$pkgbuild_path" ]] && return 1
|
||||
|
||||
# Get the path relative to repo
|
||||
local relative_path="${pkgbuild_path#$REPO_DIR/}"
|
||||
|
||||
# If force check is enabled, always return true
|
||||
if [[ "$FORCE_CHECK" == true ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if file changed in the last pull
|
||||
if git diff --name-only HEAD@{1} HEAD 2>/dev/null | grep -q "^${relative_path}$"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to list available packages
|
||||
list_packages() {
|
||||
local available_packages=()
|
||||
local changed_packages=()
|
||||
|
||||
if [[ ! -d "$ARCH_PACKAGES_DIR" ]]; then
|
||||
log_warning "No sdist/arch directory found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
for pkg_dir in "$ARCH_PACKAGES_DIR"/*/; do
|
||||
if [[ -f "${pkg_dir}/PKGBUILD" ]]; then
|
||||
local pkg_name=$(basename "$pkg_dir")
|
||||
available_packages+=("$pkg_name")
|
||||
|
||||
if check_pkgbuild_changed "$pkg_dir"; then
|
||||
changed_packages+=("$pkg_name")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#available_packages[@]} -eq 0 ]]; then
|
||||
log_info "No packages found in sdist/arch directory"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "\n${CYAN}Available packages:${NC}"
|
||||
for pkg in "${available_packages[@]}"; do
|
||||
if [[ " ${changed_packages[*]} " =~ " ${pkg} " ]]; then
|
||||
echo -e " ${GREEN}● ${pkg}${NC} (PKGBUILD changed)"
|
||||
else
|
||||
echo -e " ○ ${pkg}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#changed_packages[@]} -gt 0 ]]; then
|
||||
echo -e "\n${YELLOW}Packages with changed PKGBUILDs: ${changed_packages[*]}${NC}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to build selected packages
|
||||
build_packages() {
|
||||
local build_mode="$1" # "changed", "all", or "select"
|
||||
local packages_to_build=()
|
||||
local rebuilt_packages=0
|
||||
|
||||
case "$build_mode" in
|
||||
"changed")
|
||||
for pkg_dir in "$ARCH_PACKAGES_DIR"/*/; do
|
||||
if [[ -f "${pkg_dir}/PKGBUILD" ]]; then
|
||||
local pkg_name=$(basename "$pkg_dir")
|
||||
if check_pkgbuild_changed "$pkg_dir"; then
|
||||
packages_to_build+=("$pkg_name")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
"all")
|
||||
for pkg_dir in "$ARCH_PACKAGES_DIR"/*/; do
|
||||
if [[ -f "${pkg_dir}/PKGBUILD" ]]; then
|
||||
local pkg_name=$(basename "$pkg_dir")
|
||||
packages_to_build+=("$pkg_name")
|
||||
fi
|
||||
done
|
||||
;;
|
||||
"select")
|
||||
echo -e "\nEnter package names separated by spaces (or 'all' for all packages):"
|
||||
if ! safe_read "Packages to build: " user_selection ""; then
|
||||
log_warning "Failed to read input. Skipping package builds."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$user_selection" == "all" ]]; then
|
||||
for pkg_dir in "$ARCH_PACKAGES_DIR"/*/; do
|
||||
if [[ -f "${pkg_dir}/PKGBUILD" ]]; then
|
||||
local pkg_name=$(basename "$pkg_dir")
|
||||
packages_to_build+=("$pkg_name")
|
||||
fi
|
||||
done
|
||||
else
|
||||
read -ra packages_to_build <<<"$user_selection"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ${#packages_to_build[@]} -eq 0 ]]; then
|
||||
log_info "No packages selected for building"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "\n${CYAN}Packages to build: ${packages_to_build[*]}${NC}"
|
||||
|
||||
if ! safe_read "Proceed with building these packages? (Y/n): " confirm "Y"; then
|
||||
log_warning "Failed to read input. Skipping package builds."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$confirm" =~ ^[Nn]$ ]]; then
|
||||
log_info "Package building cancelled by user"
|
||||
return
|
||||
fi
|
||||
|
||||
for pkg_name in "${packages_to_build[@]}"; do
|
||||
local pkg_dir="${ARCH_PACKAGES_DIR}/${pkg_name}"
|
||||
|
||||
if [[ ! -d "$pkg_dir" || ! -f "${pkg_dir}/PKGBUILD" ]]; then
|
||||
log_error "Package not found or missing PKGBUILD: $pkg_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
log_info "Building package: $pkg_name"
|
||||
cd "$pkg_dir" || continue
|
||||
|
||||
if makepkg -si --noconfirm; then
|
||||
log_success "Successfully built and installed $pkg_name"
|
||||
((rebuilt_packages++))
|
||||
else
|
||||
log_error "Failed to build package $pkg_name"
|
||||
fi
|
||||
|
||||
cd "$REPO_DIR" || die "Failed to return to repository directory"
|
||||
done
|
||||
|
||||
if [[ $rebuilt_packages -eq 0 ]]; then
|
||||
log_warning "No packages were successfully built"
|
||||
else
|
||||
log_success "Successfully rebuilt $rebuilt_packages package(s)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get list of changed files since last pull or all files if force check
|
||||
get_changed_files() {
|
||||
local dir_path="$1"
|
||||
|
||||
if [[ "$FORCE_CHECK" == true ]]; then
|
||||
# Return all files in the directory
|
||||
find "$dir_path" -type f -print0 2>/dev/null
|
||||
else
|
||||
# Get files that changed in the last pull
|
||||
local changed_files=()
|
||||
while IFS= read -r file; do
|
||||
local full_path="${REPO_DIR}/${file}"
|
||||
# Check if file is in the directory we're processing
|
||||
if [[ "$full_path" == "$dir_path"/* ]] && [[ -f "$full_path" ]]; then
|
||||
printf '%s\0' "$full_path"
|
||||
fi
|
||||
done < <(git diff --name-only HEAD@{1} HEAD 2>/dev/null || true)
|
||||
|
||||
# If no files changed via git, but force_check is false, still check all files
|
||||
# This handles the case where there were no new commits but files might differ
|
||||
if ! git diff --quiet HEAD@{1} HEAD 2>/dev/null; then
|
||||
: # Files were found via git diff
|
||||
else
|
||||
# No git changes detected, check all files anyway for local differences
|
||||
find "$dir_path" -type f -print0 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check if we have new commits
|
||||
has_new_commits() {
|
||||
# Check if HEAD@{1} exists (meaning there was a previous commit)
|
||||
if git rev-parse --verify HEAD@{1} &>/dev/null; then
|
||||
# Check if HEAD and HEAD@{1} are different
|
||||
[[ "$(git rev-parse HEAD)" != "$(git rev-parse HEAD@{1})" ]]
|
||||
else
|
||||
# No previous commit reference, assume we have commits
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Main script starts here
|
||||
log_header "Dotfiles Update Script"
|
||||
|
||||
check=true
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-f | --force)
|
||||
FORCE_CHECK=true
|
||||
log_info "Force check mode enabled - will check all files regardless of git changes"
|
||||
shift
|
||||
;;
|
||||
-p | --packages)
|
||||
CHECK_PACKAGES=true
|
||||
log_info "Package checking enabled"
|
||||
shift
|
||||
;;
|
||||
-h | --help)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -f, --force Force check all files even if no new commits"
|
||||
echo " -p, --packages Enable package checking and building"
|
||||
echo " -h, --help Show this help message"
|
||||
echo ""
|
||||
echo "This script updates your dotfiles by:"
|
||||
echo " 1. Pulling latest changes from git remote"
|
||||
echo " 2. Optionally rebuilding packages (if -p flag is used)"
|
||||
echo " 3. Syncing configuration files"
|
||||
echo " 4. Updating script permissions"
|
||||
echo ""
|
||||
echo "Package modes (when -p is used):"
|
||||
echo " - If no PKGBUILDs changed: asks if you want to check packages anyway"
|
||||
echo " - If PKGBUILDs changed: offers to build changed packages"
|
||||
echo " - Interactive selection of packages to build"
|
||||
exit 0
|
||||
;;
|
||||
--skip-notice)
|
||||
log_warning "Skipping notice about script being untested"
|
||||
check=false
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown option: $1"
|
||||
echo "Use --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$check" == true ]]; then
|
||||
log_warning "THIS SCRIPT IS NOT FULLY TESTED AND MAY CAUSE ISSUES!"
|
||||
log_warning "It might be safer if you want to preserve your modifications and not delete added files,"
|
||||
log_warning " but this can cause partial updates and therefore unexpected behavior like in #1856."
|
||||
log_warning "In general, prefer install.sh for updates."
|
||||
safe_read "Continue? (y/N): " response "N"
|
||||
|
||||
if [[ ! "$response" =~ ^[Yy]$ ]]; then
|
||||
log_error "Update aborted by user"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if we're in a git repository
|
||||
cd "$REPO_DIR" || die "Failed to change to repository directory"
|
||||
|
||||
if git rev-parse --is-inside-work-tree &>/dev/null; then
|
||||
log_info "Running in git repository: $(git rev-parse --show-toplevel)"
|
||||
else
|
||||
log_error "Not in a git repository. Please run this script from your dotfiles repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 1: Pull latest commits
|
||||
log_header "Pulling Latest Changes"
|
||||
|
||||
# Check current branch
|
||||
current_branch=$(git branch --show-current)
|
||||
if [[ -z "$current_branch" ]]; then
|
||||
log_warning "In detached HEAD state. Checking out main/master branch..."
|
||||
if git show-ref --verify --quiet refs/heads/main; then
|
||||
git checkout main
|
||||
current_branch="main"
|
||||
elif git show-ref --verify --quiet refs/heads/master; then
|
||||
git checkout master
|
||||
current_branch="master"
|
||||
else
|
||||
die "Could not find main or master branch"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "Current branch: $current_branch"
|
||||
|
||||
# Check for uncommitted changes
|
||||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||
log_warning "You have uncommitted changes:"
|
||||
git status --short
|
||||
echo
|
||||
|
||||
if ! safe_read "Do you want to continue? This will stash your changes. (y/N): " response "N"; then
|
||||
echo
|
||||
log_error "Failed to read input. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$response" =~ ^[Yy]$ ]]; then
|
||||
die "Aborted by user"
|
||||
fi
|
||||
git stash push -m "Auto-stash before update $(date)"
|
||||
log_info "Changes stashed"
|
||||
fi
|
||||
|
||||
# Check if remote exists
|
||||
if git remote get-url origin &>/dev/null; then
|
||||
# Pull changes
|
||||
log_info "Pulling changes from origin/$current_branch..."
|
||||
if git pull; then
|
||||
log_success "Successfully pulled latest changes"
|
||||
else
|
||||
log_warning "Failed to pull changes from remote. Continuing with local repository..."
|
||||
log_info "You may need to resolve conflicts manually later."
|
||||
fi
|
||||
else
|
||||
log_warning "No remote 'origin' configured. Skipping pull operation."
|
||||
log_info "This appears to be a local-only repository."
|
||||
fi
|
||||
|
||||
# Step 2: Handle package building (only if requested)
|
||||
rebuilt_packages=0
|
||||
|
||||
if [[ "$CHECK_PACKAGES" == true ]]; then
|
||||
log_header "Package Management"
|
||||
|
||||
if [[ ! -d "$ARCH_PACKAGES_DIR" ]]; then
|
||||
log_warning "No sdist/arch directory found. Skipping package management."
|
||||
else
|
||||
# Check if any PKGBUILDs have changed
|
||||
changed_pkgbuilds=()
|
||||
for pkg_dir in "$ARCH_PACKAGES_DIR"/*/; do
|
||||
if [[ -f "${pkg_dir}/PKGBUILD" ]]; then
|
||||
local pkg_name=$(basename "$pkg_dir")
|
||||
if check_pkgbuild_changed "$pkg_dir"; then
|
||||
changed_pkgbuilds+=("$pkg_name")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#changed_pkgbuilds[@]} -gt 0 ]]; then
|
||||
log_info "Found ${#changed_pkgbuilds[@]} package(s) with changed PKGBUILDs: ${changed_pkgbuilds[*]}"
|
||||
echo
|
||||
echo "Package build options:"
|
||||
echo "1) Build only packages with changed PKGBUILDs"
|
||||
echo "2) List all packages and select which to build"
|
||||
echo "3) Build all packages"
|
||||
echo "4) Skip package building"
|
||||
echo
|
||||
|
||||
if safe_read "Choose an option (1-4): " pkg_choice "1"; then
|
||||
case $pkg_choice in
|
||||
1)
|
||||
build_packages "changed"
|
||||
;;
|
||||
2)
|
||||
if list_packages; then
|
||||
build_packages "select"
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
build_packages "all"
|
||||
;;
|
||||
4 | *)
|
||||
log_info "Skipping package building"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
log_warning "Failed to read input. Skipping package building."
|
||||
fi
|
||||
else
|
||||
log_info "No PKGBUILDs have changed since last update."
|
||||
echo
|
||||
if safe_read "Do you want to check and build packages anyway? (y/N): " check_anyway "N"; then
|
||||
if [[ "$check_anyway" =~ ^[Yy]$ ]]; then
|
||||
if list_packages; then
|
||||
echo
|
||||
echo "Package build options:"
|
||||
echo "1) Select specific packages to build"
|
||||
echo "2) Build all packages"
|
||||
echo "3) Skip package building"
|
||||
|
||||
if safe_read "Choose an option (1-3): " build_choice "3"; then
|
||||
case $build_choice in
|
||||
1)
|
||||
build_packages "select"
|
||||
;;
|
||||
2)
|
||||
build_packages "all"
|
||||
;;
|
||||
3 | *)
|
||||
log_info "Skipping package building"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
log_info "Skipping package building"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_info "Skipping package management"
|
||||
fi
|
||||
else
|
||||
log_info "Skipping package management"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_header "Package Management"
|
||||
log_info "Package checking disabled. Use -p or --packages flag to enable package management."
|
||||
|
||||
# Still show a hint if there are changed PKGBUILDs
|
||||
if [[ -d "$ARCH_PACKAGES_DIR" ]]; then
|
||||
changed_count=0
|
||||
for pkg_dir in "$ARCH_PACKAGES_DIR"/*/; do
|
||||
if [[ -f "${pkg_dir}/PKGBUILD" ]] && check_pkgbuild_changed "$pkg_dir"; then
|
||||
((changed_count++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $changed_count -gt 0 ]]; then
|
||||
log_warning "Note: $changed_count package(s) have changed PKGBUILDs. Use -p flag to manage packages."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Step 3: Update configuration files
|
||||
log_header "Updating Configuration Files"
|
||||
|
||||
# Check if we should process files
|
||||
process_files=false
|
||||
if [[ "$FORCE_CHECK" == true ]]; then
|
||||
process_files=true
|
||||
log_info "Force mode: checking all configuration files"
|
||||
elif has_new_commits; then
|
||||
process_files=true
|
||||
log_info "New commits detected: checking changed configuration files"
|
||||
else
|
||||
log_info "No new commits found: checking for local file differences"
|
||||
process_files=true # Always check for differences even without commits
|
||||
fi
|
||||
|
||||
if [[ "$process_files" == true ]]; then
|
||||
files_processed=0
|
||||
files_updated=0
|
||||
files_created=0
|
||||
|
||||
for dir_name in "${MONITOR_DIRS[@]}"; do
|
||||
repo_dir_path="${REPO_DIR}/${dir_name}"
|
||||
home_dir_path="${HOME}/${dir_name}"
|
||||
|
||||
if [[ ! -d "$repo_dir_path" ]]; then
|
||||
log_warning "Repository directory not found: $repo_dir_path"
|
||||
continue
|
||||
fi
|
||||
|
||||
log_info "Processing directory: $dir_name"
|
||||
|
||||
# Create home directory if it doesn't exist
|
||||
mkdir -p "$home_dir_path"
|
||||
|
||||
# Get files to process (changed files or all files based on mode)
|
||||
while IFS= read -r -d '' repo_file; do
|
||||
# Calculate relative path and corresponding home file path
|
||||
rel_path="${repo_file#$repo_dir_path/}"
|
||||
home_file="${home_dir_path}/${rel_path}"
|
||||
|
||||
# Check if file should be ignored
|
||||
if should_ignore "$home_file"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
((files_processed++))
|
||||
|
||||
# Create directory structure if needed
|
||||
mkdir -p "$(dirname "$home_file")"
|
||||
|
||||
if [[ -f "$home_file" ]]; then
|
||||
# File exists, check if different
|
||||
if ! cmp -s "$repo_file" "$home_file"; then
|
||||
log_info "Found difference in: $rel_path"
|
||||
handle_file_conflict "$repo_file" "$home_file"
|
||||
((files_updated++))
|
||||
fi
|
||||
else
|
||||
# New file, copy it
|
||||
cp -p "$repo_file" "$home_file"
|
||||
log_success "Created new file: $home_file"
|
||||
((files_created++))
|
||||
fi
|
||||
done < <(get_changed_files "$repo_dir_path")
|
||||
done
|
||||
|
||||
# Show processing summary
|
||||
echo
|
||||
log_info "File processing summary:"
|
||||
log_info "- Files processed: $files_processed"
|
||||
log_info "- Files with conflicts: $files_updated"
|
||||
log_info "- New files created: $files_created"
|
||||
else
|
||||
log_info "Skipping file updates (no changes detected and not in force mode)"
|
||||
fi
|
||||
|
||||
# Step 4: Update script permissions
|
||||
log_header "Updating Script Permissions"
|
||||
|
||||
# Make sure local bin scripts are executable
|
||||
if [[ -d "${HOME}/.local/bin" ]]; then
|
||||
find "${HOME}/.local/bin" -type f -exec chmod +x {} \; 2>/dev/null || true
|
||||
log_success "Updated ~/.local/bin script permissions"
|
||||
fi
|
||||
|
||||
log_header "Update Complete"
|
||||
log_success "Dotfiles update completed successfully!"
|
||||
|
||||
# Show summary
|
||||
echo
|
||||
echo -e "${CYAN}Summary:${NC}"
|
||||
echo "- Repository: $(git log -1 --pretty=format:'%h - %s (%cr)')"
|
||||
echo "- Branch: $current_branch"
|
||||
echo "- Mode: $([ "$FORCE_CHECK" == true ] && echo "Force check" || echo "Normal")"
|
||||
echo "- Package checking: $([ "$CHECK_PACKAGES" == true ] && echo "Enabled" || echo "Disabled")"
|
||||
|
||||
if [[ $rebuilt_packages -gt 0 ]]; then
|
||||
echo "- Packages rebuilt: $rebuilt_packages"
|
||||
fi
|
||||
|
||||
if [[ "$process_files" == true ]]; then
|
||||
echo "- Files processed: $files_processed"
|
||||
echo "- Files updated/conflicted: $files_updated"
|
||||
echo "- New files created: $files_created"
|
||||
fi
|
||||
|
||||
echo "- Configuration directories: ${MONITOR_DIRS[*]}"
|
||||
|
||||
# Remind about ignore files and show examples
|
||||
if [[ ! -f "$HOME_UPDATE_IGNORE_FILE" && ! -f "$UPDATE_IGNORE_FILE" ]]; then
|
||||
echo
|
||||
log_info "Tip: Create ignore files to exclude files from updates:"
|
||||
echo " - Repository ignore: ${REPO_DIR}/.updateignore"
|
||||
echo " - User ignore: ~/.updateignore"
|
||||
echo
|
||||
echo "Example patterns:"
|
||||
echo " *.log # Ignore all .log files"
|
||||
echo " .config/personal/ # Ignore entire directory"
|
||||
echo " secret-config.conf # Ignore specific file"
|
||||
echo " /temp-file # Ignore from root only"
|
||||
echo " *secret* # Ignore files containing 'secret'"
|
||||
fi
|
||||
|
||||
echo
|
||||
@@ -0,0 +1,31 @@
|
||||
# This is NOT a script for execution, but for loading functions, so NOT need execution permission or shebang.
|
||||
XDG_BIN_HOME=${XDG_BIN_HOME:-$HOME/.local/bin}
|
||||
XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
|
||||
XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
|
||||
XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
|
||||
XDG_STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
|
||||
BACKUP_DIR=${BACKUP_DIR:-$HOME/backup}
|
||||
|
||||
|
||||
# Note that all color styles contains a STY_RESET before it.
|
||||
STY_RED='\e[00m\e[31m'
|
||||
STY_GREEN='\e[00m\e[32m'
|
||||
STY_YELLOW='\e[00m\e[33m'
|
||||
STY_BLUE='\e[00m\e[34m'
|
||||
STY_PURPLE='\e[00m\e[35m'
|
||||
STY_CYAN='\e[00m\e[36m'
|
||||
|
||||
STY_BG_RED='\e[30m\e[41m'
|
||||
STY_BG_GREEN='\e[30m\e[42m'
|
||||
STY_BG_YELLOW='\e[30m\e[43m'
|
||||
STY_BG_BLUE='\e[30m\e[44m'
|
||||
STY_BG_PURPLE='\e[30m\e[45m'
|
||||
STY_BG_CYAN='\e[30m\e[46m'
|
||||
|
||||
STY_BOLD='\e[1m'
|
||||
STY_FAINT='\e[2m'
|
||||
STY_SLANT='\e[3m'
|
||||
STY_UNDERLINE='\e[4m'
|
||||
STY_BLINK='\e[5m'
|
||||
STY_INVERT='\e[7m'
|
||||
STY_RESET='\e[00m'
|
||||
@@ -0,0 +1,97 @@
|
||||
# This is NOT a script for execution, but for loading functions, so NOT need execution permission or shebang.
|
||||
# NOTE that you NOT need to `cd ..' because the `$0' is NOT this file, but the script file which will source this file.
|
||||
|
||||
# The script that use this file should have two lines on its top as follows:
|
||||
# cd "$(dirname "$0")"
|
||||
# export base="$(pwd)"
|
||||
|
||||
function try { "$@" || sleep 0; }
|
||||
function v(){
|
||||
echo -e "####################################################"
|
||||
echo -e "${STY_BLUE}[$0]: Next command:${STY_RESET}"
|
||||
echo -e "${STY_GREEN}$@${STY_RESET}"
|
||||
local execute=true
|
||||
if $ask;then
|
||||
while true;do
|
||||
echo -e "${STY_BLUE}Execute? ${STY_RESET}"
|
||||
echo " y = Yes"
|
||||
echo " e = Exit now"
|
||||
echo " s = Skip this command (NOT recommended - your setup might not work correctly)"
|
||||
echo " yesforall = Yes and don't ask again; NOT recommended unless you really sure"
|
||||
local p; read -p "====> " p
|
||||
case $p in
|
||||
[yY]) echo -e "${STY_BLUE}OK, executing...${STY_RESET}" ;break ;;
|
||||
[eE]) echo -e "${STY_BLUE}Exiting...${STY_RESET}" ;exit ;break ;;
|
||||
[sS]) echo -e "${STY_BLUE}Alright, skipping this one...${STY_RESET}" ;execute=false ;break ;;
|
||||
"yesforall") echo -e "${STY_BLUE}Alright, won't ask again. Executing...${STY_RESET}"; ask=false ;break ;;
|
||||
*) echo -e "${STY_RED}Please enter [y/e/s/yesforall].${STY_RESET}";;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if $execute;then x "$@";else
|
||||
echo -e "${STY_YELLOW}[$0]: Skipped \"$@\"${STY_RESET}"
|
||||
fi
|
||||
}
|
||||
# When use v() for a defined function, use x() INSIDE its definition to catch errors.
|
||||
function x(){
|
||||
if "$@";then local cmdstatus=0;else local cmdstatus=1;fi # 0=normal; 1=failed; 2=failed but ignored
|
||||
while [ $cmdstatus == 1 ] ;do
|
||||
echo -e "${STY_RED}[$0]: Command \"${STY_GREEN}$@${STY_RED}\" has failed."
|
||||
echo -e "You may need to resolve the problem manually BEFORE repeating this command."
|
||||
echo -e "[Tip] If a certain package is failing to install, try installing it separately in another terminal.${STY_RESET}"
|
||||
echo " r = Repeat this command (DEFAULT)"
|
||||
echo " e = Exit now"
|
||||
echo " i = Ignore this error and continue (your setup might not work correctly)"
|
||||
local p; read -p " [R/e/i]: " p
|
||||
case $p in
|
||||
[iI]) echo -e "${STY_BLUE}Alright, ignore and continue...${STY_RESET}";cmdstatus=2;;
|
||||
[eE]) echo -e "${STY_BLUE}Alright, will exit.${STY_RESET}";break;;
|
||||
*) echo -e "${STY_BLUE}OK, repeating...${STY_RESET}"
|
||||
if "$@";then cmdstatus=0;else cmdstatus=1;fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
case $cmdstatus in
|
||||
0) echo -e "${STY_BLUE}[$0]: Command \"${STY_GREEN}$@${STY_BLUE}\" finished.${STY_RESET}";;
|
||||
1) echo -e "${STY_RED}[$0]: Command \"${STY_GREEN}$@${STY_RED}\" has failed. Exiting...${STY_RESET}";exit 1;;
|
||||
2) echo -e "${STY_RED}[$0]: Command \"${STY_GREEN}$@${STY_RED}\" has failed but ignored by user.${STY_RESET}";;
|
||||
esac
|
||||
}
|
||||
function showfun(){
|
||||
echo -e "${STY_BLUE}[$0]: The definition of function \"$1\" is as follows:${STY_RESET}"
|
||||
printf "${STY_GREEN}"
|
||||
type -a $1
|
||||
printf "${STY_RESET}"
|
||||
}
|
||||
function pause(){
|
||||
if [ ! "$ask" == "false" ];then
|
||||
printf "${STY_FAINT}${STY_SLANT}"
|
||||
local p; read -p "(Ctrl-C to abort, others to proceed)" p
|
||||
printf "${STY_RESET}"
|
||||
fi
|
||||
}
|
||||
function remove_bashcomments_emptylines(){
|
||||
mkdir -p $(dirname $2)
|
||||
cat $1 | sed -e '/^[[:blank:]]*#/d;s/#.*//' -e '/^[[:space:]]*$/d' > $2
|
||||
}
|
||||
function prevent_sudo_or_root(){
|
||||
case $(whoami) in
|
||||
root) echo -e "${STY_RED}[$0]: This script is NOT to be executed with sudo or as root. Aborting...${STY_RESET}";exit 1;;
|
||||
esac
|
||||
}
|
||||
function git_auto_unshallow(){
|
||||
# We need this function for latest_commit_hash to work properly
|
||||
if [[ -f "$(git rev-parse --git-dir)/shallow" ]]; then
|
||||
echo "Shallow clone detected. Unshallowing..."
|
||||
git fetch --unshallow
|
||||
fi
|
||||
}
|
||||
function latest_commit_timestamp(){
|
||||
local target_path="$1"
|
||||
local result=$(git log -1 --format="%ct" -- "$target_path" 2>/dev/null)
|
||||
if [[ -z "$result" ]]; then
|
||||
echo "[latest_commit_timestamp] The timestamp of \"$target_path\" is empty. Aborting..." >&2
|
||||
return 1
|
||||
fi
|
||||
echo $result
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
# This is NOT a script for execution, but for loading functions, so NOT need execution permission or shebang.
|
||||
# NOTE that you NOT need to `cd ..' because the `$0' is NOT this file, but the script file which will source this file.
|
||||
|
||||
# The script that use this file should have two lines on its top as follows:
|
||||
# cd "$(dirname "$0")" export base="$(pwd)"
|
||||
showhelp(){
|
||||
echo -e "Syntax: $0 [Options]...
|
||||
|
||||
Idempotent installation script for dotfiles.
|
||||
If no option is specified, run default install process.
|
||||
|
||||
-h, --help Print this help message and exit
|
||||
-f, --force (Dangerous) Force mode without any confirm
|
||||
-c, --clean Clean the build cache first
|
||||
--skip-allgreeting Skip the whole process greeting
|
||||
--skip-alldeps Skip the whole process installing dependency
|
||||
--skip-allsetups Skip the whole process setting up permissions/services etc
|
||||
--skip-allfiles Skip the whole process copying configuration files
|
||||
-s, --skip-sysupdate Skip system package upgrade e.g. \"sudo pacman -Syu\"
|
||||
--skip-hyprland Skip installing the config for Hyprland
|
||||
--skip-fish Skip installing the config for Fish
|
||||
--skip-plasmaintg Skip installing plasma-browser-integration
|
||||
--skip-miscconf Skip copying the dirs and files to \".configs\" except for
|
||||
AGS, Fish and Hyprland
|
||||
--exp-files Use experimental script for the third step copying files
|
||||
--fontset <set> (Unavailable yet) Use a set of pre-defined font and config
|
||||
--via-nix (Unavailable yet) Use Nix to install dependencies
|
||||
--exp-uninstall Use experimental uninstall script
|
||||
"
|
||||
}
|
||||
|
||||
cleancache(){
|
||||
rm -rf "$base/cache"
|
||||
}
|
||||
|
||||
# `man getopt` to see more
|
||||
para=$(getopt \
|
||||
-o hfk:cs \
|
||||
-l help,force,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,skip-sysupdate,skip-fish,skip-hyprland,skip-plasmaintg,skip-miscconf,exp-files,via-nix,exp-uninstall \
|
||||
-n "$0" -- "$@")
|
||||
[ $? != 0 ] && echo "$0: Error when getopt, please recheck parameters." && exit 1
|
||||
#####################################################################################
|
||||
## getopt Phase 1
|
||||
# ignore parameter's order, execute options below first
|
||||
eval set -- "$para"
|
||||
while true ; do
|
||||
case "$1" in
|
||||
-h|--help) showhelp;exit;;
|
||||
-c|--clean) cleancache;shift;;
|
||||
--) break ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
#####################################################################################
|
||||
## getopt Phase 2
|
||||
|
||||
eval set -- "$para"
|
||||
while true ; do
|
||||
case "$1" in
|
||||
## Already processed in phase 1, but not exited
|
||||
-c|--clean) shift;;
|
||||
## Ones without parameter
|
||||
-f|--force) ask=false;shift;;
|
||||
--skip-allgreeting) SKIP_ALLGREETING=true;shift;;
|
||||
--skip-alldeps) SKIP_ALLDEPS=true;shift;;
|
||||
--skip-allsetups) SKIP_ALLSETUPS=true;shift;;
|
||||
--skip-allfiles) SKIP_ALLFILES=true;shift;;
|
||||
-s|--skip-sysupdate) SKIP_SYSUPDATE=true;shift;;
|
||||
--skip-hyprland) SKIP_HYPRLAND=true;shift;;
|
||||
--skip-fish) SKIP_FISH=true;shift;;
|
||||
--skip-miscconf) SKIP_MISCCONF=true;shift;;
|
||||
--skip-plasmaintg) SKIP_PLASMAINTG=true;shift;;
|
||||
--exp-files) EXPERIMENTAL_FILES_SCRIPT=true;shift;;
|
||||
--via-nix) INSTALL_VIA_NIX=true;shift;;
|
||||
--exp-uninstall) EXPERIMENTAL_UNINSTALL_SCRIPT=true;shift;;
|
||||
## Ones with parameter
|
||||
|
||||
--fontset)
|
||||
case $2 in
|
||||
"default"|"zh-CN"|"vi") fontset="$2";;
|
||||
*) echo -e "Wrong argument for $1.";exit 1;;
|
||||
esac;echo "The fontset is ${fontset}.";shift 2;;
|
||||
|
||||
## Ending
|
||||
--) break ;;
|
||||
*) echo -e "$0: Wrong parameters.";exit 1;;
|
||||
esac
|
||||
done
|
||||
@@ -0,0 +1,111 @@
|
||||
# This script depends on `functions.sh' .
|
||||
# This is NOT a script for execution, but for loading functions, so NOT need execution permission or shebang.
|
||||
# NOTE that you NOT need to `cd ..' because the `$0' is NOT this file, but the script file which will source this file.
|
||||
|
||||
# This file is provided for any distros, mainly non-Arch(based) distros.
|
||||
|
||||
# The script that use this file should have two lines on its top as follows:
|
||||
# cd "$(dirname "$0")"
|
||||
# export base="$(pwd)"
|
||||
|
||||
install-agsv1(){
|
||||
x mkdir -p $base/cache/agsv1
|
||||
x cd $base/cache/agsv1
|
||||
try git init -b main
|
||||
try git remote add origin https://github.com/Aylur/ags.git
|
||||
x git pull origin main && git submodule update --init --recursive
|
||||
x git fetch --tags
|
||||
x git checkout v1.9.0
|
||||
x npm install
|
||||
x meson setup build # --reconfigure
|
||||
x meson install -C build
|
||||
x sudo mv /usr/local/bin/ags{,v1}
|
||||
x cd $base
|
||||
}
|
||||
|
||||
install-Rubik(){
|
||||
x mkdir -p $base/cache/Rubik
|
||||
x cd $base/cache/Rubik
|
||||
try git init -b main
|
||||
try git remote add origin https://github.com/googlefonts/rubik.git
|
||||
x git pull origin main && git submodule update --init --recursive
|
||||
x sudo mkdir -p /usr/local/share/fonts/TTF/
|
||||
x sudo cp fonts/variable/Rubik*.ttf /usr/local/share/fonts/TTF/
|
||||
x sudo mkdir -p /usr/local/share/licenses/ttf-rubik/
|
||||
x sudo cp OFL.txt /usr/local/share/licenses/ttf-rubik/LICENSE
|
||||
x fc-cache -fv
|
||||
x gsettings set org.gnome.desktop.interface font-name 'Rubik 11'
|
||||
x cd $base
|
||||
}
|
||||
|
||||
install-Gabarito(){
|
||||
x mkdir -p $base/cache/Gabarito
|
||||
x cd $base/cache/Gabarito
|
||||
try git init -b main
|
||||
try git remote add origin https://github.com/naipefoundry/gabarito.git
|
||||
x git pull origin main && git submodule update --init --recursive
|
||||
x sudo mkdir -p /usr/local/share/fonts/TTF/
|
||||
x sudo cp fonts/ttf/Gabarito*.ttf /usr/local/share/fonts/TTF/
|
||||
x sudo mkdir -p /usr/local/share/licenses/ttf-gabarito/
|
||||
x sudo cp OFL.txt /usr/local/share/licenses/ttf-gabarito/LICENSE
|
||||
x fc-cache -fv
|
||||
x cd $base
|
||||
}
|
||||
|
||||
install-OneUI(){
|
||||
x mkdir -p $base/cache/OneUI4-Icons
|
||||
x cd $base/cache/OneUI4-Icons
|
||||
try git init -b main
|
||||
try git remote add origin https://github.com/end-4/OneUI4-Icons.git
|
||||
# try git remote add origin https://github.com/mjkim0727/OneUI4-Icons.git
|
||||
x git pull origin main && git submodule update --init --recursive
|
||||
x sudo mkdir -p /usr/local/share/icons
|
||||
x sudo cp -r OneUI /usr/local/share/icons
|
||||
x sudo cp -r OneUI-dark /usr/local/share/icons
|
||||
x sudo cp -r OneUI-light /usr/local/share/icons
|
||||
x cd $base
|
||||
}
|
||||
|
||||
install-bibata(){
|
||||
x mkdir -p $base/cache/bibata-cursor
|
||||
x cd $base/cache/bibata-cursor
|
||||
name="Bibata-Modern-Classic"
|
||||
file="$name.tar.xz"
|
||||
# Use axel because `curl -O` always downloads a file with 0 byte size, idk why
|
||||
x axel https://github.com/ful1e5/Bibata_Cursor/releases/latest/download/$file
|
||||
tar -xf $file
|
||||
x sudo mkdir -p /usr/local/share/icons
|
||||
x sudo cp -r $name /usr/local/share/icons
|
||||
x cd $base
|
||||
}
|
||||
|
||||
install-MicroTeX(){
|
||||
x mkdir -p $base/cache/MicroTeX
|
||||
x cd $base/cache/MicroTeX
|
||||
try git init -b master
|
||||
try git remote add origin https://github.com/NanoMichael/MicroTeX.git
|
||||
x git pull origin master && git submodule update --init --recursive
|
||||
x mkdir -p build
|
||||
x cd build
|
||||
x cmake ..
|
||||
x make -j32
|
||||
x sudo mkdir -p /opt/MicroTeX
|
||||
x sudo cp ./LaTeX /opt/MicroTeX/
|
||||
x sudo cp -r ./res /opt/MicroTeX/
|
||||
x cd $base
|
||||
}
|
||||
|
||||
install-uv(){
|
||||
x bash <(curl -LJs "https://astral.sh/uv/install.sh")
|
||||
}
|
||||
|
||||
install-python-packages(){
|
||||
UV_NO_MODIFY_PATH=1
|
||||
ILLOGICAL_IMPULSE_VIRTUAL_ENV=$XDG_STATE_HOME/quickshell/.venv
|
||||
x mkdir -p $(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)
|
||||
# we need python 3.12 https://github.com/python-pillow/Pillow/issues/8089
|
||||
x uv venv --prompt .venv $(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV) -p 3.12
|
||||
x source $(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate
|
||||
x uv pip install -r sdata/uv/requirements.txt
|
||||
x deactivate # We don't need the virtual environment anymore
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
# This script is meant to be sourced.
|
||||
# It's not for directly running.
|
||||
|
||||
#####################################################################################
|
||||
|
||||
printf "${STY_CYAN}[$0]: Hi there! Before we start:${STY_RESET}\n"
|
||||
printf "\n"
|
||||
printf "${STY_PURPLE}${STY_BOLD}[NEW] illogical-impulse is now powered by Quickshell.${STY_PURPLE}\n"
|
||||
printf '# If you were using the old version with AGS and would like to keep it, do not run this script.\n'
|
||||
printf '# The AGS version, although uses less memory, has much worse performance (it uses Gtk3). \n'
|
||||
printf '# If you aren'\''t running on ewaste, the Quickshell version is recommended. \n'
|
||||
printf "# If you would like the AGS version anyway, run the following to switch to its branch first:\n ${STY_INVERT} git checkout ii-ags && ./install.sh ${STY_RESET}\n"
|
||||
printf "\n"
|
||||
pause
|
||||
printf "${STY_CYAN}${STY_BOLD}Quick overview about what this script does:${STY_CYAN}\n"
|
||||
printf " 1. Install dependencies.\n"
|
||||
printf " 2. Setup permissions/services etc.\n"
|
||||
printf " 3. Copying config files.${STY_RESET}\n"
|
||||
pause
|
||||
printf "${STY_CYAN}${STY_BOLD}Tips:${STY_CYAN}\n"
|
||||
printf " a) It has been designed to be idempotent which means you can run it multiple times.\n"
|
||||
printf " b) Use ${STY_INVERT} --help ${STY_CYAN} for more options.${STY_RESET}\n"
|
||||
printf "${STY_YELLOW}${STY_BOLD}Note: ${STY_YELLOW}"
|
||||
printf "It does not handle system-level/hardware stuff like Nvidia drivers. Please do it by yourself.\n"
|
||||
printf "${STY_RESET}"
|
||||
printf "\n"
|
||||
pause
|
||||
|
||||
case $ask in
|
||||
false) sleep 0 ;;
|
||||
*)
|
||||
printf "${STY_BLUE}"
|
||||
printf "${STY_BOLD}Do you want to confirm every time before a command executes?${STY_BLUE}\n"
|
||||
printf " y = Yes, ask me before executing each of them. (DEFAULT)\n"
|
||||
printf " n = No, I know everything this script will do, just execute them automatically.\n"
|
||||
printf " a = Abort.\n"
|
||||
read -p "===> [Y/n/a]: " p
|
||||
case $p in
|
||||
n) ask=false ;;
|
||||
a) exit 1 ;;
|
||||
*) ask=true ;;
|
||||
esac
|
||||
printf "${STY_RESET}"
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,171 @@
|
||||
# This script is meant to be sourced.
|
||||
# It's not for directly running.
|
||||
|
||||
function outdate_detect(){
|
||||
# Shallow clone prevent latest_commit_timestamp() from working.
|
||||
v git_auto_unshallow
|
||||
|
||||
local source_path="$1"
|
||||
local target_path="$2"
|
||||
local source_timestamp="$(latest_commit_timestamp $source_path 2>/dev/null)"
|
||||
local target_timestamp="$(latest_commit_timestamp $target_path 2>/dev/null)"
|
||||
local outdate_detect_mode="$(cat ${target_path}/outdate-detect-mode)"
|
||||
|
||||
# outdate-detect-mode possible modes:
|
||||
# - WIP: Work in progress (should be taken as outdated)
|
||||
# - FORCE_OUTDATED: forcely taken as outdated
|
||||
# - FORCE_UPDATED: forcely taken as updated
|
||||
# - AUTO: Let the script decide automatically
|
||||
#
|
||||
# outdate status possible values:
|
||||
# - WIP,FORCE_OUTDATED,FORCE_UPDATED: Inherited directly from outdate-detect-mode
|
||||
# - EMPTY_SOURCE: source path has empty timestamp, maybe not tracked by git (should be taken as outdated)
|
||||
# - EMPTY_TARGET: target path has empty timestamp, maybe not tracked by git (should be taken as outdated)
|
||||
# - OUTDATED: target path is older than source path.
|
||||
# - UPDATED: target path is not older than source path.
|
||||
|
||||
# Does target path have an outdate-detect-mode file which content is special?
|
||||
if [[ "${outdate_detect_mode}" =~ ^(WIP|FORCE_OUTDATED|FORCE_UPDATED)$ ]]; then
|
||||
echo "${outdate_detect_mode}"
|
||||
# Does source path has an empty timestamp?
|
||||
elif [ -z "$source_timestamp" ]; then
|
||||
echo "EMPTY_SOURCE"
|
||||
# Does target path has an empty timestamp?
|
||||
elif [ -z "$target_timestamp" ]; then
|
||||
echo "EMPTY_TARGET"
|
||||
# If target path is older than source path, it's outdated.
|
||||
elif [[ "$target_timestamp" -lt "$source_timestamp" ]]; then
|
||||
echo "OUTDATED"
|
||||
else
|
||||
echo "UPDATED"
|
||||
fi
|
||||
}
|
||||
####################
|
||||
# Detect architecture
|
||||
# Helpful link(s):
|
||||
# http://stackoverflow.com/questions/45125516
|
||||
export MACHINE_ARCH=$(uname -m)
|
||||
case $MACHINE_ARCH in
|
||||
"x86_64") sleep 0;;
|
||||
*)
|
||||
printf "${STY_YELLOW}"
|
||||
printf "===WARNING===\n"
|
||||
printf "Detected machine architecture: ${MACHINE_ARCH}\n"
|
||||
printf "This script only supports x86_64.\n"
|
||||
printf "It is very likely to fail when installing dependencies on your machine.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
;;
|
||||
esac
|
||||
|
||||
####################
|
||||
# Detect distro
|
||||
# Helpful link(s):
|
||||
# http://stackoverflow.com/questions/29581754
|
||||
# https://github.com/which-distro/os-release
|
||||
export OS_RELEASE_FILE=${OS_RELEASE_FILE:-/etc/os-release}
|
||||
test -f ${OS_RELEASE_FILE} || \
|
||||
( echo "${OS_RELEASE_FILE} does not exist. Aborting..." ; exit 1 ; )
|
||||
export OS_DISTRO_ID=$(awk -F'=' '/^ID=/ { gsub("\"","",$2); print tolower($2) }' ${OS_RELEASE_FILE} 2> /dev/null)
|
||||
export OS_DISTRO_ID_LIKE=$(awk -F'=' '/^ID_LIKE=/ { gsub("\"","",$2); print tolower($2) }' ${OS_RELEASE_FILE} 2> /dev/null)
|
||||
|
||||
|
||||
if [[ "$INSTALL_VIA_NIX" == "true" ]]; then
|
||||
|
||||
TARGET_ID=nix
|
||||
printf "${STY_YELLOW}"
|
||||
printf "===WARNING===\n"
|
||||
printf "./sdist/${TARGET_ID}/install-deps.sh will be used.\n"
|
||||
printf "The process is still WIP.\n"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-deps.sh
|
||||
|
||||
elif [[ "$OS_DISTRO_ID" =~ ^(arch|endeavouros)$ ]]; then
|
||||
|
||||
TARGET_ID=arch
|
||||
printf "${STY_GREEN}"
|
||||
printf "===INFO===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "./sdist/${TARGET_ID}/install-deps.sh will be used.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-deps.sh
|
||||
|
||||
elif [[ -f "./sdist/${OS_DISTRO_ID}/install-deps.sh" ]]; then
|
||||
|
||||
TARGET_ID=${OS_DISTRO_ID}
|
||||
printf "${STY_PURPLE}"
|
||||
printf "===NOTICE===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "./sdist/${TARGET_ID}/install-deps.sh will be used.\n"
|
||||
printf "This file is provided by the community.\n"
|
||||
printf "It is not officially supported by github:end-4/dots-hyprland .\n"
|
||||
test -f "./sdist/${TARGET_ID}/README.md" && \
|
||||
printf "Read ${STY_INVERT} ./sdist/${TARGET_ID}/README.md ${STY_PURPLE} for more information.\n"
|
||||
printf "${STY_BOLD}"
|
||||
printf "If you find out any problems about it, PR is welcomed if you are able to address it. Or, create a discussion about it, but please do not submit issue, because the developers do not use this distro, therefore they cannot help.${STY_RESET}\n"
|
||||
printf "${STY_PURPLE}"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
tmp_update_status="$(outdate_detect sdist/arch sdist/${TARGET_ID})"
|
||||
if [[ "${tmp_update_status}" =~ ^(OUTDATED|EMPTY_TARGET|EMPTY_SOURCE|FORCE_OUTDATED|WIP)$ ]]; then
|
||||
printf "${STY_RED}"
|
||||
printf "${STY_BOLD}===URGENT===${STY_RED}\n"
|
||||
printf "The community provided ./sdist/${TARGET_ID}/ is not updated (update status: ${tmp_update_status}),\n"
|
||||
printf "which means it does not fully reflect the latest changes of ./sdist/arch/ .\n"
|
||||
printf "You are highly recommended to abort this script, until someone (maybe you?) has updated the ./sdist/${TARGET_ID}/ to fully reflect the latest changes in ./sdist/arch/ .\n"
|
||||
printf "PR is welcomed. Please see discussion#2140 for details.\n"
|
||||
printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/2140${STY_RESET}\n"
|
||||
printf "${STY_RED}${STY_INVERT}If you are proceeding anyway, illogical-impulse will very likely not work as expected.${STY_RESET}\n"
|
||||
if [ "$ask" = "false" ]; then
|
||||
echo "Urgent problem encountered, aborting...";exit 1
|
||||
fi
|
||||
printf "${STY_RED}Still proceed?${STY_RESET}\n"
|
||||
read -p "[y/N]: " p
|
||||
case "$p" in
|
||||
[yY])sleep 0;;
|
||||
*)echo "Aborting...";exit 1;;
|
||||
esac
|
||||
fi
|
||||
source ./sdist/${TARGET_ID}/install-deps.sh
|
||||
|
||||
elif [[ "$OS_DISTRO_ID_LIKE" == "arch" || "$OS_DISTRO_ID" == "cachyos" ]]; then
|
||||
|
||||
TARGET_ID=arch
|
||||
printf "${STY_YELLOW}"
|
||||
printf "===WARNING===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "Detected distro ID_LIKE: ${OS_DISTRO_ID_LIKE}\n"
|
||||
printf "./sdist/${TARGET_ID}/install-deps.sh will be used.\n"
|
||||
printf "Ideally, it should also work for your distro.\n"
|
||||
printf "Still, there is a chance that it not works as expected or even fails.\n"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-deps.sh
|
||||
|
||||
else
|
||||
|
||||
TARGET_ID=fallback
|
||||
printf "${STY_RED}"
|
||||
printf "${STY_BOLD}===URGENT===${STY_RED}\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "Detected distro ID_LIKE: ${OS_DISTRO_ID_LIKE}\n"
|
||||
printf "./sdist/${OS_DISTRO_ID}/install-deps.sh not found.\n"
|
||||
printf "./sdist/${TARGET_ID}/install-deps.sh will be used.\n"
|
||||
printf "1. It may disrupt your system and will likely fail without your manual intervention.\n"
|
||||
printf "2. It's WIP and only contains small number of dependencies far from enough.\n"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-deps.sh
|
||||
|
||||
fi
|
||||
@@ -0,0 +1,92 @@
|
||||
# This script is meant to be sourced.
|
||||
# It's not for directly running.
|
||||
|
||||
####################
|
||||
# Detect distro
|
||||
# Helpful link(s):
|
||||
# http://stackoverflow.com/questions/29581754
|
||||
# https://github.com/which-distro/os-release
|
||||
export OS_RELEASE_FILE=${OS_RELEASE_FILE:-/etc/os-release}
|
||||
test -f ${OS_RELEASE_FILE} || \
|
||||
( echo "${OS_RELEASE_FILE} does not exist. Aborting..." ; exit 1 ; )
|
||||
export OS_DISTRO_ID=$(awk -F'=' '/^ID=/ { gsub("\"","",$2); print tolower($2) }' ${OS_RELEASE_FILE} 2> /dev/null)
|
||||
export OS_DISTRO_ID_LIKE=$(awk -F'=' '/^ID_LIKE=/ { gsub("\"","",$2); print tolower($2) }' ${OS_RELEASE_FILE} 2> /dev/null)
|
||||
|
||||
|
||||
|
||||
if [[ "$INSTALL_VIA_NIX" == "true" ]]; then
|
||||
|
||||
TARGET_ID=fallback
|
||||
printf "${STY_YELLOW}"
|
||||
printf "===WARNING===\n"
|
||||
printf "./sdist/${TARGET_ID}/install-setups.sh will be used.\n"
|
||||
printf "The process is still WIP.\n"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-setups.sh
|
||||
|
||||
elif [[ "$OS_DISTRO_ID" == "arch" ]]; then
|
||||
|
||||
TARGET_ID=arch
|
||||
printf "${STY_GREEN}"
|
||||
printf "===INFO===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "./sdist/${TARGET_ID}/install-setups.sh will be used.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-setups.sh
|
||||
|
||||
elif [[ -f "./sdist/${OS_DISTRO_ID}/install-setups.sh" ]]; then
|
||||
|
||||
TARGET_ID=${OS_DISTRO_ID}
|
||||
printf "${STY_PURPLE}"
|
||||
printf "===NOTICE===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "./sdist/${TARGET_ID}/install-setups.sh will be used.\n"
|
||||
printf "This file is provided by the community.\n"
|
||||
printf "It is not officially supported by github:end-4/dots-hyprland .\n"
|
||||
printf "${STY_BG_PURPLE}"
|
||||
printf "If you find out any problems about it, PR is welcomed if you are able to address it. Or, create a discussion about it, but please do not submit issue, because the developers do not use this distro, therefore they cannot help.${STY_RESET}\n"
|
||||
printf "${STY_PURPLE}"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-setups.sh
|
||||
|
||||
elif [[ "$OS_DISTRO_ID_LIKE" == "arch" || "$OS_DISTRO_ID" == "cachyos" ]]; then
|
||||
|
||||
TARGET_ID=arch
|
||||
printf "${STY_YELLOW}"
|
||||
printf "===WARNING===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "Detected distro ID_LIKE: ${OS_DISTRO_ID_LIKE}\n"
|
||||
printf "./sdist/${TARGET_ID}/install-setups.sh will be used.\n"
|
||||
printf "Ideally, it should also work for your distro.\n"
|
||||
printf "Still, there is a chance that it not works as expected or even fails.\n"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-setups.sh
|
||||
|
||||
else
|
||||
|
||||
TARGET_ID=fallback
|
||||
printf "${STY_RED}"
|
||||
printf "===WARNING===\n"
|
||||
printf "Detected distro ID: ${OS_DISTRO_ID}\n"
|
||||
printf "Detected distro ID_LIKE: ${OS_DISTRO_ID_LIKE}\n"
|
||||
printf "./sdist/${OS_DISTRO_ID}/install-setups.sh not found.\n"
|
||||
printf "./sdist/${TARGET_ID}/install-setups.sh will be used.\n"
|
||||
printf "It might fail or disrupt your system.\n"
|
||||
printf "Proceed only at your own risk.\n"
|
||||
printf "\n"
|
||||
printf "${STY_RESET}"
|
||||
pause
|
||||
source ./sdist/${TARGET_ID}/install-setups.sh
|
||||
|
||||
fi
|
||||
@@ -0,0 +1,201 @@
|
||||
# This script is meant to be sourced.
|
||||
# It's not for directly running.
|
||||
|
||||
# TODO: https://github.com/end-4/dots-hyprland/issues/2137
|
||||
|
||||
# TODO: make function backup_configs only cover the possibly overwritten ones.
|
||||
function backup_configs(){
|
||||
local backup_dir="$BACKUP_DIR"
|
||||
mkdir -p "$backup_dir"
|
||||
echo "Backing up $XDG_CONFIG_HOME to $backup_dir/config_backup"
|
||||
rsync -av --progress "$XDG_CONFIG_HOME/" "$backup_dir/config_backup/"
|
||||
|
||||
echo "Backing up $HOME/.local to $backup_dir/local_backup"
|
||||
declare -a arg_excludes=()
|
||||
arg_excludes+=(--exclude "$HOME/.local/share/Steam")
|
||||
arg_excludes+=(--exclude "$HOME/.local/share/steam")
|
||||
rsync -av --progress "${arg_excludes[@]}" "$HOME/.local/" "$backup_dir/local_backup/"
|
||||
declare -a arg_excludes=()
|
||||
}
|
||||
|
||||
function warning_rsync(){
|
||||
printf "${STY_YELLOW}"
|
||||
printf "The commands using rsync will overwrite the destination when it exists already.\n"
|
||||
printf "${STY_RESET}"
|
||||
}
|
||||
|
||||
function ask_backup_configs(){
|
||||
printf "${STY_RED}"
|
||||
printf "Would you like to create a backup for \"$XDG_CONFIG_HOME\" and \"$HOME/.local/\" folders?\n[y/N]: "
|
||||
read -p " " backup_confirm
|
||||
case $backup_confirm in
|
||||
[yY][eE][sS]|[yY]) backup_configs ;;
|
||||
*) echo "Skipping backup..." ;;
|
||||
esac
|
||||
printf "${STY_RESET}"
|
||||
}
|
||||
|
||||
#####################################################################################
|
||||
|
||||
# In case some folders does not exists
|
||||
v mkdir -p $XDG_BIN_HOME $XDG_CACHE_HOME $XDG_CONFIG_HOME $XDG_DATA_HOME
|
||||
|
||||
case $ask in
|
||||
false) sleep 0 ;;
|
||||
*) ask_backup_configs ;;
|
||||
esac
|
||||
|
||||
# TODO: A better method for users to choose their customization,
|
||||
# for example some users may prefer ZSH over FISH, and foot over kitty.
|
||||
# But the dot files are using FISH and kitty as the default software, e.g. `.local/share/Konsole` has `Command=/bin/fish`.
|
||||
# It may be possible that we provide options for users to make their decision.
|
||||
|
||||
|
||||
# `--delete' for rsync to make sure that
|
||||
# original dotfiles and new ones in the SAME DIRECTORY
|
||||
# (eg. in ~/.config/hypr) won't be mixed together
|
||||
|
||||
# MISC (For dots/.config/* but not fish, not Hyprland)
|
||||
case $SKIP_MISCCONF in
|
||||
true) sleep 0;;
|
||||
*)
|
||||
for i in $(find dots/.config/ -mindepth 1 -maxdepth 1 ! -name 'fish' ! -name 'hypr' -exec basename {} \;); do
|
||||
# i="dots/.config/$i"
|
||||
echo "[$0]: Found target: dots/.config/$i"
|
||||
if [ -d "dots/.config/$i" ];then warning_rsync; v rsync -av --delete "dots/.config/$i/" "$XDG_CONFIG_HOME/$i/"
|
||||
elif [ -f "dots/.config/$i" ];then warning_rsync; v rsync -av "dots/.config/$i" "$XDG_CONFIG_HOME/$i"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
case $SKIP_FISH in
|
||||
true) sleep 0;;
|
||||
*)
|
||||
warning_rsync; v rsync -av --delete dots/.config/fish/ "$XDG_CONFIG_HOME"/fish/
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Hyprland
|
||||
declare -a arg_excludes=()
|
||||
arg_excludes+=(--exclude '/custom')
|
||||
arg_excludes+=(--exclude '/hyprlock.conf')
|
||||
arg_excludes+=(--exclude '/hypridle.conf')
|
||||
arg_excludes+=(--exclude '/hyprland.conf')
|
||||
case $SKIP_HYPRLAND in
|
||||
true) sleep 0;;
|
||||
*)
|
||||
warning_rsync; v rsync -av --delete "${arg_excludes[@]}" dots/.config/hypr/ "$XDG_CONFIG_HOME"/hypr/
|
||||
t="$XDG_CONFIG_HOME/hypr/hyprland.conf"
|
||||
if [ -f $t ];then
|
||||
echo -e "${STY_BLUE}[$0]: \"$t\" already exists.${STY_RESET}"
|
||||
v mv $t $t.old
|
||||
v cp -f dots/.config/hypr/hyprland.conf $t
|
||||
existed_hypr_conf_firstrun=y
|
||||
else
|
||||
echo -e "${STY_YELLOW}[$0]: \"$t\" does not exist yet.${STY_RESET}"
|
||||
v cp dots/.config/hypr/hyprland.conf $t
|
||||
existed_hypr_conf=n
|
||||
fi
|
||||
t="$XDG_CONFIG_HOME/hypr/hypridle.conf"
|
||||
if [ -f $t ];then
|
||||
echo -e "${STY_BLUE}[$0]: \"$t\" already exists.${STY_RESET}"
|
||||
v cp -f dots/.config/hypr/hypridle.conf $t.new
|
||||
existed_hypridle_conf=y
|
||||
else
|
||||
echo -e "${STY_YELLOW}[$0]: \"$t\" does not exist yet.${STY_RESET}"
|
||||
v cp dots/.config/hypr/hypridle.conf $t
|
||||
existed_hypridle_conf=n
|
||||
fi
|
||||
t="$XDG_CONFIG_HOME/hypr/hyprlock.conf"
|
||||
if [ -f $t ];then
|
||||
echo -e "${STY_BLUE}[$0]: \"$t\" already exists.${STY_RESET}"
|
||||
v cp -f dots/.config/hypr/hyprlock.conf $t.new
|
||||
existed_hyprlock_conf=y
|
||||
else
|
||||
echo -e "${STY_YELLOW}[$0]: \"$t\" does not exist yet.${STY_RESET}"
|
||||
v cp dots/.config/hypr/hyprlock.conf $t
|
||||
existed_hyprlock_conf=n
|
||||
fi
|
||||
t="$XDG_CONFIG_HOME/hypr/custom"
|
||||
if [ -d $t ];then
|
||||
echo -e "${STY_BLUE}[$0]: \"$t\" already exists, will not do anything.${STY_RESET}"
|
||||
else
|
||||
echo -e "${STY_YELLOW}[$0]: \"$t\" does not exist yet.${STY_RESET}"
|
||||
warning_rsync; v rsync -av --delete dots/.config/hypr/custom/ $t/
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
declare -a arg_excludes=()
|
||||
|
||||
|
||||
# some foldes (eg. .local/bin) should be processed separately to avoid `--delete' for rsync,
|
||||
# since the files here come from different places, not only about one program.
|
||||
# v rsync -av ".local/bin/" "$XDG_BIN_HOME" # No longer needed since scripts are no longer in ~/.local/bin
|
||||
warning_rsync; v rsync -av ".local/share/icons/" "${XDG_DATA_HOME:-$HOME/.local/share}"/icons/
|
||||
warning_rsync; v rsync -av ".local/share/konsole/" "${XDG_DATA_HOME:-$HOME/.local/share}"/konsole/
|
||||
|
||||
# Prevent hyprland from not fully loaded
|
||||
sleep 1
|
||||
try hyprctl reload
|
||||
|
||||
existed_zsh_conf=n
|
||||
grep -q 'source ${XDG_CONFIG_HOME:-~/.config}/zshrc.d/dots-hyprland.zsh' ~/.zshrc && existed_zsh_conf=y
|
||||
|
||||
warn_files=()
|
||||
warn_files_tests=()
|
||||
warn_files_tests+=(/usr/local/lib/{GUtils-1.0.typelib,Gvc-1.0.typelib,libgutils.so,libgvc.so})
|
||||
warn_files_tests+=(/usr/local/share/fonts/TTF/Rubik{,-Italic}'[wght]'.ttf)
|
||||
warn_files_tests+=(/usr/local/share/licenses/ttf-rubik)
|
||||
warn_files_tests+=(/usr/local/share/fonts/TTF/Gabarito-{Black,Bold,ExtraBold,Medium,Regular,SemiBold}.ttf)
|
||||
warn_files_tests+=(/usr/local/share/licenses/ttf-gabarito)
|
||||
warn_files_tests+=(/usr/local/share/icons/OneUI{,-dark,-light})
|
||||
warn_files_tests+=(/usr/local/share/icons/Bibata-Modern-Classic)
|
||||
warn_files_tests+=(/usr/local/bin/{LaTeX,res})
|
||||
for i in ${warn_files_tests[@]}; do
|
||||
echo $i
|
||||
test -f $i && warn_files+=($i)
|
||||
test -d $i && warn_files+=($i)
|
||||
done
|
||||
|
||||
#####################################################################################
|
||||
# TODO: output the logs below to a temp file and cat that file, also show the path of the file so users will be able to read it again.
|
||||
printf "\n"
|
||||
printf "\n"
|
||||
printf "\n"
|
||||
printf "${STY_CYAN}[$0]: Finished${STY_RESET}\n"
|
||||
printf "\n"
|
||||
printf "${STY_CYAN}When starting Hyprland from your display manager (login screen) ${STY_RED} DO NOT SELECT UWSM ${STY_RESET}\n"
|
||||
printf "\n"
|
||||
printf "${STY_CYAN}If you are already running Hyprland,${STY_RESET}\n"
|
||||
printf "${STY_CYAN}Press ${STY_BG_CYAN} Ctrl+Super+T ${STY_BG_CYAN} to select a wallpaper${STY_RESET}\n"
|
||||
printf "${STY_CYAN}Press ${STY_BG_CYAN} Super+/ ${STY_CYAN} for a list of keybinds${STY_RESET}\n"
|
||||
printf "\n"
|
||||
printf "${STY_CYAN}For suggestions/hints after installation:${STY_RESET}\n"
|
||||
printf "${STY_CYAN}${STY_UNDERLINE} https://ii.clsty.link/en/ii-qs/01setup/#post-installation ${STY_RESET}\n"
|
||||
printf "\n"
|
||||
|
||||
case $existed_hypr_conf_firstrun in
|
||||
y) printf "\n${STY_YELLOW}[$0]: Warning: \"$XDG_CONFIG_HOME/hypr/hyprland.conf\" already existed before. As it seems it is your first run, we replaced it with a new one. ${STY_RESET}\n"
|
||||
printf "${STY_YELLOW}As it seems it is your first run, we replaced it with a new one. The old one has been renamed to \"$XDG_CONFIG_HOME/hypr/hyprland.conf.old\".${STY_RESET}\n"
|
||||
;;esac
|
||||
case $existed_hypr_conf in
|
||||
y) printf "\n${STY_YELLOW}[$0]: Warning: \"$XDG_CONFIG_HOME/hypr/hyprland.conf\" already existed before and we didn't overwrite it. ${STY_RESET}\n"
|
||||
printf "${STY_YELLOW}Please use \"$XDG_CONFIG_HOME/hypr/hyprland.conf.new\" as a reference for a proper format.${STY_RESET}\n"
|
||||
;;esac
|
||||
case $existed_hypridle_conf in
|
||||
y) printf "\n${STY_YELLOW}[$0]: Warning: \"$XDG_CONFIG_HOME/hypr/hypridle.conf\" already existed before and we didn't overwrite it. ${STY_RESET}\n"
|
||||
printf "${STY_YELLOW}Please use \"$XDG_CONFIG_HOME/hypr/hypridle.conf.new\" as a reference for a proper format.${STY_RESET}\n"
|
||||
;;esac
|
||||
case $existed_hyprlock_conf in
|
||||
y) printf "\n${STY_YELLOW}[$0]: Warning: \"$XDG_CONFIG_HOME/hypr/hyprlock.conf\" already existed before and we didn't overwrite it. ${STY_RESET}\n"
|
||||
printf "${STY_YELLOW}Please use \"$XDG_CONFIG_HOME/hypr/hyprlock.conf.new\" as a reference for a proper format.${STY_RESET}\n"
|
||||
;;esac
|
||||
|
||||
if [[ -z "${ILLOGICAL_IMPULSE_VIRTUAL_ENV}" ]]; then
|
||||
printf "\n${STY_RED}[$0]: \!! Important \!! : Please ensure environment variable ${STY_RESET} \$ILLOGICAL_IMPULSE_VIRTUAL_ENV ${STY_RED} is set to proper value (by default \"~/.local/state/quickshell/.venv\"), or Quickshell config will not work. We have already provided this configuration in ~/.config/hypr/hyprland/env.conf, but you need to ensure it is included in hyprland.conf, and also a restart is needed for applying it.${STY_RESET}\n"
|
||||
fi
|
||||
|
||||
if [[ ! -z "${warn_files[@]}" ]]; then
|
||||
printf "\n${STY_RED}[$0]: \!! Important \!! : Please delete ${STY_RESET} ${warn_files[*]} ${STY_RED} manually as soon as possible, since we\'re now using AUR package or local PKGBUILD to install them for Arch(based) Linux distros, and they'll take precedence over our installation, or at least take up more space.${STY_RESET}\n"
|
||||
fi
|
||||
@@ -0,0 +1,139 @@
|
||||
## Why is this important?
|
||||
Instead of installing python packages via system package manager, we should install them into virtual environment.
|
||||
|
||||
This is important because there has been so many complaints about the failure installing/updating python packages via system package manager, see [#1017](https://github.com/end-4/dots-hyprland/issues/1017).
|
||||
|
||||
## How to add/remove python package?
|
||||
|
||||
1. Edit `requirements.in`. You may refer to [PyPI](https://pypi.org/) for possible package names.
|
||||
- If PyPI does not have the needed package, we probably need to build it manually inside the venv. In such case we need to edit the install scripts.
|
||||
2. Run `uv pip compile requirements.in -o requirements.txt` in this folder.
|
||||
|
||||
**Notes:**
|
||||
- For reference see [uv doc](https://docs.astral.sh/uv/pip/dependencies/#using-requirementsin).
|
||||
- `requirements.txt` is included in Git. It's for locking package versions to enhance stability and reproducibility.[^1]
|
||||
|
||||
[^1]: In fact, including package version lock file in Git is also the most common way for similar situations, for example the `package-lock.json` of Node.js projects (see also [this stackoverflow question](https://stackoverflow.com/questions/48524417/should-the-package-lock-json-file-be-added-to-gitignore)). Although there are some situations when it's not suitable to include the lock file, for example [the poetry document](https://python-poetry.org/docs/basic-usage/#committing-your-poetrylock-file-to-version-control) recommend application developers to include package version lock file in Git, but library developers should consider more, such as not inluding the lock file or including it but refreshing regularly.
|
||||
|
||||
## How will the python packages get installed?
|
||||
|
||||
For summary:
|
||||
- They will be installed to the virtual environment `$ILLOGICAL_IMPULSE_VIRTUAL_ENV`.
|
||||
- The default value of `$ILLOGICAL_IMPULSE_VIRTUAL_ENV` is `$XDG_STATE_HOME/quickshell/.venv`.
|
||||
- The default value of `$XDG_STATE_HOME` is `$HOME/.local/state`.
|
||||
- Currently we use `env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv` in `~/.config/hypr/hyprland/env.conf` to set this environment variable.[^2]
|
||||
|
||||
For details: see the function `install-python-packages()` defined in `/sdata/lib/package-installers.sh`.
|
||||
|
||||
[^2]: Hyprland seems to have weird problem dealing with recursive variable, so we can not use `$XDG_STATE_HOME/quickshell/.venv` even if we had set `$XDG_STATE_HOME` to `~/.local/state` explicitly, else `$XDG_STATE_HOME` will possibly not get expanded but get recognised as literally `$XDG_STATE_HOME`. This problem never happens for some users, but according to some issues when we were using recursive variable setting in the past, it's possible to happen for other users. Reason unknown.
|
||||
|
||||
## How to use the python packages installed through here?
|
||||
|
||||
Basically you'll need to activate the virtual environment first:
|
||||
```bash
|
||||
source $(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate
|
||||
```
|
||||
|
||||
It will add the python executable located in the venv to `$PATH` and give it the highest priority.
|
||||
Run `which python` and you'll understand.
|
||||
|
||||
This python executable will also search and use the python package inside the venv,
|
||||
which enables running any python script or running command provided via python package using the venv.
|
||||
|
||||
After that you probably need to deactivate it:
|
||||
```bash
|
||||
deactivate
|
||||
```
|
||||
|
||||
### Situation 1: As a single command
|
||||
**Description:** At someplace which accept a single command,
|
||||
- run a python script,
|
||||
- or run a command provided by python package.
|
||||
|
||||
Example: In `~/.config/quickshell/ii/screenshot.qml`:
|
||||
```qml
|
||||
Process {
|
||||
id: imageDetectionProcess
|
||||
command: ["bash", "-c", `${Directories.scriptPath}/images/find_regions.py `
|
||||
+ `--hyprctl `
|
||||
+ `--image '${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)}' `
|
||||
+ `--max-width ${Math.round(panelWindow.screen.width * root.falsePositivePreventionRatio)} `
|
||||
```
|
||||
In this example, python script `find_regions.py` is called and receives some arguments.
|
||||
|
||||
#### Solution A: shebang
|
||||
|
||||
Add the shebang below to the beginning of python script:
|
||||
```python
|
||||
#!/usr/bin/env -S\_/bin/sh\_-c\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@""
|
||||
```
|
||||
And that's it!
|
||||
|
||||
**Note:** This is the simplest solution as it only modifies the shebang of python script.
|
||||
However:
|
||||
- It's only for python script, not the command provided by python package.
|
||||
- It can not deal with complex argument (e.g. filename containing spaces) passed to the python script.
|
||||
- If we apply this solution to the example above, it may cause problem, considering that `--image '${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)}'` could be a rather complex argument passed to `find_regions.py`.
|
||||
- This solution rely on shebang to activate the correct python venv, but the shebang will be ignored if the script is passed as a parameter to python, e.g. `python3 foo.py`.
|
||||
|
||||
#### Solution B: bash script as wrapper
|
||||
|
||||
First make sure the python script is using the shebang `#!/usr/bin/env python3`, instead of `#!/usr/bin/python3` or something else.
|
||||
|
||||
Then write a wrapper script in bash.
|
||||
Let's continue the `screenshot.qml` example, in the same directory as `find_regions.py`, write a `find-regions-venv.sh`:
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Specify the path of the python script.
|
||||
# The example below only applies when `find_regions.py` and this wrapper script are under the same folder.
|
||||
PY_SCRIPT="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)/find_regions.py"
|
||||
|
||||
source $(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate
|
||||
"$PY_SCRIPT" "$@"
|
||||
deactivate
|
||||
```
|
||||
**Not done yet!** Do not forget to update the code calling the original python script.
|
||||
In this example, in `~/.config/quickshell/ii/screenshot.qml` we should modify `find_regions.py` to the wrapper script `find-regions-venv.sh`:
|
||||
```qml
|
||||
Process {
|
||||
id: imageDetectionProcess
|
||||
command: ["bash", "-c", `${Directories.scriptPath}/images/find-regions-venv.sh `
|
||||
+ `--hyprctl `
|
||||
+ `--image '${StringUtils.shellSingleQuoteEscape(panelWindow.screenshotPath)}' `
|
||||
+ `--max-width ${Math.round(panelWindow.screen.width * root.falsePositivePreventionRatio)} `
|
||||
```
|
||||
|
||||
### Situation 2: Inside a bash script
|
||||
Note: the solutions for `Situation 1: As a single command` also apply here; but **not** vice versa.
|
||||
|
||||
**Description:**
|
||||
Inside a bash script,
|
||||
- run a python script,
|
||||
- or run a command provided by python package.
|
||||
|
||||
**Solution:**
|
||||
- Add "activation command" before the target line,
|
||||
- Also add "deactivation command" after the target line.
|
||||
|
||||
**Example:**
|
||||
|
||||
For running a python script,
|
||||
take `generate_colors_material.py` as example:
|
||||
```bash
|
||||
source "$(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate"
|
||||
python3 "$SCRIPT_DIR/generate_colors_material.py" "${generate_colors_material_args[@]}" \
|
||||
> "$STATE_DIR"/user/generated/material_colors.scss
|
||||
"$SCRIPT_DIR"/applycolor.sh
|
||||
```
|
||||
|
||||
For running a python script provided by python package,
|
||||
take `kde-material-you-colors` as example:
|
||||
```bash
|
||||
source "$(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate"
|
||||
kde-material-you-colors "$mode_flag" --color "$color" -sv "$sv_num"
|
||||
deactivate
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
build
|
||||
pillow
|
||||
setuptools-scm
|
||||
wheel
|
||||
pywayland
|
||||
psutil
|
||||
kde-material-you-colors
|
||||
materialyoucolor
|
||||
libsass
|
||||
material-color-utilities
|
||||
setproctitle
|
||||
click
|
||||
loguru
|
||||
pycairo
|
||||
pygobject
|
||||
tqdm
|
||||
numpy
|
||||
opencv-contrib-python
|
||||
@@ -0,0 +1,63 @@
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile sdata/uv/requirements.in -o sdata/uv/requirements.txt
|
||||
build==1.2.2.post1
|
||||
# via -r sdata/uv/requirements.in
|
||||
cffi==1.17.1
|
||||
# via pywayland
|
||||
click==8.2.1
|
||||
# via -r sdata/uv/requirements.in
|
||||
dbus-python==1.4.0
|
||||
# via kde-material-you-colors
|
||||
kde-material-you-colors==1.10.1
|
||||
# via -r sdata/uv/requirements.in
|
||||
libsass==0.23.0
|
||||
# via -r sdata/uv/requirements.in
|
||||
loguru==0.7.3
|
||||
# via -r sdata/uv/requirements.in
|
||||
material-color-utilities==0.2.1
|
||||
# via -r sdata/uv/requirements.in
|
||||
materialyoucolor==2.0.10
|
||||
# via
|
||||
# -r sdata/uv/requirements.in
|
||||
# kde-material-you-colors
|
||||
numpy==2.2.2
|
||||
# via
|
||||
# -r sdata/uv/requirements.in
|
||||
# kde-material-you-colors
|
||||
# material-color-utilities
|
||||
# opencv-contrib-python
|
||||
opencv-contrib-python==4.12.0.88
|
||||
# via -r sdata/uv/requirements.in
|
||||
packaging==24.2
|
||||
# via
|
||||
# build
|
||||
# setuptools-scm
|
||||
pillow==11.1.0
|
||||
# via
|
||||
# -r sdata/uv/requirements.in
|
||||
# kde-material-you-colors
|
||||
# material-color-utilities
|
||||
psutil==6.1.1
|
||||
# via -r sdata/uv/requirements.in
|
||||
pycairo==1.28.0
|
||||
# via
|
||||
# -r sdata/uv/requirements.in
|
||||
# pygobject
|
||||
pycparser==2.22
|
||||
# via cffi
|
||||
pygobject==3.52.3
|
||||
# via -r sdata/uv/requirements.in
|
||||
pyproject-hooks==1.2.0
|
||||
# via build
|
||||
pywayland==0.4.18
|
||||
# via -r sdata/uv/requirements.in
|
||||
setproctitle==1.3.4
|
||||
# via -r sdata/uv/requirements.in
|
||||
setuptools==80.9.0
|
||||
# via setuptools-scm
|
||||
setuptools-scm==8.1.0
|
||||
# via -r sdata/uv/requirements.in
|
||||
tqdm==4.67.1
|
||||
# via -r sdata/uv/requirements.in
|
||||
wheel==0.45.1
|
||||
# via -r sdata/uv/requirements.in
|
||||
Reference in New Issue
Block a user