forked from Shinonome/alt-illogical-impulse
Initial clean flake structure - Phase 3 complete
This commit is contained in:
+33
@@ -0,0 +1,33 @@
|
|||||||
|
# Nix build results
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
|
||||||
|
# Nix development
|
||||||
|
.direnv/
|
||||||
|
.envrc
|
||||||
|
|
||||||
|
# Cache directories
|
||||||
|
.cache/
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Editor files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.bak
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
# External repositories (for reference only)
|
||||||
|
dots-hyprland/
|
||||||
|
dots-hyprland-wiki/
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
# dots-hyprland for NixOS
|
||||||
|
|
||||||
|
A NixOS adaptation of [end-4's dots-hyprland](https://github.com/end-4/dots-hyprland) desktop environment, bringing the beautiful "illogical-impulse" style to NixOS with full declarative configuration.
|
||||||
|
|
||||||
|
## 🎯 Project Status: Phase 3 Complete ✅
|
||||||
|
|
||||||
|
**Current Achievement: Core Desktop Environment Functional**
|
||||||
|
|
||||||
|
- ✅ **Quickshell Integration** - Official flake support resolved
|
||||||
|
- ✅ **Hyprland Configuration** - Complete window manager setup with Material You theming
|
||||||
|
- ✅ **Essential Applications** - foot terminal, fuzzel launcher, nautilus file manager
|
||||||
|
- ✅ **Home Manager Integration** - Fully declarative configuration
|
||||||
|
- ✅ **Package Management** - All dependencies properly integrated
|
||||||
|
- ✅ **Development Environment** - Ready for Phase 4 advanced features
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- NixOS with flakes enabled
|
||||||
|
- Home Manager (optional but recommended)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone <repository-url>
|
||||||
|
cd dots-hyprland-nixos
|
||||||
|
|
||||||
|
# Build and activate Home Manager configuration
|
||||||
|
nix build .#homeConfigurations.example.activationPackage
|
||||||
|
./result/activate
|
||||||
|
|
||||||
|
# Or use with your existing Home Manager setup
|
||||||
|
# Add to your flake inputs:
|
||||||
|
# dots-hyprland.url = "github:your-org/dots-hyprland-nixos";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enter development environment
|
||||||
|
nix develop
|
||||||
|
|
||||||
|
# Available development tools:
|
||||||
|
# - update-flake: Manage flake inputs and GitHub synchronization
|
||||||
|
# - compare-modes: Compare declarative vs writable configuration modes
|
||||||
|
# - test-python-env: Test Python virtual environment setup
|
||||||
|
# - test-quickshell: Test quickshell configuration
|
||||||
|
|
||||||
|
# Flake management examples:
|
||||||
|
update-flake status # Show current flake status
|
||||||
|
update-flake update # Update all flake inputs
|
||||||
|
update-flake update-source # Update only dots-hyprland source
|
||||||
|
update-flake verify # Test that configurations build
|
||||||
|
update-flake help # Show all available options
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 Features
|
||||||
|
|
||||||
|
### ✅ Implemented (Phase 3)
|
||||||
|
- **Hyprland Window Manager** - Complete configuration with Material You theming
|
||||||
|
- **foot Terminal** - Tokyo Night color scheme, JetBrainsMono Nerd Font
|
||||||
|
- **fuzzel Launcher** - Material You themed application launcher
|
||||||
|
- **Essential Keybinds** - All core window management and application shortcuts
|
||||||
|
- **Package Integration** - Declarative package management through Nix
|
||||||
|
- **Home Manager Support** - Full integration with Home Manager modules
|
||||||
|
|
||||||
|
### 🔄 In Progress (Phase 4)
|
||||||
|
- **AI Integration** - Gemini and Ollama support
|
||||||
|
- **Advanced Widgets** - Overview with live previews, sidebars
|
||||||
|
- **Comprehensive Theming** - Dynamic Material You color generation
|
||||||
|
- **Quality of Life** - Screen corners, session management, cheatsheet
|
||||||
|
|
||||||
|
### 📅 Planned (Future Phases)
|
||||||
|
- **NixOS System Integration** - Full system-level configuration
|
||||||
|
- **Testing & Validation** - Comprehensive test suite
|
||||||
|
- **Community & Maintenance** - Documentation, contribution guidelines
|
||||||
|
|
||||||
|
## 🔄 Flake Management
|
||||||
|
|
||||||
|
The project includes a comprehensive flake management utility for keeping your configuration synchronized with GitHub:
|
||||||
|
|
||||||
|
### Quick Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current status
|
||||||
|
update-flake status
|
||||||
|
|
||||||
|
# Update all flake inputs
|
||||||
|
update-flake update
|
||||||
|
|
||||||
|
# Update only dots-hyprland source
|
||||||
|
update-flake update-source
|
||||||
|
|
||||||
|
# Verify configurations build
|
||||||
|
update-flake verify
|
||||||
|
|
||||||
|
# Update and verify in one command
|
||||||
|
update-flake update --auto-verify
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pin to a specific commit
|
||||||
|
update-flake pin abc123def
|
||||||
|
|
||||||
|
# Switch to tracking a different branch
|
||||||
|
update-flake branch main
|
||||||
|
|
||||||
|
# Dry run to see what would happen
|
||||||
|
update-flake update --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
The utility automatically detects synchronization status and provides clear feedback about your flake's relationship to the GitHub repository.
|
||||||
|
|
||||||
|
## 🎨 Configuration
|
||||||
|
|
||||||
|
### Basic Configuration
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
programs.dots-hyprland = {
|
||||||
|
enable = true;
|
||||||
|
style = "illogical-impulse";
|
||||||
|
|
||||||
|
components = {
|
||||||
|
hyprland = true;
|
||||||
|
quickshell = true;
|
||||||
|
theming = false; # Phase 4
|
||||||
|
ai = false; # Phase 4
|
||||||
|
audio = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
features = {
|
||||||
|
overview = true;
|
||||||
|
sidebar = false; # Phase 4
|
||||||
|
notifications = true;
|
||||||
|
mediaControls = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
keybinds = {
|
||||||
|
modifier = "SUPER";
|
||||||
|
terminal = "foot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keybinds
|
||||||
|
|
||||||
|
| Key Combination | Action |
|
||||||
|
|----------------|--------|
|
||||||
|
| `SUPER + Return` | Open terminal |
|
||||||
|
| `SUPER + Space` | Open application launcher |
|
||||||
|
| `SUPER + Q` | Close window |
|
||||||
|
| `SUPER + E` | Open file manager |
|
||||||
|
| `SUPER + F` | Toggle fullscreen |
|
||||||
|
| `SUPER + V` | Toggle floating |
|
||||||
|
| `SUPER + 1-0` | Switch to workspace |
|
||||||
|
| `SUPER + Shift + 1-0` | Move window to workspace |
|
||||||
|
|
||||||
|
## 🏗️ Architecture
|
||||||
|
|
||||||
|
### Module Structure
|
||||||
|
```
|
||||||
|
modules/
|
||||||
|
├── home-manager.nix # Main Home Manager integration
|
||||||
|
├── nixos.nix # NixOS system integration
|
||||||
|
└── components/
|
||||||
|
├── packages.nix # Package management
|
||||||
|
├── hyprland.nix # Hyprland configuration
|
||||||
|
└── applications.nix # Application configurations
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flake Structure
|
||||||
|
```
|
||||||
|
├── flake.nix # Main flake with inputs/outputs
|
||||||
|
├── modules/ # NixOS/Home Manager modules
|
||||||
|
├── packages/ # Custom package derivations
|
||||||
|
├── configs/ # Configuration templates
|
||||||
|
└── assets/ # Static assets (icons, themes)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 Gameplan Progress
|
||||||
|
|
||||||
|
This project follows a systematic 7-phase development approach:
|
||||||
|
|
||||||
|
- [x] **Phase 1: Dependency Analysis** - All dependencies mapped to NixOS
|
||||||
|
- [x] **Phase 2: Module Structure** - Complete flake and module architecture
|
||||||
|
- [x] **Phase 3: Core Implementation** - ✅ **CURRENT MILESTONE**
|
||||||
|
- [ ] **Phase 4: Advanced Features** - AI, advanced widgets, comprehensive theming
|
||||||
|
- [ ] **Phase 5: NixOS Adaptations** - Full NixOS integration patterns
|
||||||
|
- [ ] **Phase 6: Testing & Validation** - Comprehensive testing suite
|
||||||
|
- [ ] **Phase 7: Community & Maintenance** - Documentation, contribution guidelines
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
This project is in active development. Contributions are welcome!
|
||||||
|
|
||||||
|
### Development Setup
|
||||||
|
1. Clone the repository
|
||||||
|
2. Run `nix develop` to enter the development environment
|
||||||
|
3. Make your changes
|
||||||
|
4. Test with `nix build .#homeConfigurations.example.activationPackage`
|
||||||
|
5. Submit a pull request
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
This project is licensed under the GPL-3.0 License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## 🙏 Acknowledgments
|
||||||
|
|
||||||
|
- **end-4** - Original dots-hyprland creator
|
||||||
|
- **outfoxxed** - Quickshell developer (official Nix flake support was crucial!)
|
||||||
|
- **NixOS Community** - For the amazing ecosystem
|
||||||
|
- **Hyprland Team** - For the fantastic window manager
|
||||||
|
|
||||||
|
## 📞 Support
|
||||||
|
|
||||||
|
- **Issues**: Report bugs and request features via GitHub Issues
|
||||||
|
- **Discussions**: General questions and ideas via GitHub Discussions
|
||||||
|
- **Community**: Join the NixOS and Hyprland communities for broader support
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status**: Phase 3 Complete - Core desktop environment functional and ready for advanced features! 🚀
|
||||||
Generated
+100
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"dots-hyprland": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754709786,
|
||||||
|
"narHash": "sha256-NDEupEt2F2yMCI2cWNy1tE8FsuLwW4NGvgJierzMPwQ=",
|
||||||
|
"owner": "celesrenata",
|
||||||
|
"repo": "dots-hyprland",
|
||||||
|
"rev": "65b10e45fdc082f6f1b7a6135393f870510e2f51",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "celesrenata",
|
||||||
|
"ref": "installer-replication",
|
||||||
|
"repo": "dots-hyprland",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"home-manager": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754613544,
|
||||||
|
"narHash": "sha256-ueR1mGX4I4DWfDRRxxMphbKDNisDeMPMusN72VV1+cc=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"rev": "cc2fa2331aebf9661d22bb507d362b39852ac73f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754498491,
|
||||||
|
"narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "c2ae88e026f9525daf89587f3cbee584b92b6134",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1749285348,
|
||||||
|
"narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "3e3afe5174c561dee0df6f2c2b2236990146329f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quickshell": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1753595452,
|
||||||
|
"narHash": "sha256-vqkSDvh7hWhPvNjMjEDV4KbSCv2jyl2Arh73ZXe274k=",
|
||||||
|
"owner": "outfoxxed",
|
||||||
|
"repo": "quickshell",
|
||||||
|
"rev": "a5431dd02dc23d9ef1680e67777fed00fe5f7cda",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "outfoxxed",
|
||||||
|
"repo": "quickshell",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"dots-hyprland": "dots-hyprland",
|
||||||
|
"home-manager": "home-manager",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"quickshell": "quickshell"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,452 @@
|
|||||||
|
{
|
||||||
|
description = "NixOS adaptation of end-4's dots-hyprland using installer replication";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
home-manager = {
|
||||||
|
url = "github:nix-community/home-manager";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Official quickshell flake (our breakthrough discovery!)
|
||||||
|
quickshell.url = "github:outfoxxed/quickshell";
|
||||||
|
|
||||||
|
# Original dots-hyprland source from GitHub - tracks installer-replication branch
|
||||||
|
dots-hyprland = {
|
||||||
|
url = "github:celesrenata/dots-hyprland/installer-replication";
|
||||||
|
flake = false; # Use as source only, don't build
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, home-manager, quickshell, dots-hyprland, ... }:
|
||||||
|
let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [ self.overlays.default ];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Package overlays
|
||||||
|
overlays.default = final: prev: {
|
||||||
|
# Make quickshell available from official flake
|
||||||
|
quickshell = quickshell.packages.${system}.default;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Packages
|
||||||
|
packages.${system} = {
|
||||||
|
# Flake management utilities
|
||||||
|
update-flake = pkgs.writeShellScriptBin "update-flake" ''
|
||||||
|
# dots-hyprland Flake Update Utility
|
||||||
|
# Manages flake input updates and GitHub synchronization
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "''${GREEN}[update-flake]''${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo -e "''${YELLOW}[update-flake]''${NC} WARNING: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "''${RED}[update-flake]''${NC} ERROR: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "''${BLUE}[update-flake]''${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
header() {
|
||||||
|
echo -e "''${CYAN}=== $1 ===''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat << EOF
|
||||||
|
dots-hyprland Flake Update Utility
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
update-flake [OPTIONS] [COMMAND]
|
||||||
|
|
||||||
|
COMMANDS:
|
||||||
|
update Update all flake inputs (default)
|
||||||
|
update-source Update only dots-hyprland source input
|
||||||
|
pin <commit> Pin dots-hyprland to specific commit
|
||||||
|
branch <name> Switch to tracking a specific branch
|
||||||
|
status Show current flake input status
|
||||||
|
verify Verify flake builds after update
|
||||||
|
help Show this help message
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--auto-verify Automatically verify builds after update
|
||||||
|
--dry-run Show what would be done without executing
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
update-flake # Update all inputs
|
||||||
|
update-flake update-source # Update only dots-hyprland source
|
||||||
|
update-flake pin abc123def # Pin to specific commit
|
||||||
|
update-flake branch main # Track main branch
|
||||||
|
update-flake status # Show current status
|
||||||
|
update-flake update --auto-verify # Update and verify builds
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
get_current_commit() {
|
||||||
|
git rev-parse HEAD
|
||||||
|
}
|
||||||
|
|
||||||
|
get_current_branch() {
|
||||||
|
git branch --show-current
|
||||||
|
}
|
||||||
|
|
||||||
|
get_flake_source_info() {
|
||||||
|
if [[ -f flake.lock ]]; then
|
||||||
|
local rev=$(${pkgs.jq}/bin/jq -r '.nodes."dots-hyprland".locked.rev // "unknown"' flake.lock)
|
||||||
|
local ref=$(${pkgs.jq}/bin/jq -r '.nodes."dots-hyprland".original.ref // .nodes."dots-hyprland".original.rev // "unknown"' flake.lock)
|
||||||
|
echo "$rev|$ref"
|
||||||
|
else
|
||||||
|
echo "unknown|unknown"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
show_status() {
|
||||||
|
header "Flake Status"
|
||||||
|
|
||||||
|
local current_commit=$(get_current_commit)
|
||||||
|
local current_branch=$(get_current_branch)
|
||||||
|
local flake_info=$(get_flake_source_info)
|
||||||
|
local flake_rev=$(echo "$flake_info" | cut -d'|' -f1)
|
||||||
|
local flake_ref=$(echo "$flake_info" | cut -d'|' -f2)
|
||||||
|
|
||||||
|
echo "📁 Project Directory: $(pwd)"
|
||||||
|
echo "🌿 Current Branch: $current_branch"
|
||||||
|
echo "📝 Current Commit: ''${current_commit:0:12}..."
|
||||||
|
echo "🔒 Flake Locked To: ''${flake_rev:0:12}..."
|
||||||
|
echo "🎯 Flake Tracking: $flake_ref"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ "$flake_rev" == "$current_commit" ]]; then
|
||||||
|
log "✅ Flake is synchronized with current commit"
|
||||||
|
elif [[ "$flake_ref" == "$current_branch" ]]; then
|
||||||
|
warn "🔄 Flake tracks branch but may need update"
|
||||||
|
info "Run 'update-flake update' to sync with latest commits"
|
||||||
|
else
|
||||||
|
warn "⚠️ Flake is out of sync"
|
||||||
|
info "Flake: $flake_ref (''${flake_rev:0:12}...)"
|
||||||
|
info "Local: $current_branch (''${current_commit:0:12}...)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_all_inputs() {
|
||||||
|
header "Updating All Flake Inputs"
|
||||||
|
|
||||||
|
log "Running nix flake update..."
|
||||||
|
if nix flake update; then
|
||||||
|
log "✅ All inputs updated successfully"
|
||||||
|
else
|
||||||
|
error "Failed to update flake inputs"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_source_only() {
|
||||||
|
header "Updating dots-hyprland Source Input"
|
||||||
|
|
||||||
|
log "Running nix flake lock --update-input dots-hyprland..."
|
||||||
|
if nix flake lock --update-input dots-hyprland; then
|
||||||
|
log "✅ dots-hyprland source updated successfully"
|
||||||
|
else
|
||||||
|
error "Failed to update dots-hyprland source input"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_builds() {
|
||||||
|
header "Verifying Flake Builds"
|
||||||
|
|
||||||
|
local configs=("declarative" "writable")
|
||||||
|
local success=true
|
||||||
|
|
||||||
|
for config in "''${configs[@]}"; do
|
||||||
|
info "🔨 Testing $config configuration..."
|
||||||
|
if nix build ".#homeConfigurations.$config.activationPackage" --no-link --quiet; then
|
||||||
|
log "✅ $config configuration builds successfully"
|
||||||
|
else
|
||||||
|
error "❌ $config configuration failed to build"
|
||||||
|
success=false
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if $success; then
|
||||||
|
log "🎉 All configurations build successfully!"
|
||||||
|
else
|
||||||
|
error "Some configurations failed to build"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
AUTO_VERIFY=false
|
||||||
|
DRY_RUN=false
|
||||||
|
COMMAND="update"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--auto-verify)
|
||||||
|
AUTO_VERIFY=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
update|update-source|status|verify|help)
|
||||||
|
COMMAND="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ "$1" != -* ]]; then
|
||||||
|
COMMAND="$1"
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
error "Unknown option: $1"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
case "$COMMAND" in
|
||||||
|
help)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
update)
|
||||||
|
if $DRY_RUN; then
|
||||||
|
info "DRY RUN: Would update all flake inputs"
|
||||||
|
show_status
|
||||||
|
else
|
||||||
|
update_all_inputs
|
||||||
|
if $AUTO_VERIFY; then
|
||||||
|
verify_builds
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
update-source)
|
||||||
|
if $DRY_RUN; then
|
||||||
|
info "DRY RUN: Would update dots-hyprland source input"
|
||||||
|
show_status
|
||||||
|
else
|
||||||
|
update_source_only
|
||||||
|
if $AUTO_VERIFY; then
|
||||||
|
verify_builds
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
verify)
|
||||||
|
verify_builds
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Test utilities
|
||||||
|
test-python-env = pkgs.writeShellScriptBin "test-python-env" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "🧪 Testing dots-hyprland Python environment..."
|
||||||
|
|
||||||
|
VENV_PATH="$HOME/.local/state/quickshell/.venv"
|
||||||
|
|
||||||
|
if [[ ! -d "$VENV_PATH" ]]; then
|
||||||
|
echo "❌ Virtual environment not found at $VENV_PATH"
|
||||||
|
echo "💡 Run: home-manager switch"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "$VENV_PATH/bin/activate"
|
||||||
|
python -c "
|
||||||
|
import sys
|
||||||
|
print(f'✅ Python {sys.version}')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import material_color_utilities
|
||||||
|
print('✅ material-color-utilities')
|
||||||
|
except ImportError:
|
||||||
|
print('❌ material-color-utilities')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import materialyoucolor
|
||||||
|
print('✅ materialyoucolor')
|
||||||
|
except ImportError:
|
||||||
|
print('❌ materialyoucolor')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pywayland
|
||||||
|
print('✅ pywayland')
|
||||||
|
except ImportError:
|
||||||
|
print('❌ pywayland')
|
||||||
|
"
|
||||||
|
deactivate
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Test quickshell with clean config
|
||||||
|
test-quickshell = pkgs.writeShellScriptBin "test-quickshell" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "🧪 Testing quickshell with dots-hyprland config..."
|
||||||
|
|
||||||
|
if [[ ! -d "$HOME/.config/quickshell" ]]; then
|
||||||
|
echo "❌ No quickshell configuration found"
|
||||||
|
echo "💡 Run: home-manager switch"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$HOME/.config/quickshell"
|
||||||
|
echo "🚀 Starting quickshell (timeout 10s)..."
|
||||||
|
timeout 10 ${pkgs.quickshell}/bin/quickshell 2>&1 | head -20
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Mode comparison utility
|
||||||
|
compare-modes = pkgs.writeShellScriptBin "compare-modes" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo "🔍 dots-hyprland Configuration Modes"
|
||||||
|
echo "===================================="
|
||||||
|
echo ""
|
||||||
|
echo "📋 Available modes:"
|
||||||
|
echo ""
|
||||||
|
echo "1. 🔒 DECLARATIVE MODE"
|
||||||
|
echo " • Files managed by Home Manager"
|
||||||
|
echo " • Read-only configuration"
|
||||||
|
echo " • Automatic updates with 'home-manager switch'"
|
||||||
|
echo " • Best for: Set-and-forget users"
|
||||||
|
echo " • Build: nix build .#homeConfigurations.declarative.activationPackage"
|
||||||
|
echo ""
|
||||||
|
echo "2. ✏️ WRITABLE MODE"
|
||||||
|
echo " • Files staged to ~/.configstaging"
|
||||||
|
echo " • User copies/modifies configuration"
|
||||||
|
echo " • Full control over files"
|
||||||
|
echo " • Best for: Customization and development"
|
||||||
|
echo " • Build: nix build .#homeConfigurations.writable.activationPackage"
|
||||||
|
echo ""
|
||||||
|
echo "🚀 Quick start:"
|
||||||
|
echo " # For declarative mode:"
|
||||||
|
echo " nix build .#homeConfigurations.declarative.activationPackage && ./result/activate"
|
||||||
|
echo ""
|
||||||
|
echo " # For writable mode:"
|
||||||
|
echo " nix build .#homeConfigurations.writable.activationPackage && ./result/activate"
|
||||||
|
echo " ~/.local/bin/initialSetup.sh"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Default package for easy testing
|
||||||
|
default = self.packages.${system}.update-flake;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Development shell
|
||||||
|
devShells.${system}.default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
nixpkgs-fmt
|
||||||
|
nil
|
||||||
|
git
|
||||||
|
|
||||||
|
# Our utilities
|
||||||
|
self.packages.${system}.update-flake
|
||||||
|
self.packages.${system}.test-python-env
|
||||||
|
self.packages.${system}.test-quickshell
|
||||||
|
self.packages.${system}.compare-modes
|
||||||
|
];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
echo "🚀 dots-hyprland installer replication development environment"
|
||||||
|
echo ""
|
||||||
|
echo "📋 Available commands:"
|
||||||
|
echo " update-flake - Manage flake inputs and GitHub sync"
|
||||||
|
echo " compare-modes - Compare declarative vs writable modes"
|
||||||
|
echo " test-python-env - Test Python virtual environment"
|
||||||
|
echo " test-quickshell - Test quickshell with config"
|
||||||
|
echo ""
|
||||||
|
echo "🔄 Flake management:"
|
||||||
|
echo " update-flake status - Show current flake status"
|
||||||
|
echo " update-flake update - Update all flake inputs"
|
||||||
|
echo " update-flake verify - Test configurations build"
|
||||||
|
echo ""
|
||||||
|
echo "🎯 Build configurations:"
|
||||||
|
echo " nix build .#homeConfigurations.declarative.activationPackage"
|
||||||
|
echo " nix build .#homeConfigurations.writable.activationPackage"
|
||||||
|
echo ""
|
||||||
|
echo "🔑 Key insight: Both modes use the same Python venv and packages!"
|
||||||
|
echo "📁 Branch: $(git branch --show-current)"
|
||||||
|
echo ""
|
||||||
|
echo "💡 Run 'update-flake help' for full flake management options"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Home Manager module
|
||||||
|
homeManagerModules.default = import ./modules/home-manager.nix;
|
||||||
|
homeManagerModules.dots-hyprland = self.homeManagerModules.default;
|
||||||
|
|
||||||
|
# Example Home Manager configurations
|
||||||
|
homeConfigurations = {
|
||||||
|
# Declarative approach (read-only, managed by Home Manager)
|
||||||
|
declarative = home-manager.lib.homeManagerConfiguration {
|
||||||
|
inherit pkgs;
|
||||||
|
modules = [
|
||||||
|
self.homeManagerModules.default
|
||||||
|
{
|
||||||
|
home.username = "celes";
|
||||||
|
home.homeDirectory = "/home/celes";
|
||||||
|
home.stateVersion = "24.05";
|
||||||
|
|
||||||
|
programs.dots-hyprland = {
|
||||||
|
enable = true;
|
||||||
|
source = dots-hyprland;
|
||||||
|
packageSet = "essential";
|
||||||
|
# Declarative mode (default)
|
||||||
|
mode = "declarative";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Writable approach (staging + user modification)
|
||||||
|
writable = home-manager.lib.homeManagerConfiguration {
|
||||||
|
inherit pkgs;
|
||||||
|
modules = [
|
||||||
|
self.homeManagerModules.default
|
||||||
|
{
|
||||||
|
home.username = "celes";
|
||||||
|
home.homeDirectory = "/home/celes";
|
||||||
|
home.stateVersion = "24.05";
|
||||||
|
|
||||||
|
programs.dots-hyprland = {
|
||||||
|
enable = true;
|
||||||
|
source = dots-hyprland;
|
||||||
|
packageSet = "essential";
|
||||||
|
# Writable mode - stages to .configstaging
|
||||||
|
mode = "writable";
|
||||||
|
writable = {
|
||||||
|
stagingDir = ".configstaging";
|
||||||
|
setupScript = "initialSetup.sh";
|
||||||
|
backupExisting = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Alias for backward compatibility
|
||||||
|
example = self.homeConfigurations.declarative;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
# Quickshell service integration with staging system
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.dots-hyprland.quickshell;
|
||||||
|
mainCfg = config.programs.dots-hyprland;
|
||||||
|
|
||||||
|
# Our working quickshell build with QtPositioning support
|
||||||
|
workingQuickshell =
|
||||||
|
let
|
||||||
|
quickshellSrc = pkgs.fetchFromGitHub {
|
||||||
|
owner = "quickshell-mirror";
|
||||||
|
repo = "quickshell";
|
||||||
|
rev = "a5431dd02dc23d9ef1680e67777fed00fe5f7cda";
|
||||||
|
hash = "sha256-vqkSDvh7hWhPvNjMjEDV4KbSCv2jyl2Arh73ZXe274k=";
|
||||||
|
};
|
||||||
|
quickshellBase = pkgs.callPackage (quickshellSrc + "/default.nix") {
|
||||||
|
debug = true;
|
||||||
|
gitRev = "a5431dd02dc23d9ef1680e67777fed00fe5f7cda";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
quickshellBase.withModules (with pkgs.qt6; [ qtpositioning qtmultimedia ]);
|
||||||
|
|
||||||
|
# Service startup script that handles initial setup
|
||||||
|
quickshellStartup = pkgs.writeShellScript "quickshell-startup" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for logging
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "''${GREEN}[quickshell-service]''${NC} $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo -e "''${YELLOW}[quickshell-service]''${NC} WARNING: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "''${RED}[quickshell-service]''${NC} ERROR: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
STAGING_DIR="$HOME/${mainCfg.writable-mode.stagingDir}"
|
||||||
|
CONFIG_DIR="$HOME/.config"
|
||||||
|
SETUP_SCRIPT="$HOME/${mainCfg.writable-mode.setupScript}"
|
||||||
|
SETUP_MARKER="$HOME/.cache/dots-hyprland/setup-complete"
|
||||||
|
|
||||||
|
# Ensure cache directory exists
|
||||||
|
mkdir -p "$(dirname "$SETUP_MARKER")"
|
||||||
|
|
||||||
|
# Check if initial setup has been run
|
||||||
|
if [[ ! -f "$SETUP_MARKER" ]]; then
|
||||||
|
log "🚀 First run detected - running initial setup"
|
||||||
|
|
||||||
|
# Check if staging directory exists
|
||||||
|
if [[ ! -d "$STAGING_DIR" ]]; then
|
||||||
|
error "Staging directory not found: $STAGING_DIR"
|
||||||
|
error "Please run 'home-manager switch' first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if setup script exists
|
||||||
|
if [[ ! -x "$SETUP_SCRIPT" ]]; then
|
||||||
|
error "Setup script not found or not executable: $SETUP_SCRIPT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "📋 Running initial setup script..."
|
||||||
|
if "$SETUP_SCRIPT"; then
|
||||||
|
# Mark setup as complete
|
||||||
|
echo "$(date)" > "$SETUP_MARKER"
|
||||||
|
log "✅ Initial setup completed successfully"
|
||||||
|
else
|
||||||
|
error "❌ Initial setup failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "✅ Setup already completed ($(cat "$SETUP_MARKER"))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify quickshell configuration exists
|
||||||
|
if [[ ! -d "$CONFIG_DIR/quickshell" ]]; then
|
||||||
|
error "Quickshell configuration not found at $CONFIG_DIR/quickshell"
|
||||||
|
error "Initial setup may have failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up environment variables
|
||||||
|
export ILLOGICAL_IMPULSE_VIRTUAL_ENV="$HOME/.local/state/quickshell/.venv"
|
||||||
|
export QT_SCALE_FACTOR="${toString cfg.scaling}"
|
||||||
|
export QT_QUICK_CONTROLS_STYLE="Basic"
|
||||||
|
export QT_QUICK_FLICKABLE_WHEEL_DECELERATION="10000"
|
||||||
|
|
||||||
|
# Ensure PATH includes user applications - CRITICAL for app launching
|
||||||
|
export PATH="${config.home.profileDirectory}/bin:/run/wrappers/bin:${config.home.homeDirectory}/.nix-profile/bin:/etc/profiles/per-user/${config.home.username}/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:$PATH"
|
||||||
|
export XDG_DATA_DIRS="${config.home.profileDirectory}/share:${config.home.homeDirectory}/.nix-profile/share:/etc/profiles/per-user/${config.home.username}/share:/nix/var/nix/profiles/default/share:/run/current-system/sw/share:$XDG_DATA_DIRS"
|
||||||
|
|
||||||
|
# Create application launcher wrapper that quickshell can use
|
||||||
|
LAUNCHER_WRAPPER="$HOME/.cache/dots-hyprland/app-launcher"
|
||||||
|
mkdir -p "$(dirname "$LAUNCHER_WRAPPER")"
|
||||||
|
cat > "$LAUNCHER_WRAPPER" << 'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Application launcher wrapper for quickshell
|
||||||
|
# Ensures proper PATH and environment for launched applications
|
||||||
|
|
||||||
|
# Use the same PATH that quickshell has
|
||||||
|
export PATH="${config.home.profileDirectory}/bin:/run/wrappers/bin:${config.home.homeDirectory}/.nix-profile/bin:/etc/profiles/per-user/${config.home.username}/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"
|
||||||
|
export XDG_DATA_DIRS="${config.home.profileDirectory}/share:${config.home.homeDirectory}/.nix-profile/share:/etc/profiles/per-user/${config.home.username}/share:/nix/var/nix/profiles/default/share:/run/current-system/sw/share"
|
||||||
|
|
||||||
|
# Launch the application
|
||||||
|
exec "$@"
|
||||||
|
EOF
|
||||||
|
chmod +x "$LAUNCHER_WRAPPER"
|
||||||
|
|
||||||
|
# Export the launcher wrapper path for quickshell to use
|
||||||
|
export DOTS_HYPRLAND_APP_LAUNCHER="$LAUNCHER_WRAPPER"
|
||||||
|
|
||||||
|
# Verify Python virtual environment
|
||||||
|
if [[ ! -d "$ILLOGICAL_IMPULSE_VIRTUAL_ENV" ]]; then
|
||||||
|
warn "Python virtual environment not found at $ILLOGICAL_IMPULSE_VIRTUAL_ENV"
|
||||||
|
warn "Some features may not work correctly"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "🎯 Starting quickshell with dots-hyprland configuration"
|
||||||
|
log "📁 Config: $CONFIG_DIR/quickshell/ii/shell.qml"
|
||||||
|
log "🐍 Python venv: $ILLOGICAL_IMPULSE_VIRTUAL_ENV"
|
||||||
|
log "🚀 App launcher: $LAUNCHER_WRAPPER"
|
||||||
|
|
||||||
|
# Start quickshell
|
||||||
|
exec ${workingQuickshell}/bin/quickshell -p "$CONFIG_DIR/quickshell/ii/shell.qml"
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.dots-hyprland.quickshell = {
|
||||||
|
enable = mkEnableOption "Quickshell service with staging integration";
|
||||||
|
|
||||||
|
autoStart = mkEnableOption "Auto-start with Hyprland session" // { default = true; };
|
||||||
|
|
||||||
|
restartOnFailure = mkEnableOption "Restart service on failure" // { default = true; };
|
||||||
|
|
||||||
|
scaling = mkOption {
|
||||||
|
type = types.float;
|
||||||
|
default = 1.0;
|
||||||
|
description = "UI scaling factor";
|
||||||
|
};
|
||||||
|
|
||||||
|
logLevel = mkOption {
|
||||||
|
type = types.enum [ "debug" "info" "warning" "error" ];
|
||||||
|
default = "info";
|
||||||
|
description = "Logging level for quickshell service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Install the working quickshell build and service management scripts
|
||||||
|
home.packages = [ workingQuickshell ] ++ (with pkgs; [
|
||||||
|
(writeShellScriptBin "quickshell-restart" ''
|
||||||
|
systemctl --user restart quickshell.service
|
||||||
|
echo "✅ Quickshell service restarted"
|
||||||
|
'')
|
||||||
|
|
||||||
|
(writeShellScriptBin "quickshell-status" ''
|
||||||
|
echo "🔍 Quickshell Service Status"
|
||||||
|
echo "=========================="
|
||||||
|
systemctl --user status quickshell.service --no-pager
|
||||||
|
echo ""
|
||||||
|
echo "📋 Recent logs:"
|
||||||
|
journalctl --user -u quickshell.service -n 10 --no-pager
|
||||||
|
'')
|
||||||
|
|
||||||
|
(writeShellScriptBin "quickshell-logs" ''
|
||||||
|
echo "📋 Following quickshell logs (Ctrl+C to exit):"
|
||||||
|
journalctl --user -u quickshell.service -f
|
||||||
|
'')
|
||||||
|
|
||||||
|
(writeShellScriptBin "quickshell-debug" ''
|
||||||
|
echo "🐛 Starting quickshell in debug mode..."
|
||||||
|
systemctl --user stop quickshell.service
|
||||||
|
QT_LOGGING_RULES="quickshell.*=true" ${quickshellStartup}
|
||||||
|
'')
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Systemd user service for quickshell
|
||||||
|
systemd.user.services.quickshell = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Quickshell - QtQuick based desktop shell with dots-hyprland";
|
||||||
|
Documentation = [ "https://quickshell.org" "https://end-4.github.io/dots-hyprland-wiki/" ];
|
||||||
|
PartOf = [ "hyprland-session.target" ];
|
||||||
|
After = [ "hyprland-session.target" "graphical-session.target" ];
|
||||||
|
Wants = [ "hyprland-session.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = quickshellStartup;
|
||||||
|
ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID";
|
||||||
|
Restart = if cfg.restartOnFailure then "on-failure" else "no";
|
||||||
|
RestartSec = 2;
|
||||||
|
TimeoutStartSec = 30;
|
||||||
|
TimeoutStopSec = 10;
|
||||||
|
|
||||||
|
# Environment variables - include full user environment
|
||||||
|
Environment = [
|
||||||
|
"QT_SCALE_FACTOR=${toString cfg.scaling}"
|
||||||
|
"QT_QUICK_CONTROLS_STYLE=Basic"
|
||||||
|
"QT_QUICK_FLICKABLE_WHEEL_DECELERATION=10000"
|
||||||
|
"QT_LOGGING_RULES=${
|
||||||
|
if cfg.logLevel == "debug" then "quickshell.*=true"
|
||||||
|
else if cfg.logLevel == "warning" then "*.warning=true"
|
||||||
|
else if cfg.logLevel == "error" then "*.critical=true"
|
||||||
|
else "*.info=true"
|
||||||
|
}"
|
||||||
|
# Include user's full PATH so applications can be launched
|
||||||
|
"PATH=${config.home.profileDirectory}/bin:/run/wrappers/bin:${config.home.homeDirectory}/.nix-profile/bin:/etc/profiles/per-user/${config.home.username}/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"
|
||||||
|
# Include XDG data directories for application discovery
|
||||||
|
"XDG_DATA_DIRS=${config.home.profileDirectory}/share:${config.home.homeDirectory}/.nix-profile/share:/etc/profiles/per-user/${config.home.username}/share:/nix/var/nix/profiles/default/share:/run/current-system/sw/share"
|
||||||
|
# Application launcher wrapper path
|
||||||
|
"DOTS_HYPRLAND_APP_LAUNCHER=%h/.cache/dots-hyprland/app-launcher"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Working directory
|
||||||
|
WorkingDirectory = "%h";
|
||||||
|
|
||||||
|
# Security settings
|
||||||
|
PrivateNetwork = false;
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = false; # Need access to home directory
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
MemoryMax = "2G";
|
||||||
|
CPUQuota = "200%";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = mkIf cfg.autoStart {
|
||||||
|
WantedBy = [ "hyprland-session.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create hyprland session target if it doesn't exist
|
||||||
|
systemd.user.targets.hyprland-session = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Hyprland compositor session";
|
||||||
|
Documentation = [ "man:systemd.special(7)" ];
|
||||||
|
BindsTo = [ "graphical-session.target" ];
|
||||||
|
Wants = [ "graphical-session-pre.target" ];
|
||||||
|
After = [ "graphical-session-pre.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
# Touchegg gesture support for dots-hyprland
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.dots-hyprland.touchegg;
|
||||||
|
mainCfg = config.programs.dots-hyprland;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.dots-hyprland.touchegg = {
|
||||||
|
enable = mkEnableOption "Touchegg gesture support";
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = ''
|
||||||
|
<touchégg>
|
||||||
|
<settings>
|
||||||
|
<property name="animation_delay">150</property>
|
||||||
|
<property name="action_execute_threshold">80</property>
|
||||||
|
<property name="color">auto</property>
|
||||||
|
<property name="borderColor">auto</property>
|
||||||
|
</settings>
|
||||||
|
<application name="All">
|
||||||
|
<!-- 3-finger pinch in: Close window -->
|
||||||
|
<gesture type="PINCH" fingers="3" direction="IN">
|
||||||
|
<action type="CLOSE_WINDOW">
|
||||||
|
<animate>true</animate>
|
||||||
|
<color>F84A53</color>
|
||||||
|
<borderColor>F84A53</borderColor>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 2-finger tap: Right click -->
|
||||||
|
<gesture type="TAP" fingers="2" direction="UNKNOWN">
|
||||||
|
<action type="MOUSE_CLICK">
|
||||||
|
<button>3</button>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 3-finger tap: Middle click -->
|
||||||
|
<gesture type="TAP" fingers="3" direction="UNKNOWN">
|
||||||
|
<action type="MOUSE_CLICK">
|
||||||
|
<button>2</button>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 4-finger pinch in: Fullscreen mode 0 -->
|
||||||
|
<gesture type="PINCH" fingers="4" direction="IN">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch fullscreen 0</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 4-finger pinch out: Fullscreen mode 1 -->
|
||||||
|
<gesture type="PINCH" fingers="4" direction="OUT">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch fullscreen 1</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- Note: 3-finger left/right swipes removed - handled by Hyprland's built-in workspace_swipe -->
|
||||||
|
|
||||||
|
<!-- 3-finger swipe up: Show overview -->
|
||||||
|
<gesture type="SWIPE" fingers="3" direction="UP">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch global quickshell:overviewToggle</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 3-finger swipe down: Show all windows -->
|
||||||
|
<gesture type="SWIPE" fingers="3" direction="DOWN">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch overview</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 4-finger swipe left: Move window left -->
|
||||||
|
<gesture type="SWIPE" fingers="4" direction="LEFT">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch movewindow l</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 4-finger swipe right: Move window right -->
|
||||||
|
<gesture type="SWIPE" fingers="4" direction="RIGHT">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch movewindow r</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 4-finger swipe up: Move window up -->
|
||||||
|
<gesture type="SWIPE" fingers="4" direction="UP">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch movewindow u</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
|
||||||
|
<!-- 4-finger swipe down: Move window down -->
|
||||||
|
<gesture type="SWIPE" fingers="4" direction="DOWN">
|
||||||
|
<action type="RUN_COMMAND">
|
||||||
|
<command>hyprctl dispatch movewindow d</command>
|
||||||
|
<repeat>false</repeat>
|
||||||
|
<animation>NONE</animation>
|
||||||
|
<on>begin</on>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<!-- Browser-specific gestures for zoom -->
|
||||||
|
<application name="chromium-browser">
|
||||||
|
<gesture type="PINCH" fingers="2" direction="IN">
|
||||||
|
<action type="SEND_KEYS">
|
||||||
|
<repeat>true</repeat>
|
||||||
|
<modifiers>Control_L</modifiers>
|
||||||
|
<keys>KP_Subtract</keys>
|
||||||
|
<decreaseKeys>KP_Add</decreaseKeys>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
<gesture type="PINCH" fingers="2" direction="OUT">
|
||||||
|
<action type="SEND_KEYS">
|
||||||
|
<repeat>true</repeat>
|
||||||
|
<modifiers>Control_L</modifiers>
|
||||||
|
<keys>KP_Add</keys>
|
||||||
|
<decreaseKeys>KP_Subtract</decreaseKeys>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<application name="google-chrome">
|
||||||
|
<gesture type="PINCH" fingers="2" direction="IN">
|
||||||
|
<action type="SEND_KEYS">
|
||||||
|
<repeat>true</repeat>
|
||||||
|
<modifiers>Control_L</modifiers>
|
||||||
|
<keys>KP_Subtract</keys>
|
||||||
|
<decreaseKeys>KP_Add</decreaseKeys>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
<gesture type="PINCH" fingers="2" direction="OUT">
|
||||||
|
<action type="SEND_KEYS">
|
||||||
|
<repeat>true</repeat>
|
||||||
|
<modifiers>Control_L</modifiers>
|
||||||
|
<keys>KP_Add</keys>
|
||||||
|
<decreaseKeys>KP_Subtract</decreaseKeys>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<application name="firefox">
|
||||||
|
<gesture type="PINCH" fingers="2" direction="IN">
|
||||||
|
<action type="SEND_KEYS">
|
||||||
|
<repeat>true</repeat>
|
||||||
|
<modifiers>Control_L</modifiers>
|
||||||
|
<keys>KP_Subtract</keys>
|
||||||
|
<decreaseKeys>KP_Add</decreaseKeys>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
<gesture type="PINCH" fingers="2" direction="OUT">
|
||||||
|
<action type="SEND_KEYS">
|
||||||
|
<repeat>true</repeat>
|
||||||
|
<modifiers>Control_L</modifiers>
|
||||||
|
<keys>KP_Add</keys>
|
||||||
|
<decreaseKeys>KP_Subtract</decreaseKeys>
|
||||||
|
</action>
|
||||||
|
</gesture>
|
||||||
|
</application>
|
||||||
|
</touchégg>
|
||||||
|
'';
|
||||||
|
description = "Touchegg configuration XML";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Note: touchegg service needs to be enabled at system level
|
||||||
|
# Add this to your NixOS configuration: services.touchegg.enable = true;
|
||||||
|
|
||||||
|
# Install touchegg configuration (both user and system locations)
|
||||||
|
xdg.configFile."touchegg/touchegg.conf" = {
|
||||||
|
text = cfg.config;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Also create system config that touchegg service can read
|
||||||
|
# Note: This requires the touchegg service to be enabled at system level
|
||||||
|
home.activation.toucheggSystemConfig = lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||||
|
echo "📄 Creating system-wide touchegg configuration..."
|
||||||
|
$DRY_RUN_CMD sudo mkdir -p /etc/touchegg
|
||||||
|
$DRY_RUN_CMD sudo cp ${config.xdg.configHome}/touchegg/touchegg.conf /etc/touchegg/touchegg.conf
|
||||||
|
echo "✅ System touchegg config updated"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Create touchegg client service (required for gesture execution)
|
||||||
|
systemd.user.services.touchegg-client = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Touchegg Client";
|
||||||
|
After = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${pkgs.touchegg}/bin/touchegg --client";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "default.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Install touchegg and management scripts
|
||||||
|
home.packages = [ pkgs.touchegg ] ++ [
|
||||||
|
(pkgs.writeShellScriptBin "touchegg-restart" ''
|
||||||
|
echo "🔄 Restarting touchegg service..."
|
||||||
|
sudo systemctl restart touchegg
|
||||||
|
echo "✅ Touchegg restarted"
|
||||||
|
'')
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "touchegg-status" ''
|
||||||
|
echo "📊 Touchegg service status:"
|
||||||
|
systemctl status touchegg --no-pager
|
||||||
|
echo ""
|
||||||
|
echo "📄 Touchegg configuration:"
|
||||||
|
echo " ~/.config/touchegg/touchegg.conf"
|
||||||
|
if [[ -f ~/.config/touchegg/touchegg.conf ]]; then
|
||||||
|
echo " ✅ Configuration file exists"
|
||||||
|
else
|
||||||
|
echo " ❌ Configuration file missing"
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "touchegg-reload-config" ''
|
||||||
|
echo "🔄 Reloading touchegg configuration..."
|
||||||
|
if systemctl is-active touchegg >/dev/null 2>&1; then
|
||||||
|
sudo systemctl reload touchegg 2>/dev/null || sudo systemctl restart touchegg
|
||||||
|
echo "✅ Touchegg configuration reloaded"
|
||||||
|
else
|
||||||
|
echo "❌ Touchegg service is not running"
|
||||||
|
echo "💡 Try: sudo systemctl start touchegg"
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# Session variables for touchegg
|
||||||
|
home.sessionVariables = {
|
||||||
|
TOUCHEGG_CONFIG_PATH = "$HOME/.config/touchegg/touchegg.conf";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
# Configuration management for dots-hyprland
|
||||||
|
# Replicates the installer's rsync behavior exactly
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.dots-hyprland.configuration;
|
||||||
|
mainCfg = config.programs.dots-hyprland;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.dots-hyprland.configuration = {
|
||||||
|
enable = mkEnableOption "dots-hyprland configuration management";
|
||||||
|
|
||||||
|
source = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = "Source path for dots-hyprland configuration";
|
||||||
|
example = "inputs.dots-hyprland";
|
||||||
|
};
|
||||||
|
|
||||||
|
copyMiscConfig = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Copy miscellaneous config files (everything except fish and hypr)";
|
||||||
|
};
|
||||||
|
|
||||||
|
copyFishConfig = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Copy fish shell configuration";
|
||||||
|
};
|
||||||
|
|
||||||
|
copyHyprlandConfig = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Copy Hyprland configuration";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Replicate installer's MISC config copying
|
||||||
|
# "for i in $(find .config/ -mindepth 1 -maxdepth 1 ! -name 'fish' ! -name 'hypr' -exec basename {} \;)"
|
||||||
|
xdg.configFile = mkMerge [
|
||||||
|
# MISC configs (everything except fish and hypr)
|
||||||
|
(mkIf cfg.copyMiscConfig (
|
||||||
|
let
|
||||||
|
# Get all directories in .config except fish and hypr
|
||||||
|
configDirs = [
|
||||||
|
"quickshell"
|
||||||
|
"kitty"
|
||||||
|
"foot"
|
||||||
|
"fuzzel"
|
||||||
|
"wlogout"
|
||||||
|
"matugen"
|
||||||
|
# Add more as discovered in the source
|
||||||
|
];
|
||||||
|
|
||||||
|
configFiles = listToAttrs (map (dir: {
|
||||||
|
name = dir;
|
||||||
|
value = {
|
||||||
|
source = "${cfg.source}/.config/${dir}";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
}) configDirs);
|
||||||
|
in
|
||||||
|
configFiles
|
||||||
|
))
|
||||||
|
|
||||||
|
# Fish configuration
|
||||||
|
(mkIf cfg.copyFishConfig {
|
||||||
|
"fish" = {
|
||||||
|
source = "${cfg.source}/.config/fish";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
# Hyprland configuration (special handling like installer)
|
||||||
|
(mkIf cfg.copyHyprlandConfig {
|
||||||
|
# Copy hypr directory excluding specific files
|
||||||
|
# rsync -av --delete --exclude '/custom' --exclude '/hyprlock.conf' --exclude '/hypridle.conf' --exclude '/hyprland.conf'
|
||||||
|
"hypr" = {
|
||||||
|
source = pkgs.runCommand "hypr-config-filtered" {} ''
|
||||||
|
mkdir -p $out
|
||||||
|
|
||||||
|
# Copy everything from source hypr directory
|
||||||
|
cp -r ${cfg.source}/.config/hypr/* $out/ 2>/dev/null || true
|
||||||
|
|
||||||
|
# Remove excluded files (replicating installer --exclude logic)
|
||||||
|
rm -rf $out/custom 2>/dev/null || true
|
||||||
|
rm -f $out/hyprlock.conf 2>/dev/null || true
|
||||||
|
rm -f $out/hypridle.conf 2>/dev/null || true
|
||||||
|
rm -f $out/hyprland.conf 2>/dev/null || true
|
||||||
|
|
||||||
|
# Ensure we have the directory structure
|
||||||
|
mkdir -p $out
|
||||||
|
'';
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Copy the main config files separately (installer does this)
|
||||||
|
"hypr/hyprland.conf" = {
|
||||||
|
source = "${cfg.source}/.config/hypr/hyprland.conf";
|
||||||
|
};
|
||||||
|
"hypr/hypridle.conf" = {
|
||||||
|
source = "${cfg.source}/.config/hypr/hypridle.conf";
|
||||||
|
};
|
||||||
|
"hypr/hyprlock.conf" = {
|
||||||
|
source = "${cfg.source}/.config/hypr/hyprlock.conf";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# Copy .local/share files (replicating installer)
|
||||||
|
home.file = {
|
||||||
|
".local/share/icons" = mkIf cfg.copyMiscConfig {
|
||||||
|
source = "${cfg.source}/.local/share/icons";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
".local/share/konsole" = mkIf cfg.copyMiscConfig {
|
||||||
|
source = "${cfg.source}/.local/share/konsole";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Ensure XDG directories exist (installer creates these)
|
||||||
|
home.activation.createXdgDirs = lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||||
|
$DRY_RUN_CMD mkdir -p $HOME/.local/bin
|
||||||
|
$DRY_RUN_CMD mkdir -p $HOME/.cache
|
||||||
|
$DRY_RUN_CMD mkdir -p $HOME/.config
|
||||||
|
$DRY_RUN_CMD mkdir -p $HOME/.local/share
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
# Main Home Manager module for dots-hyprland
|
||||||
|
# Supports both declarative and writable modes
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.dots-hyprland;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./python-environment.nix
|
||||||
|
./configuration.nix
|
||||||
|
./writable-mode.nix
|
||||||
|
./components/quickshell-service.nix
|
||||||
|
./components/touchegg.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
options.programs.dots-hyprland = {
|
||||||
|
enable = mkEnableOption "dots-hyprland desktop environment";
|
||||||
|
|
||||||
|
source = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = "Source path for clean dots-hyprland configuration";
|
||||||
|
example = "inputs.dots-hyprland";
|
||||||
|
};
|
||||||
|
|
||||||
|
packageSet = mkOption {
|
||||||
|
type = types.enum [ "minimal" "essential" "all" ];
|
||||||
|
default = "essential";
|
||||||
|
description = "Which package set to install";
|
||||||
|
};
|
||||||
|
|
||||||
|
mode = mkOption {
|
||||||
|
type = types.enum [ "declarative" "writable" ];
|
||||||
|
default = "declarative";
|
||||||
|
description = ''
|
||||||
|
Configuration mode:
|
||||||
|
- declarative: Files managed by Home Manager (read-only)
|
||||||
|
- writable: Files staged to .configstaging, user copies and modifies
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
writable = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
stagingDir = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = ".configstaging";
|
||||||
|
description = "Directory to stage configuration files";
|
||||||
|
};
|
||||||
|
|
||||||
|
setupScript = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "initialSetup.sh";
|
||||||
|
description = "Name of the setup script in ~/.local/bin/";
|
||||||
|
};
|
||||||
|
|
||||||
|
backupExisting = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Backup existing configuration files";
|
||||||
|
};
|
||||||
|
|
||||||
|
symlinkMode = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Create symlinks instead of copying files";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = {};
|
||||||
|
description = "Writable mode configuration";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Install packages based on selected set
|
||||||
|
home.packages =
|
||||||
|
let
|
||||||
|
packageSets = import ../packages/dots-hyprland-packages.nix { inherit lib pkgs; };
|
||||||
|
in
|
||||||
|
if cfg.packageSet == "minimal" then packageSets.minimalPackages
|
||||||
|
else if cfg.packageSet == "essential" then packageSets.essentialPackages
|
||||||
|
else packageSets.allPackages;
|
||||||
|
|
||||||
|
# Enable Python virtual environment (CRITICAL for both modes)
|
||||||
|
programs.dots-hyprland.python = {
|
||||||
|
enable = true;
|
||||||
|
autoSetup = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable configuration management based on mode
|
||||||
|
programs.dots-hyprland.configuration = mkIf (cfg.mode == "declarative") {
|
||||||
|
enable = true;
|
||||||
|
source = cfg.source;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable writable mode
|
||||||
|
programs.dots-hyprland.writable-mode = mkIf (cfg.mode == "writable") {
|
||||||
|
enable = true;
|
||||||
|
source = cfg.source;
|
||||||
|
inherit (cfg.writable) stagingDir setupScript backupExisting symlinkMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable quickshell service (works with both modes)
|
||||||
|
programs.dots-hyprland.quickshell = {
|
||||||
|
enable = true;
|
||||||
|
autoStart = true;
|
||||||
|
restartOnFailure = true;
|
||||||
|
logLevel = "info";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable touchegg gesture support
|
||||||
|
programs.dots-hyprland.touchegg = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable custom keybindings
|
||||||
|
|
||||||
|
# Set critical environment variable (required for both modes)
|
||||||
|
home.sessionVariables = {
|
||||||
|
ILLOGICAL_IMPULSE_VIRTUAL_ENV = "$HOME/.local/state/quickshell/.venv";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Ensure XDG directories exist (installer requirement)
|
||||||
|
xdg.enable = true;
|
||||||
|
xdg.userDirs.enable = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
# Python Virtual Environment for dots-hyprland
|
||||||
|
# This replicates the installer's Python setup exactly
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.dots-hyprland.python;
|
||||||
|
mainCfg = config.programs.dots-hyprland;
|
||||||
|
|
||||||
|
# Virtual environment setup script that replicates installer behavior
|
||||||
|
setupVenvScript = pkgs.writeShellScript "setup-dots-hyprland-venv" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
VENV_PATH="$HOME/.local/state/quickshell/.venv"
|
||||||
|
|
||||||
|
echo "🐍 Setting up dots-hyprland Python virtual environment..."
|
||||||
|
echo "📁 Target: $VENV_PATH"
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
mkdir -p "$(dirname "$VENV_PATH")"
|
||||||
|
|
||||||
|
# Remove existing venv if it exists
|
||||||
|
if [[ -d "$VENV_PATH" ]]; then
|
||||||
|
echo "🗑️ Removing existing virtual environment..."
|
||||||
|
rm -rf "$VENV_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up proper library path for Python packages (64-bit only)
|
||||||
|
export LD_LIBRARY_PATH="${lib.makeLibraryPath (with pkgs; [
|
||||||
|
gcc-unwrapped.lib
|
||||||
|
glibc
|
||||||
|
zlib
|
||||||
|
libffi
|
||||||
|
openssl
|
||||||
|
bzip2
|
||||||
|
xz.out
|
||||||
|
ncurses
|
||||||
|
readline
|
||||||
|
sqlite
|
||||||
|
])}"
|
||||||
|
|
||||||
|
# Clear Python path to avoid conflicts
|
||||||
|
export PYTHONPATH=""
|
||||||
|
export PYTHONDONTWRITEBYTECODE=1
|
||||||
|
|
||||||
|
echo "📚 Library path: $LD_LIBRARY_PATH"
|
||||||
|
|
||||||
|
# Create virtual environment with Python 3.12 (installer requirement)
|
||||||
|
echo "🏗️ Creating Python 3.12 virtual environment..."
|
||||||
|
${pkgs.python312}/bin/python -m venv "$VENV_PATH" --prompt .venv
|
||||||
|
|
||||||
|
# Activate and install exact requirements from installer
|
||||||
|
echo "📦 Installing Python packages with proper library linking..."
|
||||||
|
source "$VENV_PATH/bin/activate"
|
||||||
|
|
||||||
|
# Upgrade pip first
|
||||||
|
pip install --upgrade pip
|
||||||
|
|
||||||
|
# Install exact versions from scriptdata/requirements.txt
|
||||||
|
pip install --no-cache-dir --force-reinstall \
|
||||||
|
build==1.2.2.post1 \
|
||||||
|
cffi==1.17.1 \
|
||||||
|
libsass==0.23.0 \
|
||||||
|
material-color-utilities==0.2.1 \
|
||||||
|
materialyoucolor==2.0.10 \
|
||||||
|
numpy==2.2.2 \
|
||||||
|
packaging==24.2 \
|
||||||
|
pillow==11.1.0 \
|
||||||
|
psutil==6.1.1 \
|
||||||
|
pycparser==2.22 \
|
||||||
|
pyproject-hooks==1.2.0 \
|
||||||
|
pywayland==0.4.18 \
|
||||||
|
setproctitle==1.3.4 \
|
||||||
|
setuptools==80.9.0 \
|
||||||
|
setuptools-scm==8.1.0 \
|
||||||
|
wheel==0.45.1
|
||||||
|
|
||||||
|
# Test critical imports
|
||||||
|
echo "🧪 Testing critical package imports..."
|
||||||
|
python -c "
|
||||||
|
import sys
|
||||||
|
print(f'Python: {sys.version}')
|
||||||
|
|
||||||
|
tests = [
|
||||||
|
('materialyoucolor', 'materialyoucolor'),
|
||||||
|
('material_color_utilities', 'material_color_utilities'),
|
||||||
|
('sass', 'sass'),
|
||||||
|
('numpy', 'numpy'),
|
||||||
|
('PIL', 'PIL'),
|
||||||
|
('pywayland.client', 'pywayland.client'),
|
||||||
|
('psutil', 'psutil'),
|
||||||
|
('setproctitle', 'setproctitle')
|
||||||
|
]
|
||||||
|
|
||||||
|
working = 0
|
||||||
|
for name, module in tests:
|
||||||
|
try:
|
||||||
|
__import__(module)
|
||||||
|
print(f'✅ {name}')
|
||||||
|
working += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f'❌ {name}: {e}')
|
||||||
|
|
||||||
|
print(f'📊 {working}/{len(tests)} packages working')
|
||||||
|
if working == len(tests):
|
||||||
|
print('🎉 All critical packages imported successfully!')
|
||||||
|
else:
|
||||||
|
print('⚠️ Some packages failed - may need additional system libraries')
|
||||||
|
"
|
||||||
|
|
||||||
|
deactivate
|
||||||
|
|
||||||
|
echo "✅ Python virtual environment setup complete!"
|
||||||
|
echo "🔗 Environment variable: ILLOGICAL_IMPULSE_VIRTUAL_ENV=$VENV_PATH"
|
||||||
|
echo "📚 Library path configured for NixOS compatibility"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Test script to verify the Python environment works
|
||||||
|
testVenvScript = pkgs.writeShellScript "test-dots-hyprland-venv" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
VENV_PATH="$HOME/.local/state/quickshell/.venv"
|
||||||
|
|
||||||
|
echo "🧪 Testing dots-hyprland Python virtual environment..."
|
||||||
|
|
||||||
|
if [[ ! -d "$VENV_PATH" ]]; then
|
||||||
|
echo "❌ Virtual environment not found at $VENV_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "$VENV_PATH/bin/activate"
|
||||||
|
|
||||||
|
# Test critical packages
|
||||||
|
echo "📦 Testing Python packages..."
|
||||||
|
python -c "import material_color_utilities; print('✅ material-color-utilities')" || echo "❌ material-color-utilities"
|
||||||
|
python -c "import materialyoucolor; print('✅ materialyoucolor')" || echo "❌ materialyoucolor"
|
||||||
|
python -c "import pywayland; print('✅ pywayland')" || echo "❌ pywayland"
|
||||||
|
python -c "import PIL; print('✅ pillow')" || echo "❌ pillow"
|
||||||
|
python -c "import numpy; print('✅ numpy')" || echo "❌ numpy"
|
||||||
|
python -c "import psutil; print('✅ psutil')" || echo "❌ psutil"
|
||||||
|
|
||||||
|
deactivate
|
||||||
|
|
||||||
|
echo "🎉 Python environment test complete!"
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.dots-hyprland.python = {
|
||||||
|
enable = mkEnableOption "Python virtual environment for dots-hyprland";
|
||||||
|
|
||||||
|
venvPath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "$HOME/.local/state/quickshell/.venv";
|
||||||
|
description = "Path to Python virtual environment";
|
||||||
|
};
|
||||||
|
|
||||||
|
autoSetup = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Automatically set up virtual environment on activation";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Install system Python and required build dependencies + test script
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
python312
|
||||||
|
python312Packages.pip
|
||||||
|
python312Packages.virtualenv
|
||||||
|
|
||||||
|
# System dependencies for Python packages (from illogical-impulse-python PKGBUILD)
|
||||||
|
clang
|
||||||
|
gtk4
|
||||||
|
libadwaita
|
||||||
|
libsoup_3
|
||||||
|
libportal-gtk4
|
||||||
|
gobject-introspection
|
||||||
|
sassc
|
||||||
|
opencv4
|
||||||
|
|
||||||
|
# Critical system libraries for Python packages (64-bit)
|
||||||
|
gcc-unwrapped.lib # Provides proper libstdc++.so.6
|
||||||
|
glibc
|
||||||
|
zlib
|
||||||
|
libffi
|
||||||
|
openssl
|
||||||
|
|
||||||
|
# Additional libraries that might be needed
|
||||||
|
bzip2
|
||||||
|
xz
|
||||||
|
ncurses
|
||||||
|
readline
|
||||||
|
sqlite
|
||||||
|
|
||||||
|
# Development tools
|
||||||
|
pkg-config
|
||||||
|
cairo
|
||||||
|
gdk-pixbuf
|
||||||
|
glib
|
||||||
|
|
||||||
|
# Test script
|
||||||
|
(writeShellScriptBin "test-dots-hyprland-venv" ''
|
||||||
|
${testVenvScript}
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# Set up virtual environment on Home Manager activation
|
||||||
|
home.activation.setupDotsHyprlandVenv = mkIf cfg.autoSetup (
|
||||||
|
lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||||
|
$DRY_RUN_CMD ${setupVenvScript}
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
|
# Set critical environment variable and library paths
|
||||||
|
home.sessionVariables = {
|
||||||
|
ILLOGICAL_IMPULSE_VIRTUAL_ENV = cfg.venvPath;
|
||||||
|
# Ensure Python packages can find system libraries (64-bit only)
|
||||||
|
LD_LIBRARY_PATH = lib.makeLibraryPath (with pkgs; [
|
||||||
|
gcc-unwrapped.lib
|
||||||
|
glibc
|
||||||
|
zlib
|
||||||
|
libffi
|
||||||
|
openssl
|
||||||
|
bzip2
|
||||||
|
xz.out
|
||||||
|
ncurses
|
||||||
|
readline
|
||||||
|
sqlite
|
||||||
|
]);
|
||||||
|
# Additional environment variables for Python
|
||||||
|
PYTHONPATH = ""; # Clear to avoid conflicts
|
||||||
|
PYTHONDONTWRITEBYTECODE = "1"; # Prevent .pyc files
|
||||||
|
|
||||||
|
# QML import paths for quickshell
|
||||||
|
QML2_IMPORT_PATH = lib.concatStringsSep ":" (with pkgs; [
|
||||||
|
"${kdePackages.qt5compat}/lib/qt-6/qml"
|
||||||
|
"${kdePackages.qtdeclarative}/lib/qt-6/qml"
|
||||||
|
"${kdePackages.qtwayland}/lib/qt-6/qml"
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,348 @@
|
|||||||
|
# Writable mode for dots-hyprland
|
||||||
|
# Stages configuration to .configstaging and provides setup script
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.dots-hyprland.writable-mode;
|
||||||
|
mainCfg = config.programs.dots-hyprland;
|
||||||
|
|
||||||
|
# Create the initial setup script
|
||||||
|
setupScript = pkgs.writeShellScript "dots-hyprland-setup" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "''${GREEN}[dots-hyprland]''${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo -e "''${YELLOW}[dots-hyprland]''${NC} WARNING: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "''${RED}[dots-hyprland]''${NC} ERROR: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "''${BLUE}[dots-hyprland]''${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
STAGING_DIR="$HOME/${cfg.stagingDir}"
|
||||||
|
CONFIG_DIR="$HOME/.config"
|
||||||
|
BACKUP_DIR="$HOME/.config-backup-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
|
||||||
|
log "🚀 dots-hyprland Initial Setup"
|
||||||
|
log "📁 Staging: $STAGING_DIR"
|
||||||
|
log "🎯 Target: $CONFIG_DIR"
|
||||||
|
|
||||||
|
# Check if staging directory exists
|
||||||
|
if [[ ! -d "$STAGING_DIR" ]]; then
|
||||||
|
error "Staging directory not found: $STAGING_DIR"
|
||||||
|
error "Please run 'home-manager switch' first to create the staging area"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup existing configuration if requested
|
||||||
|
${optionalString cfg.backupExisting ''
|
||||||
|
if [[ -d "$CONFIG_DIR" ]]; then
|
||||||
|
log "💾 Creating backup at $BACKUP_DIR"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Backup specific directories that will be overwritten
|
||||||
|
for dir in quickshell hypr fish foot kitty fuzzel wlogout; do
|
||||||
|
if [[ -d "$CONFIG_DIR/$dir" ]]; then
|
||||||
|
info " Backing up $dir"
|
||||||
|
cp -r "$CONFIG_DIR/$dir" "$BACKUP_DIR/" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log "✅ Backup complete"
|
||||||
|
fi
|
||||||
|
''}
|
||||||
|
|
||||||
|
# Function to copy or symlink files
|
||||||
|
copy_config() {
|
||||||
|
local src="$1"
|
||||||
|
local dst="$2"
|
||||||
|
local name="$(basename "$src")"
|
||||||
|
|
||||||
|
if [[ -d "$src" ]]; then
|
||||||
|
info "📂 Processing directory: $name"
|
||||||
|
mkdir -p "$dst"
|
||||||
|
|
||||||
|
${if cfg.symlinkMode then ''
|
||||||
|
# Create symlink
|
||||||
|
if [[ -L "$dst" ]]; then
|
||||||
|
rm "$dst"
|
||||||
|
elif [[ -d "$dst" ]]; then
|
||||||
|
rm -rf "$dst"
|
||||||
|
fi
|
||||||
|
ln -sf "$src" "$dst"
|
||||||
|
info " 🔗 Symlinked: $name"
|
||||||
|
'' else ''
|
||||||
|
# Copy files
|
||||||
|
cp -rf "$src"/* "$dst/" 2>/dev/null || true
|
||||||
|
info " 📋 Copied: $name"
|
||||||
|
''}
|
||||||
|
elif [[ -f "$src" ]]; then
|
||||||
|
info "📄 Processing file: $name"
|
||||||
|
mkdir -p "$(dirname "$dst")"
|
||||||
|
|
||||||
|
${if cfg.symlinkMode then ''
|
||||||
|
# Create symlink
|
||||||
|
if [[ -L "$dst" ]] || [[ -f "$dst" ]]; then
|
||||||
|
rm "$dst"
|
||||||
|
fi
|
||||||
|
ln -sf "$src" "$dst"
|
||||||
|
info " 🔗 Symlinked: $name"
|
||||||
|
'' else ''
|
||||||
|
# Copy file
|
||||||
|
cp "$src" "$dst"
|
||||||
|
info " 📋 Copied: $name"
|
||||||
|
''}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy/symlink all staged configuration
|
||||||
|
log "🔄 ${if cfg.symlinkMode then "Symlinking" else "Copying"} configuration files..."
|
||||||
|
|
||||||
|
# Process all directories in staging
|
||||||
|
for item in "$STAGING_DIR"/*; do
|
||||||
|
if [[ -e "$item" ]]; then
|
||||||
|
name="$(basename "$item")"
|
||||||
|
copy_config "$item" "$CONFIG_DIR/$name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy .local/share files if they exist
|
||||||
|
if [[ -d "$STAGING_DIR/.local/share" ]]; then
|
||||||
|
log "📦 Processing .local/share files..."
|
||||||
|
mkdir -p "$HOME/.local/share"
|
||||||
|
copy_config "$STAGING_DIR/.local/share/icons" "$HOME/.local/share/icons"
|
||||||
|
copy_config "$STAGING_DIR/.local/share/konsole" "$HOME/.local/share/konsole"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "✅ Configuration setup complete!"
|
||||||
|
log ""
|
||||||
|
log "📋 Next steps:"
|
||||||
|
log " 1. Your configuration is now ${if cfg.symlinkMode then "symlinked" else "copied"} to ~/.config/"
|
||||||
|
log " 2. ${if cfg.symlinkMode then "Files are symlinked - changes to staging will reflect immediately" else "Files are copied - you can now modify them freely"}"
|
||||||
|
log " 3. Test quickshell: quickshell"
|
||||||
|
log " 4. Test Python environment: test-dots-hyprland-venv"
|
||||||
|
${optionalString cfg.backupExisting ''
|
||||||
|
log " 5. Your original config was backed up to: $BACKUP_DIR"
|
||||||
|
''}
|
||||||
|
log ""
|
||||||
|
log "🎉 Enjoy your dots-hyprland setup!"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Create a status/info script
|
||||||
|
statusScript = pkgs.writeShellScript "dots-hyprland-status" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
echo -e "''${GREEN}dots-hyprland Status''${NC}"
|
||||||
|
echo "===================="
|
||||||
|
|
||||||
|
# Check staging directory
|
||||||
|
STAGING_DIR="$HOME/${cfg.stagingDir}"
|
||||||
|
if [[ -d "$STAGING_DIR" ]]; then
|
||||||
|
echo -e "✅ Staging directory: ''${GREEN}$STAGING_DIR''${NC}"
|
||||||
|
echo " $(find "$STAGING_DIR" -type f | wc -l) files staged"
|
||||||
|
else
|
||||||
|
echo -e "❌ Staging directory: ''${RED}Not found''${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Python virtual environment
|
||||||
|
VENV_PATH="$HOME/.local/state/quickshell/.venv"
|
||||||
|
if [[ -d "$VENV_PATH" ]]; then
|
||||||
|
echo -e "✅ Python venv: ''${GREEN}$VENV_PATH''${NC}"
|
||||||
|
if [[ -f "$VENV_PATH/bin/python" ]]; then
|
||||||
|
VERSION=$("$VENV_PATH/bin/python" --version 2>&1)
|
||||||
|
echo " $VERSION"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "❌ Python venv: ''${RED}Not found''${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check quickshell config
|
||||||
|
if [[ -d "$HOME/.config/quickshell" ]]; then
|
||||||
|
echo -e "✅ Quickshell config: ''${GREEN}~/.config/quickshell''${NC}"
|
||||||
|
if [[ -L "$HOME/.config/quickshell" ]]; then
|
||||||
|
echo " (symlinked to staging)"
|
||||||
|
else
|
||||||
|
echo " (copied from staging)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "❌ Quickshell config: ''${RED}Not found''${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check environment variable
|
||||||
|
if [[ -n "$ILLOGICAL_IMPULSE_VIRTUAL_ENV" ]]; then
|
||||||
|
echo -e "✅ Environment variable: ''${GREEN}ILLOGICAL_IMPULSE_VIRTUAL_ENV''${NC}"
|
||||||
|
echo " $ILLOGICAL_IMPULSE_VIRTUAL_ENV"
|
||||||
|
else
|
||||||
|
echo -e "❌ Environment variable: ''${RED}ILLOGICAL_IMPULSE_VIRTUAL_ENV not set''${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " ${cfg.setupScript} - Run initial setup"
|
||||||
|
echo " dots-hyprland-status - Show this status"
|
||||||
|
echo " test-dots-hyprland-venv - Test Python environment"
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.dots-hyprland.writable-mode = {
|
||||||
|
enable = mkEnableOption "Writable mode for dots-hyprland configuration";
|
||||||
|
|
||||||
|
source = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = "Source path for dots-hyprland configuration";
|
||||||
|
};
|
||||||
|
|
||||||
|
stagingDir = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = ".configstaging";
|
||||||
|
description = "Directory to stage configuration files";
|
||||||
|
};
|
||||||
|
|
||||||
|
setupScript = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "initialSetup.sh";
|
||||||
|
description = "Name of the setup script";
|
||||||
|
};
|
||||||
|
|
||||||
|
backupExisting = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Backup existing configuration files";
|
||||||
|
};
|
||||||
|
|
||||||
|
symlinkMode = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Create symlinks instead of copying files";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Stage all configuration files and install scripts
|
||||||
|
home.file =
|
||||||
|
let
|
||||||
|
# Get all config directories from source
|
||||||
|
configDirs = [
|
||||||
|
"quickshell" "hypr" "fish" "foot" "kitty" "fuzzel" "wlogout" "matugen"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Create staging entries for each config directory
|
||||||
|
stagingEntries = listToAttrs (map (dir: {
|
||||||
|
name = "${cfg.stagingDir}/${dir}";
|
||||||
|
value = {
|
||||||
|
source = "${cfg.source}/.config/${dir}";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
}) configDirs);
|
||||||
|
|
||||||
|
# Add NixOS-specific patches
|
||||||
|
nixosPatches = {
|
||||||
|
};
|
||||||
|
|
||||||
|
# Add .local/share files to staging
|
||||||
|
localShareEntries = {
|
||||||
|
"${cfg.stagingDir}/.local/share/icons" = {
|
||||||
|
source = "${cfg.source}/.local/share/icons";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
"${cfg.stagingDir}/.local/share/konsole" = {
|
||||||
|
source = "${cfg.source}/.local/share/konsole";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Scripts and utilities
|
||||||
|
scriptEntries = {
|
||||||
|
".local/bin/${cfg.setupScript}" = {
|
||||||
|
source = setupScript;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
".local/bin/dots-hyprland-status" = {
|
||||||
|
source = statusScript;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
"${cfg.stagingDir}/README.md" = {
|
||||||
|
text = ''
|
||||||
|
# dots-hyprland Configuration Staging
|
||||||
|
|
||||||
|
This directory contains the staged configuration files from the original dots-hyprland repository.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Run the setup script to copy/symlink these files to your ~/.config directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.local/bin/${cfg.setupScript}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mode: ${if cfg.symlinkMode then "Symlink" else "Copy"}
|
||||||
|
|
||||||
|
${if cfg.symlinkMode then ''
|
||||||
|
**Symlink Mode**: Files will be symlinked to ~/.config/
|
||||||
|
- Changes to files in staging will reflect immediately
|
||||||
|
- Useful for development and testing
|
||||||
|
- Files remain managed by Home Manager
|
||||||
|
'' else ''
|
||||||
|
**Copy Mode**: Files will be copied to ~/.config/
|
||||||
|
- You can modify the copied files freely
|
||||||
|
- Changes won't affect the staging area
|
||||||
|
- Full user control over configuration
|
||||||
|
''}
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Check the current status with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dots-hyprland-status
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files Staged
|
||||||
|
|
||||||
|
- quickshell/ - Widget system configuration
|
||||||
|
- hypr/ - Hyprland window manager configuration
|
||||||
|
- fish/ - Fish shell configuration
|
||||||
|
- foot/ - Foot terminal configuration
|
||||||
|
- kitty/ - Kitty terminal configuration
|
||||||
|
- fuzzel/ - Fuzzel launcher configuration
|
||||||
|
- wlogout/ - Logout menu configuration
|
||||||
|
- .local/share/icons/ - Custom icons
|
||||||
|
- .local/share/konsole/ - Konsole profiles
|
||||||
|
|
||||||
|
## Python Environment
|
||||||
|
|
||||||
|
The Python virtual environment is managed separately and will be created at:
|
||||||
|
`~/.local/state/quickshell/.venv`
|
||||||
|
|
||||||
|
Test it with: `test-dots-hyprland-venv`
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
stagingEntries // localShareEntries // scriptEntries // nixosPatches;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
# Package mappings from dots-hyprland meta-packages to nixpkgs
|
||||||
|
# Direct mapping from PKGBUILD files in arch-packages/
|
||||||
|
{ lib, pkgs }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# illogical-impulse-basic PKGBUILD
|
||||||
|
basicPackages = with pkgs; [
|
||||||
|
axel
|
||||||
|
bc
|
||||||
|
coreutils
|
||||||
|
cliphist
|
||||||
|
cmake
|
||||||
|
curl
|
||||||
|
rsync
|
||||||
|
wget
|
||||||
|
ripgrep
|
||||||
|
jq
|
||||||
|
meson
|
||||||
|
xdg-user-dirs
|
||||||
|
];
|
||||||
|
|
||||||
|
# illogical-impulse-widgets PKGBUILD
|
||||||
|
widgetPackages = with pkgs; [
|
||||||
|
fuzzel
|
||||||
|
glib # for gsettings
|
||||||
|
hypridle
|
||||||
|
hyprutils
|
||||||
|
hyprlock
|
||||||
|
hyprpicker
|
||||||
|
networkmanagerapplet # nm-connection-editor
|
||||||
|
# quickshell-git -> provided by quickshell flake input
|
||||||
|
translate-shell
|
||||||
|
wlogout
|
||||||
|
|
||||||
|
# Qt modules needed for quickshell widgets
|
||||||
|
kdePackages.qt5compat # For Qt5Compat.GraphicalEffects
|
||||||
|
kdePackages.qtdeclarative # For QML
|
||||||
|
kdePackages.qtwayland # For Wayland support
|
||||||
|
];
|
||||||
|
|
||||||
|
# illogical-impulse-hyprland PKGBUILD
|
||||||
|
hyprlandPackages = with pkgs; [
|
||||||
|
hypridle
|
||||||
|
hyprcursor
|
||||||
|
hyprland
|
||||||
|
hyprland-qtutils
|
||||||
|
# hyprland-qt-support -> might be in hyprland-qtutils
|
||||||
|
hyprlang
|
||||||
|
hyprlock
|
||||||
|
hyprpicker
|
||||||
|
hyprsunset
|
||||||
|
hyprutils
|
||||||
|
hyprwayland-scanner
|
||||||
|
xdg-desktop-portal-hyprland
|
||||||
|
wl-clipboard
|
||||||
|
];
|
||||||
|
|
||||||
|
# illogical-impulse-python PKGBUILD (system dependencies)
|
||||||
|
pythonSystemPackages = with pkgs; [
|
||||||
|
clang
|
||||||
|
# uv -> not needed in NixOS approach, we use pip directly
|
||||||
|
gtk4
|
||||||
|
libadwaita
|
||||||
|
libsoup_3 # libsoup3
|
||||||
|
libportal-gtk4
|
||||||
|
gobject-introspection
|
||||||
|
sassc
|
||||||
|
opencv4 # python-opencv
|
||||||
|
];
|
||||||
|
|
||||||
|
# Additional packages that might be needed
|
||||||
|
audioPackages = with pkgs; [
|
||||||
|
pipewire
|
||||||
|
wireplumber
|
||||||
|
pavucontrol
|
||||||
|
playerctl
|
||||||
|
];
|
||||||
|
|
||||||
|
# Font packages (from installer analysis)
|
||||||
|
fontPackages = with pkgs; [
|
||||||
|
# Rubik font (installer sets this as default)
|
||||||
|
# Note: might need to add custom font derivation
|
||||||
|
noto-fonts
|
||||||
|
noto-fonts-cjk-sans
|
||||||
|
noto-fonts-emoji
|
||||||
|
font-awesome
|
||||||
|
material-design-icons
|
||||||
|
nerd-fonts.jetbrains-mono
|
||||||
|
nerd-fonts.fira-code
|
||||||
|
];
|
||||||
|
|
||||||
|
# Theme and appearance packages
|
||||||
|
themePackages = with pkgs; [
|
||||||
|
matugen # for Material You color generation
|
||||||
|
# Additional theme packages as needed
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit
|
||||||
|
basicPackages
|
||||||
|
widgetPackages
|
||||||
|
hyprlandPackages
|
||||||
|
pythonSystemPackages
|
||||||
|
audioPackages
|
||||||
|
fontPackages
|
||||||
|
themePackages;
|
||||||
|
|
||||||
|
# Combined package sets for different use cases
|
||||||
|
essentialPackages = basicPackages ++ widgetPackages ++ hyprlandPackages;
|
||||||
|
|
||||||
|
allPackages = basicPackages ++ widgetPackages ++ hyprlandPackages ++
|
||||||
|
pythonSystemPackages ++ audioPackages ++ fontPackages ++ themePackages;
|
||||||
|
|
||||||
|
# Minimal set for testing
|
||||||
|
minimalPackages = basicPackages ++ widgetPackages;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user