init
This commit is contained in:
29
modules/home/scripts/default.nix
Normal file
29
modules/home/scripts/default.nix
Normal file
@@ -0,0 +1,29 @@
|
||||
{ pkgs
|
||||
, username
|
||||
, profile
|
||||
, ...
|
||||
}: {
|
||||
home.packages = [
|
||||
(import ./emopicker9000.nix { inherit pkgs; })
|
||||
(import ./hm-find.nix { inherit pkgs; })
|
||||
(import ./keybinds.nix { inherit pkgs; })
|
||||
(import ./note.nix { inherit pkgs; })
|
||||
(import ./note-from-clipboard.nix { inherit pkgs; })
|
||||
(import ./nvidia-offload.nix { inherit pkgs; })
|
||||
(import ./rofi-launcher.nix { inherit pkgs; })
|
||||
(import ./screenshootin.nix { inherit pkgs; })
|
||||
(import ./squirtle.nix { inherit pkgs; })
|
||||
(import ./task-waybar.nix { inherit pkgs; })
|
||||
(import ./wallsetter.nix {
|
||||
inherit pkgs;
|
||||
inherit username;
|
||||
})
|
||||
(import ./web-search.nix { inherit pkgs; })
|
||||
(import ./zcli.nix {
|
||||
inherit pkgs profile;
|
||||
backupFiles = [
|
||||
".config/mimeapps.list.backup"
|
||||
];
|
||||
})
|
||||
];
|
||||
}
|
||||
22
modules/home/scripts/emopicker9000.nix
Normal file
22
modules/home/scripts/emopicker9000.nix
Normal file
@@ -0,0 +1,22 @@
|
||||
{ pkgs }:
|
||||
pkgs.writeShellScriptBin "emopicker9000" ''
|
||||
# check if rofi is already running
|
||||
if pidof rofi > /dev/null; then
|
||||
pkill rofi
|
||||
fi
|
||||
|
||||
# Get user selection via wofi from emoji file.
|
||||
chosen=$(cat $HOME/.config/.emoji | ${pkgs.rofi-wayland}/bin/rofi -i -dmenu -config ~/.config/rofi/config-long.rasi | awk '{print $1}')
|
||||
|
||||
# Exit if none chosen.
|
||||
[ -z "$chosen" ] && exit
|
||||
|
||||
# If you run this command with an argument, it will automatically insert the
|
||||
# character. Otherwise, show a message that the emoji has been copied.
|
||||
if [ -n "$1" ]; then
|
||||
${pkgs.ydotool}/bin/ydotool type "$chosen"
|
||||
else
|
||||
printf "$chosen" | ${pkgs.wl-clipboard}/bin/wl-copy
|
||||
${pkgs.libnotify}/bin/notify-send "'$chosen' copied to clipboard." &
|
||||
fi
|
||||
''
|
||||
37
modules/home/scripts/gemini-cli.nix
Normal file
37
modules/home/scripts/gemini-cli.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
gemini-launcher = pkgs.writeShellScriptBin "gemini-launcher" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
|
||||
# Define the path to your API key file
|
||||
KEY_FILE="${config.home.homeDirectory}/gem.key"
|
||||
|
||||
# Check if the key file exists and is readable
|
||||
if [ -f "$KEY_FILE" ]; then
|
||||
# Source the API key from the file.
|
||||
source "$KEY_FILE"
|
||||
# Launch Gemini directly; it will pick up the exported key.
|
||||
exec ${pkgs.kitty}/bin/kitty -e ${pkgs.gemini-cli}/bin/gemini
|
||||
else
|
||||
# If the key file doesn't exist, launch kitty with an informational message, then start gemini.
|
||||
exec ${pkgs.kitty}/bin/kitty -e bash -c "echo 'NOTE: Gemini API key file not found at ~/.gem.key.'; echo 'To use a key, create this file with content: export GEMINI_API_KEY=\"YOUR_KEY\"'; echo; echo 'Starting Gemini CLI, which will fall back to web-based login...'; echo; exec ${pkgs.gemini-cli}/bin/gemini"
|
||||
fi
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
home.packages = [
|
||||
gemini-launcher
|
||||
];
|
||||
|
||||
xdg.desktopEntries.gemini-cli = {
|
||||
name = "Gemini CLI";
|
||||
comment = "Launch the Gemini CLI in Kitty terminal";
|
||||
icon = "utilities-terminal";
|
||||
exec = "gemini-launcher";
|
||||
terminal = false;
|
||||
type = "Application";
|
||||
categories = [ "Development" "Utility" ];
|
||||
};
|
||||
}
|
||||
60
modules/home/scripts/hm-find.nix
Normal file
60
modules/home/scripts/hm-find.nix
Normal file
@@ -0,0 +1,60 @@
|
||||
{ pkgs }:
|
||||
pkgs.writeShellScriptBin "hm-find" ''
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Script Metadata
|
||||
#===============================================
|
||||
# This script searches recent journalctl entries for Home Manager errors
|
||||
# It identifies backup files that prevent rebuilds and allows removal.
|
||||
# Author: Don Williams
|
||||
# Creation Date: May 6th, 2025
|
||||
# Revision History:
|
||||
#-----------------------------------------------
|
||||
# 0.1 - 5/6/25 - Initial version
|
||||
# 0.2 - 5/7/25 - Improved messaging, added log directory check
|
||||
|
||||
# Display WARNING message
|
||||
echo "==============================================="
|
||||
echo " ⚠️ WARNING ⚠️ "
|
||||
echo "==============================================="
|
||||
echo "*** This script is experimental! ***"
|
||||
echo "It will attempt to find old backup files that are preventing Home Manager from rebuilding."
|
||||
echo "If conflicting files are found, you will be prompted to remove them."
|
||||
echo "A log of any deletions will be stored in \$HOME/hm-logs."
|
||||
echo "==============================================="
|
||||
|
||||
# Define the time range (default: last 30 minutes)
|
||||
TIME_RANGE="30m"
|
||||
LOG_DIR="$HOME/hm-logs"
|
||||
LOG_FILE="$LOG_DIR/hm-cleanup-$(date +'%Y-%m-%d_%H-%M-%S').log"
|
||||
|
||||
# Ensure the log directory exists
|
||||
if [ ! -d "$LOG_DIR" ]; then
|
||||
echo "Creating log directory: $LOG_DIR"
|
||||
mkdir -p "$LOG_DIR"
|
||||
fi
|
||||
|
||||
# Search journal logs for backup conflicts and extract file paths
|
||||
FILES=$(journalctl --since "-$TIME_RANGE" -xe | grep hm-activate | awk -F "'|'" '/would be clobbered by backing up/ {print $2}')
|
||||
|
||||
# Check if any files were found
|
||||
if [ -z "$FILES" ]; then
|
||||
echo "No conflicting backup files found in the last $TIME_RANGE."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Display found backup files
|
||||
echo "🚨 The following backup files are preventing Home Manager from rebuilding:"
|
||||
echo "$FILES" | tr ' ' '\n'
|
||||
|
||||
# Ask for user confirmation before deletion
|
||||
read -p "❓ Do you want to remove these files? (y/N): " confirm
|
||||
|
||||
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
|
||||
echo "🗑️ Deleting files..." | tee -a "$LOG_FILE"
|
||||
echo "$FILES" | xargs rm -v | tee -a "$LOG_FILE"
|
||||
echo "✅ Cleanup completed at $(date)" | tee -a "$LOG_FILE"
|
||||
else
|
||||
echo "⛔ No files were removed." | tee -a "$LOG_FILE"
|
||||
fi
|
||||
''
|
||||
17
modules/home/scripts/keybinds.nix
Normal file
17
modules/home/scripts/keybinds.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{ pkgs }:
|
||||
pkgs.writeShellScriptBin "list-keybinds" ''
|
||||
# check if rofi is already running
|
||||
if pidof rofi > /dev/null; then
|
||||
pkill rofi
|
||||
fi
|
||||
|
||||
msg='☣️ NOTE ☣️: Clicking with Mouse or Pressing ENTER will have NO function'
|
||||
keybinds=$(cat ~/.config/hypr/hyprland.conf | grep -E '^bind')
|
||||
|
||||
# replace #modifier with SUPER in the displayed keybinds for rofi
|
||||
display_keybinds=$(echo "$keybinds" | sed 's/\$modifier/SUPER/g')
|
||||
|
||||
# use rofi to display the keybinds with the modified content
|
||||
echo "$display_keybinds" | rofi -dmenu -i -config ~/.config/rofi/config-long.rasi -mesg "$msg"
|
||||
|
||||
''
|
||||
20
modules/home/scripts/note-from-clipboard.nix
Normal file
20
modules/home/scripts/note-from-clipboard.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
{ pkgs, ... }:
|
||||
pkgs.writeShellScriptBin "note-from-clipboard" ''
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Check clipboard content type
|
||||
clipboard_type=$(${pkgs.wl-clipboard}/bin/wl-paste --list-types | head -n 1)
|
||||
|
||||
if [[ "$clipboard_type" == "text/plain"* ]]; then
|
||||
# It's text, let's create a note
|
||||
${pkgs.wl-clipboard}/bin/wl-paste | note
|
||||
if [ $? -eq 0 ]; then
|
||||
${pkgs.libnotify}/bin/notify-send -t 3000 "📝 Note Created" "Clipboard content added as a new note."
|
||||
else
|
||||
${pkgs.libnotify}/bin/notify-send -t 5000 -u critical "❌ Note Creation Failed" "There was an error creating the note."
|
||||
fi
|
||||
else
|
||||
# It's not text, so we do nothing and notify the user
|
||||
${pkgs.libnotify}/bin/notify-send -t 4000 -u low "📋 Note Skipped" "Clipboard does not contain text."
|
||||
fi
|
||||
''
|
||||
244
modules/home/scripts/note.nix
Normal file
244
modules/home/scripts/note.nix
Normal file
@@ -0,0 +1,244 @@
|
||||
{ pkgs, ... }:
|
||||
pkgs.writeShellScriptBin "note" ''
|
||||
|
||||
# Colors for nice output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
MAGENTA='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
GRAY='\033[0;37m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# XDG-compliant notes directory and file
|
||||
NOTES_DIR="$HOME/.local/share/notes"
|
||||
NOTES_FILE="$NOTES_DIR/notes.txt"
|
||||
|
||||
# Create notes directory if it doesn't exist
|
||||
mkdir -p "$NOTES_DIR"
|
||||
|
||||
# Function to display usage
|
||||
show_usage() {
|
||||
echo -e "''${BOLD}''${BLUE}📝 Note Manager''${NC}"
|
||||
echo -e "''${GRAY}Usage:''${NC}"
|
||||
echo -e " ''${CYAN}note''${NC} ''${YELLOW}<text>''${NC} - Add a new note"
|
||||
echo -e " ''${CYAN}note''${NC} - Display all notes"
|
||||
echo -e " ''${CYAN}note del''${NC} ''${YELLOW}<number>''${NC} - Delete note by number"
|
||||
echo -e " ''${CYAN}note clear''${NC} - Clear all notes"
|
||||
echo -e " ''${CYAN}echo 'text' | note''${NC} - Add note from stdin"
|
||||
echo -e " ''${CYAN}cat file | note''${NC} - Add file contents as note"
|
||||
echo ""
|
||||
echo -e "''${GRAY}Examples:''${NC}"
|
||||
echo -e " ''${GREEN}note call plumber tomorrow''${NC}"
|
||||
echo -e " ''${GREEN}cat todo.txt | note''${NC}"
|
||||
echo -e " ''${GREEN}note del 3''${NC}"
|
||||
}
|
||||
|
||||
# Function to add a note
|
||||
add_note() {
|
||||
local note_text="$1"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
local date_only=$(date '+%Y-%m-%d')
|
||||
|
||||
# Create notes file if it doesn't exist
|
||||
touch "$NOTES_FILE"
|
||||
|
||||
# Get next note number
|
||||
local note_num=1
|
||||
if [ -f "$NOTES_FILE" ] && [ -s "$NOTES_FILE" ]; then
|
||||
note_num=$(grep -E "^#[0-9]+" "$NOTES_FILE" | sed 's/^#\([0-9]*\).*/\1/' | sort -n | tail -1)
|
||||
note_num=$((note_num + 1))
|
||||
fi
|
||||
|
||||
# Add the note with proper formatting
|
||||
{
|
||||
echo "#$note_num [$timestamp]"
|
||||
echo "$note_text"
|
||||
echo ""
|
||||
} >> "$NOTES_FILE"
|
||||
|
||||
echo -e "''${GREEN}✓''${NC} Note #$note_num added ''${GRAY}($date_only)''${NC}"
|
||||
}
|
||||
|
||||
# Function to display all notes
|
||||
display_notes() {
|
||||
if [ ! -f "$NOTES_FILE" ] || [ ! -s "$NOTES_FILE" ]; then
|
||||
echo -e "''${YELLOW}📝 No notes found''${NC}"
|
||||
echo -e "''${GRAY}Use ''${CYAN}note <text>''${GRAY} to add your first note''${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "''${BOLD}''${BLUE}📝 Your Notes''${NC}"
|
||||
echo -e "''${GRAY}📁 $NOTES_FILE''${NC}"
|
||||
echo -e "''${GRAY}$(printf '%.0s─' {1..50})''${NC}"
|
||||
|
||||
local in_note=false
|
||||
local note_content=""
|
||||
|
||||
while IFS= read -r line; do
|
||||
# Check if line starts with # followed by numbers and space and [
|
||||
if echo "$line" | grep -q "^#[0-9][0-9]* \["; then
|
||||
# Print previous note content if exists
|
||||
if [ "$in_note" = true ] && [ -n "$note_content" ]; then
|
||||
echo -e "$note_content"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Extract note number and timestamp
|
||||
local num=$(echo "$line" | sed 's/^#\([0-9]*\) \[.*/\1/')
|
||||
local timestamp=$(echo "$line" | sed 's/^#[0-9]* \[\(.*\)\]/\1/')
|
||||
local date_part=$(echo "$timestamp" | cut -d' ' -f1)
|
||||
local time_part=$(echo "$timestamp" | cut -d' ' -f2)
|
||||
|
||||
echo -e "''${BOLD}''${CYAN}#$num''${NC} ''${GRAY}[$date_part ''${YELLOW}$time_part''${GRAY}]''${NC}"
|
||||
in_note=true
|
||||
note_content=""
|
||||
elif [ -n "$line" ] && [ "$in_note" = true ]; then
|
||||
# Accumulate note content
|
||||
if [ -z "$note_content" ]; then
|
||||
note_content="''${WHITE}$line''${NC}"
|
||||
else
|
||||
note_content="$note_content\n''${WHITE}$line''${NC}"
|
||||
fi
|
||||
elif [ -z "$line" ] && [ "$in_note" = true ]; then
|
||||
# End of current note
|
||||
if [ -n "$note_content" ]; then
|
||||
echo -e "$note_content"
|
||||
echo ""
|
||||
fi
|
||||
in_note=false
|
||||
note_content=""
|
||||
fi
|
||||
done < "$NOTES_FILE"
|
||||
|
||||
# Print last note if file doesn't end with empty line
|
||||
if [ "$in_note" = true ] && [ -n "$note_content" ]; then
|
||||
echo -e "$note_content"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
local total_notes=$(grep -c "^#[0-9]" "$NOTES_FILE")
|
||||
echo -e "''${GRAY}$(printf '%.0s─' {1..50})''${NC}"
|
||||
echo -e "''${GRAY}Total: ''${BOLD}$total_notes''${NC} ''${GRAY}notes''${NC}"
|
||||
}
|
||||
|
||||
# Function to delete a note
|
||||
delete_note() {
|
||||
local note_num="$1"
|
||||
|
||||
if [ ! -f "$NOTES_FILE" ] || [ ! -s "$NOTES_FILE" ]; then
|
||||
echo -e "''${RED}✗''${NC} No notes found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! echo "$note_num" | grep -q "^[0-9][0-9]*$"; then
|
||||
echo -e "''${RED}✗''${NC} Invalid note number: $note_num"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if note exists
|
||||
if ! grep -q "^#$note_num " "$NOTES_FILE"; then
|
||||
echo -e "''${RED}✗''${NC} Note #$note_num not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create temporary file without the specified note
|
||||
local temp_file=$(mktemp)
|
||||
local skip_lines=false
|
||||
|
||||
while IFS= read -r line; do
|
||||
if echo "$line" | grep -q "^#[0-9][0-9]* "; then
|
||||
local current_num=$(echo "$line" | sed 's/^#\([0-9]*\) .*/\1/')
|
||||
if [ "$current_num" = "$note_num" ]; then
|
||||
skip_lines=true
|
||||
continue
|
||||
else
|
||||
skip_lines=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$skip_lines" = false ]; then
|
||||
echo "$line" >> "$temp_file"
|
||||
elif [ -z "$line" ]; then
|
||||
# Stop skipping when we hit an empty line (end of note)
|
||||
skip_lines=false
|
||||
fi
|
||||
done < "$NOTES_FILE"
|
||||
|
||||
mv "$temp_file" "$NOTES_FILE"
|
||||
echo -e "''${GREEN}✓''${NC} Note #$note_num deleted"
|
||||
}
|
||||
|
||||
# Function to clear all notes
|
||||
clear_notes() {
|
||||
if [ ! -f "$NOTES_FILE" ] || [ ! -s "$NOTES_FILE" ]; then
|
||||
echo -e "''${YELLOW}📝 No notes to clear''${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
local total_notes=$(grep -c "^#[0-9]" "$NOTES_FILE")
|
||||
echo -e "''${YELLOW}⚠''${NC} This will delete all $total_notes notes. Are you sure? ''${GRAY}[y/N]''${NC}"
|
||||
read -r confirmation
|
||||
|
||||
if echo "$confirmation" | grep -qi "^y"; then
|
||||
> "$NOTES_FILE"
|
||||
echo -e "''${GREEN}✓''${NC} All notes cleared"
|
||||
else
|
||||
echo -e "''${BLUE}ℹ''${NC} Operation cancelled"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main script logic
|
||||
main() {
|
||||
# Check if input is being piped
|
||||
if [ ! -t 0 ]; then
|
||||
# Read from stdin (pipe)
|
||||
local piped_content=""
|
||||
while IFS= read -r line; do
|
||||
if [ -z "$piped_content" ]; then
|
||||
piped_content="$line"
|
||||
else
|
||||
piped_content="$piped_content"$'\n'"$line"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$piped_content" ]; then
|
||||
add_note "$piped_content"
|
||||
else
|
||||
echo -e "''${RED}✗''${NC} No input received from pipe"
|
||||
exit 1
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
# Handle command line arguments
|
||||
case "$1" in
|
||||
"")
|
||||
display_notes
|
||||
;;
|
||||
"del")
|
||||
if [ -z "$2" ]; then
|
||||
echo -e "''${RED}✗''${NC} Please specify note number to delete"
|
||||
echo -e "''${GRAY}Usage: ''${CYAN}note del <number>''${NC}"
|
||||
exit 1
|
||||
fi
|
||||
delete_note "$2"
|
||||
;;
|
||||
"clear")
|
||||
clear_notes
|
||||
;;
|
||||
"help"|"--help"|"-h")
|
||||
show_usage
|
||||
;;
|
||||
*)
|
||||
# Everything else is treated as note content
|
||||
add_note "$*"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
''
|
||||
9
modules/home/scripts/nvidia-offload.nix
Normal file
9
modules/home/scripts/nvidia-offload.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "nvidia-offload" ''
|
||||
export __NV_PRIME_RENDER_OFFLOAD=1
|
||||
export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
|
||||
export __GLX_VENDOR_LIBRARY_NAME=nvidia
|
||||
export __VK_LAYER_NV_optimus=NVIDIA_only
|
||||
exec "$@"
|
||||
''
|
||||
8
modules/home/scripts/rofi-launcher.nix
Normal file
8
modules/home/scripts/rofi-launcher.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{ pkgs }:
|
||||
pkgs.writeShellScriptBin "rofi-launcher" ''
|
||||
# check if rofi is already running
|
||||
if pidof rofi > /dev/null; then
|
||||
pkill rofi
|
||||
fi
|
||||
rofi -show drun
|
||||
''
|
||||
5
modules/home/scripts/screenshootin.nix
Normal file
5
modules/home/scripts/screenshootin.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "screenshootin" ''
|
||||
grim -g "$(slurp)" - | swappy -f -
|
||||
''
|
||||
23
modules/home/scripts/squirtle.nix
Normal file
23
modules/home/scripts/squirtle.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "squirtle" ''
|
||||
echo "
|
||||
[38;2;0;0;0m ████████ ██████
|
||||
[38;2;0;0;0m ██[38;2;82;156;154m██[38;2;115;198;243m██████[38;2;0;0;0m████ ██[38;2;115;198;243m██████[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;115;200;243m████████████[38;2;85;137;157m██[38;2;8;0;0m██[38;2;0;0;0m██ ██[38;2;115;198;243m██████[38;2;79;159;151m████[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;115;200;243m████████████[38;2;123;206;235m██[38;2;46;69;78m██[38;2;189;107;37m██[38;2;0;0;0m████ ██[38;2;115;198;243m████[38;2;82;156;154m██[38;2;57;66;65m██[38;2;68;113;108m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m██[38;2;115;198;243m██[38;2;115;200;243m████[38;2;159;208;204m██[38;2;96;162;155m██[38;2;115;198;243m██████[38;2;82;156;154m██[38;2;66;61;66m██[38;2;214;132;38m██[38;2;198;119;38m██[38;2;0;0;0m██[38;2;86;146;154m██[38;2;107;214;243m██[38;2;82;156;154m██[38;2;66;66;66m██[38;2;82;156;154m████[38;2;0;0;0m██
|
||||
[38;2;0;0;0m██[38;2;115;198;243m██[38;2;115;200;243m████[38;2;33;115;105m██[38;2;222;255;254m██[38;2;0;0;0m██[38;2;115;198;243m████[38;2;82;156;154m██[38;2;66;61;66m██[38;2;140;96;52m██[38;2;198;119;38m████[38;2;66;78;66m██[38;2;86;146;154m██[38;2;82;156;154m██[38;2;66;66;66m██[38;2;82;156;154m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m██[38;2;115;198;243m██[38;2;115;200;243m████[38;2;77;144;162m██[38;2;0;4;0m██[38;2;41;8;1m██[38;2;123;214;235m██[38;2;82;156;154m████[38;2;66;66;66m██[38;2;255;255;255m██[38;2;140;82;44m██[38;2;214;140;46m██[38;2;90;103;88m██[38;2;49;111;121m██[38;2;85;159;151m██[38;2;46;80;76m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;115;200;243m████[38;2;115;214;243m██[38;2;0;4;0m██[38;2;68;77;79m██[38;2;96;145;157m██[38;2;82;156;154m██[38;2;66;66;66m██[38;2;192;192;192m██[38;2;255;255;255m██[38;2;140;82;44m██[38;2;214;140;46m██[38;2;173;86;21m██[38;2;90;103;88m██[38;2;85;159;151m██[38;2;8;0;0m██[38;2;0;0;0m
|
||||
[38;2;0;0;0m [38;2;8;0;0m██[38;2;49;77;76m██[38;2;82;156;154m████[38;2;99;132;115m████[38;2;57;74;81m██[38;2;118;129;107m██[38;2;66;66;66m██[38;2;148;198;220m██[38;2;255;255;255m██[38;2;140;82;44m██[38;2;189;103;37m██[38;2;66;66;66m██[38;2;82;156;154m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m [38;2;8;0;0m██[38;2;91;154;152m██[38;2;66;66;66m████[38;2;49;103;113m██[38;2;198;189;118m██[38;2;239;239;159m██[38;2;57;74;81m██[38;2;148;198;220m██[38;2;66;66;66m██[38;2;255;255;255m██[38;2;140;82;44m██[38;2;148;91;47m██[38;2;66;66;66m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ████[38;2;247;231;143m██████[38;2;66;66;66m██[38;2;115;198;243m██████[38;2;66;66;66m██[38;2;140;82;44m██[38;2;189;107;37m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;206;173;94m████[38;2;66;66;66m██[38;2;115;198;243m████[38;2;82;156;154m██[38;2;66;66;66m██[38;2;140;82;44m██[38;2;189;107;37m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;57;115;105m██[38;2;80;85;69m██[38;2;239;239;159m██[38;2;255;231;127m██[38;2;74;66;58m██[38;2;82;156;154m██[38;2;66;66;66m██[38;2;58;69;71m██[38;2;173;198;197m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;57;115;105m██[38;2;80;85;69m██[38;2;0;8;24m██[38;2;195;176;104m████[38;2;66;66;66m████[38;2;115;133;134m██[38;2;58;69;71m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ████ ██[38;2;66;66;66m██[38;2;115;206;243m██[38;2;76;151;151m██[38;2;82;156;154m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██[38;2;76;151;151m██[38;2;57;123;105m██[38;2;82;156;154m██[38;2;0;0;0m██
|
||||
[38;2;0;0;0m ██████ [0m
|
||||
"
|
||||
''
|
||||
6
modules/home/scripts/task-waybar.nix
Normal file
6
modules/home/scripts/task-waybar.nix
Normal file
@@ -0,0 +1,6 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "task-waybar" ''
|
||||
sleep 0.1
|
||||
${pkgs.swaynotificationcenter}/bin/swaync-client -t &
|
||||
''
|
||||
24
modules/home/scripts/wallsetter.nix
Normal file
24
modules/home/scripts/wallsetter.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
pkgs.writeShellScriptBin "wallsetter" ''
|
||||
|
||||
TIMEOUT=720
|
||||
|
||||
for pid in $(pidof -o %PPID -x wallsetter); do
|
||||
kill $pid
|
||||
done
|
||||
|
||||
if ! [ -d ~/Pictures/Wallpapers ]; then notify-send -t 5000 "~/Pictures/Wallpapers does not exist" && exit 1; fi
|
||||
if [ $(ls -1 ~/Pictures/Wallpapers | wc -l) -lt 1 ]; then notify-send -t 9000 "The wallpaper folder is expected to have more than 1 image. Exiting Wallsetter." && exit 1; fi
|
||||
|
||||
while true; do
|
||||
while [ "$WALLPAPER" == "$PREVIOUS" ]; do
|
||||
WALLPAPER=$(find ~/Pictures/Wallpapers -name '*' | awk '!/.git/' | tail -n +2 | shuf -n 1)
|
||||
done
|
||||
|
||||
PREVIOUS=$WALLPAPER
|
||||
|
||||
${pkgs.swww}/bin/swww img "$WALLPAPER" --transition-type random --transition-step 1 --transition-fps 60
|
||||
sleep $TIMEOUT
|
||||
done
|
||||
''
|
||||
47
modules/home/scripts/web-search.nix
Normal file
47
modules/home/scripts/web-search.nix
Normal file
@@ -0,0 +1,47 @@
|
||||
{ pkgs }:
|
||||
pkgs.writeShellScriptBin "web-search" ''
|
||||
# check if rofi is already running
|
||||
if pidof rofi > /dev/null; then
|
||||
pkill rofi
|
||||
fi
|
||||
|
||||
declare -A URLS
|
||||
|
||||
URLS=(
|
||||
["🌎 Search"]="https://search.brave.com/search?q="
|
||||
["❄️ Unstable Packages"]="https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query="
|
||||
["🎞️ YouTube"]="https://www.youtube.com/results?search_query="
|
||||
["🦥 Arch Wiki"]="https://wiki.archlinux.org/title/"
|
||||
["🐃 Gentoo Wiki"]="https://wiki.gentoo.org/index.php?title="
|
||||
)
|
||||
|
||||
# List for rofi
|
||||
gen_list() {
|
||||
for i in "''${!URLS[@]}"
|
||||
do
|
||||
echo "$i"
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
# Pass the list to rofi
|
||||
platform=$( (gen_list) | ${pkgs.rofi-wayland}/bin/rofi -dmenu -config ~/.config/rofi/config-long.rasi )
|
||||
|
||||
if [[ -n "$platform" ]]; then
|
||||
query=$( (echo ) | ${pkgs.rofi-wayland}/bin/rofi -dmenu -config ~/.config/rofi/config-long.rasi )
|
||||
|
||||
if [[ -n "$query" ]]; then
|
||||
url=''${URLS[$platform]}$query
|
||||
xdg-open "$url"
|
||||
else
|
||||
exit
|
||||
fi
|
||||
else
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
|
||||
exit 0
|
||||
''
|
||||
700
modules/home/scripts/zcli.nix
Normal file
700
modules/home/scripts/zcli.nix
Normal file
@@ -0,0 +1,700 @@
|
||||
{ pkgs
|
||||
, profile
|
||||
, backupFiles ? [ ".config/mimeapps.list.backup" ]
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
backupFilesString = pkgs.lib.strings.concatStringsSep " " backupFiles;
|
||||
|
||||
# Create the get-doom script as a dependency
|
||||
get-doom-script = pkgs.writeShellScriptBin "get-doom" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- Icons ---
|
||||
ICON_CHECK="✔"
|
||||
ICON_INFO="ℹ"
|
||||
ICON_ROCKET="🚀"
|
||||
|
||||
# --- Helper Functions ---
|
||||
print_status() {
|
||||
echo
|
||||
echo "--- $ICON_INFO $1 ---"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo "--- $ICON_CHECK $1 ---"
|
||||
}
|
||||
|
||||
print_banner() {
|
||||
echo "==============================="
|
||||
echo " Doom Emacs Installer $ICON_ROCKET"
|
||||
echo "==============================="
|
||||
}
|
||||
|
||||
is_doom_installed() {
|
||||
local dir="$1"
|
||||
[[ -x "$dir/bin/doom" ]] && [[ -f "$dir/core/doom.el" ]]
|
||||
}
|
||||
|
||||
emacsdir_is_empty() {
|
||||
local dir="$1"
|
||||
[[ -d "$dir" ]] && [[ -z "$(ls -A "$dir" 2>/dev/null)" ]]
|
||||
}
|
||||
|
||||
# --- Main Script ---
|
||||
print_banner
|
||||
EMACSDIR="$HOME/.emacs.d"
|
||||
|
||||
if is_doom_installed "$EMACSDIR"; then
|
||||
print_success "Doom Emacs is already installed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -d "$EMACSDIR" ]]; then
|
||||
if emacsdir_is_empty "$EMACSDIR"; then
|
||||
print_status "Found empty $EMACSDIR; proceeding to install Doom Emacs into it..."
|
||||
else
|
||||
echo "Error: Found $EMACSDIR but it does not look like a Doom Emacs installation." >&2
|
||||
echo "Refusing to overwrite a non-empty directory. Move it away and re-run, e.g.:" >&2
|
||||
echo " mv \"$EMACSDIR\" \"$EMACSDIR.bak\"" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
print_status "Cloning Doom Emacs..."
|
||||
${pkgs.git}/bin/git clone --depth 1 https://github.com/doomemacs/doomemacs "$EMACSDIR"
|
||||
print_success "Doom Emacs cloned."
|
||||
|
||||
print_status "Running Doom install..."
|
||||
"$EMACSDIR/bin/doom" install
|
||||
print_success "Doom install complete."
|
||||
|
||||
print_status "Running doom sync..."
|
||||
"$EMACSDIR/bin/doom" sync
|
||||
print_success "Doom sync complete."
|
||||
|
||||
echo
|
||||
print_success "All done! Doom Emacs is ready to use."
|
||||
'';
|
||||
in
|
||||
|
||||
pkgs.writeShellScriptBin "zcli" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- Program info ---
|
||||
#
|
||||
# zcli - NixOS System Management CLI
|
||||
# ==================================
|
||||
#
|
||||
# Purpose: NixOS system management utility for ZaneyOS distribution
|
||||
# Author: Don Williams (ddubs) & Zaney
|
||||
# Start Date: June 7th, 2025
|
||||
# Version: 1.0.2
|
||||
#
|
||||
# Architecture:
|
||||
# - Nix-generated shell script using writeShellScriptBin
|
||||
# - Configuration via Nix parameters (profile, backupFiles)
|
||||
# - Uses 'nh' tool for NixOS operations, 'inxi' for diagnostics
|
||||
# - Git integration for host configuration versioning
|
||||
#
|
||||
# Helper Functions:
|
||||
# verify_hostname() - Validates current hostname against flake.nix host variable
|
||||
# Exits with error if mismatch or missing host directory
|
||||
# detect_gpu_profile() - Parses lspci output to identify GPU hardware
|
||||
# Returns: nvidia/nvidia-laptop/amd/intel/vm/empty
|
||||
# handle_backups() - Removes files listed in BACKUP_FILES array from $HOME
|
||||
# parse_nh_args() - Parses command-line arguments for nh operations
|
||||
# print_help() - Outputs command usage and available operations
|
||||
#
|
||||
# Command Functions:
|
||||
# cleanup - Interactive cleanup of old generations via 'nh clean'
|
||||
# diag - Generate system report using 'inxi --full'
|
||||
# list-gens - Display user/system generations via nix-env and nix profile
|
||||
# rebuild - NixOS rebuild using 'nh os switch'
|
||||
# rebuild-boot - NixOS rebuild for next boot using 'nh os boot'
|
||||
# trim - SSD optimization via 'sudo fstrim -v /'
|
||||
# update - Flake update + rebuild using 'nh os switch --update'
|
||||
# update-host - Modify flake.nix host/profile variables via sed
|
||||
# add-host - Add new host configuration
|
||||
# del-host - Delete host configuration
|
||||
# doom [sub] - Doom Emacs management (install/status/remove/update)
|
||||
#
|
||||
# Variables:
|
||||
# PROJECT - Base directory name (ddubsos/zaneyos)
|
||||
# PROFILE - Hardware profile from Nix parameter
|
||||
# BACKUP_FILES - Array of backup file paths to clean
|
||||
# FLAKE_NIX_PATH - Path to flake.nix for host/profile updates
|
||||
#
|
||||
|
||||
|
||||
# --- Configuration ---
|
||||
PROJECT="zaneyos" #ddubos or zaneyos
|
||||
PROFILE="${profile}"
|
||||
BACKUP_FILES_STR="${backupFilesString}"
|
||||
VERSION="1.0.2"
|
||||
FLAKE_NIX_PATH="$HOME/$PROJECT/flake.nix"
|
||||
|
||||
read -r -a BACKUP_FILES <<< "$BACKUP_FILES_STR"
|
||||
|
||||
# --- Helper Functions ---
|
||||
verify_hostname() {
|
||||
local current_hostname
|
||||
local flake_hostname
|
||||
|
||||
current_hostname="$(hostname)"
|
||||
|
||||
# Extract the host value from flake.nix
|
||||
if [ -f "$FLAKE_NIX_PATH" ]; then
|
||||
flake_hostname=$(${pkgs.gnugrep}/bin/grep -E '^[[:space:]]*host[[:space:]]*=' "$FLAKE_NIX_PATH" | ${pkgs.gnused}/bin/sed 's/.*=[[:space:]]*"\([^"]*\)".*/\1/')
|
||||
|
||||
if [ -z "$flake_hostname" ]; then
|
||||
echo "Error: Could not find 'host' variable in $FLAKE_NIX_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$current_hostname" != "$flake_hostname" ]; then
|
||||
echo "Error: Hostname mismatch!" >&2
|
||||
echo " Current hostname: '$current_hostname'" >&2
|
||||
echo " Flake.nix host: '$flake_hostname'" >&2
|
||||
echo "" >&2
|
||||
echo "Hint: Run 'zcli update-host' to automatically update flake.nix" >&2
|
||||
echo " or manually edit $FLAKE_NIX_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Error: Flake.nix not found at $FLAKE_NIX_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Also check if host folder exists
|
||||
local folder="$HOME/$PROJECT/hosts/$current_hostname"
|
||||
if [ ! -d "$folder" ]; then
|
||||
echo "Error: Matching host not found in $PROJECT, Missing folder: $folder" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
print_help() {
|
||||
echo "ZaneyOS CLI Utility -- version $VERSION"
|
||||
echo ""
|
||||
echo "Usage: zcli [command] [options]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " cleanup - Clean up old system generations. Can specify a number to keep."
|
||||
echo " diag - Create a system diagnostic report."
|
||||
echo " (Filename: homedir/diag.txt)"
|
||||
echo " list-gens - List user and system generations."
|
||||
echo " rebuild - Rebuild the NixOS system configuration."
|
||||
echo " rebuild-boot - Rebuild and set as boot default (activates on next restart)."
|
||||
echo " trim - Trim filesystems to improve SSD performance."
|
||||
echo " update - Update the flake and rebuild the system."
|
||||
echo " update-host - Auto set host and profile in flake.nix."
|
||||
echo " (Opt: zcli update-host [hostname] [profile])"
|
||||
echo ""
|
||||
echo "Options for rebuild, rebuild-boot, and update commands:"
|
||||
echo " --dry, -n - Show what would be done without doing it"
|
||||
echo " --ask, -a - Ask for confirmation before proceeding"
|
||||
echo " --cores N - Limit build to N cores (useful for VMs)"
|
||||
echo " --verbose, -v - Show verbose output"
|
||||
echo " --no-nom - Don't use nix-output-monitor"
|
||||
echo ""
|
||||
echo "Doom Emacs:"
|
||||
echo " doom install - Install Doom Emacs using get-doom script."
|
||||
echo " doom status - Check if Doom Emacs is installed."
|
||||
echo " doom remove - Remove Doom Emacs installation."
|
||||
echo " doom update - Update Doom Emacs (runs doom sync)."
|
||||
echo ""
|
||||
echo " help - Show this help message."
|
||||
}
|
||||
|
||||
handle_backups() {
|
||||
if [ ''${#BACKUP_FILES[@]} -eq 0 ]; then
|
||||
echo "No backup files configured to check."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Checking for backup files to remove..."
|
||||
for file_path in "''${BACKUP_FILES[@]}"; do
|
||||
full_path="$HOME/$file_path"
|
||||
if [ -f "$full_path" ]; then
|
||||
echo "Removing stale backup file: $full_path"
|
||||
rm "$full_path"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
detect_gpu_profile() {
|
||||
local detected_profile=""
|
||||
local has_nvidia=false
|
||||
local has_intel=false
|
||||
local has_amd=false
|
||||
local has_vm=false
|
||||
|
||||
if ${pkgs.pciutils}/bin/lspci &> /dev/null; then # Check if lspci is available
|
||||
if ${pkgs.pciutils}/bin/lspci | ${pkgs.gnugrep}/bin/grep -qi 'vga\|3d'; then
|
||||
while read -r line; do
|
||||
if echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'nvidia'; then
|
||||
has_nvidia=true
|
||||
elif echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'amd'; then
|
||||
has_amd=true
|
||||
elif echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'intel'; then
|
||||
has_intel=true
|
||||
elif echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'virtio\|vmware'; then
|
||||
has_vm=true
|
||||
fi
|
||||
done < <(${pkgs.pciutils}/bin/lspci | ${pkgs.gnugrep}/bin/grep -i 'vga\|3d')
|
||||
|
||||
if "$has_vm"; then
|
||||
detected_profile="vm"
|
||||
elif "$has_nvidia" && "$has_intel"; then
|
||||
detected_profile="nvidia-laptop"
|
||||
elif "$has_nvidia"; then
|
||||
detected_profile="nvidia"
|
||||
elif "$has_amd"; then
|
||||
detected_profile="amd"
|
||||
elif "$has_intel"; then
|
||||
detected_profile="intel"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Warning: lspci command not found. Cannot auto-detect GPU profile." >&2
|
||||
fi
|
||||
echo "$detected_profile" # Return the detected profile
|
||||
}
|
||||
|
||||
# --- Helper function to parse additional arguments ---
|
||||
parse_nh_args() {
|
||||
local args_string=""
|
||||
local options_selected=()
|
||||
shift # Remove the main command (rebuild, rebuild-boot, update)
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--dry|-n)
|
||||
args_string="$args_string --dry"
|
||||
options_selected+=("dry run mode (showing what would be done)")
|
||||
shift
|
||||
;;
|
||||
--ask|-a)
|
||||
args_string="$args_string --ask"
|
||||
options_selected+=("confirmation prompts enabled")
|
||||
shift
|
||||
;;
|
||||
--cores)
|
||||
if [[ -n $2 && $2 =~ ^[0-9]+$ ]]; then
|
||||
args_string="$args_string -- --cores $2"
|
||||
options_selected+=("limited to $2 CPU cores")
|
||||
shift 2
|
||||
else
|
||||
echo "Error: --cores requires a numeric argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--verbose|-v)
|
||||
args_string="$args_string --verbose"
|
||||
options_selected+=("verbose output enabled")
|
||||
shift
|
||||
;;
|
||||
--no-nom)
|
||||
args_string="$args_string --no-nom"
|
||||
options_selected+=("nix-output-monitor disabled")
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
args_string="$args_string -- $*"
|
||||
options_selected+=("additional arguments: $*")
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "Warning: Unknown flag '$1' - passing through to nh" >&2
|
||||
args_string="$args_string $1"
|
||||
options_selected+=("unknown flag '$1' passed through")
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unexpected argument '$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Print friendly confirmation of selected options to stderr so it doesn't interfere with return value
|
||||
if [[ ''${#options_selected[@]} -gt 0 ]]; then
|
||||
echo "Options selected:" >&2
|
||||
for option in "''${options_selected[@]}"; do
|
||||
echo " ✓ $option" >&2
|
||||
done
|
||||
echo >&2
|
||||
fi
|
||||
|
||||
# Return only the args string
|
||||
echo "$args_string"
|
||||
}
|
||||
|
||||
# --- Main Logic ---
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "Error: No command provided." >&2
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
cleanup)
|
||||
echo "Warning! This will remove old generations of your system."
|
||||
read -p "How many generations to keep (default: all)? " keep_count
|
||||
|
||||
if [ -z "$keep_count" ]; then
|
||||
read -p "This will remove all but the current generation. Continue (y/N)? " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
${pkgs.nh}/bin/nh clean all -v
|
||||
else
|
||||
echo "Cleanup cancelled."
|
||||
fi
|
||||
else
|
||||
read -p "This will keep the last $keep_count generations. Continue (y/N)? " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
${pkgs.nh}/bin/nh clean all -k "$keep_count" -v
|
||||
else
|
||||
echo "Cleanup cancelled."
|
||||
fi
|
||||
fi
|
||||
|
||||
LOG_DIR="$HOME/zcli-cleanup-logs"
|
||||
mkdir -p "$LOG_DIR"
|
||||
LOG_FILE="$LOG_DIR/zcli-cleanup-$(${pkgs.coreutils}/bin/date +%Y-%m-%d_%H-%M-%S).log"
|
||||
echo "Cleaning up old log files..." >> "$LOG_FILE"
|
||||
${pkgs.findutils}/bin/find "$LOG_DIR" -type f -mtime +3 -name "*.log" -delete >> "$LOG_FILE" 2>&1
|
||||
echo "Cleanup process logged to $LOG_FILE"
|
||||
;;
|
||||
diag)
|
||||
echo "Generating system diagnostic report..."
|
||||
${pkgs.inxi}/bin/inxi --full > "$HOME/diag.txt"
|
||||
echo "Diagnostic report saved to $HOME/diag.txt"
|
||||
;;
|
||||
help)
|
||||
print_help
|
||||
;;
|
||||
list-gens)
|
||||
echo "--- User Generations ---"
|
||||
${pkgs.nix}/bin/nix-env --list-generations | ${pkgs.coreutils}/bin/cat || echo "Could not list user generations."
|
||||
echo ""
|
||||
echo "--- System Generations ---"
|
||||
${pkgs.nix}/bin/nix profile history --profile /nix/var/nix/profiles/system | ${pkgs.coreutils}/bin/cat || echo "Could not list system generations."
|
||||
;;
|
||||
rebuild)
|
||||
verify_hostname
|
||||
handle_backups
|
||||
|
||||
# Parse additional arguments
|
||||
extra_args=$(parse_nh_args "$@")
|
||||
|
||||
echo "Starting NixOS rebuild for host: $(${pkgs.nettools}/bin/hostname)"
|
||||
if eval "${pkgs.nh}/bin/nh os switch --hostname '$PROFILE' $extra_args"; then
|
||||
echo "Rebuild finished successfully"
|
||||
else
|
||||
echo "Rebuild Failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
rebuild-boot)
|
||||
verify_hostname
|
||||
handle_backups
|
||||
|
||||
# Parse additional arguments
|
||||
extra_args=$(parse_nh_args "$@")
|
||||
|
||||
echo "Starting NixOS rebuild (boot) for host: $(${pkgs.nettools}/bin/hostname)"
|
||||
echo "Note: Configuration will be activated on next reboot"
|
||||
if eval "${pkgs.nh}/bin/nh os boot --hostname '$PROFILE' $extra_args"; then
|
||||
echo "Rebuild-boot finished successfully"
|
||||
echo "New configuration set as boot default - restart to activate"
|
||||
else
|
||||
echo "Rebuild-boot Failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
trim)
|
||||
echo "Running 'sudo fstrim -v /' may take a few minutes and impact system performance."
|
||||
read -p "Enter (y/Y) to run now or enter to exit (y/N): " -n 1 -r
|
||||
echo # move to a new line
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Running fstrim..."
|
||||
sudo ${pkgs.util-linux}/bin/fstrim -v /
|
||||
echo "fstrim complete."
|
||||
else
|
||||
echo "Trim operation cancelled."
|
||||
fi
|
||||
;;
|
||||
update)
|
||||
verify_hostname
|
||||
handle_backups
|
||||
|
||||
# Parse additional arguments
|
||||
extra_args=$(parse_nh_args "$@")
|
||||
|
||||
echo "Updating flake and rebuilding system for host: $(${pkgs.nettools}/bin/hostname)"
|
||||
if eval "${pkgs.nh}/bin/nh os switch --hostname '$PROFILE' --update $extra_args"; then
|
||||
echo "Update and rebuild finished successfully"
|
||||
else
|
||||
echo "Update and rebuild Failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
update-host)
|
||||
target_hostname=""
|
||||
target_profile=""
|
||||
|
||||
if [ "$#" -eq 3 ]; then # zcli update-host <hostname> <profile>
|
||||
target_hostname="$2"
|
||||
target_profile="$3"
|
||||
elif [ "$#" -eq 1 ]; then # zcli update-host (auto-detect)
|
||||
echo "Attempting to auto-detect hostname and GPU profile..."
|
||||
target_hostname=$(${pkgs.nettools}/bin/hostname)
|
||||
target_profile=$(detect_gpu_profile)
|
||||
|
||||
if [ -z "$target_profile" ]; then
|
||||
echo "Error: Could not auto-detect a specific GPU profile. Please provide it manually." >&2
|
||||
echo "Usage: zcli update-host [hostname] [profile]" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Auto-detected Hostname: $target_hostname"
|
||||
echo "Auto-detected Profile: $target_profile"
|
||||
else
|
||||
echo "Error: Invalid number of arguments for 'update-host'." >&2
|
||||
echo "Usage: zcli update-host [hostname] [profile]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating $FLAKE_NIX_PATH..."
|
||||
|
||||
# Update host
|
||||
if ${pkgs.gnused}/bin/sed -i "s/^[[:space:]]*host[[:space:]]*=[[:space:]]*\".*\"/ host = \"$target_hostname\"/" "$FLAKE_NIX_PATH"; then
|
||||
echo "Successfully updated host to: $target_hostname"
|
||||
else
|
||||
echo "Error: Failed to update host in $FLAKE_NIX_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update profile
|
||||
if ${pkgs.gnused}/bin/sed -i "s/^[[:space:]]*profile[[:space:]]*=[[:space:]]*\".*\"/ profile = \"$target_profile\"/" "$FLAKE_NIX_PATH"; then
|
||||
echo "Successfully updated profile to: $target_profile"
|
||||
else
|
||||
echo "Error: Failed to update profile in $FLAKE_NIX_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Flake.nix updated successfully!"
|
||||
;;
|
||||
add-host)
|
||||
hostname=""
|
||||
profile_arg=""
|
||||
|
||||
if [ "$#" -ge 2 ]; then
|
||||
hostname="$2"
|
||||
fi
|
||||
if [ "$#" -eq 3 ]; then
|
||||
profile_arg="$3"
|
||||
fi
|
||||
|
||||
if [ -z "$hostname" ]; then
|
||||
read -p "Enter the new hostname: " hostname
|
||||
fi
|
||||
|
||||
if [ -d "$HOME/$PROJECT/hosts/$hostname" ]; then
|
||||
echo "Error: Host '$hostname' already exists." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Copying default host configuration..."
|
||||
${pkgs.coreutils}/bin/cp -r "$HOME/$PROJECT/hosts/default" "$HOME/$PROJECT/hosts/$hostname"
|
||||
|
||||
detected_profile=""
|
||||
if [[ -n "$profile_arg" && "$profile_arg" =~ ^(intel|amd|nvidia|nvidia-hybrid|vm)$ ]]; then
|
||||
detected_profile="$profile_arg"
|
||||
else
|
||||
echo "Detecting GPU profile..."
|
||||
detected_profile=$(detect_gpu_profile)
|
||||
echo "Detected GPU profile: $detected_profile"
|
||||
read -p "Is this correct? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||
read -p "Enter the correct profile (intel, amd, nvidia, nvidia-hybrid, vm): " new_profile
|
||||
while [[ ! "$new_profile" =~ ^(intel|amd|nvidia|nvidia-hybrid|vm)$ ]]; do
|
||||
echo "Invalid profile. Please enter one of the following: intel, amd, nvidia, nvidia-hybrid, vm"
|
||||
read -p "Enter the correct profile: " new_profile
|
||||
done
|
||||
detected_profile=$new_profile
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Setting profile to '$detected_profile'..."
|
||||
${pkgs.gnused}/bin/sed -i "s/profile = .*/profile = \"$detected_profile\";/" "$HOME/$PROJECT/hosts/$hostname/default.nix"
|
||||
|
||||
read -p "Generate new hardware.nix? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Generating hardware.nix..."
|
||||
sudo nixos-generate-config --show-hardware-config > "$HOME/$PROJECT/hosts/$hostname/hardware.nix"
|
||||
echo "hardware.nix generated."
|
||||
fi
|
||||
|
||||
echo "Adding new host to git..."
|
||||
${pkgs.git}/bin/git -C "$HOME/$PROJECT" add .
|
||||
echo "hostname: $hostname added"
|
||||
;;
|
||||
del-host)
|
||||
hostname=""
|
||||
if [ "$#" -eq 2 ]; then
|
||||
hostname="$2"
|
||||
else
|
||||
read -p "Enter the hostname to delete: " hostname
|
||||
fi
|
||||
|
||||
if [ ! -d "$HOME/$PROJECT/hosts/$hostname" ]; then
|
||||
echo "Error: Host '$hostname' does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
read -p "Are you sure you want to delete the host '$hostname'? (y/N) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Deleting host '$hostname'..."
|
||||
${pkgs.coreutils}/bin/rm -rf "$HOME/$PROJECT/hosts/$hostname"
|
||||
${pkgs.git}/bin/git -C "$HOME/$PROJECT" add .
|
||||
echo "hostname: $hostname removed"
|
||||
else
|
||||
echo "Deletion cancelled."
|
||||
fi
|
||||
;;
|
||||
doom)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "Error: doom command requires a subcommand." >&2
|
||||
echo "Usage: zcli doom [install|status|remove|update]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure we're acting on a valid host and we can locate variables.nix
|
||||
verify_hostname
|
||||
current_hostname="$(hostname)"
|
||||
host_vars_file="$HOME/$PROJECT/hosts/$current_hostname/variables.nix"
|
||||
|
||||
if [ ! -f "$host_vars_file" ]; then
|
||||
echo "Error: Host variables file not found: $host_vars_file" >&2
|
||||
echo "Please ensure your host folder exists and contains variables.nix." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
is_doom_enabled() {
|
||||
# Return 0 if doomEmacsEnable = true; appears (ignoring leading spaces)
|
||||
${pkgs.gnugrep}/bin/grep -Eq '^[[:space:]]*doomEmacsEnable[[:space:]]*=[[:space:]]*true[[:space:]]*;' "$host_vars_file"
|
||||
}
|
||||
|
||||
ensure_doom_enabled() {
|
||||
# If the variable is present but false, flip it; if missing, append it
|
||||
if ${pkgs.gnugrep}/bin/grep -Eq '^[[:space:]]*doomEmacsEnable[[:space:]]*=' "$host_vars_file"; then
|
||||
${pkgs.gnused}/bin/sed -i 's/^[[:space:]]*doomEmacsEnable[[:space:]]*=.*/ doomEmacsEnable = true;/' "$host_vars_file"
|
||||
else
|
||||
echo "" >> "$host_vars_file"
|
||||
echo " # Enabled by zcli doom on $(date)" >> "$host_vars_file"
|
||||
echo " doomEmacsEnable = true;" >> "$host_vars_file"
|
||||
fi
|
||||
}
|
||||
|
||||
doom_subcommand="$2"
|
||||
case "$doom_subcommand" in
|
||||
install)
|
||||
if ! is_doom_enabled; then
|
||||
echo "✗ Doom Emacs is disabled for host '$current_hostname' (doomEmacsEnable = false)." >&2
|
||||
echo "To enable, set doomEmacsEnable = true; in:" >&2
|
||||
echo " $host_vars_file" >&2
|
||||
echo "and rebuild your system before installing Doom." >&2
|
||||
echo
|
||||
read -p "Enable Doom for this host now and rebuild? (y/N) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Enabling Doom Emacs in $host_vars_file..."
|
||||
ensure_doom_enabled
|
||||
echo "Rebuilding system so user modules are applied..."
|
||||
if ${pkgs.nh}/bin/nh os switch --hostname "$PROFILE"; then
|
||||
echo "Rebuild complete. Proceeding with Doom installation."
|
||||
else
|
||||
echo "Error: Rebuild failed. Please fix the build and re-run 'zcli doom install'." >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Aborting. Please enable doomEmacsEnable and rebuild before installing." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Installing Doom Emacs..."
|
||||
${get-doom-script}/bin/get-doom
|
||||
;;
|
||||
status)
|
||||
if [ -x "$HOME/.emacs.d/bin/doom" ] && [ -f "$HOME/.emacs.d/core/doom.el" ]; then
|
||||
echo "✔ Doom Emacs appears installed at $HOME/.emacs.d"
|
||||
if [ -f "$HOME/.doom.d/init.el" ]; then
|
||||
echo " • User config found: $HOME/.doom.d/init.el"
|
||||
else
|
||||
echo " • Warning: User config (~/.doom.d) not found"
|
||||
fi
|
||||
echo "Version information:"
|
||||
"$HOME/.emacs.d/bin/doom" version 2>/dev/null || echo "Could not get version information"
|
||||
else
|
||||
if [ -d "$HOME/.emacs.d" ]; then
|
||||
if [ -z "$(ls -A "$HOME/.emacs.d" 2>/dev/null)" ]; then
|
||||
echo "✗ Found empty ~/.emacs.d (not a valid Doom installation)"
|
||||
else
|
||||
echo "✗ ~/.emacs.d exists but Doom was not detected"
|
||||
fi
|
||||
else
|
||||
echo "✗ Doom Emacs is not installed"
|
||||
fi
|
||||
echo "Run 'zcli doom install' to install it"
|
||||
fi
|
||||
;;
|
||||
remove)
|
||||
if [ ! -d "$HOME/.emacs.d" ]; then
|
||||
echo "Doom Emacs is not installed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Warning: This will completely remove Doom Emacs and all your configuration!"
|
||||
read -p "Are you sure you want to continue? (y/N) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Removing Doom Emacs..."
|
||||
${pkgs.coreutils}/bin/rm -rf "$HOME/.emacs.d"
|
||||
echo "✔ Doom Emacs has been removed"
|
||||
else
|
||||
echo "Removal cancelled"
|
||||
fi
|
||||
;;
|
||||
update)
|
||||
if [ ! -x "$HOME/.emacs.d/bin/doom" ] || [ ! -f "$HOME/.emacs.d/core/doom.el" ]; then
|
||||
echo "Error: Doom Emacs is not installed correctly. Run 'zcli doom install' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating Doom Emacs..."
|
||||
"$HOME/.emacs.d/bin/doom" sync
|
||||
echo "✔ Doom Emacs update complete"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid doom subcommand '$doom_subcommand'" >&2
|
||||
echo "Usage: zcli doom [install|status|remove|update]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid command '$1'" >&2
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
''
|
||||
Reference in New Issue
Block a user