50 Commits

Author SHA1 Message Date
Hadi 0cef4320fd Waybar here i come (#58) 2026-08-13 13:55:30 +02:00
Hadi f1f22de7b7 feat: new zsh config
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-12 20:31:52 +02:00
Hadi f73f992540 change theme
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 21:20:44 +02:00
Hadi d29e164c99 remove spicetify
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 21:20:37 +02:00
Hadi 9787f677de remove docker from dev pkgs
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 21:12:21 +02:00
Hadi 16eb64de6e pin docker version
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 21:10:28 +02:00
Hadi f3d9a4b428 edit yazi config
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 20:50:05 +02:00
Hadi 30e14103d1 add sheets, pom & slides
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 20:24:21 +02:00
Hadi 23d7c0b460 Change themes
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-09 20:19:27 +02:00
Hadi 075f8c4a11 add chafa to nvim
Signed-off-by: Hadi <hadi@example.com>
2026-06-09 15:51:49 +02:00
Hadi 0c89a3d7e5 Edit dashboard, colors & add yazi
Signed-off-by: Hadi <hadi@example.com>
2026-06-09 15:19:37 +02:00
Hadi 9000ed8e28 remove full border
Signed-off-by: Hadi <hadi@example.com>
2026-06-09 15:19:07 +02:00
Hadi 9365de4822 Execute shell commands, surrounds.nvim, ...
Signed-off-by: Hadi <hadi@example.com>
2026-06-09 13:59:52 +02:00
Hadi 207c49fff8 edit yazi config
Signed-off-by: Hadi <hadi@example.com>
2026-06-09 13:29:26 +02:00
Hadi 120a6df4ed add chafa
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-08 20:51:27 +02:00
Hadi f036f367da add gh & gh-dash
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-08 20:28:40 +02:00
Hadi 6fc06f8616 add yazi plugins
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-08 20:04:48 +02:00
Hadi 9880cbeb0f impala -> wifitui
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-08 20:04:22 +02:00
Hadi bb6cb8c00e remove deadcode
Signed-off-by: Hadi <hadi@example.com>
2026-06-08 15:18:48 +02:00
Hadi beeb29276c nur-anotherhadi
Signed-off-by: Hadi <hadi@example.com>
2026-06-08 14:47:28 +02:00
Hadi a2aa6c3d08 add yazi, wiremix, impala, ..
Signed-off-by: Hadi <hadi@example.com>
2026-06-05 11:43:09 +02:00
Hadi 83b0a34256 update & add packages
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-04 22:29:02 +02:00
Hadi 1459743717 run in background
Signed-off-by: Hadi <hadi@example.com>
2026-06-04 16:35:15 +02:00
Hadi c76f503dcc add TUIs
Signed-off-by: Hadi <hadi@example.com>
2026-06-04 16:20:41 +02:00
Hadi 7931f68e41 init spotatui
Signed-off-by: Hadi <hadi@example.com>
2026-06-04 16:12:55 +02:00
Hadi 5f74119742 Merge branch 'main' of github.com:anotherhadi/nixy 2026-06-04 11:12:07 +02:00
Hadi e593974327 disable rounded_frame
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-01 22:23:04 +02:00
Hadi b245cfacf9 woops
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-01 22:22:50 +02:00
Hadi 38c00b16f1 change tuigreet config
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-06-01 20:36:40 +02:00
Hadi 5a0bf2e2ac Merge branch 'main' of github.com:anotherhadi/nixy 2026-06-01 20:36:18 +02:00
Hadi 66758b8c24 add clear alias
Signed-off-by: Hadi <hadi@example.com>
2026-06-01 16:08:35 +02:00
Hadi 4c4035acf3 add bookmark
Signed-off-by: Hadi <hadi@example.com>
2026-06-01 16:08:31 +02:00
Hadi cced6d4f3a remove hardtime
Signed-off-by: Hadi <hadi@example.com>
2026-06-01 11:39:21 +02:00
Hadi 8aa58a2d0d Merge branch 'main' of github.com:anotherhadi/nixy 2026-06-01 10:02:40 +02:00
Hadi 94903f7b8a add apps
Signed-off-by: Hadi <hadi@example.com>
2026-06-01 10:02:28 +02:00
Hadi bf44f38fa0 Change tuigreet bin
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-05-30 23:32:47 +02:00
Hadi dbc68cdfc5 fix keyboards
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-05-30 22:02:32 +02:00
Hadi d25bc65534 remove hardtime.nvim
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-05-30 20:25:15 +02:00
Hadi 8d4f4cfd41 getting back to tuigreet
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-05-30 20:25:08 +02:00
Hadi ff31020187 Add ilovetui colors
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
2026-05-29 20:08:20 +02:00
Hadi 93971606b9 use theme opacity
Signed-off-by: Hadi <hadi@example.com>
2026-05-28 11:58:35 +02:00
Hadi 092cf1cbd7 solve warnings
Signed-off-by: Hadi <hadi@example.com>
2026-05-28 11:50:53 +02:00
Hadi 37c6211cb8 windowrules for helium
Signed-off-by: Hadi <hadi@example.com>
2026-05-28 11:43:17 +02:00
Hadi 7793ac81c4 edit spf config
Signed-off-by: Hadi <hadi@example.com>
2026-05-28 10:10:56 +02:00
Hadi bc6dd4e7a2 add a new usb key
Signed-off-by: Hadi <hadi@example.com>
2026-05-28 09:22:49 +02:00
Hadi 517465799f transparent backgroud
Signed-off-by: Hadi <hadi@example.com>
2026-05-27 16:57:10 +02:00
Hadi e5dc149b99 add hardtime.nvim
Signed-off-by: Hadi <hadi@example.com>
2026-05-27 15:09:52 +02:00
Hadi bae9ba2206 add superfile
Signed-off-by: Hadi <hadi@example.com>
2026-05-27 15:02:23 +02:00
Hadi f578134eda add nvf bookmark
Signed-off-by: Hadi <hadi@example.com>
2026-05-27 15:02:18 +02:00
Hadi c082fd0e34 update flakes
Signed-off-by: Hadi <hadi@example.com>
2026-05-27 14:13:43 +02:00
142 changed files with 3909 additions and 3347 deletions
+1
View File
@@ -0,0 +1 @@
use flake
-134
View File
@@ -1,134 +0,0 @@
<div align="center">
<img alt="nixy logo" src="./.github/assets/logo.png" width="120px" />
</div>
<br>
# Nixy
<br>
<div align="center">
<a href="https://github.com/anotherhadi/nixy/stargazers">
<img src="https://img.shields.io/github/stars/anotherhadi/nixy?color={primarycolor}&labelColor={backgroundcolor}&style=for-the-badge&logo=starship&logoColor={primarycolor}">
</a>
<a href="https://github.com/anotherhadi/nixy/">
<img src="https://img.shields.io/github/repo-size/anotherhadi/nixy?color={primarycolor}&labelColor={backgroundcolor}&style=for-the-badge&logo=github&logoColor={primarycolor}">
</a>
<a href="https://nixos.org">
<img src="https://img.shields.io/badge/NixOS-unstable-blue.svg?style=for-the-badge&labelColor={backgroundcolor}&logo=NixOS&logoColor={primarycolor}&color={primarycolor}">
</a>
<a href="https://github.com/anotherhadi/nixy/blob/main/LICENSE">
<img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=MIT&colorA={backgroundcolor}&colorB={primarycolor}&logo=unlicense&logoColor={primarycolor}"/>
</a>
</div>
<br>
**Nixy simplifies and unifies** the Hyprland ecosystem with a modular, easily
customizable setup. It provides a structured way to manage your system
configuration and dotfiles with minimal effort. It includes _home-manager_,
_secrets_, and _custom theming_ all in one place.
**Features:**
- 💻 Hyprland & Caelestia: Preconfigured Hyprland ecosystem with Caelestia-shell (Ty to both projects!)
- 🎨 Consistent Theming: Base16 & Stylix-powered themes
- ⌨️ Vim-like Everywhere: Unified keybindings (Hyprland, nvim, vimium, etc.)
## Table of Content
{md_table_of_content}
## Screenshots
![Home](.github/assets/rose-pine/home.png)
![Flake & Spotify](.github/assets/rose-pine/flake-spotify.png)
![Browser and notification center](.github/assets/rose-pine/browser-and-notifications.png)
## Architecture
### 🏠 /home (User-level configuration)
Contains **dotfiles and settings** that apply to your user environment.
**Subfolders:**
- `programs` is a collection of apps configured with home-manager
- `system` is some "desktop environment" configuration
### 🐧 /nixos
Those are the system-level configurations. (audio, bluetooth, gpu, bootloader,
...)
### 🎨 /themes
This folder contains all system themes. Mainly
[stylix](https://stylix.danth.me/) configurations. Check out the available
themes and learn how to create your own in [THEMES.md](docs/THEMES.md)
### 💻 /hosts
This directory contains host-specific configurations. Each host includes:
- `configuration.nix` for system-wide settings
- `home.nix` for user-level configuration
- `variables.nix` for global variables
- `secrets/` for sensitive data
### 🖥️ /server-modules
This folder contains server-related nixos modules. (bitwarden, nextcloud, ...)
## Installation
1. [Fork](https://github.com/anotherhadi/nixy/fork) this repo and clone it to
your system:
```sh
git clone https://github.com/anotherhadi/nixy ~/.config/nixos
```
2. Copy the `hosts/laptop` folder, rename it to match your systems hostname,
and update `variables.nix` with your machines settings.
3. Copy your `hardware-configuration.nix` into your new host's folder to ensure
proper hardware support.
4. Register your new host in `flake.nix` by adding it under nixosConfigurations.
> [!IMPORTANT]
> `# CHANGEME` comments are placed throughout the config to
> indicate necessary modifications. Use the following command to quickly locate
> them:
>
> ```sh
> rg "CHANGEME" ~/.config/nixos
> ```
> [!TIP]
> When you add new files, don't forget to run `git add .` to add them to the git
> repository
5. Build the system
```sh
sudo nixos-rebuild switch --flake ~/.config/nixos#yourhostname
```
## Documentation
- [SERVER](docs/SERVER.md): Check out the server documentation
- [THEMES](docs/THEMES.md): How themes work and how to create your own
- [WALLPAPERS](https://github.com/anotherhadi/awesome-wallpapers): An awesome
collection of wallpapers
- [NEOVIM](docs/NEOVIM.md): How to use the Neovim config in your own flake
- [GROUPS](docs/GROUPS.md): Reusable package groups (dev, cybersecurity)
- [CONTRIBUTING](docs/CONTRIBUTING.md): How to contribute
- [LICENSE](LICENSE): MIT License
---
<div align="center">
<a href="https://github.com/anotherhadi/nixy">github</a> |
<a href="https://gitlab.com/anotherhadi_mirror/nixy">gitlab (mirror)</a> |
<a href="https://git.hadi.icu/anotherhadi/nixy">gitea (mirror)</a>
</div
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env bash
# Create the README.md file from the .github/assets/README_template.md file
[[ -d "./docs" ]] || (echo "Folder ./docs not found" && exit 1)
README_FILE="./README.md"
table_of_content=$(markdown-table-of-contents --start-by 2 ./.github/assets/README_template.md) # https://github.com/anotherhadi/markdown-table-of-contents
readme_content=$(cat "./.github/assets/README_template.md")
# Replace variables
readme_content=${readme_content//\{primarycolor\}/A89AD1}
readme_content=${readme_content//\{backgroundcolor\}/0b0b0b}
readme_content=${readme_content//\{md_table_of_content\}/$table_of_content}
echo "[//]: # (This file is autogenerated)" >"$README_FILE"
echo "$readme_content" >>"$README_FILE"
sed 's/\r//' "$README_FILE" >"/tmp/readme.md"
mv "/tmp/readme.md" "$README_FILE"
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
import re
import subprocess
import sys
from pathlib import Path
PATTERN = re.compile(r"<!-- exec: (.+?) -->.*?<!-- endexec -->", re.DOTALL)
def replace(match):
cmd = match.group(1).strip()
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
output = result.stdout
if result.returncode != 0:
print(
f"[inject-exec] command failed ({result.returncode}): {cmd}",
file=sys.stderr,
)
print(result.stderr, file=sys.stderr)
sys.exit(1)
output = re.sub(r"<!-- exec: .+? -->\n?|<!-- endexec -->\n?", "", output)
if output and not output.endswith("\n"):
output += "\n"
return f"<!-- exec: {cmd} -->\n{output}<!-- endexec -->"
def process(path):
content = Path(path).read_text()
new_content = PATTERN.sub(replace, content)
if new_content != content:
Path(path).write_text(new_content)
print(f"[inject-exec] updated {path}")
for p in sys.argv[1:]:
process(p)
-31
View File
@@ -1,31 +0,0 @@
on:
push:
paths:
- '.github/assets/README_template.md'
permissions:
contents: write
jobs:
update-readme:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./
steps:
- name: Check out the repository to the runner
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '^1.23'
- name: Install required dependencies
run: |
go install github.com/anotherhadi/markdown-table-of-contents@latest
- name: Run a script
run: |
chmod +x ./.github/scripts/create_readme.sh
./.github/scripts/create_readme.sh
git config user.name github-actions
git config user.email github-actions@github.com
git add .
git commit -m "Update README.md (auto)" && git push
exit 0
+5
View File
@@ -1,3 +1,8 @@
.sops.yaml .sops.yaml
.claude/ .claude/
old/ old/
docs/superpowers/
.superpowers/
result/
.pre-commit-config.yaml
.direnv/
+11 -9
View File
@@ -1,4 +1,3 @@
[//]: # (This file is autogenerated)
<div align="center"> <div align="center">
<img alt="nixy logo" src="./.github/assets/logo.png" width="120px" /> <img alt="nixy logo" src="./.github/assets/logo.png" width="120px" />
</div> </div>
@@ -24,20 +23,22 @@
</div> </div>
<br> <br>
**Nixy simplifies and unifies** the Hyprland ecosystem with a modular, easily **Nixy simplifies and unifies** the Hyprland ecosystem with a modular, minimalist & easily
customizable setup. It provides a structured way to manage your system customizable setup. It provides a structured way to manage your system
configuration and dotfiles with minimal effort. It includes _home-manager_, configuration and dotfiles with minimal effort. It includes _home-manager_,
_secrets_, and _custom theming_ all in one place. _secrets_, and _custom theming_ all in one place.
**Features:** **Features:**
- 💻 Hyprland & Caelestia: Preconfigured Hyprland ecosystem with Caelestia-shell (Ty to both projects!) - 💻 Hyprland & TUIs: Preconfigured Hyprland ecosystem with a lot of cool TUIs
- 🎨 Consistent Theming: Base16 & Stylix-powered themes - 🎨 Consistent Theming: Base16 & Stylix-powered themes
- ⌨️ Vim-like Everywhere: Unified keybindings (Hyprland, nvim, vimium, etc.) - ⌨️ Vim-like Everywhere: Unified keybindings (Hyprland, nvim, vimium, etc.)
## Table of Content ## Table of Content
- [Table of Content](#table-of-content) <!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Screenshots](#screenshots) - [Screenshots](#screenshots)
- [Architecture](#architecture) - [Architecture](#architecture)
- [🏠 /home (User-level configuration)](#-home-user-level-configuration) - [🏠 /home (User-level configuration)](#-home-user-level-configuration)
@@ -48,11 +49,13 @@ _secrets_, and _custom theming_ all in one place.
- [Installation](#installation) - [Installation](#installation)
- [Documentation](#documentation) - [Documentation](#documentation)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Screenshots ## Screenshots
![Home](.github/assets/rose-pine/home.png) ![Home](.github/assets/screenshots/1.png)
![Flake & Spotify](.github/assets/rose-pine/flake-spotify.png) ![Neovim and spotify](.github/assets/screenshots/2.png)
![Browser and notification center](.github/assets/rose-pine/browser-and-notifications.png) ![Browser and file explorer](.github/assets/screenshots/3.png)
## Architecture ## Architecture
@@ -87,7 +90,7 @@ This directory contains host-specific configurations. Each host includes:
### 🖥️ /server-modules ### 🖥️ /server-modules
This folder contains server-related nixos modules. (bitwarden, nextcloud, ...) This folder contains server-related nixos modules. (gitea, cloudflared, self-hosted apps, ...)
## Installation ## Installation
@@ -130,7 +133,6 @@ sudo nixos-rebuild switch --flake ~/.config/nixos#yourhostname
- [WALLPAPERS](https://github.com/anotherhadi/awesome-wallpapers): An awesome - [WALLPAPERS](https://github.com/anotherhadi/awesome-wallpapers): An awesome
collection of wallpapers collection of wallpapers
- [NEOVIM](docs/NEOVIM.md): How to use the Neovim config in your own flake - [NEOVIM](docs/NEOVIM.md): How to use the Neovim config in your own flake
- [GROUPS](docs/GROUPS.md): Reusable package groups (dev, cybersecurity)
- [CONTRIBUTING](docs/CONTRIBUTING.md): How to contribute - [CONTRIBUTING](docs/CONTRIBUTING.md): How to contribute
- [LICENSE](LICENSE): MIT License - [LICENSE](LICENSE): MIT License
-3
View File
@@ -9,8 +9,5 @@ The process is straight-forward.
- Write your changes (new theme, bug fixes, issues fix, ...). - Write your changes (new theme, bug fixes, issues fix, ...).
- Create a Pull Request against the main branch of Nixy. - Create a Pull Request against the main branch of Nixy.
> [!TIP]
> To update the README, change the `./.github/assets/README_template.md`
> [!IMPORTANT] > [!IMPORTANT]
> Don't push your host's folder > Don't push your host's folder
-44
View File
@@ -1,44 +0,0 @@
# Groups
Groups are curated sets of packages exposed as flake outputs. Each group has two forms:
- **`homeManagerModules.<group>`** — full home-manager module (packages + files + systemd units)
- **`packages.<group>`** — standalone environment for `nix shell` (packages only)
## Available groups
- dev (go, bun, air, ...)
- cybersecurity (nmap, john, dirb, ffuf, ...)
For the Cybersecurity group, the home-manager module also sets up:
- `~/Cyber/wordlists/` with SecLists, fuzz4bounty, and hashcat rules
- `~/Cyber/tmp/` as a temporary workspace
## Use in another flake
Add this repo as an input:
```nix
inputs.nixy.url = "github:anotherhadi/nixy";
```
Import the home-manager module in your home configuration:
```nix
{ inputs, ... }: {
imports = [
inputs.nixy.homeManagerModules.cybersecurity
# inputs.nixy.homeManagerModules.dev
];
}
```
## Quick shell without installing
```sh
nix shell github:anotherhadi/nixy#cybersecurity
nix shell github:anotherhadi/nixy#dev
```
This drops you into a shell with all tools in `PATH`. No home-manager required, no wordlists or systemd units.
+1 -1
View File
@@ -37,4 +37,4 @@ Then import the home-manager module in your home configuration:
| `picker.nix` | Snacks picker + oil.nvim | | `picker.nix` | Snacks picker + oil.nvim |
| `snacks.nix` | Snacks extras: image preview, zen mode, git signs, statuscolumn | | `snacks.nix` | Snacks extras: image preview, zen mode, git signs, statuscolumn |
| `utils.nix` | Bufferline, lualine, copilot, lazygit, toggleterm, autocomplete | | `utils.nix` | Bufferline, lualine, copilot, lazygit, toggleterm, autocomplete |
| `mini.nix` | Mini.nvim suite: pairs, comment, icons, indentscope, diff, git | | `mini.nix` | Mini.nvim suite: ai, clue, comment, diff, git, icons, indentscope, jump2d, pairs, starter, statusline, surround |
+8 -4
View File
@@ -5,7 +5,7 @@
This document describes the architecture and setup of the self-hosted **NixOS server**, which is securely accessible via **a Cloudflare Tunnel**. This document describes the architecture and setup of the self-hosted **NixOS server**, which is securely accessible via **a Cloudflare Tunnel**.
The server is designed for private, secure, and easily manageable self-hosting of various services. The server is designed for private, secure, and easily manageable self-hosting of various services.
![server dashboard](../.github/assets/server_dashboard.png) ![server dashboard](../.github/assets/screenshots/server_dashboard.png)
## **Why This Setup?** ## **Why This Setup?**
@@ -17,13 +17,17 @@ The server is designed for private, secure, and easily manageable self-hosting o
The server hosts several key applications: The server hosts several key applications:
- **NGINX**: Reverse proxy for routing traffic to services via my domain name.
- **AdGuard Home**: A self-hosted DNS ad blocker for network-wide ad and tracker filtering. - **AdGuard Home**: A self-hosted DNS ad blocker for network-wide ad and tracker filtering.
- **Glance**: An awesome dashboard! (See the screenshot above) - **Glance**: An awesome dashboard! (See the screenshot above)
- **Arr Stack (Radarr, Sonarr, etc.)**: Automated media management tools for handling movies and TV shows. (legaly ofc) - **Arr Stack (Radarr, Sonarr, etc.)**: Automated media management tools for handling movies and TV shows. (legally ofc)
- **Mealie**: A self-hosted recipe manager and meal planner with a clean user interface. - **Mealie**: A self-hosted recipe manager and meal planner with a clean user interface.
- **Stirling-PDF**: A powerful, locally hosted web application for editing, merging, and converting PDF files. - **Stirling-PDF**: A powerful, locally hosted web application for editing, merging, and converting PDF files.
- **CyberChef**: The "Cyber Swiss Army Knife" for data analysis, decoding, and encryption tasks. - **CyberChef**: The "Cyber Swiss Army Knife" for data analysis, decoding, and encryption tasks.
- **Mazanoke**: A utility service for image processing, specialized in format conversion and downgrading/optimization. - **Mazanoke**: A utility service for image processing, specialized in format conversion and downgrading/optimization.
- **Umami**: Privacy-focused web analytics.
- **Gitea**: Self-hosted git forge.
- **Blog**: Personal website/blog.
- **iknowyou**: Personal project hosted in two containers (prod + demo).
- **Awesome Wallpapers**: Wallpaper browser served via NGINX inside a container.
- **SSH**: Secure remote access configuration for server management. (via browser too) - **SSH**: Secure remote access configuration for server management. (via browser too)
- **Security related stuff**: Cloudflared, Fail2Ban, Firewall - **Security related stuff**: Cloudflared, Fail2Ban, Firewall, Kernel Hardening
+4 -12
View File
@@ -1,17 +1,9 @@
# Themes # Themes
Themes are defined in `themes`. Those themes define the colors, fonts, icons, etc, used by Hyprland and the apps/programs installed. Themes are defined in `themes/`. They define the colors, fonts, icons, wallpaper, and other visual settings used by Hyprland and all apps/programs.
You can change the selected theme by changing the import statement of your host's variables.nix file. You can change the selected theme by changing the import statement in your host's `variables.nix` file.
## Create your theme ## Create your theme
Create a copy of one of the existing themes and change the variables. Create a copy of `themes/nixy.nix` and change the variables.
Wallpapers are loaded from the [hadi's awesome-wallpapers](https://github.com/anotherhadi/awesome-wallpapers) repo. Wallpapers are loaded from my [awesome-wallpapers](https://github.com/anotherhadi/awesome-wallpapers) repo.
## Gallery
### Rose-pine
![Home](../.github/assets/rose-pine/home.png)
![Flake & Spotify](../.github/assets/rose-pine/flake-spotify.png)
![Browser and notification center](../.github/assets/rose-pine/browser-and-notifications.png)
Generated
+281 -1149
View File
File diff suppressed because it is too large Load Diff
+49 -26
View File
@@ -6,78 +6,101 @@
''; '';
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-26.05";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.11"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
nixos-hardware.url = "github:NixOS/nixos-hardware/master"; nixos-hardware.url = "github:NixOS/nixos-hardware";
hyprland.url = "git+https://github.com/hyprwm/Hyprland?submodules=1";
stylix.url = "github:danth/stylix";
sops-nix.url = "github:Mic92/sops-nix";
nvf.url = "github:notashelf/nvf"; nvf.url = "github:notashelf/nvf";
bun2nix.url = "github:nix-community/bun2nix"; nvf-config = {
usbguard-tui.url = "github:anotherhadi/usbguard-tui"; url = "path:./home/programs/tui/nvf";
jwt-tui.url = "github:anotherhadi/jwt-tui"; inputs.nixpkgs.follows = "nixpkgs";
inputs.nvf.follows = "nvf";
};
nur = {
url = "github:nix-community/nur";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-index-database = { nix-index-database = {
url = "github:nix-community/nix-index-database"; url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
home-manager = { home-manager = {
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager/release-26.05";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
caelestia-shell = { stylix = {
url = "github:caelestia-dots/shell"; url = "github:nix-community/stylix/release-26.05";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
caelestia-cli = { sops-nix = {
url = "github:caelestia-dots/cli"; url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
spicetify-nix = { notashelf-tuigreet = {
url = "github:Gerg-L/spicetify-nix"; url = "github:NotAShelf/tuigreet";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
helium-browser = {
url = "github:oxcl/nix-flake-helium-browser";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
# Server # Server
# FIXME: Deleted repo for now
# eleakxir.url = "github:anotherhadi/eleakxir";
nixarr.url = "github:rasmus-kirk/nixarr"; nixarr.url = "github:rasmus-kirk/nixarr";
default-creds.url = "github:anotherhadi/default-creds"; default-creds.url = "github:anotherhadi/default-creds";
blog.url = "github:anotherhadi/blog"; blog.url = "github:anotherhadi/blog";
awesome-wallpapers.url = "github:anotherhadi/awesome-wallpapers"; awesome-wallpapers.url = "github:anotherhadi/awesome-wallpapers";
iknowyou.url = "github:anotherhadi/iknowyou"; iknowyou.url = "github:anotherhadi/iknowyou";
spilltea.url = "github:anotherhadi/spilltea";
helium-browser.url = "github:oxcl/nix-flake-helium-browser";
}; };
outputs = inputs @ { outputs = inputs @ {
nixpkgs, nixpkgs,
nixpkgs-stable, nixpkgs-unstable,
git-hooks,
... ...
}: let }: let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs-unstable = import nixpkgs-unstable {
inherit system;
config.allowUnfree = true;
};
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
args = { args = {
inherit inherit
inputs inputs
nixpkgs nixpkgs
system system
pkgs-unstable
pkgs pkgs
; ;
pkgs-stable = nixpkgs-stable.legacyPackages.${system};
}; };
merge = nixpkgs.lib.foldl nixpkgs.lib.recursiveUpdate {}; merge = nixpkgs.lib.foldl nixpkgs.lib.recursiveUpdate {};
supportedSystems = ["x86_64-linux" "aarch64-linux"];
forAllSystems = f:
nixpkgs.lib.genAttrs supportedSystems
(system: f system (import nixpkgs {inherit system;}));
in in
merge [ merge [
(import ./home/programs/nvf/flake.nix args) (import ./home/programs/tui/nixy/flake.nix args)
(import ./home/programs/group/flake.nix args)
(import ./home/programs/nixy/flake.nix args)
{ {
formatter.${system} = pkgs.alejandra; formatter.${system} = pkgs.alejandra;
packages.${system}.nvim = inputs.nvf-config.packages.${system}.nvim;
apps.${system}.nvim = inputs.nvf-config.apps.${system}.nvim;
nixosConfigurations = { nixosConfigurations = {
h-laptop = import ./hosts/laptop/flake.nix args; h-laptop = import ./hosts/laptop/flake.nix args;
h-work = import ./hosts/work/flake.nix args; h-work = import ./hosts/work/flake.nix args;
jack = import ./hosts/server/flake.nix args; jack = import ./hosts/server/flake.nix args;
}; };
devShells = forAllSystems (system: pkgs: {
default = import ./shell.nix {
inherit pkgs;
gitHooksLib = git-hooks.lib.${system};
};
});
} }
]; ];
} }
+34 -33
View File
@@ -1,39 +1,40 @@
{ {pkgs}: (with pkgs; [
pkgs, # Web
pkgs-stable,
inputs,
system,
}:
(with pkgs-stable; [
httpie
trufflehog
sttr
wireshark
nmap
john
hashcat
metasploit
haiti
hydra
dnsrecon
whois
dig
nosqli
jwt-cli
nuclei
caido
gobuster
dirb dirb
ffuf ffuf
sqlmap
katana katana
inetutils whatweb
samba sqlmap
openvpn nosqli
# Hashes
hashcat
haiti
john
# Databases
mariadb mariadb
redis redis
# Network
inetutils
termshark # wireshark in TUI
whois
dig
nmap
samba
hydra
# Misc
metasploit
nuclei
openvpn
# Secrets
trufflehog
# Forensics
binwalk
pkgs.nur.repos.anotherhadi.spilltea
pkgs.nur.repos.anotherhadi.jwt-tui
]) ])
++ [
inputs.spilltea.packages.${system}.default
inputs.jwt-tui.packages.${system}.default
]
+2 -8
View File
@@ -1,12 +1,6 @@
{ {pkgs, ...}: {
inputs,
pkgs-stable,
pkgs,
...
}: {
home.packages = import ./cybersecurity-packages.nix { home.packages = import ./cybersecurity-packages.nix {
inherit pkgs pkgs-stable inputs; inherit pkgs;
system = pkgs.stdenv.hostPlatform.system;
}; };
systemd.user.tmpfiles.rules = [ systemd.user.tmpfiles.rules = [
-22
View File
@@ -1,22 +0,0 @@
{
pkgs,
pkgs-stable,
inputs,
system,
}:
(with pkgs; [
go
bun
nodejs
claude-code
inputs.bun2nix.packages.${system}.default
])
++ (with pkgs-stable; [
air
duckdb
docker
python3
jq
just
nix-prefetch-github
])
+15 -6
View File
@@ -1,11 +1,20 @@
{ {
pkgs, pkgs,
pkgs-stable, pkgs-unstable,
inputs,
... ...
}: { }: {
home.packages = import ./dev-packages.nix { home.packages = with pkgs-unstable;
inherit pkgs pkgs-stable inputs; [
system = pkgs.stdenv.hostPlatform.system; go
}; claude-code
]
++ (with pkgs; [
nodejs
air
duckdb
python3
jq
nix-prefetch-github
rsync
]);
} }
-21
View File
@@ -1,21 +0,0 @@
{
inputs,
pkgs,
pkgs-stable,
system,
...
}: let
devPackages = import ./dev-packages.nix {inherit pkgs pkgs-stable inputs system;};
cyberPackages = import ./cybersecurity-packages.nix {inherit pkgs pkgs-stable inputs system;};
in {
packages.${system} = {
dev = pkgs.buildEnv {
name = "dev-tools";
paths = devPackages;
};
cybersecurity = pkgs.buildEnv {
name = "cybersecurity-tools";
paths = cyberPackages;
};
};
}
-14
View File
@@ -1,14 +0,0 @@
{
pkgs-stable,
inputs,
...
}: {
home.packages = with pkgs-stable; [
peaclock
cbonsai
pipes
cmatrix
fastfetch
inputs.usbguard-tui.packages.${system}.default
];
}
@@ -1,7 +1,7 @@
{ {
config, config,
lib, lib,
pkgs, pkgs-unstable,
... ...
}: let }: let
bookmarkList = bookmarkList =
@@ -451,7 +451,7 @@ in {
}; };
Service = { Service = {
Type = "simple"; Type = "simple";
ExecStart = "${pkgs.darkhttpd}/bin/darkhttpd %h/.local/share/helium-startpage --port 8888 --addr 127.0.0.1 --no-listing"; ExecStart = "${pkgs-unstable.darkhttpd}/bin/darkhttpd %h/.local/share/helium-startpage --port 8888 --addr 127.0.0.1 --no-listing";
Restart = "on-failure"; Restart = "on-failure";
}; };
Install.WantedBy = ["default.target"]; Install.WantedBy = ["default.target"];
@@ -7,6 +7,10 @@
name = "Nix 4 Cyber"; name = "Nix 4 Cyber";
url = "https://n4c.hadi.icu"; url = "https://n4c.hadi.icu";
} }
{
name = "Infosec Notes - Anotherhadi";
url = "https://hadi.icu/notes";
}
{ {
name = "Cyberchef"; name = "Cyberchef";
url = "https://cyberchef.hadi.icu"; url = "https://cyberchef.hadi.icu";
@@ -31,6 +35,10 @@
name = "Exploit-DB"; name = "Exploit-DB";
url = "https://exploit-db.com"; url = "https://exploit-db.com";
} }
{
name = "Reverse Shell Generator";
url = "https://revshells.com";
}
{ {
name = "GTFOBins"; name = "GTFOBins";
url = "https://gtfobins.org/"; url = "https://gtfobins.org/";
@@ -11,6 +11,18 @@
name = "Hyprland Wiki"; name = "Hyprland Wiki";
url = "https://wiki.hypr.land"; url = "https://wiki.hypr.land";
} }
{
name = "Nerdfont Cheatsheet";
url = "https://www.nerdfonts.com/cheat-sheet";
}
{
name = "Helium Bangs";
url = "https://helium.computer/bangs";
}
{
name = "NVF Options";
url = "https://nvf.notashelf.dev/";
}
{ {
name = "Stylix Wiki"; name = "Stylix Wiki";
url = "https://nix-community.github.io/stylix/"; url = "https://nix-community.github.io/stylix/";
@@ -43,6 +43,10 @@
name = "Gemini"; name = "Gemini";
url = "https://gemini.google.com"; url = "https://gemini.google.com";
} }
{
name = "Lumo";
url = "https://lumo.proton.me";
}
]; ];
} }
] ]
@@ -1,7 +1,7 @@
{ {
inputs, inputs,
config, config,
pkgs, pkgs-unstable,
lib, lib,
... ...
}: let }: let
@@ -44,11 +44,11 @@
"--show-avatar-button=never" "--show-avatar-button=never"
]; ];
originalPkg = (inputs.helium-browser.packages.${pkgs.stdenv.hostPlatform.system}.helium).override { originalPkg = (inputs.helium-browser.packages.${pkgs-unstable.stdenv.hostPlatform.system}.helium).override {
flags = heliumFlags; flags = heliumFlags;
}; };
patchScript = pkgs.writeShellScript "helium-patch-prefs" '' patchScript = pkgs-unstable.writeShellScript "helium-patch-prefs" ''
PROFILE="$HOME/.config/net.imput.helium/Default" PROFILE="$HOME/.config/net.imput.helium/Default"
THEME_DIR="$PROFILE/Extensions/${themeId}/1.0_0" THEME_DIR="$PROFILE/Extensions/${themeId}/1.0_0"
PREFS="$PROFILE/Preferences" PREFS="$PROFILE/Preferences"
@@ -59,13 +59,14 @@
if [ -f "$PREFS" ]; then if [ -f "$PREFS" ]; then
tmp=$(mktemp) tmp=$(mktemp)
${lib.getExe pkgs.jq} \ ${lib.getExe pkgs-unstable.jq} \
--arg id "${themeId}" \ --arg id "${themeId}" \
--slurpfile manifest "$THEME_DIR/manifest.json" \ --slurpfile manifest "$THEME_DIR/manifest.json" \
' '
.helium.browser.layout = 3 | .helium.browser.layout = 3 |
.helium.browser.minimal_location_bar = true | .helium.browser.minimal_location_bar = true |
.helium.browser.show_dynamic_new_tab_button = false | .helium.browser.show_dynamic_new_tab_button = false |
.helium.browser.rounded_frame = false |
.bookmark_bar.show_tab_groups = false | .bookmark_bar.show_tab_groups = false |
.extensions.settings[$id] = { .extensions.settings[$id] = {
"active_permissions": {"api": [], "explicit_host": [], "manifest_permissions": [], "scriptable_host": []}, "active_permissions": {"api": [], "explicit_host": [], "manifest_permissions": [], "scriptable_host": []},
@@ -84,12 +85,13 @@
fi fi
''; '';
baseWrapped = pkgs.symlinkJoin { baseWrapped = pkgs-unstable.symlinkJoin {
name = "helium-wrapped"; name = "helium-wrapped";
paths = [originalPkg]; paths = [originalPkg];
nativeBuildInputs = [pkgs.makeWrapper]; nativeBuildInputs = [pkgs-unstable.makeWrapper];
postBuild = '' postBuild = ''
wrapProgram $out/bin/helium \ wrapProgram $out/bin/helium \
--set-default GTK_USE_PORTAL 1 \
--run ${lib.escapeShellArg (toString patchScript)} --run ${lib.escapeShellArg (toString patchScript)}
''; '';
}; };
@@ -110,7 +112,7 @@ in {
xdg.desktopEntries.helium = { xdg.desktopEntries.helium = {
name = "Helium"; name = "Helium";
genericName = "Navigateur Web"; genericName = "Web Browser";
exec = "${config.programs.helium.package}/bin/helium %U"; exec = "${config.programs.helium.package}/bin/helium %U";
icon = "${config.programs.helium.package}/share/icons/hicolor/256x256/apps/helium.png"; icon = "${config.programs.helium.package}/share/icons/hicolor/256x256/apps/helium.png";
terminal = false; terminal = false;
@@ -127,7 +129,7 @@ in {
xdg.desktopEntries.helium-private = { xdg.desktopEntries.helium-private = {
name = "Helium (Private window)"; name = "Helium (Private window)";
genericName = "Navigateur Web"; genericName = "Web Browser";
exec = "${config.programs.helium.package}/bin/helium --incognito %U"; exec = "${config.programs.helium.package}/bin/helium --incognito %U";
icon = "${config.programs.helium.package}/share/icons/hicolor/256x256/apps/helium.png"; icon = "${config.programs.helium.package}/share/icons/hicolor/256x256/apps/helium.png";
terminal = false; terminal = false;
@@ -41,7 +41,7 @@ in {
DefaultBrowserSettingEnabled = false; DefaultBrowserSettingEnabled = false;
DeveloperToolsAvailability = 1; DeveloperToolsAvailability = 1;
DnsOverHttpsMode = "secure"; DnsOverHttpsMode = "automatic";
DnsOverHttpsTemplates = "https://dns.quad9.net/dns-query"; DnsOverHttpsTemplates = "https://dns.quad9.net/dns-query";
DefaultSearchProviderEnabled = true; DefaultSearchProviderEnabled = true;
@@ -1,16 +1,17 @@
{pkgs-stable, ...}: { {pkgs, ...}: {
home.packages = with pkgs-stable; [ home.packages = with pkgs; [
vlc # Video player vlc # Video player
obsidian # Note taking app obsidian # Note taking app
textpieces # Manipulate texts textpieces # Manipulate texts
resources # Ressource monitor resources # Resource monitor
gnome-clocks # Clocks app gnome-clocks # Clocks app
gnome-text-editor # Basic graphic text editor gnome-text-editor # Basic graphic text editor
ticktick # Todo app ticktick # Todo app
pinta # Image editor pinta # Image editor
switcheroo # Convert images between different formats
onlyoffice-desktopeditors # Office suite onlyoffice-desktopeditors # Office suite
blanket # Listen to different sounds
signal-desktop # Messaging app signal-desktop # Messaging app
librewolf thunar # File explorer
]; ];
} }
-19
View File
@@ -1,19 +0,0 @@
{pkgs, ...}: let
nightshift-toggle =
pkgs.writeShellScriptBin "nightshift-toggle"
# bash
''
if pidof "hyprsunset"; then
pkill hyprsunset
${pkgs.libnotify}/bin/notify-send "Night Shift Disabled" "Returning to full spectrum light. Filter disabled."
else
${pkgs.hyprsunset}/bin/hyprsunset -t 4500 &
${pkgs.libnotify}/bin/notify-send "Night Shift Activated" "Welcome to the warm side. Blue light filtering is now active."
fi
'';
in {
home.packages = with pkgs; [
hyprsunset
nightshift-toggle
];
}
-21
View File
@@ -1,21 +0,0 @@
{
inputs,
pkgs,
...
}: {
imports = [inputs.nvf.homeManagerModules.default];
programs.nvf = {
enable = true;
settings = {
imports = [
./options.nix
./languages.nix
./picker.nix
./snacks.nix
./keymaps.nix
./utils.nix
./mini.nix
];
};
};
}
-37
View File
@@ -1,37 +0,0 @@
{
inputs,
pkgs,
system,
...
}: let
nvimConfig = inputs.nvf.lib.neovimConfiguration {
inherit pkgs;
modules = [
./options.nix
./languages.nix
./picker.nix
./snacks.nix
./keymaps.nix
./utils.nix
./mini.nix
];
};
in {
packages.${system}.nvim = nvimConfig.neovim;
apps.${system}.nvim = {
type = "app";
program = "${nvimConfig.neovim}/bin/nvim";
};
defaultApp.${system} = {
type = "app";
program = "${nvimConfig.neovim}/bin/nvim";
};
homeManagerModules.nvim = {
imports = [
inputs.nvf.homeManagerModules.default
./default.nix
];
};
}
-48
View File
@@ -1,48 +0,0 @@
{
vim.luaConfigRC.mini-clue = ''
local miniclue = require('mini.clue')
miniclue.setup({
triggers = {
{ mode = 'n', keys = '<Leader>' },
{ mode = 'x', keys = '<Leader>' },
{ mode = 'n', keys = 'g' },
{ mode = 'x', keys = 'g' },
{ mode = 'n', keys = "'" },
{ mode = 'n', keys = '`' },
{ mode = 'n', keys = '"' },
{ mode = 'i', keys = '<C-r>' },
{ mode = 'c', keys = '<C-r>' },
{ mode = 'n', keys = '<C-w>' },
{ mode = 'n', keys = 'z' },
},
clues = {
miniclue.gen_clues.g(),
miniclue.gen_clues.marks(),
miniclue.gen_clues.registers(),
miniclue.gen_clues.windows({ submode_resize = true }),
miniclue.gen_clues.z(),
{ mode = 'n', keys = '<Leader>f', desc = '+find' },
{ mode = 'n', keys = '<Leader>s', desc = '+search' },
{ mode = 'n', keys = '<Leader>t', desc = '+terminal' },
{ mode = 'n', keys = '<Leader>u', desc = '+ui' },
{ mode = 'n', keys = '<Leader>l', desc = '+lsp' },
{ mode = 'n', keys = '<Leader>x', desc = '+trouble' },
},
window = { delay = 300 },
})
'';
vim.mini = {
ai.enable = true;
starter.enable = true;
comment.enable = true;
icons.enable = true;
indentscope.enable = true;
pairs.enable = true;
diff.enable = true;
git.enable = true;
jump2d.enable = true;
statusline.enable = true;
clue.enable = true;
};
}
-5
View File
@@ -1,5 +0,0 @@
{
wayland.windowManager.hyprland.settings.exec-once = [
"protonvpn-app --start-minimized &"
];
}
-33
View File
@@ -1,33 +0,0 @@
# Fzf is a general-purpose command-line fuzzy finder.
{
config,
lib,
...
}: let
accent = "#" + config.lib.stylix.colors.base0D;
foreground = "#" + config.lib.stylix.colors.base05;
muted = "#" + config.lib.stylix.colors.base03;
in {
programs.fzf = {
enable = true;
enableZshIntegration = true;
colors = lib.mkForce {
"fg+" = accent;
"bg+" = "-1";
"fg" = foreground;
"bg" = "-1";
"prompt" = muted;
"pointer" = accent;
};
defaultOptions = [
"--margin=1"
"--layout=reverse"
"--border=none"
"--info='hidden'"
"--header=''"
"--prompt='/ '"
"-i"
"--no-bold"
];
};
}
-188
View File
@@ -1,188 +0,0 @@
# My shell configuration
{
pkgs,
lib,
config,
...
}: let
fetch = config.theme.fetch; # neofetch, nerdfetch, pfetch
in {
home.packages = with pkgs; [
bat
ripgrep
tldr
witr
];
# Add go binaries to the PATH
home.sessionPath = ["$HOME/go/bin"];
home.sessionVariables = {
COLORTERM = "truecolor";
};
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting = {
enable = true;
highlighters = [
"main"
"brackets"
"pattern"
"regexp"
"root"
"line"
];
};
historySubstringSearch.enable = true;
history = {
ignoreDups = true;
save = 10000;
size = 10000;
};
profileExtra = lib.optionalString (config.home.sessionPath != []) ''
export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" config.home.sessionPath}"
'';
shellAliases = {
vim = "nvim";
vi = "nvim";
v = "nvim";
c = "clear";
clera = "clear";
celar = "clear";
e = "exit";
cd = "z";
ls = "eza --icons=always --no-quotes";
tree = "eza --icons=always --tree --no-quotes";
sl = "ls";
open = "${pkgs.xdg-utils}/bin/xdg-open";
cat = "bat --theme=base16 --color=always --paging=never --tabs=2 --wrap=never --plain";
mkdir = "mkdir -p";
obsidian-no-gpu = "env ELECTRON_OZONE_PLATFORM_HINT=auto obsidian --ozone-platform=x11";
wireguard-import = "nmcli connection import type wireguard file";
notes = "nvim ~/notes/index.md --cmd 'cd ~/notes' -c ':lua Snacks.picker.smart()'";
note = "notes";
tmp = "nvim /tmp/$(date | sed 's/ //g;s/\\.//g').md";
nix-shell = "nix-shell --command zsh";
# git
g = "lazygit";
ga = "git add";
gc = "git commit";
gcu = "git add . && git commit -m 'Update'";
gp = "git push";
gpl = "git pull";
gs = "git status";
gd = "git diff";
gco = "git checkout";
gcb = "git checkout -b";
gbr = "git branch";
grs = "git reset HEAD~1";
grh = "git reset --hard HEAD~1";
gaa = "git add .";
gcm = "git commit -m";
};
initContent =
# bash
''
bindkey -e
${
if fetch == "neofetch"
then pkgs.neofetch + "/bin/neofetch"
else if fetch == "nerdfetch"
then "nerdfetch"
else if fetch == "pfetch"
then "echo; ${pkgs.pfetch}/bin/pfetch"
else ""
}
function n4c() {
category=''${1:-all}
shift
args=''${*}
nix develop "github:nix4cyber/n4c#''${category}" ''${args} -c zsh
}
# search history based on what's typed in the prompt
autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end
# General completion behavior
zstyle ':completion:*' completer _extensions _complete _approximate
# Use cache
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "$XDG_CACHE_HOME/zsh/.zcompcache"
# Complete the alias
zstyle ':completion:*' complete true
# Autocomplete options
zstyle ':completion:*' complete-options true
# Completion matching control
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' keep-prefix true
# Group matches and describe
zstyle ':completion:*' menu select
zstyle ':completion:*' list-grouped false
zstyle ':completion:*' list-separator '''
zstyle ':completion:*' group-name '''
zstyle ':completion:*' verbose yes
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*:warnings' format '%F{red}%B-- No match for: %d --%b%f'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*:descriptions' format '[%d]'
# Colors
zstyle ':completion:*' list-colors ''${(s.:.)LS_COLORS}
# case insensitive tab completion
zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories
zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
zstyle ':completion:*:*:-command-:*:*' group-order aliases builtins functions commands
zstyle ':completion:*' special-dirs true
zstyle ':completion:*' squeeze-slashes true
# Sort
zstyle ':completion:*' sort false
zstyle ":completion:*:git-checkout:*" sort false
zstyle ':completion:*' file-sort modification
zstyle ':completion:*:eza' sort false
zstyle ':completion:complete:*:options' sort false
zstyle ':completion:files' sort false
${lib.optionalString config.services.gpg-agent.enable ''
gnupg_path=$(ls $XDG_RUNTIME_DIR/gnupg)
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gnupg/$gnupg_path/S.gpg-agent.ssh"
''}
# Allow foot to pipe command output
function precmd {
if ! builtin zle; then
print -n "\e]133;D\e\\"
fi
}
function preexec {
print -n "\e]133;C\e\\"
}
'';
};
}
-43
View File
@@ -1,43 +0,0 @@
# Spicetify is a spotify client customizer
{
pkgs,
pkgs-stable,
config,
lib,
inputs,
...
}: let
spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.stdenv.hostPlatform.system};
accent = "${config.lib.stylix.colors.base0D}";
background = "${config.lib.stylix.colors.base00}";
in {
imports = [inputs.spicetify-nix.homeManagerModules.default];
stylix.targets.spicetify.enable = false;
programs.spicetify = {
enable = true;
spotifyPackage = pkgs-stable.spotify;
theme = lib.mkForce spicePkgs.themes.dribbblish;
colorScheme = "custom";
customColorScheme = {
button = accent;
button-active = accent;
tab-active = accent;
player = background;
main = background;
sidebar = background;
};
enabledExtensions = with spicePkgs.extensions; [
playlistIcons
historyShortcut
hidePodcasts
adblock
fullAppDisplay
keyboardShortcut
];
};
}
-178
View File
@@ -1,178 +0,0 @@
# Thunar is a file explorer
{
pkgs,
pkgs-stable,
config,
lib,
...
}: let
user = config.var.username;
in {
# ctrl + m to toggle the menubar
home.packages =
(with pkgs-stable; [
xfce.thunar
xfce.xfconf
xfce.tumbler
xfce.thunar-archive-plugin
xfce.thunar-volman
xfce.thunar-media-tags-plugin
p7zip
xarchiver
])
++ (with pkgs; [
# Icon themes: keep on global pkgs to avoid conflicts with other modules
papirus-icon-theme
material-icons
material-design-icons
material-symbols
]);
gtk = {
enable = true;
iconTheme = {
name = "Papirus-Dark";
package = pkgs.papirus-icon-theme;
};
gtk4.theme = null;
# bookmarks for the side pane
gtk3.bookmarks = [
"file:///home/${user}/Downloads Downloads"
"file:///home/${user}/Pictures Pictures"
"file:///home/${user}/.config/nixos NixOS"
"file:///home/${user}/dev Development"
];
};
qt.enable = true;
home.sessionVariables = {
XDG_ICON_DIR = "${pkgs.papirus-icon-theme}/share/icons/Papirus";
QS_ICON_THEME = "Papirus";
QT_STYLE_OVERRIDE = lib.mkForce "Fusion";
};
home.file.".config/xarchiver/xarchiverrc".text = ''
[xarchiver]
preferred_format=0
prefer_unzip=true
confirm_deletion=true
sort_filename_content=false
advanced_isearch=true
auto_expand=true
store_output=false
icon_size=2
show_archive_comment=false
show_sidebar=true
show_location_bar=true
show_toolbar=true
preferred_custom_cmd=
preferred_temp_dir=/tmp
preferred_extract_dir=./
allow_sub_dir=0
ensure_directory=true
overwrite=false
full_path=2
touch=false
fresh=false
update=false
store_path=false
updadd=true
freshen=false
recurse=true
solid_archive=false
remove_files=false
'';
home.file.".config/xfce4/xfconf/xfce-perchannel-xml/thunar.xml" = {
text = ''
<?xml version="1.1" encoding="UTF-8"?>
<channel name="thunar" version="1.0">
<property name="last-view" type="string" value="ThunarIconView"/>
<property name="last-icon-view-zoom-level" type="string" value="THUNAR_ZOOM_LEVEL_100_PERCENT"/>
<property name="last-window-maximized" type="bool" value="true"/>
<property name="last-separator-position" type="int" value="230"/>
<property name="last-statusbar-visible" type="bool" value="false"/>
<property name="last-menubar-visible" type="bool" value="false"/>
<property name="misc-single-click" type="bool" value="false"/>
<property name="shortcuts-icon-emblems" type="bool" value="true"/>
<property name="tree-icon-emblems" type="bool" value="true"/>
<property name="misc-file-size-binary" type="bool" value="false"/>
<property name="misc-thumbnail-draw-frames" type="bool" value="true"/>
<property name="misc-text-beside-icons" type="bool" value="false"/>
<property name="misc-change-window-icon" type="bool" value="false"/>
<property name="hidden-bookmarks" type="array">
<value type="string" value="computer:///"/>
<value type="string" value="recent:///"/>
<value type="string" value="network:///"/>
</property>
<property name="hidden-devices" type="array">
<value type="string" value="52FEA905FEA8E309"/>
</property>
<property name="last-toolbar-item-order" type="string" value="0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17"/>
<property name="last-toolbar-visible-buttons" type="string" value="0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0"/>
<property name="last-location-bar" type="string" value="ThunarLocationButtons"/>
<property name="last-show-hidden" type="bool" value="false"/>
<property name="last-details-view-zoom-level" type="string" value="THUNAR_ZOOM_LEVEL_38_PERCENT"/>
<property name="last-details-view-column-widths" type="string" value="50,50,118,111,50,50,50,50,993,50,50,84,50,151"/>
<property name="last-toolbar-items" type="string" value="menu:1,undo:1,back:1,forward:1,open-parent:0,open-home:0,redo:0,zoom-in:0,zoom-out:0,zoom-reset:0,location-bar:1,view-switcher:1,search:1,view-as-icons:0,view-as-detailed-list:0,view-as-compact-list:0,toggle-split-view:0,reload:0,new-tab:0,new-window:0,uca-action-1700000000000001:0"/>
<property name="last-side-pane" type="string" value="THUNAR_SIDEPANE_TYPE_SHORTCUTS"/>
<property name="last-image-preview-visible" type="bool" value="false"/>
<property name="misc-use-csd" type="bool" value="true"/>
<property name="default-view" type="string" value="ThunarIconView"/>
<property name="misc-thumbnail-max-file-size" type="uint64" value="1073741824"/>
<property name="misc-symbolic-icons-in-toolbar" type="bool" value="true"/>
<property name="misc-date-style" type="string" value="THUNAR_DATE_STYLE_SIMPLE"/>
<property name="shortcuts-icon-size" type="string" value="THUNAR_ICON_SIZE_16"/>
<property name="tree-icon-size" type="string" value="THUNAR_ICON_SIZE_16"/>
<property name="misc-symbolic-icons-in-sidepane" type="bool" value="true"/>
<property name="misc-open-new-window-as-tab" type="bool" value="false"/>
<property name="misc-full-path-in-tab-title" type="bool" value="true"/>
<property name="misc-show-delete-action" type="bool" value="false"/>
</channel>
'';
force = true;
};
xdg.configFile."Thunar/uca.xml".text = ''
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action>
<icon>utilities-terminal</icon>
<name>Open Terminal Here</name>
<unique-id>1700000000000001</unique-id>
<command>ghostty -d %f</command>
<description>Opens terminal in the selected folder</description>
<patterns>*</patterns>
<startup-notify/>
<directories/>
</action>
<action>
<icon></icon>
<name>Extract here</name>
<submenu></submenu>
<unique-id>1689618425925956-3</unique-id>
<command>xarchiver -x . %f</command>
<description>Extracts the archive into the directory it is located in.</description>
<range>*</range>
<patterns>*.tar.bz2;*.tar.gz;*.tar.xz;*.tar.Z;*.tar;*.taz;*.tb2;*.tbz;*.tbz2;*.tgz;*.txz;*.zip;*.bz2;*.docx;*.apk;*.gz;*.odt;</patterns>
<other-files/>
</action>
<action>
<icon>package-x-generic</icon>
<name>Compress here (tar.gz)</name>
<submenu></submenu>
<unique-id>1700000000000003</unique-id>
<command>tar -czvf %n.tar.gz %N</command>
<description>Creates a compressed archive (.tar.gz) of selected files/folders.</description>
<range>*</range>
<patterns>*</patterns>
<directories/>
<other-files/>
</action>
</actions>
'';
}
+119
View File
@@ -0,0 +1,119 @@
{
pkgs,
config,
...
}: let
c = config.lib.stylix.colors;
# TODO: Waiting for a version in nixpkgs
version = "1.11.2";
sources = {
"x86_64-linux" = {
url = "https://github.com/elio-fm/elio/releases/download/v${version}/elio-${version}-x86_64-unknown-linux-gnu.tar.gz";
hash = "sha256-9cW/xUA9p0LEYI3/j4MGPVZvcyJpV1JYKYBuHur4sTM=";
};
"aarch64-linux" = {
url = "https://github.com/elio-fm/elio/releases/download/v${version}/elio-${version}-aarch64-unknown-linux-gnu.tar.gz";
hash = "sha256-zg141Dp+jHwAqzoaCNvOoC7ZFeAX+cO8HZF5W7wz1Qs=";
};
};
source =
sources.${pkgs.stdenv.hostPlatform.system}
or (throw "elio: unsupported platform ${pkgs.stdenv.hostPlatform.system}");
elio = pkgs.stdenv.mkDerivation {
pname = "elio";
inherit version;
src = pkgs.fetchurl {inherit (source) url hash;};
nativeBuildInputs = [pkgs.autoPatchelfHook];
buildInputs = [pkgs.stdenv.cc.cc.lib];
installPhase = ''
runHook preInstall
install -Dm755 elio -t $out/bin
for size in 48 128 256 512; do
install -Dm644 \
"packaging/linux/icons/hicolor/''${size}x''${size}/apps/elio.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/elio.png"
done
install -Dm644 packaging/linux/elio.desktop -t $out/share/applications
runHook postInstall
'';
meta = {
description = "Terminal file manager";
homepage = "https://github.com/elio-fm/elio";
license = pkgs.lib.licenses.mit;
mainProgram = "elio";
platforms = builtins.attrNames sources;
sourceProvenance = [pkgs.lib.sourceTypes.binaryNativeCode];
};
};
in {
home.packages = [elio];
xdg.desktopEntries.elio = {
name = "elio";
exec = "${pkgs.ghostty}/bin/ghostty +new-window -e ${elio}/bin/elio %f";
terminal = false;
icon = "elio";
mimeType = ["inode/directory"];
categories = ["System" "FileManager" "FileTools" "ConsoleOnly"];
};
xdg.configFile."elio/theme.toml".text = ''
[palette]
bg = "#${c.base00}"
chrome = "#${c.base01}"
chrome_alt = "#${c.base01}"
chip_text = "#${c.base00}"
panel = "#${c.base00}"
panel_alt = "#${c.base00}"
surface = "#${c.base02}"
elevated = "#${c.base02}"
border = "#${c.base03}"
text = "#${c.base05}"
muted = "#${c.base04}"
accent = "#${c.base0D}"
accent_soft = "#${c.base02}"
accent_text = "#${c.base06}"
selected_bg = "#${c.base02}"
selected_border = "#${c.base0D}"
selection_bar = "#${c.base09}"
yank_bar = "#${c.base0B}"
cut_bar = "#${c.base08}"
progress_bar = "#${c.base0D}"
grid_selection_band = "#${c.base02}"
grid_yank_band = "#${c.base01}"
grid_cut_band = "#${c.base01}"
sidebar_active = "#${c.base02}"
button_bg = "#${c.base01}"
button_disabled_bg = "#${c.base01}"
path_bg = "#${c.base00}"
[preview.code]
fg = "#${c.base05}"
bg = "#${c.base01}"
selection_bg = "#${c.base02}"
selection_fg = "#${c.base06}"
caret = "#${c.base0C}"
line_highlight = "#${c.base01}"
line_number = "#${c.base03}"
comment = "#${c.base03}"
string = "#${c.base0B}"
constant = "#${c.base09}"
keyword = "#${c.base0E}"
function = "#${c.base0D}"
type = "#${c.base0A}"
parameter = "#${c.base08}"
tag = "#${c.base0C}"
operator = "#${c.base0C}"
macro = "#${c.base0F}"
invalid = "#${c.base08}"
'';
}
@@ -1,16 +1,20 @@
{pkgs, ...}: let # Ghostty is a terminal emulator
{
pkgs,
config,
...
}: let
cursorShaders = pkgs.fetchFromGitHub { cursorShaders = pkgs.fetchFromGitHub {
owner = "sahaj-b"; owner = "sahaj-b";
repo = "ghostty-cursor-shaders"; repo = "ghostty-cursor-shaders";
rev = "06d4e90fb5410e9c4d0b3131584060adddf89406"; rev = "06d4e90fb5410e9c4d0b3131584060adddf89406";
hash = "sha256-G/UIr1bKnxn1AcHl/4FL/jou6b7M2VeREslYVELxdmw="; hash = "sha256-G/UIr1bKnxn1AcHl/4FL/jou6b7M2VeREslYVELxdmw=";
}; };
c = config.lib.stylix.colors;
in { in {
home.sessionVariables = { home.sessionVariables = {
TERMINAL = "ghostty"; TERMINAL = "ghostty";
TERM = "ghostty"; TERM = "ghostty";
XMODIFIERS = "@im=none";
GTK_IM_MODULE = "simple";
}; };
programs.ghostty = { programs.ghostty = {
@@ -21,6 +25,7 @@ in {
window-padding-x = 10; window-padding-x = 10;
confirm-close-surface = false; confirm-close-surface = false;
window-padding-y = 10; window-padding-y = 10;
gtk-single-instance = true;
clipboard-read = "allow"; clipboard-read = "allow";
clipboard-write = "allow"; clipboard-write = "allow";
copy-on-select = "clipboard"; copy-on-select = "clipboard";
@@ -28,14 +33,6 @@ in {
custom-shader = "${cursorShaders}/cursor_warp.glsl"; custom-shader = "${cursorShaders}/cursor_warp.glsl";
custom-shader-animation = "always"; custom-shader-animation = "always";
keybind = [ keybind = [
# "ctrl+j=goto_split:left"
# "ctrl+i=goto_split:up"
# "ctrl+k=goto_split:down"
# "ctrl+l=goto_split:right"
# "shift+ctrl+h=new_split:left"
# "shift+ctrl+j=new_split:down"
# "shift+ctrl+k=new_split:up"
# "shift+ctrl+l=new_split:right"
"shift+ctrl+tab=new_tab" "shift+ctrl+tab=new_tab"
]; ];
}; };
@@ -16,6 +16,9 @@ in {
"node_modules" "node_modules"
"result" "result"
"result-*" "result-*"
".superpowers/"
".claude/"
"docs/superpowers/"
]; ];
settings = { settings = {
user.name = username; user.name = username;
@@ -40,13 +43,10 @@ in {
d = "diff"; d = "diff";
ps = "!git push origin $(git rev-parse --abbrev-ref HEAD)"; ps = "!git push origin $(git rev-parse --abbrev-ref HEAD)";
pl = "!git pull origin $(git rev-parse --abbrev-ref HEAD)"; pl = "!git pull origin $(git rev-parse --abbrev-ref HEAD)";
af = "!git add $(git ls-files -m -o --exclude-standard | sk -m)";
st = "status"; st = "status";
br = "branch"; br = "branch";
df = "!git hist | peco | awk '{print $2}' | xargs -I {} git diff {}^ {}";
hist = ''log --pretty=format:"%Cgreen%h %Creset%cd %Cblue[%cn] %Creset%s%C(yellow)%d%C(reset)" --graph --date=relative --decorate --all''; hist = ''log --pretty=format:"%Cgreen%h %Creset%cd %Cblue[%cn] %Creset%s%C(yellow)%d%C(reset)" --graph --date=relative --decorate --all'';
llog = ''log --graph --name-status --pretty=format:"%C(red)%h %C(reset)(%cd) %C(green)%an %Creset%s %C(yellow)%d%Creset" --date=relative''; llog = ''log --graph --name-status --pretty=format:"%C(red)%h %C(reset)(%cd) %C(green)%an %Creset%s %C(yellow)%d%Creset" --date=relative'';
edit-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; hx `f`";
}; };
}; };
}; };
+23
View File
@@ -0,0 +1,23 @@
{config, ...}: let
c = config.lib.stylix.colors;
in {
home.file.".config/ilovetui/config.yaml".text = ''
colors:
base00: "#${c.base00}" # Background
base01: "#${c.base01}" # Lighter Background / Status Bars
base02: "#${c.base02}" # Selection Background
base03: "#${c.base03}" # Comments / Invisibles
base04: "#${c.base04}" # Dark Foreground / Status Bars
base05: "#${c.base05}" # Default Foreground
base06: "#${c.base06}" # Light Foreground
base07: "#${c.base07}" # Light Background
base08: "#${c.base08}" # Variables / Errors / Diff Deleted
base09: "#${c.base09}" # Integers / Constants / Booleans
base0a: "#${c.base0A}" # Classes / Warnings / Search Background
base0b: "#${c.base0B}" # Strings / Success / Diff Inserted
base0c: "#${c.base0C}" # Support / Regex / Escape Characters
base0d: "#${c.base0D}" # Functions / Methods / Headings / Accent
base0e: "#${c.base0E}" # Keywords / Storage / Diff Changed
base0f: "#${c.base0F}" # Embedded / Misc
'';
}
+38
View File
@@ -0,0 +1,38 @@
{
config,
lib,
...
}: {
home.sessionVariables = {
EDITOR = "nvim";
VISUAL = "nvim";
};
programs.nvf = {
enable = true;
settings = {
vim.luaConfigRC = lib.mkIf (config ? stylix && config.stylix.enable) {
hl-overrides = let
c = config.lib.stylix.colors;
in ''
local function apply_hl()
vim.api.nvim_set_hl(0, "MiniStarterHeader", { fg = "#${c.base0D}", bold = true })
vim.api.nvim_set_hl(0, "SnacksPickerBorder", { fg = "#${c.base0D}" })
vim.api.nvim_set_hl(0, "SnacksPickerTitle", { fg = "#${c.base0D}", bold = true })
end
apply_hl()
vim.api.nvim_create_autocmd("ColorScheme", { pattern = "*", callback = apply_hl })
'';
};
imports = [
./options.nix
./languages.nix
./picker.nix
./snacks.nix
./keymaps.nix
./utils.nix
./mini.nix
];
};
};
}
+133
View File
@@ -0,0 +1,133 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1777699697,
"narHash": "sha256-Eg9b/rq/ECYwNwEXs5i9wHyhxNI0JrYx2srdI2uZMaQ=",
"ref": "refs/heads/main",
"rev": "382052b74656a369c5408822af3f2501e9b1af81",
"revCount": 94,
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nvf",
"nixpkgs"
]
},
"locked": {
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"mnw": {
"locked": {
"lastModified": 1780772958,
"narHash": "sha256-VKKe8r4pwCGWZ3Yr9CPN129R4S3CKLSrlYqdYz3vKpM=",
"owner": "Gerg-L",
"repo": "mnw",
"rev": "0871dbf63a53610c95db04439ed8ea4d6ec9c160",
"type": "github"
},
"original": {
"owner": "Gerg-L",
"repo": "mnw",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1785133411,
"narHash": "sha256-Yjv0WEg39KRYS0rBdTbu6Fc/or/ihAKk13W9sQ6VWd0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2f5a153c270b70cb0f8c11f46d96d6d3bc39f4e3",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-26.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1781216227,
"narHash": "sha256-9mUW6gNwoN2SWc/l0fW4svPNOulXLl8ijqKyeSOGgJE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a0374025a863d007d98e3297f6aa46cc3141c2f0",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-26.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nvf": {
"inputs": {
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"mnw": "mnw",
"nixpkgs": "nixpkgs_2",
"systems": "systems"
},
"locked": {
"lastModified": 1781997110,
"narHash": "sha256-6D6xtYN5t1kZGNd69eMZsRBkgX5Df1roErn/kFR1C+A=",
"owner": "notashelf",
"repo": "nvf",
"rev": "320f60b97075a58d38b90fc5e39f478421dbd38a",
"type": "github"
},
"original": {
"owner": "notashelf",
"repo": "nvf",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nvf": "nvf"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+57
View File
@@ -0,0 +1,57 @@
{
description = "Hadi's NVF Neovim configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-26.05";
nvf.url = "github:notashelf/nvf";
};
outputs = {
self,
nixpkgs,
nvf,
...
}: let
systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
forAllSystems = f: nixpkgs.lib.genAttrs systems f;
modules = [
./options.nix
./languages.nix
./picker.nix
./snacks.nix
./keymaps.nix
./utils.nix
./mini.nix
];
in {
packages = forAllSystems (system: let
pkgs = nixpkgs.legacyPackages.${system};
nvim = (nvf.lib.neovimConfiguration {inherit pkgs modules;}).neovim;
in {
inherit nvim;
default = nvim;
});
apps = forAllSystems (system: let
nvim = {
type = "app";
program = "${self.packages.${system}.nvim}/bin/nvim";
};
in {
inherit nvim;
default = nvim;
});
homeManagerModules = rec {
nvim = {
imports = [
nvf.homeManagerModules.default
./default.nix
];
};
default = nvim;
};
formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.alejandra);
};
}
@@ -1,6 +1,7 @@
{ {
vim = { vim = {
globals.mapleader = " "; globals.mapleader = " ";
keymaps = [ keymaps = [
{ {
key = "s"; key = "s";
@@ -97,7 +98,7 @@
mode = "n"; mode = "n";
silent = true; silent = true;
action = "<cmd>set spell!<cr>"; action = "<cmd>set spell!<cr>";
desc = "Toggle spellLazyGitcheck"; desc = "Toggle spell check";
} }
{ {
key = "<leader>uc"; key = "<leader>uc";
@@ -144,6 +145,52 @@
desc = "Todo (Trouble)"; desc = "Todo (Trouble)";
} }
# Shell
{
key = "<leader>!";
mode = "n";
silent = true;
lua = true;
desc = "Insert command output";
action = ''
function()
local cmd = vim.fn.input("Command: ")
if cmd == "" then return end
local lines = vim.fn.systemlist(cmd)
while #lines > 0 and lines[#lines] == "" do
table.remove(lines)
end
if #lines == 0 then return end
vim.api.nvim_put(lines, "l", true, true)
end
'';
}
{
key = "<leader>!";
mode = "v";
silent = true;
lua = true;
desc = "Run command with selection";
action = ''
function()
local start_line = vim.fn.line("'<")
local end_line = vim.fn.line("'>")
local lines = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, false)
local input_text = table.concat(lines, "\n")
local cmd = vim.fn.input("$ ")
if cmd == "" then return end
local result = vim.fn.system({"bash", "-c", cmd}, input_text)
local output = vim.split(result, "\n", { plain = true })
if output[#output] == "" then table.remove(output) end
if #output == 0 then return end
vim.api.nvim_buf_set_lines(0, start_line - 1, end_line, false, output)
end
'';
}
# QOL # QOL
{ {
key = ">"; key = ">";
@@ -1,4 +1,4 @@
{...}: { {pkgs, ...}: {
vim = { vim = {
diagnostics = { diagnostics = {
enable = true; enable = true;
@@ -24,6 +24,8 @@
autotagHtml = true; autotagHtml = true;
context.enable = true; context.enable = true;
highlight.enable = true; highlight.enable = true;
textobjects.enable = true;
grammars = [pkgs.vimPlugins.nvim-treesitter.grammarPlugins.http];
}; };
lsp = { lsp = {
enable = true; enable = true;
+99
View File
@@ -0,0 +1,99 @@
{lib, ...}: {
vim.luaConfigRC.mini-clue = ''
local miniclue = require('mini.clue')
miniclue.setup({
triggers = {
{ mode = 'n', keys = '<Leader>' },
{ mode = 'x', keys = '<Leader>' },
{ mode = 'n', keys = 'g' },
{ mode = 'x', keys = 'g' },
{ mode = 'n', keys = "'" },
{ mode = 'n', keys = '`' },
{ mode = 'n', keys = '"' },
{ mode = 'i', keys = '<C-r>' },
{ mode = 'c', keys = '<C-r>' },
{ mode = 'n', keys = '<C-w>' },
{ mode = 'n', keys = 'z' },
},
clues = {
miniclue.gen_clues.g(),
miniclue.gen_clues.marks(),
miniclue.gen_clues.registers(),
miniclue.gen_clues.windows({ submode_resize = true }),
miniclue.gen_clues.z(),
{ mode = 'n', keys = '<Leader>f', desc = '+find' },
{ mode = 'n', keys = '<Leader>s', desc = '+search' },
{ mode = 'n', keys = '<Leader>t', desc = '+tools' },
{ mode = 'n', keys = '<Leader>u', desc = '+ui' },
{ mode = 'n', keys = '<Leader>l', desc = '+lsp' },
{ mode = 'n', keys = '<Leader>x', desc = '+trouble' },
{ mode = 'n', keys = '<Leader>!', desc = 'shell' },
{ mode = 'v', keys = '<Leader>!', desc = 'shell' },
},
window = { delay = 300 },
})
'';
vim.mini = {
ai.enable = true;
starter = {
enable = true;
setupOpts = {
header = ''
'';
footer = "";
items = [
{
name = "files";
action = lib.mkLuaInline "function() Snacks.picker.files() end";
section = "";
}
{
name = "directories";
action = lib.mkLuaInline "function() Snacks.explorer() end";
section = "";
}
{
name = "tmp";
action = lib.mkLuaInline ''
function()
local uuid = vim.fn.system("uuidgen"):match("(%S+)")
vim.cmd("edit /tmp/" .. uuid .. ".md")
end
'';
section = "";
}
{
name = "recent";
action = lib.mkLuaInline "function() Snacks.picker.recent() end";
section = "";
}
];
};
};
comment.enable = true;
icons.enable = true;
indentscope.enable = true;
pairs.enable = true;
diff.enable = true;
git.enable = true;
jump2d.enable = true;
statusline.enable = true;
clue.enable = true;
surround.enable = true;
};
}
@@ -6,10 +6,6 @@
''; '';
undoFile.enable = true; undoFile.enable = true;
notes.todo-comments.enable = true; notes.todo-comments.enable = true;
assistant.copilot = {
enable = true;
cmp.enable = true;
};
autocomplete = { autocomplete = {
nvim-cmp = { nvim-cmp = {
+39
View File
@@ -0,0 +1,39 @@
{pkgs, ...}: {
home.packages = with pkgs; [
# I love TUIs
caligula # User-friendly, lightweight TUI for disk imaging (ISO, USB BOOT)
dysk # A terminal-based disk usage analyzer
wikiman # Offline search engine for manual pages (arch wiki, tldr)
tealdeer # Fast tldr client
sttr # A minimalist CyberChef-like, cross-platform CLI app for performing various operations on strings
slides # A terminal-based presentation tool that allows you to create and deliver presentations directly from the command line
pom # Pomodoro timer in your terminal
tabiew # A terminal-based CSV viewer and manipulator
jless # A pager for JSON
pkgs.nur.repos.anotherhadi.usbguard-tui # TUI for managing USBGuard rules
pkgs.nur.repos.anotherhadi.sheets # Terminal based spreadsheet tool
pkgs.nur.repos.anotherhadi.settuings # Terminal based settings (wifi, bluetooth, audio, ...)
rainfrog # TODO: To test
posting # TODO: To test
newsboat # TODO: To test
dooit # TODO: To test
# I love CLIs
httpie # Command-line HTTP client, a user-friendly cURL replacement
gh # GitHub
gh-dash # A terminal dashboard for GitHub
figlet # Transform text into ASCII art
pastel # Command-line tool to generate, analyze, convert and manipulate colors
imagemagick # Image manipulation tool
chafa # Image to ANSI/Unicode converter and more.
# Just cool
tty-solitaire
bastet
peaclock
cbonsai
pipes
cmatrix
fastfetch
];
}
@@ -1,6 +1,8 @@
{ {
programs.direnv = { programs.direnv = {
enable = true; enable = true;
nix-direnv.enable = true; nix-direnv = {
enable = true;
};
}; };
} }
@@ -1,5 +1,8 @@
# Eza is a ls replacement # Eza is a ls replacement
{ {
programs.zsh.initContent = ''
compdef eza=ls
'';
programs.eza = { programs.eza = {
enable = true; enable = true;
icons = "auto"; icons = "auto";
+50
View File
@@ -0,0 +1,50 @@
# Fzf is a general-purpose command-line fuzzy finder.
{
config,
lib,
...
}: let
accent = "#" + config.lib.stylix.colors.base0D;
foreground = "#" + config.lib.stylix.colors.base05;
muted = "#" + config.lib.stylix.colors.base03;
previewCmd = "bat --color=always --style=plain,numbers --line-range=:500 {}";
in {
programs.fzf = {
enable = true;
enableZshIntegration = true;
defaultCommand = "fd --type f --hidden --strip-cwd-prefix";
fileWidgetCommand = "fd --type f --hidden --strip-cwd-prefix";
fileWidgetOptions = ["--preview '${previewCmd}'"];
colors = lib.mkForce {
"fg+" = accent;
"bg+" = "-1";
"fg" = foreground;
"bg" = "-1";
"prompt" = muted;
"pointer" = accent;
};
defaultOptions = [
"--height=60%"
"--layout=reverse"
"--border=none"
"--prompt='/ '"
"--preview-window=right:65%:wrap:border-left"
"-i"
"--no-bold"
];
};
programs.zsh.initContent = lib.mkAfter ''
_fzf_file_no_hidden() {
local cmd result
cmd="''${FZF_DEFAULT_COMMAND/--hidden /}"
result=$(eval "''${cmd:-find . -type f}" | fzf --preview "${previewCmd}") \
&& LBUFFER+="$result"
zle reset-prompt
}
zle -N _fzf_file_no_hidden
'';
}
+152
View File
@@ -0,0 +1,152 @@
# My shell configuration
{
pkgs,
lib,
config,
...
}: {
home.packages = with pkgs; [
bat
ripgrep
];
home = {
sessionPath = ["$HOME/go/bin"];
sessionVariables = {
COLORTERM = "truecolor";
MANPAGER = "bat -l man -p";
};
};
programs.zsh = {
enable = true;
autocd = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
historySubstringSearch.enable = true;
plugins = [
{
name = "zsh-vi-mode";
src = pkgs.zsh-vi-mode;
file = "share/zsh-vi-mode/zsh-vi-mode.plugin.zsh";
}
];
history = {
ignoreDups = true;
findNoDups = true;
expireDuplicatesFirst = true;
ignoreSpace = true;
append = true;
save = 10000;
size = 10000;
};
setOptions = [
"NOBEEP"
"AUTOCD"
"NUMERIC_GLOB_SORT"
];
profileExtra = lib.optionalString (config.home.sessionPath != []) ''
export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" config.home.sessionPath}"
'';
shellAliases = {
# Change default
vim = "nvim";
vi = "nvim";
cd = "z";
ls = "eza --icons=always --no-quotes";
tree = "eza --icons=always --tree --no-quotes";
cat = "bat --theme=base16 --color=always --paging=never --tabs=2 --wrap=never --plain";
mkdir = "mkdir -p";
nix-shell = "nix-shell --command zsh";
grep = "rg --color=auto";
diff = "diff --color=auto";
df = "df -h";
# Shortcuts
spt = "spotatui";
open = "${pkgs.xdg-utils}/bin/xdg-open";
notes = "nvim ~/notes/index.md --cmd 'cd ~/notes' -c ':lua Snacks.picker.smart()'";
# git
g = "lazygit";
ga = "git add";
gc = "git commit";
gp = "git push";
gpl = "git pull";
gs = "git status";
gd = "git diff";
gco = "git checkout";
gcb = "git checkout -b";
gbr = "git branch";
grs = "git reset HEAD~1";
grh = "git reset --hard HEAD~1";
gaa = "git add .";
gcm = "git commit -m";
# Original binaries
ocat = "/run/current-system/sw/bin/cat";
ols = "/run/current-system/sw/bin/ls";
ocd = "builtin cd";
# Typo
clera = "clear";
celar = "clear";
claer = "clear";
sl = "ls";
};
initContent = lib.mkMerge [
(lib.mkOrder 550 ''
function zvm_config() {
ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BEAM
ZVM_NORMAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK
ZVM_VISUAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK
ZVM_VI_HIGHLIGHT_BACKGROUND=none
ZVM_VI_HIGHLIGHT_FOREGROUND=none
ZVM_VI_HIGHLIGHT_EXTRASTYLE=none
}
'')
# bash
''
# Suffix Aliases
alias -s {nix,md,txt,yml,yaml,go}=nvim
alias -s {json,jsonl}=jless
alias -s {csv,tsv,parquet,pqt,arrow,db,sqlite,xls,xlsx,xlsm,xlsb,fwf}=tw
alias -s {png,jpg,jpeg,gif,pdf}=xdg-open
# Global Aliases
alias -g G="| rg"
alias -g L="| less"
alias -g V="| nvim"
alias -g H="| head"
alias -g T="| tail"
alias -g JQ="| jq"
alias -g C="| wl-copy"
alias -g NE="2>/dev/null"
alias -g ND=">/dev/null"
alias -g NUL=">/dev/null 2>&1"
autoload zmv # Mv for multiple files
zstyle ':completion:*' menu select
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}'
zvm_after_init() {
bindkey '^[[1;5C' forward-word
bindkey '^[[1;5D' backward-word
bindkey '^F' _fzf_file_no_hidden
bindkey '^[[A' history-substring-search-up
bindkey '^[[B' history-substring-search-down
}
''
];
};
}
+104
View File
@@ -0,0 +1,104 @@
# Spotatui is a terminal user interface for Spotify, written in Rust. It allows you to control your Spotify playback and manage your playlists directly from the terminal.
{
config,
pkgs,
...
}: let
c = config.lib.stylix.colors;
rgb = base: "${c."${base}-rgb-r"}, ${c."${base}-rgb-g"}, ${c."${base}-rgb-b"}";
in {
home.packages = with pkgs; [
spotatui
];
home.file.".config/spotatui/config.yml".text = ''
keybindings:
back: q
next_page: ctrl-d
previous_page: ctrl-u
jump_to_start: ctrl-a
jump_to_end: ctrl-e
jump_to_album: a
jump_to_artist_album: A
jump_to_context: o
manage_devices: d
decrease_volume: '-'
increase_volume: +
toggle_playback: space
seek_backwards: <
seek_forwards: '>'
next_track: n
previous_track: p
force_previous_track: P
help: '?'
shuffle: ctrl-s
repeat: ctrl-r
search: /
submit: enter
copy_song_url: c
copy_album_url: C
audio_analysis: v
lyrics_view: B
cover_art_view: G
add_item_to_queue: z
show_queue: Q
open_settings: alt-,
save_settings: alt-s
listening_party: ctrl-p
like_track: F
behavior:
seek_milliseconds: 5000
volume_increment: 10
volume_percent: 100
tick_rate_milliseconds: 16
enable_text_emphasis: true
show_loading_indicator: true
enforce_wide_search_bar: true
enable_global_song_count: false
disable_mouse_inputs: false
enable_discord_rpc: false
discord_rpc_client_id: null
enable_announcements: false
announcement_feed_url: null
seen_announcement_ids:
- 2026-05-19-sonos-help-wanted
- 2026-02-27-major-refactor-complete
shuffle_enabled: false
liked_icon:
shuffle_icon: 🔀
repeat_track_icon: 🔂
repeat_context_icon: 🔁
playing_icon:
paused_icon:
set_window_title: true
visualizer_style: Equalizer
dismissed_announcements: []
relay_server_url: wss://spotatui-party.spotatui.workers.dev/ws
stop_after_current_track: false
sidebar_width_percent: 20
playbar_height_rows: 6
library_height_percent: 30
startup_behavior: continue
disable_auto_update: true
auto_update_delay: '0'
keepawake_enabled: true
theme:
preset: Custom
active: ${rgb "base0D"}
banner: ${rgb "base0C"}
error_border: ${rgb "base08"}
error_text: ${rgb "base08"}
hint: ${rgb "base0A"}
hovered: ${rgb "base0E"}
inactive: ${rgb "base03"}
playbar_background: Reset
playbar_progress: ${rgb "base0D"}
playbar_progress_text: ${rgb "base05"}
playbar_text: Reset
selected: ${rgb "base0D"}
text: Reset
background: Reset
header: Reset
highlighted_lyrics: ${rgb "base0B"}
'';
}
@@ -1,50 +0,0 @@
{
pkgs,
config,
...
}: let
rounding = config.theme.rounding + config.theme.gaps-out;
inherit (config.stylix) fonts;
in {
home.packages = with pkgs; [
papirus-icon-theme
];
programs.caelestia.settings = {
paths.sessionGif = ./session-gif-hacker-cat.gif;
background.enabled = false;
appearance = {
transparency = {
enabled = true;
base = 0.85;
layers = 0.4;
};
font.family = {
material = "Material Symbols Rounded";
mono = fonts.monospace.name;
sans = fonts.sansSerif.name;
};
};
utilities = {
enabled = true;
maxToasts = 4;
toasts = {
audioInputChanged = false;
audioOutputChanged = false;
capsLockChanged = false;
chargingChanged = true;
configLoaded = false;
dndChanged = true;
gameModeChanged = true;
numLockChanged = false;
nowPlaying = false;
kbLayoutChanged = false;
};
};
dashboard.showOnHover = false;
border = {
inherit rounding;
thickness = 8;
};
};
}
-68
View File
@@ -1,68 +0,0 @@
{
programs.caelestia.settings.bar = {
clock.showIcon = false;
popouts.activeWindow = false;
persistent = true;
status = {
showBattery = true;
showMicrophone = false;
showLockStatus = false;
showBluetooth = true;
showAudio = true;
showKbLayout = false;
showNetwork = true;
};
workspaces = {
activeIndicator = true;
activeLabel = "󰪥 ";
activeTrail = false;
label = " ";
occupiedBg = true;
occupiedLabel = "󰪥 ";
showWindows = false;
shown = 5;
};
entries = [
{
id = "logo";
enabled = true;
}
{
id = "workspaces";
enabled = true;
}
{
id = "spacer";
enabled = true;
}
{
id = "activeWindow";
enabled = true;
}
{
id = "spacer";
enabled = true;
}
{
id = "tray";
enabled = true;
}
{
id = "clock";
enabled = true;
}
{
id = "statusIcons";
enabled = true;
}
{
id = "power";
enabled = true;
}
];
tray = {
background = false;
recolour = false;
};
};
}
-74
View File
@@ -1,74 +0,0 @@
# Caelestia Shell Home Manager Configuration
# See https://github.com/caelestia-dots/shell
{
pkgs,
inputs,
lib,
...
}: {
imports = [
inputs.caelestia-shell.homeManagerModules.default
./bar.nix
./launcher.nix
./appearance.nix
./scheme.nix
./swappy.nix
];
programs.caelestia = {
enable = true;
systemd.enable = false;
settings = {
services.weatherLocation = "Paris";
general = {
apps = {
terminal = ["ghostty"];
audio = ["pavucontrol"];
explorer = ["thunar"];
};
idle = {
timeouts = [];
};
};
};
cli = {
enable = true;
settings.theme = {
enableTerm = false;
enableDiscord = false;
enableSpicetify = false;
enableBtop = false;
enableCava = false;
enableHypr = false;
enableGtk = false;
enableQt = false;
};
};
};
home.packages = with pkgs; [
gpu-screen-recorder
];
wayland.windowManager.hyprland.settings.exec-once = [
"uwsm app -- caelestia resizer -d"
"uwsm app -- caelestia shell -d"
"caelestia scheme set -n onedark"
"caelestia scheme set -n custom"
];
# shell.json is managed by home-manager (read-only symlink) but caelestia
# needs to write to it at runtime: replace the symlink with a mutable copy
home.activation.caelestiaWritableShellConfig = lib.hm.dag.entryAfter ["linkGeneration"] ''
if [ -L "$HOME/.config/caelestia/shell.json" ]; then
$DRY_RUN_CMD cp --remove-destination \
"$(readlink -f "$HOME/.config/caelestia/shell.json")" \
"$HOME/.config/caelestia/shell.json"
fi
'';
services.cliphist = {
enable = true;
allowImages = true;
};
}
-173
View File
@@ -1,173 +0,0 @@
{
programs.caelestia.settings = {
session.commands = {
shutdown = [
"systemctl"
"poweroff"
];
logout = [
"loginctl"
"lock-session"
];
hibernate = [
"systemctl"
"hibernate"
];
reboot = [
"systemctl"
"reboot"
];
};
launcher = {
actionPrefix = "/";
actions = [
{
name = "Calculator";
icon = "calculate";
description = "Do simple math equations (powered by Qalc)";
command = [
"autocomplete"
"calc"
];
enabled = true;
dangerous = false;
}
{
name = "Shutdown";
icon = "power_settings_new";
description = "Shutdown the system";
command = [
"systemctl"
"poweroff"
];
enabled = true;
dangerous = true;
}
{
name = "Reboot";
icon = "cached";
description = "Reboot the system";
command = [
"systemctl"
"reboot"
];
enabled = true;
dangerous = true;
}
{
name = "Logout";
icon = "exit_to_app";
description = "Log out of the current session";
command = [
"loginctl"
"terminate-user"
""
];
enabled = true;
dangerous = true;
}
{
name = "Lock";
icon = "lock";
description = "Lock the current session";
command = [
"loginctl"
"lock-session"
];
enabled = true;
dangerous = false;
}
{
name = "Sleep";
icon = "bedtime";
description = "Suspend then hibernate";
command = [
"systemctl"
"suspend-then-hibernate"
];
enabled = true;
dangerous = false;
}
{
name = "Restart caelestia";
icon = "cached";
description = "Restart caelestia";
command = [
"hyprctl"
"dispatch"
"exec"
"caelestia-shell kill | sleep 1 | caelestia-shell"
];
enabled = true;
dangerous = false;
}
{
name = "Emoji Picker";
icon = "mood";
description = "Toggle the emoji picker";
command = [
"caelestia"
"emoji"
"-p"
];
enabled = true;
dangerous = false;
}
{
name = "Clipboard History";
icon = "content_paste";
description = "Toggle the clipboard history";
command = [
"caelestia"
"clipboard"
];
enabled = true;
dangerous = false;
}
{
name = "Delete from Clipboard History";
icon = "content_paste_off";
description = "Delete a line from the clipboard history";
command = [
"caelestia"
"clipboard"
];
enabled = true;
dangerous = false;
}
{
name = "Night Shift";
icon = "moon_stars";
description = "Toggle Night Shift, the blue light filter";
command = ["nightshift-toggle"];
enabled = true;
dangerous = false;
}
{
name = "Hyprpicker";
icon = "colorize";
description = "Pick an hex color";
command = [
"hyprpicker"
"-a"
];
enabled = true;
dangerous = false;
}
];
dragThreshold = 50;
enableDangerousActions = false;
maxShown = 7;
specialPrefix = "@";
useFuzzy = {
apps = false;
actions = false;
schemes = false;
variants = false;
wallpapers = false;
};
showOnHover = false;
hiddenApps = [];
};
};
}
-137
View File
@@ -1,137 +0,0 @@
# This Nix module customizes the color scheme of the Caelestia CLI application using the Stylix base16 color palette.
{
pkgs,
inputs,
config,
...
}: let
colors = config.lib.stylix.colors;
customSchemeFile = pkgs.writeText "custom-dark.txt" ''
primary_paletteKeyColor ${colors.base0D}
secondary_paletteKeyColor ${colors.base04}
tertiary_paletteKeyColor ${colors.base08}
neutral_paletteKeyColor ${colors.base03}
neutral_variant_paletteKeyColor ${colors.base03}
background ${colors.base00}
onBackground ${colors.base05}
surface ${colors.base00}
surfaceDim ${colors.base00}
surfaceBright ${colors.base02}
surfaceContainerLowest ${colors.base01}
surfaceContainerLow ${colors.base01}
surfaceContainer ${colors.base01}
surfaceContainerHigh ${colors.base02}
surfaceContainerHighest ${colors.base02}
onSurface ${colors.base05}
surfaceVariant ${colors.base02}
onSurfaceVariant ${colors.base04}
inverseSurface ${colors.base05}
inverseOnSurface ${colors.base00}
outline ${colors.base03}
outlineVariant ${colors.base02}
shadow ${colors.base00}
scrim ${colors.base00}
surfaceTint ${colors.base0D}
primary ${colors.base0D}
onPrimary ${colors.base00}
primaryContainer ${colors.base0D}
onPrimaryContainer ${colors.base05}
inversePrimary ${colors.base0D}
secondary ${colors.base0C}
onSecondary ${colors.base00}
secondaryContainer ${colors.base02}
onSecondaryContainer ${colors.base0C}
tertiary ${colors.base08}
onTertiary ${colors.base00}
tertiaryContainer ${colors.base08}
onTertiaryContainer ${colors.base00}
error ${colors.base08}
onError ${colors.base00}
errorContainer ${colors.base08}
onErrorContainer ${colors.base05}
primaryFixed ${colors.base0D}
primaryFixedDim ${colors.base0D}
onPrimaryFixed ${colors.base00}
onPrimaryFixedVariant ${colors.base00}
secondaryFixed ${colors.base0C}
secondaryFixedDim ${colors.base0C}
onSecondaryFixed ${colors.base00}
onSecondaryFixedVariant ${colors.base02}
tertiaryFixed ${colors.base08}
tertiaryFixedDim ${colors.base08}
onTertiaryFixed ${colors.base00}
onTertiaryFixedVariant ${colors.base00}
term0 ${colors.base00}
term1 ${colors.base08}
term2 ${colors.base0B}
term3 ${colors.base0A}
term4 ${colors.base0D}
term5 ${colors.base0E}
term6 ${colors.base0C}
term7 ${colors.base05}
term8 ${colors.base03}
term9 ${colors.base08}
term10 ${colors.base0B}
term11 ${colors.base0A}
term12 ${colors.base0D}
term13 ${colors.base0E}
term14 ${colors.base0C}
term15 ${colors.base07}
rosewater ${colors.base06}
flamingo ${colors.base0F}
pink ${colors.base0E}
mauve ${colors.base0D}
red ${colors.base08}
maroon ${colors.base08}
peach ${colors.base09}
yellow ${colors.base0A}
green ${colors.base0B}
teal ${colors.base0C}
sky ${colors.base0C}
sapphire ${colors.base0C}
blue ${colors.base0D}
lavender ${colors.base0D}
klink ${colors.base0D}
klinkSelection ${colors.base0D}
kvisited ${colors.base0E}
kvisitedSelection ${colors.base0E}
knegative ${colors.base08}
knegativeSelection ${colors.base08}
kneutral ${colors.base0A}
kneutralSelection ${colors.base0A}
kpositive ${colors.base0B}
kpositiveSelection ${colors.base0B}
text ${colors.base05}
subtext1 ${colors.base04}
subtext0 ${colors.base03}
overlay2 ${colors.base03}
overlay1 ${colors.base03}
overlay0 ${colors.base02}
surface2 ${colors.base02}
surface1 ${colors.base01}
surface0 ${colors.base01}
base ${colors.base00}
mantle ${colors.base00}
crust ${colors.base00}
success ${colors.base0B}
onSuccess ${colors.base00}
successContainer ${colors.base0B}
onSuccessContainer ${colors.base05}
'';
colorsHash = builtins.hashString "sha256" (builtins.toJSON colors);
customCli =
inputs.caelestia-cli.packages.${pkgs.stdenv.hostPlatform.system}.default.overrideAttrs
(oldAttrs: {
name = "${oldAttrs.name or "caelestia-cli"}-themed-${colorsHash}";
postUnpack = ''
mkdir -p $sourceRoot/src/caelestia/data/schemes/custom/main
cp ${customSchemeFile} $sourceRoot/src/caelestia/data/schemes/custom/main/dark.txt
echo "Custom scheme added to source"
'';
});
in {
programs.caelestia.cli.package = customCli;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

-11
View File
@@ -1,11 +0,0 @@
{
xdg.configFile."swappy/config".text = ''
[Default]
save_dir=~/Pictures/Screenshots
save_filename_format=screenshot-%Y%m%d-%H%M%S.png
show_panel=false
line_size=5
text_size=20
text_font=sans-serif
'';
}
+24
View File
@@ -0,0 +1,24 @@
# Clipboard history: cliphist watches the Wayland clipboard and stores every
# entry (text + images) so it can be recalled later via the `clipboard-menu`
# script (tofi). Uses the home-manager module so the watcher services are
# managed the same way as swaync/hypridle.
{pkgs, ...}: {
services.cliphist = {
enable = true;
allowImages = true;
};
systemd.user.services.cliphist-wipe = {
Unit = {
Description = "Wipe cliphist history on login and logout";
After = ["cliphist.service"];
};
Service = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.cliphist}/bin/cliphist wipe";
ExecStop = "${pkgs.cliphist}/bin/cliphist wipe";
};
Install.WantedBy = ["default.target"];
};
}
+31
View File
@@ -0,0 +1,31 @@
# hypridle handles idle management: lock the screen, turn the display off, and
# suspend after periods of inactivity. The `caffeine-toggle` script pauses it.
{pkgs, ...}: {
services.hypridle = {
enable = true;
settings = {
general = {
# Avoid starting multiple hyprlock instances.
lock_cmd = "${pkgs.procps}/bin/pidof ${pkgs.hyprlock}/bin/hyprlock || ${pkgs.hyprlock}/bin/hyprlock";
before_sleep_cmd = "loginctl lock-session";
after_sleep_cmd = "${pkgs.hyprland}/bin/hyprctl dispatch dpms on";
};
listener = [
{
timeout = 300; # 5 min → lock
on-timeout = "loginctl lock-session";
}
{
timeout = 360; # 6 min → screen off
on-timeout = "${pkgs.hyprland}/bin/hyprctl dispatch dpms off";
on-resume = "${pkgs.hyprland}/bin/hyprctl dispatch dpms on";
}
{
timeout = 1800; # 30 min → suspend
on-timeout = "systemctl suspend";
}
];
};
};
}
+4 -8
View File
@@ -6,13 +6,9 @@
then "4" then "4"
else if animationSpeed == "medium" else if animationSpeed == "medium"
then "2.5" then "2.5"
else "1.5"; else if animationSpeed == "fast"
borderDuration = then "1.5"
if animationSpeed == "slow" else "0.5";
then "10"
else if animationSpeed == "medium"
then "6"
else "3";
in { in {
wayland.windowManager.hyprland.settings = { wayland.windowManager.hyprland.settings = {
animations = { animations = {
@@ -38,7 +34,7 @@ in {
"windows, 1, ${animationDuration}, md3_decel, popin 60%" "windows, 1, ${animationDuration}, md3_decel, popin 60%"
"windowsIn, 1, ${animationDuration}, md3_decel, popin 60%" "windowsIn, 1, ${animationDuration}, md3_decel, popin 60%"
"windowsOut, 1, ${animationDuration}, md3_accel, popin 60%" "windowsOut, 1, ${animationDuration}, md3_accel, popin 60%"
"border, 1, ${borderDuration}, default" "border, 1, ${animationDuration}, default"
"fade, 1, ${animationDuration}, md3_decel" "fade, 1, ${animationDuration}, md3_decel"
"layersIn, 1, ${animationDuration}, menu_decel, slide" "layersIn, 1, ${animationDuration}, menu_decel, slide"
"layersOut, 1, ${animationDuration}, menu_accel" "layersOut, 1, ${animationDuration}, menu_accel"
+25 -45
View File
@@ -5,6 +5,7 @@
... ...
}: let }: let
colors = config.lib.stylix.colors; colors = config.lib.stylix.colors;
scripts = import ../waybar/scripts.nix {inherit pkgs config;};
mkMenu = menu: let mkMenu = menu: let
configFile = pkgs.writeText "config.yaml" ( configFile = pkgs.writeText "config.yaml" (
@@ -91,14 +92,13 @@ in {
"$mod,B, exec, uwsm app -- ${config.programs.helium.package}/bin/helium" # Browser "$mod,B, exec, uwsm app -- ${config.programs.helium.package}/bin/helium" # Browser
# Power # Power
"$mod, X, global, caelestia:session" # Powermenu
( (
"$shiftMod, X, exec, " "$mod, X, exec, "
+ lib.getExe (mkMenu [ + lib.getExe (mkMenu [
{ {
key = "l"; key = "l";
desc = "Lock"; desc = "Lock";
cmd = "hyprctl dispatch global caelestia:lock"; cmd = "${pkgs.hyprlock}/bin/hyprlock";
} }
{ {
key = "s"; key = "s";
@@ -115,31 +115,20 @@ in {
desc = "Power Off"; desc = "Power Off";
cmd = "systemctl poweroff"; cmd = "systemctl poweroff";
} }
{
key = "n";
desc = "Nightshift";
cmd = "nightshift-toggle";
}
{
key = "c";
desc = "Restart caelestia";
cmd = "hyprctl dispatch exec 'caelestia-shell kill | sleep 1 | caelestia-shell'";
}
]) ])
) )
# Quick launch # Quick launch
"$mod,RETURN, exec, uwsm app -- ${pkgs.ghostty}/bin/ghostty" # Ghostty (terminal) "$mod,RETURN, exec, ${pkgs.ghostty}/bin/ghostty +new-window" # Ghostty (terminal, via daemon D-Bus)
"$mod,E, exec, uwsm app -- ${pkgs.thunar}/bin/thunar" # Thunar "$mod,E, exec, ${pkgs.ghostty}/bin/ghostty +new-window -e elio" # Elio
"$shiftMod, E, exec, pkill fuzzel || caelestia emoji -p" # Emoji picker "$mod, SPACE, exec, ${pkgs.tofi}/bin/tofi-drun" # Launcher
"$mod, SPACE, global, caelestia:launcher" # Launcher "$mod, N, exec, ${pkgs.swaynotificationcenter}/bin/swaync-client -t" # Notification center
"$mod, N, exec, caelestia shell drawers toggle sidebar" # Sidebar (Notifications, quick actions)
"$mod, D, exec, caelestia shell drawers toggle dashboard" # Dashboard
# Windows # Windows
"$mod,Q, killactive," # Close window "$mod,Q, killactive," # Close window
"$mod,F, fullscreen" # Toggle Fullscreen "$mod,F, fullscreen" # Toggle Fullscreen
"$shiftMod,F, togglefloating," # Toggle Floating "$shiftMod,F, togglefloating," # Toggle Floating
"$shiftMod, SPACE, exec, ${scripts.focus-toggle}/bin/focus-toggle" # Toggle focus mode
# Focus Windows # Focus Windows
"$mod,H, movefocus, l" # Move focus left "$mod,H, movefocus, l" # Move focus left
@@ -151,11 +140,13 @@ in {
"$shiftMod,K, layoutmsg, addmaster" # Add to master "$shiftMod,K, layoutmsg, addmaster" # Add to master
"$shiftMod,L, focusmonitor, 1" # Focus next monitor "$shiftMod,L, focusmonitor, 1" # Focus next monitor
# Special workspaces
"$mod, S, togglespecialworkspace, scratch" # Toggle scratch workspace
"$shiftMod, S, movetoworkspace, special:scratch" # Move to scratch workspace
# Utilities # Utilities
"$shiftMod, SPACE, exec, caelestia shell gameMode toggle" # Toggle Focus/Game mode ", Print, exec, ${pkgs.hyprshot}/bin/hyprshot -m region" # Capture region
"$shiftMod, S, global, caelestia:screenshotFreeze" # Capture region (freeze) "$shiftMod, Print, exec, ${pkgs.hyprshot}/bin/hyprshot -m output" # Capture screen
", Print, global, caelestia:screenshotFreeze" # Capture region (freeze)
"$shiftMod+Alt, S, global, caelestia:screenshot" # Capture region
] ]
++ (builtins.concatLists ( ++ (builtins.concatLists (
builtins.genList ( builtins.genList (
@@ -176,32 +167,21 @@ in {
bindl = [ bindl = [
# Brightness # Brightness
", XF86MonBrightnessUp, global, caelestia:brightnessUp" ", XF86MonBrightnessUp, exec, ${scripts.bright-up}/bin/bright-up"
", XF86MonBrightnessDown, global, caelestia:brightnessDown" ", XF86MonBrightnessDown, exec, ${scripts.bright-down}/bin/bright-down"
# Media # Media
", XF86AudioPlay, global, caelestia:mediaToggle" ", XF86AudioPlay, exec, ${pkgs.playerctl}/bin/playerctl play-pause"
", XF86AudioPause, global, caelestia:mediaToggle" ", XF86AudioPause, exec, ${pkgs.playerctl}/bin/playerctl play-pause"
", XF86AudioNext, global, caelestia:mediaNext" ", XF86AudioNext, exec, ${pkgs.playerctl}/bin/playerctl next"
", XF86AudioPrev, global, caelestia:mediaPrev" ", XF86AudioPrev, exec, ${pkgs.playerctl}/bin/playerctl previous"
", XF86AudioStop, global, caelestia:mediaStop" ", XF86AudioStop, exec, ${pkgs.playerctl}/bin/playerctl stop"
# Sound # Sound
", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" ", XF86AudioMute, exec, ${scripts.vol-mute}/bin/vol-mute"
", XF86AudioRaiseVolume, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ 0; wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+" ", XF86AudioRaiseVolume, exec, ${scripts.vol-up}/bin/vol-up"
", XF86AudioLowerVolume, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ 0; wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" ", XF86AudioLowerVolume, exec, ${scripts.vol-down}/bin/vol-down"
]; ", XF86AudioMicMute, exec, ${scripts.mic-mute}/bin/mic-mute"
bindin = [
# Launcher
"$mod, mouse:272, global, caelestia:launcherInterrupt"
"$mod, mouse:273, global, caelestia:launcherInterrupt"
"$mod, mouse:274, global, caelestia:launcherInterrupt"
"$mod, mouse:275, global, caelestia:launcherInterrupt"
"$mod, mouse:276, global, caelestia:launcherInterrupt"
"$mod, mouse:277, global, caelestia:launcherInterrupt"
"$mod, mouse_up, global, caelestia:launcherInterrupt"
"$mod, mouse_down, global, caelestia:launcherInterrupt"
]; ];
}; };
} }
+62 -33
View File
@@ -1,5 +1,6 @@
# Hyprland is a dynamic tiling Wayland compositor that is highly customizable and performant. # Hyprland is a dynamic tiling Wayland compositor that is highly customizable and performant.
{ {
pkgs-unstable,
pkgs, pkgs,
config, config,
lib, lib,
@@ -19,50 +20,52 @@ in {
./animations.nix ./animations.nix
./bindings.nix ./bindings.nix
./polkitagent.nix ./polkitagent.nix
./keyboard-backlight.nix # CHANGEME: This is for omen laptop only ./hyprpaper.nix
]; ];
home.packages = with pkgs; [ home.packages =
qt5.qtwayland (with pkgs-unstable; [
qt6.qtwayland qt5.qtwayland
libsForQt5.qt5ct qt6.qtwayland
qt6Packages.qt6ct hyprland-qtutils
xcb-util-cursor ])
libxcb ++ (with pkgs; [
hyprland-qtutils libsForQt5.qt5ct
adw-gtk3 qt6Packages.qt6ct
hyprshot xcb-util-cursor
hyprpicker papirus-icon-theme
swappy material-icons
imv material-design-icons
wf-recorder material-symbols
wlr-randr libxcb
brightnessctl adw-gtk3
gnome-themes-extra hyprshot
dconf hyprpicker
wayland-utils satty
wayland-protocols imv
]; wf-recorder
brightnessctl
gnome-themes-extra
dconf
wayland-utils
wayland-protocols
]);
wayland.windowManager.hyprland = { wayland.windowManager.hyprland = {
enable = true; enable = true;
configType = "hyprlang";
xwayland.enable = true; xwayland.enable = true;
systemd = { systemd.enable = false;
enable = false;
variables = [
"--all"
]; # https://wiki.hyprland.org/Nix/Hyprland-on-Home-Manager/#programs-dont-work-in-systemd-services-but-do-on-the-terminal
};
package = null; package = null;
portalPackage = null; portalPackage = null;
settings = { settings = {
exec-once = [ monitor = [
"dbus-update-activation-environment --systemd --all &" ",preferred,auto,1" # default
]; ];
monitor = [ exec-once = [
",prefered,auto,1" # default "systemctl --user start app-com.mitchellh.ghostty.service"
]; ];
env = [ env = [
@@ -83,7 +86,6 @@ in {
cursor = { cursor = {
no_hardware_cursors = true; no_hardware_cursors = true;
default_monitor = "eDP-2";
}; };
general = { general = {
@@ -121,8 +123,15 @@ in {
gesture = "3, horizontal, workspace"; gesture = "3, horizontal, workspace";
layerrule = [
"match:namespace launcher, animation popin 70%"
"match:namespace swaync-control-center, animation slide right"
];
windowrule = [ windowrule = [
"match:class .*, suppress_event maximize" "match:class .*, suppress_event maximize"
"match:class helium, suppress_event fullscreen"
"match:class helium, sync_fullscreen false"
"match:class proton-authenticator, float on" "match:class proton-authenticator, float on"
"match:class proton-authenticator, center on" "match:class proton-authenticator, center on"
@@ -131,6 +140,10 @@ in {
"match:class protonvpn-app, float on" "match:class protonvpn-app, float on"
"match:class protonvpn-app, center on" "match:class protonvpn-app, center on"
"match:class protonvpn-app, size 500 400" "match:class protonvpn-app, size 500 400"
"match:title run-bg, float on"
"match:title run-bg, center on"
"match:title run-bg, size 700 80"
]; ];
misc = { misc = {
@@ -161,4 +174,20 @@ in {
}; };
}; };
}; };
qt.enable = true;
gtk = {
enable = true;
iconTheme = {
name = "Papirus-Dark";
package = pkgs.papirus-icon-theme;
};
};
home.sessionVariables = {
XDG_ICON_DIR = "${pkgs.papirus-icon-theme}/share/icons/Papirus";
QS_ICON_THEME = "Papirus";
QT_STYLE_OVERRIDE = lib.mkForce "Fusion";
};
} }
@@ -1,44 +0,0 @@
# Turn the keyboard red/off when the battery is low
# Include this one only if you have a omen laptop with RGB keyboard
{
pkgs,
config,
...
}: let
alert-when-low-battery = false;
keyboard-backlight = pkgs.writeShellScriptBin "keyboard-backlight" ''
function set_keyboard_backlight {
local color=$1
echo $color > /sys/devices/platform/hp-wmi/rgb_zones/zone00
echo $color > /sys/devices/platform/hp-wmi/rgb_zones/zone01
echo $color > /sys/devices/platform/hp-wmi/rgb_zones/zone02
echo $color > /sys/devices/platform/hp-wmi/rgb_zones/zone03
}
state="white"
set_keyboard_backlight ${config.lib.stylix.colors.base0D}
if [ "${toString alert-when-low-battery}" = "false" ]; then
exit 0
fi
while true; do
BATTERY_LEVEL=$(cat /sys/class/power_supply/BAT*/capacity)
IS_CHARGING=$(cat /sys/class/power_supply/BAT*/status)
if [[ $BATTERY_LEVEL -le 10 && $IS_CHARGING != "Charging" ]]; then
if [[ $state == "red" ]];then
state="white"
set_keyboard_backlight "000000"
else
state="red"
set_keyboard_backlight "FF0000"
fi
else
state="white"
set_keyboard_backlight ${config.lib.stylix.colors.base0D}
fi
sleep 2
done
'';
command = "bash ${keyboard-backlight}/bin/keyboard-backlight &";
in {
wayland.windowManager.hyprland.settings.exec-once = [command];
}
+82
View File
@@ -0,0 +1,82 @@
{config, ...}: let
c = config.lib.stylix.colors;
in {
stylix.targets.hyprlock.enable = false;
programs.hyprlock = {
enable = true;
settings = {
background = [
{
monitor = "";
color = "rgba(${c.base00}FF)";
}
];
label = [
{
monitor = "";
text = ''cmd[update:0] echo "[$USER@$(hostname) ~]"'';
color = "rgb(${c.base0D})";
font_size = 13;
font_family = "Maple Mono NF";
position = "48, -48";
halign = "left";
valign = "top";
}
{
monitor = "";
text = ''cmd[update:1000] echo "$(date +'%H:%M:%S')"'';
color = "rgb(${c.base05})";
font_size = 13;
font_family = "Maple Mono NF";
position = "48, -70";
halign = "left";
valign = "top";
}
{
monitor = "";
text = ''cmd[update:60000] echo "$(date +'%A %d %B %Y')"'';
color = "rgb(${c.base04})";
font_size = 13;
font_family = "Maple Mono NF";
position = "48, -92";
halign = "left";
valign = "top";
}
{
monitor = "";
text = "passwd:";
color = "rgb(${c.base0D})";
font_size = 13;
font_family = "Maple Mono NF";
position = "48, -141";
halign = "left";
valign = "top";
}
];
"input-field" = [
{
monitor = "";
size = "200, 20";
outline_thickness = 0;
outer_color = "rgba(00000000)";
inner_color = "rgba(00000000)";
font_color = "rgb(${c.base05})";
fade_on_empty = false;
placeholder_text = "";
hide_input = true;
rounding = 0;
check_color = "rgb(${c.base0B})";
fail_color = "rgb(${c.base08})";
fail_text = ''<span font_desc="Maple Mono NF 13">auth failed</span>'';
capslock_color = "rgb(${c.base0A})";
position = "116, -138";
halign = "left";
valign = "top";
}
];
};
};
}
+36 -34
View File
@@ -1,25 +1,18 @@
# Mime type associations for the system.
{ {
lib, lib,
pkgs, pkgs,
... ...
}: }: let
with lib; let
defaultApps = { defaultApps = {
# check desktop files here: `ls $(echo $XDG_DATA_DIRS| sed "s/:/ /g")` text = ["nvim-ghostty.desktop"];
text = [
# "org.gnome.TextEditor.desktop"
"nvim-ghostty.desktop"
];
code = ["nvim-ghostty.desktop"]; code = ["nvim-ghostty.desktop"];
image = ["imv-dir.desktop"]; image = ["imv-dir.desktop"];
audio = ["mpv.desktop"]; audio = ["vlc.desktop"];
video = ["mpv.desktop"]; video = ["vlc.desktop"];
directory = ["thunar.desktop"]; directory = ["elio.desktop"];
office = ["libreoffice.desktop"]; office = ["onlyoffice-desktopeditors.desktop"];
pdf = ["zathura.desktop"]; pdf = ["onlyoffice-desktopeditors.desktop"];
terminal = ["ghostty.desktop"]; archive = ["elio.desktop"];
archive = ["xarchiver.desktop"];
browser = ["helium.desktop"]; browser = ["helium.desktop"];
}; };
@@ -34,7 +27,6 @@ with lib; let
"text/x-go" "text/x-go"
"text/x-java" "text/x-java"
"text/x-csharp" "text/x-csharp"
"text/x-python" "text/x-python"
"application/x-shellscript" "application/x-shellscript"
"text/javascript" "text/javascript"
@@ -42,7 +34,6 @@ with lib; let
"text/css" "text/css"
"text/x-php" "text/x-php"
"text/x-ruby" "text/x-ruby"
"application/json" "application/json"
"application/xml" "application/xml"
"text/xml" "text/xml"
@@ -51,11 +42,8 @@ with lib; let
"application/toml" "application/toml"
"text/x-nix" "text/x-nix"
"text/markdown" "text/markdown"
"text/x-dockerfile" "text/x-dockerfile"
"application/x-yaml"
"text/x-terraform" "text/x-terraform"
"application/x-perl" "application/x-perl"
"text/x-lua" "text/x-lua"
"text/x-haskell" "text/x-haskell"
@@ -104,12 +92,17 @@ with lib; let
"application/rtf" "application/rtf"
]; ];
pdf = ["application/pdf"]; pdf = ["application/pdf"];
terminal = ["terminal"];
archive = [ archive = [
"application/zip" "application/zip"
"application/rar" "application/x-rar-compressed"
"application/7z" "application/vnd.rar"
"application/*tar" "application/x-7z-compressed"
"application/x-tar"
"application/gzip"
"application/x-bzip2"
"application/x-xz"
"application/x-zstd"
"application/x-compressed-tar"
]; ];
browser = [ browser = [
"text/html" "text/html"
@@ -123,19 +116,19 @@ with lib; let
nvim-ghostty = pkgs.makeDesktopItem { nvim-ghostty = pkgs.makeDesktopItem {
name = "nvim-ghostty"; name = "nvim-ghostty";
desktopName = "Neovim (Ghostty)"; desktopName = "Neovim (Ghostty)";
exec = ''ghostty --title="Neovim Editor" -e nvim %F''; exec = ''${pkgs.ghostty}/bin/ghostty +new-window --title="Neovim Editor" -e nvim %F'';
terminal = false; terminal = false;
categories = [ categories = ["Development" "TextEditor"];
"Development"
"TextEditor"
];
mimeTypes = mimeMap.code ++ mimeMap.text; mimeTypes = mimeMap.code ++ mimeMap.text;
}; };
associations = with lists; associations = lib.listToAttrs (
listToAttrs ( lib.flatten (
flatten (mapAttrsToList (key: map (type: attrsets.nameValuePair type defaultApps."${key}")) mimeMap) lib.mapAttrsToList
); (key: map (type: lib.nameValuePair type defaultApps.${key}))
mimeMap
)
);
in { in {
home.packages = [nvim-ghostty]; home.packages = [nvim-ghostty];
@@ -144,7 +137,16 @@ in {
mimeApps = { mimeApps = {
enable = true; enable = true;
associations.added = associations; associations.added = associations;
defaultApplications = associations; defaultApplications = lib.mapAttrs (_: lib.mkForce) associations;
};
userDirs = {
enable = true;
createDirectories = true;
desktop = null;
music = null;
publicShare = null;
templates = null;
}; };
}; };
} }
+421
View File
@@ -0,0 +1,421 @@
{
config,
pkgs,
...
}: let
scripts = import ../waybar/scripts.nix {inherit pkgs config;};
c = config.lib.stylix.colors;
font = config.stylix.fonts.sansSerif.name;
monofont = config.stylix.fonts.monospace.name;
rounding = config.theme.rounding;
border-size = config.theme.border-size;
gaps-in = config.theme.gaps-in;
opacityToHex = opacity: let
val = builtins.floor (opacity * 255);
high = val / 16;
low = val - high * 16;
digits = "0123456789abcdef";
in "${builtins.substring high 1 digits}${builtins.substring low 1 digits}";
alphaHex = opacityToHex config.theme.inactive-opacity;
in {
services.swaync = {
enable = true;
settings = {
positionX = "right";
positionY = "top";
layer = "overlay";
"control-center-layer" = "overlay";
cssPriority = "user";
"control-center-width" = 450;
"control-center-margin-top" = config.theme.gaps-out * 2;
"control-center-margin-bottom" = config.theme.gaps-out * 2;
"control-center-margin-right" = 0;
"fit-to-screen" = true;
"notification-window-width" = 400;
"notification-icon-size" = 40;
"notification-body-image-height" = 500;
"notification-body-image-width" = 500;
"notification-inline-replies" = true;
"notification-2fa-action" = false;
timeout = 3;
"timeout-low" = 2;
"timeout-critical" = 6;
"keyboard-shortcuts" = true;
"image-visibility" = "when-available";
"transition-time" = 200;
"hide-on-clear" = false;
"hide-on-action" = false;
"script-fail-notify" = true;
widgets = ["mpris" "volume" "backlight" "dnd" "buttons-grid" "notifications"];
"widget-config" = {
dnd.text = "Do not disturb";
volume = {
label = "󰕾";
"show-per-app" = false;
};
backlight = {
label = "󰃠";
"min" = 0;
};
mpris = {
"image-size" = 100;
"image-radius" = 10;
autohide = false;
blacklist = ["org.mpris.MediaPlayer2.playerctld"];
};
"buttons-grid" = {
actions = [
{
label = "󰖔";
type = "toggle";
command = "${scripts.nightshift-toggle}/bin/nightshift-toggle";
"update-command" = "${pkgs.procps}/bin/pidof ${pkgs.hyprsunset}/bin/hyprsunset > /dev/null && echo true || echo false";
}
{
label = "󰈈";
type = "toggle";
command = "${scripts.focus-toggle}/bin/focus-toggle";
"update-command" = "test -f /tmp/hypr-focus-mode && echo true || echo false";
}
{
label = "󰍭";
type = "toggle";
command = "${scripts.mic-mute}/bin/mic-mute";
"update-command" = "${scripts.mic-status}/bin/mic-status";
}
{
label = "󰌾";
command = "${pkgs.swaynotificationcenter}/bin/swaync-client -cp ; ${pkgs.hyprlock}/bin/hyprlock";
}
{
label = "󰐥";
command = "${pkgs.swaynotificationcenter}/bin/swaync-client -cp ; systemctl poweroff";
}
];
};
};
};
style = ''
@define-color center-bg #${c.base01}${alphaHex};
@define-color notification-bg #${c.base00}${alphaHex};
@define-color center-notification-bg #${c.base01};
@define-color background #${c.base00}${alphaHex};
@define-color background-alt #${c.base01};
@define-color text #${c.base05};
@define-color text-alt #${c.base03};
@define-color selected #${c.base03}66;
@define-color hover #${c.base03}28;
@define-color urgent #${c.base08};
* {
all: unset;
font-family: "${font}";
font-weight: 700;
--border-radius: ${toString rounding}px;
--border-radius-s: ${toString gaps-in}px;
--border-radius-xl: ${toString (rounding - 2)}px;
}
.notification { padding: 5px; }
.notification-row { background: transparent; border: none; box-shadow: none; }
.control-center .notification { padding: 0; }
.notification-background {
background: @notification-bg;
border-radius: var(--border-radius);
border: ${toString border-size}px solid @selected;
box-shadow: none;
outline: none;
margin: ${toString gaps-in}px;
padding: 0;
}
.notification-background .close-button {
margin: 6px;
padding: 2px;
border-radius: ${toString (gaps-in - 2)}px;
background: transparent;
color: @text;
}
.notification-background .close-button:hover { background: @hover; }
.notification.low,
.notification.normal { border: none; }
.notification.critical {
border: ${toString border-size}px solid @urgent;
border-radius: var(--border-radius);
}
.notification-content {
color: @text;
margin: 10px;
font-weight: 700;
border: none;
}
.notification-content .text-box { margin: 0 0 0 15px; }
.notification-content .time {
padding: 2px;
font-size: 0.95rem;
font-weight: 800;
}
.notification-content .summary {
font-size: 1rem;
font-weight: 800;
padding: 2px 0;
margin-bottom: 2px;
}
.notification-content .body {
color: @text-alt;
font-size: 0.8rem;
}
.notification-row .inline-reply-entry,
.notification-row .inline-reply-button {
margin: 5px -5px -5px -5px;
padding: 10px 15px;
border-radius: var(--border-radius);
background: @background-alt;
}
.notification-row .inline-reply-entry { margin-right: 10px; }
.notification-row .inline-reply-button:hover { background: @selected; }
.notification-alt-actions { padding: 5px 0; }
.notification-action {
font-weight: 700;
border-radius: var(--border-radius);
background: @hover;
color: @text;
margin: 0 5px;
padding: 10px 0;
}
.notification-action:hover,
.notification-action:active { background: @selected; }
.control-center {
background: @center-bg;
border-radius: var(--border-radius) 0 0 var(--border-radius);
border-left: ${toString border-size}px solid @selected;
margin: 0;
padding: 5px 5px 0 5px;
}
.control-center .notification-background {
background: @center-notification-bg;
}
.control-center .notification-background .close-button,
.notification-group-close-button { opacity: 0; }
.notification-group { transition: 200ms; }
.notification-group:not(.collapsed) { margin: ${toString gaps-in}px; }
.notification-group-headers,
.notification-group-buttons {
color: @text;
font-weight: bold;
background: @background;
border-radius: var(--border-radius);
padding: 4px 8px;
}
.notification-group-headers > label {
margin: 0 3px;
font-size: 1rem;
}
.notification-group-icon { color: @text; }
.notification-group-buttons .image-button {
background: transparent;
color: @text;
padding: 4px;
border-radius: var(--border-radius);
}
.notification-group-buttons .image-button:hover { background: @hover; }
.widget {
margin: 5px;
color: @text;
}
.widget-mpris-album-art {
border-radius: var(--border-radius);
margin: 6px 4px;
}
.widget-mpris-title {
font-weight: 700;
font-size: 1.2rem;
margin: 0 3px;
}
.widget-mpris-subtitle {
color: @text-alt;
font-weight: 700;
font-size: 0.9rem;
margin: 0 3px;
}
.mpris-background { border-radius: 14px; margin: 3px; }
.widget-mpris {
border-radius: var(--border-radius);
}
.mpris-overlay {
border-radius: var(--border-radius);
padding: 10px;
background: @background;
}
.mpris-overlay > box:last-child {
border-radius: var(--border-radius-xl);
padding: 0 5px;
background: alpha(@hover, .6);
}
.widget-mpris-player button {
padding: 5px;
margin: 0 2.5px;
}
.widget-mpris-player button:hover {
border-radius: var(--border-radius-s);
background: @hover;
}
.widget-volume,
.widget-backlight {
border-radius: var(--border-radius);
padding: 10px 15px;
background: @background-alt;
color: @text;
}
.widget-volume > box,
.widget-backlight > box {
color: @text;
}
.widget-volume label,
.widget-backlight label {
font-size: 1rem;
font-weight: 700;
min-width: 1.2rem;
}
.widget-volume slider,
.widget-backlight slider {
background: @text;
border-radius: var(--border-radius-s);
min-height: 12px;
min-width: 12px;
}
.widget-volume trough,
.widget-backlight trough {
background: @hover;
border-radius: var(--border-radius-s);
min-height: 4px;
}
.widget-volume highlight,
.widget-backlight highlight {
background: @text;
border-radius: var(--border-radius-s);
}
.widget-dnd {
padding: 10px 15px;
border-radius: var(--border-radius);
background: @background-alt;
color: @text;
}
.widget-dnd > label {
font-size: 1rem;
font-weight: 700;
}
.widget-dnd switch {
background: @hover;
border-radius: var(--border-radius-s);
box-shadow: none;
padding: 2px;
transition: 200ms;
}
.widget-dnd switch slider {
background: @text;
border-radius: var(--border-radius-s);
}
.widget-dnd switch:hover,
.widget-dnd switch:checked { background-color: @selected; }
.widget-notifications { margin: 0; }
.widget-buttons-grid {
border-radius: var(--border-radius);
padding: 5px 15px;
margin-bottom: 5px;
background: @background-alt;
}
.widget-buttons-grid button {
padding: 10px;
margin: 3px;
min-width: 2rem;
font-family: "${monofont}";
background: @hover;
border-radius: var(--border-radius);
transition: 200ms;
}
.widget-buttons-grid button > label {
font-family: "${monofont}";
font-size: 18px;
font-weight: normal;
font-style: normal;
color: @text;
}
.widget-buttons-grid button:hover { background: @selected; }
.widget-buttons-grid button:checked { background-color: @text; }
.widget-buttons-grid button:checked > label { color: @background; }
.control-center-list-placeholder { color: @text; }
.blank-window { background: transparent; }
'';
};
stylix.targets.swaync.enable = false;
# GTK 4.22 defaults to the Vulkan renderer, which compiles its graphics
# pipelines lazily on the first frame. The control center has many distinct
# visual elements, so the first open triggers a big burst of pipeline
# compilation (a multi-second stall on a cold boot) while later opens reuse
# the in-process cache. The GL (ngl) renderer avoids this: it stays
# GPU-accelerated and benefits from Mesa's on-disk shader cache, so the
# first open is as fast as the rest. Scoped to swaync so other GTK4 apps
# keep the Vulkan renderer.
systemd.user.services.swaync.Service.Environment = ["GSK_RENDERER=ngl"];
}
+65
View File
@@ -0,0 +1,65 @@
# Use elio as the file picker for portal dialogs (browser "select file(s)" and
# "save download to..."). The backend is xdg-desktop-portal-termfilechooser,
# enabled system-wide in nixos/utils.nix (extraPortals + FileChooser routing).
{
config,
pkgs,
...
}: let
wrapper = pkgs.writeShellScript "elio-wrapper" ''
multiple="$1"
directory="$2"
save="$3"
path="$4"
out="$5"
debug="$6"
set -e
if [[ "$debug" = 1 ]]; then
set -x
fi
cmd="elio"
termcmd="''${TERMCMD:-ghostty --gtk-single-instance=false --title=termfilechooser -e}"
if [[ "$save" = "1" ]]; then
set -- --chooser-file="$out" "$path"
elif [[ "$directory" = "1" ]]; then
set -- --chooser-file="$out" --cwd-file="$out.1" "$path"
else
set -- --chooser-file="$out" "$path"
fi
command="$termcmd $cmd"
for arg in "$@"; do
escaped=$(printf "%s" "$arg" | sed 's/"/\\"/g')
command="$command \"$escaped\""
done
sh -c "$command"
if [[ "$directory" = "1" ]]; then
if [[ ! -s "$out" ]] && [[ -s "$out.1" ]]; then
cat "$out.1" > "$out"
rm "$out.1"
else
rm "$out.1"
fi
fi
'';
# ghostty must run in the foreground instead of handing off to the
# single-instance daemon, otherwise the wrapper returns before you've picked
# anything and the portal reads an empty selection.
termcmd = "ghostty --gtk-single-instance=false --title=termfilechooser -e";
in {
xdg.configFile."xdg-desktop-portal-termfilechooser/config".text = ''
[filechooser]
cmd=${wrapper}
default_dir=$HOME
open_mode=suggested
save_mode=suggested
env=TERMCMD=${termcmd}
PATH=${config.home.profileDirectory}/bin:/run/current-system/sw/bin:/run/wrappers/bin
'';
}
+47
View File
@@ -0,0 +1,47 @@
{
config,
lib,
...
}: let
c = config.lib.stylix.colors;
font = config.stylix.fonts.serif.name;
gaps = config.theme.gaps-out;
barHeight = config.theme.bar-height;
rounding =
if config.theme.rounding > barHeight / 2
then barHeight / 2
else config.theme.rounding;
in {
imports = [./desktop-actions.nix];
programs.tofi = {
enable = true;
settings = {
anchor = "top";
height = barHeight;
margin-top = gaps;
margin-left = 350;
margin-right = 350;
horizontal = true;
num-results = 8;
result-spacing = 20;
padding-top = 2;
padding-bottom = 2;
padding-left = 14;
padding-right = 14;
font = lib.mkForce font;
prompt-color = lib.mkForce "#${c.base0D}ff";
selection-color = lib.mkForce "#${c.base0D}ff";
outline-width = 0;
border-width = 0;
corner-radius = rounding;
prompt-text = " ";
placeholder-text = "Search...";
drun-launch = true;
};
};
}
+333
View File
@@ -0,0 +1,333 @@
{
pkgs,
config,
...
}: let
scripts = import ../waybar/scripts.nix {inherit pkgs config;};
in {
xdg.desktopEntries = {
focus-toggle = {
name = "Focus Mode";
exec = "${scripts.focus-toggle}/bin/focus-toggle";
icon = "do-not-disturb-symbolic";
comment = "Toggle focus mode";
categories = ["System"];
terminal = false;
};
nightshift-toggle = {
name = "Night Shift";
exec = "${scripts.nightshift-toggle}/bin/nightshift-toggle";
icon = "night-light-symbolic";
comment = "Toggle night shift";
categories = ["System"];
terminal = false;
};
mic-mute = {
name = "Mute Microphone";
exec = "${scripts.mic-mute}/bin/mic-mute";
icon = "microphone-sensitivity-muted-symbolic";
comment = "Toggle microphone mute";
categories = ["System"];
terminal = false;
};
lock = {
name = "Lock";
exec = "${pkgs.hyprlock}/bin/hyprlock";
icon = "system-lock-screen-symbolic";
comment = "Lock the screen";
categories = ["System"];
terminal = false;
};
reboot = {
name = "Reboot";
exec = "systemctl reboot";
icon = "system-restart-symbolic";
comment = "Restart the system";
categories = ["System"];
terminal = false;
};
shutdown = {
name = "Shutdown";
exec = "systemctl poweroff";
icon = "system-shutdown-symbolic";
comment = "Power off the system";
categories = ["System"];
terminal = false;
};
hibernate = {
name = "Hibernate";
exec = "systemctl hibernate";
icon = "drive-harddisk-symbolic";
comment = "Hibernate the system";
categories = ["System"];
terminal = false;
};
waybar-toggle = {
name = "Toggle Waybar";
exec = "${scripts.waybar-toggle}/bin/waybar-toggle";
icon = "panel-applets-symbolic";
comment = "Show or hide the status bar";
categories = ["System"];
terminal = false;
};
wifi-toggle = {
name = "Toggle Wi-Fi";
exec = "${scripts.wifi-toggle}/bin/wifi-toggle";
icon = "network-wireless-symbolic";
comment = "Enable or disable Wi-Fi";
categories = ["System"];
terminal = false;
};
bluetooth-toggle = {
name = "Toggle Bluetooth";
exec = "${scripts.bluetooth-toggle}/bin/bluetooth-toggle";
icon = "bluetooth-symbolic";
comment = "Enable or disable Bluetooth";
categories = ["System"];
terminal = false;
};
color-pick = {
name = "Pick Color";
exec = "${scripts.color-pick}/bin/color-pick";
icon = "color-select-symbolic";
comment = "Pick a screen color to the clipboard";
categories = ["Utility"];
terminal = false;
settings.Keywords = "color;picker;hex;eyedropper;";
};
screenshot-region = {
name = "Screenshot Region";
exec = "${pkgs.hyprshot}/bin/hyprshot -m region";
icon = "screenshot-recorded-symbolic";
comment = "Capture a selected region";
categories = ["Utility"];
terminal = false;
settings.Keywords = "screenshot;capture;region;";
};
screenshot-window = {
name = "Screenshot Window";
exec = "${pkgs.hyprshot}/bin/hyprshot -m window";
icon = "screenshot-recorded-symbolic";
comment = "Capture the active window";
categories = ["Utility"];
terminal = false;
settings.Keywords = "screenshot;capture;window;";
};
screenshot-screen = {
name = "Screenshot Screen";
exec = "${pkgs.hyprshot}/bin/hyprshot -m output";
icon = "screenshot-recorded-symbolic";
comment = "Capture the whole screen";
categories = ["Utility"];
terminal = false;
settings.Keywords = "screenshot;capture;screen;monitor;";
};
screenshot-edit = {
name = "Screenshot & Annotate";
exec = "${scripts.screenshot-edit}/bin/screenshot-edit";
icon = "edit-symbolic";
comment = "Capture a region and open it in Satty";
categories = ["Utility"];
terminal = false;
settings.Keywords = "screenshot;annotate;satty;edit;";
};
record-toggle = {
name = "Screen Recording";
exec = "${scripts.record-toggle}/bin/record-toggle";
icon = "media-record-symbolic";
comment = "Start or stop screen recording";
categories = ["Utility" "AudioVideo"];
terminal = false;
settings.Keywords = "record;recording;screencast;video;";
};
power-cycle = {
name = "Power Profile";
exec = "${scripts.power-cycle}/bin/power-cycle";
icon = "power-profile-balanced-symbolic";
comment = "Cycle power-saver / balanced / performance";
categories = ["System"];
terminal = false;
settings.Keywords = "power;profile;performance;battery;";
};
airplane-toggle = {
name = "Airplane Mode";
exec = "${scripts.airplane-toggle}/bin/airplane-toggle";
icon = "airplane-mode-symbolic";
comment = "Toggle Wi-Fi and Bluetooth together";
categories = ["System"];
terminal = false;
settings.Keywords = "airplane;flight;wifi;bluetooth;offline;";
};
clipboard-menu = {
name = "Clipboard History";
exec = "${scripts.clipboard-menu}/bin/clipboard-menu";
icon = "edit-paste-symbolic";
comment = "Pick a past clipboard entry";
categories = ["Utility"];
terminal = false;
settings.Keywords = "clipboard;history;paste;cliphist;";
};
clipboard-wipe = {
name = "Clear Clipboard History";
exec = "${pkgs.cliphist}/bin/cliphist wipe";
icon = "edit-clear-all-symbolic";
comment = "Delete all clipboard history entries";
categories = ["Utility"];
terminal = false;
settings.Keywords = "clipboard;history;clear;wipe;delete;cliphist;";
};
emoji-picker = {
name = "Emoji Picker";
exec = "${scripts.emoji-picker}/bin/emoji-picker";
icon = "face-smile-symbolic";
comment = "Pick an emoji and type it";
categories = ["Utility"];
terminal = false;
settings.Keywords = "emoji;emoticon;smiley;symbol;";
};
icon-picker = {
name = "Icon Picker";
exec = "${scripts.icon-picker}/bin/icon-picker";
icon = "character-map-symbolic";
comment = "Pick a Nerd Font icon and type it";
categories = ["Utility"];
terminal = false;
settings.Keywords = "icon;nerdfont;glyph;symbol;";
};
caffeine-toggle = {
name = "Keep Awake";
exec = "${scripts.caffeine-toggle}/bin/caffeine-toggle";
icon = "my-caffeine-on-symbolic";
comment = "Pause or resume idle locking and suspend";
categories = ["System"];
terminal = false;
settings.Keywords = "caffeine;idle;awake;inhibit;suspend;";
};
logout = {
name = "Logout";
exec = "${pkgs.hyprland}/bin/hyprctl dispatch exit";
icon = "system-log-out-symbolic";
comment = "End the current session";
categories = ["System"];
terminal = false;
};
dnd-toggle = {
name = "Do Not Disturb";
exec = "${scripts.dnd-toggle}/bin/dnd-toggle";
icon = "notifications-disabled-symbolic";
comment = "Toggle Do Not Disturb";
categories = ["System"];
terminal = false;
settings.Keywords = "dnd;notifications;disturb;swaync;silence;";
};
vol-mute = {
name = "Mute Volume";
exec = "${scripts.vol-mute}/bin/vol-mute";
icon = "audio-volume-muted-symbolic";
comment = "Toggle output mute";
categories = ["System"];
terminal = false;
};
vol-up = {
name = "Volume Up";
exec = "${scripts.vol-up}/bin/vol-up";
icon = "audio-volume-high-symbolic";
comment = "Raise the volume by 5%";
categories = ["System"];
terminal = false;
};
vol-down = {
name = "Volume Down";
exec = "${scripts.vol-down}/bin/vol-down";
icon = "audio-volume-low-symbolic";
comment = "Lower the volume by 5%";
categories = ["System"];
terminal = false;
};
bright-up = {
name = "Brightness Up";
exec = "${scripts.bright-up}/bin/bright-up";
icon = "display-brightness-high-symbolic";
comment = "Raise the brightness by 5%";
categories = ["System"];
terminal = false;
};
bright-down = {
name = "Brightness Down";
exec = "${scripts.bright-down}/bin/bright-down";
icon = "display-brightness-low-symbolic";
comment = "Lower the brightness by 5%";
categories = ["System"];
terminal = false;
};
output-cycle = {
name = "Cycle Audio Output";
exec = "${scripts.output-cycle}/bin/output-cycle";
icon = "audio-speakers-symbolic";
comment = "Switch to the next audio output";
categories = ["System"];
terminal = false;
settings.Keywords = "audio;output;sink;speaker;headphones;";
};
input-cycle = {
name = "Cycle Audio Input";
exec = "${scripts.input-cycle}/bin/input-cycle";
icon = "audio-input-microphone-symbolic";
comment = "Switch to the next audio input";
categories = ["System"];
terminal = false;
settings.Keywords = "audio;input;source;microphone;mic;";
};
spotatui = {
name = "Spotify";
exec = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.spotatui}/bin/spotatui";
icon = "spotify";
comment = "Control Spotify from the terminal";
categories = ["Audio" "Music"];
terminal = false;
settings.Keywords = "spotify;spotatui;music;";
};
settuings = {
name = "Settings";
exec = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings";
icon = "preferences-system-symbolic";
comment = "Terminal based settings (wifi, bluetooth, audio, ...)";
categories = ["Settings"];
terminal = false;
settings.Keywords = "settings;wifi;bluetooth;audio;settuings;";
};
};
}
+1
View File
@@ -4,5 +4,6 @@
enable = true; enable = true;
notify = true; notify = true;
automount = true; automount = true;
tray = "never";
}; };
} }
+103
View File
@@ -0,0 +1,103 @@
# battery-monitor: low-battery alerts for waybar/swaync.
# Runs main once (triggered by the battery-monitor systemd timer).
POWER_SUPPLY_DIR="${POWER_SUPPLY_DIR:-/sys/class/power_supply}"
STATE_FILE="${BATTERY_STATE_FILE:-/tmp/battery-alert-state}"
CRIT_ID_FILE="${BATTERY_CRIT_ID_FILE:-/tmp/battery-crit-id}"
WARN_THRESHOLD=10
CRIT_THRESHOLD=5
# Pure decision. Prints "<action>:<newstate>".
# action ∈ noop | osd_warn | crit_show | crit_clear ; state ∈ none | warn10 | crit5
battery_decide() {
status=$1
cap=$2
prev=$3
if [ "$status" = "Discharging" ]; then
if [ "$cap" -le "$CRIT_THRESHOLD" ]; then
echo "crit_show:crit5"
elif [ "$cap" -le "$WARN_THRESHOLD" ]; then
if [ "$prev" = "crit5" ]; then
echo "crit_clear:warn10"
elif [ "$prev" = "warn10" ]; then
echo "noop:warn10"
else
echo "osd_warn:warn10"
fi
else
if [ "$prev" = "crit5" ]; then
echo "crit_clear:none"
else
echo "noop:none"
fi
fi
else
if [ "$prev" = "crit5" ]; then
echo "crit_clear:none"
else
echo "noop:none"
fi
fi
}
# First real battery (type == Battery, with status + capacity).
resolve_battery() {
for d in "$POWER_SUPPLY_DIR"/*; do
[ -r "$d/type" ] || continue
[ "$(cat "$d/type")" = "Battery" ] || continue
[ -r "$d/status" ] && [ -r "$d/capacity" ] || continue
printf '%s' "$d"
return 0
done
return 1
}
show_warn_osd() {
waybar-osd "󰂃 Low battery · $1%"
}
show_crit_notification() {
cap=$1
id=$(cat "$CRIT_ID_FILE" 2>/dev/null || echo 0)
newid=$(notify-send --print-id --replace-id="$id" \
--urgency=critical --expire-time=0 \
"󰂃 Critical battery" "Battery at $cap%: plug in the charger")
printf '%s' "$newid" >"$CRIT_ID_FILE"
}
clear_crit_notification() {
id=$(cat "$CRIT_ID_FILE" 2>/dev/null || echo 0)
if [ "$id" != "0" ]; then
gdbus call --session \
--dest org.freedesktop.Notifications \
--object-path /org/freedesktop/Notifications \
--method org.freedesktop.Notifications.CloseNotification "$id" \
>/dev/null 2>&1 || true
fi
rm -f "$CRIT_ID_FILE"
}
main() {
dir=$(resolve_battery) || exit 0
status=$(cat "$dir/status")
cap=$(cat "$dir/capacity")
prev=$(cat "$STATE_FILE" 2>/dev/null || echo none)
result=$(battery_decide "$status" "$cap" "$prev")
action=${result%%:*}
newstate=${result##*:}
case "$action" in
osd_warn) show_warn_osd "$cap" ;;
crit_show) show_crit_notification "$cap" ;;
crit_clear) clear_crit_notification ;;
noop) : ;;
esac
printf '%s' "$newstate" >"$STATE_FILE"
}
main "$@"
+59
View File
@@ -0,0 +1,59 @@
{
pkgs,
config,
...
}: let
scripts = import ./scripts.nix {inherit pkgs config;};
in {
imports = [
./settings.nix
./style.nix
];
_module.args.networkScript = scripts.networkScript;
_module.args.bluetoothScript = scripts.bluetoothScript;
_module.args.volMuteScript = scripts.vol-mute;
_module.args.caffeineToggleScript = scripts.caffeine-toggle;
_module.args.osdStatusScript = scripts.waybar-osd-status;
_module.args.nightshiftToggleScript = scripts.nightshift-toggle;
programs.waybar.enable = true;
stylix.targets.waybar.enable = false;
home.packages = with pkgs;
[
playerctl
pavucontrol
blueman
hyprsunset
]
++ (with scripts; [waybar-osd waybar-osd-status battery-monitor vol-up vol-down vol-mute mic-mute bright-up bright-down nightshift-toggle focus-toggle waybar-toggle wifi-toggle bluetooth-toggle dnd-toggle output-cycle input-cycle color-pick screenshot-edit record-toggle power-cycle airplane-toggle clipboard-menu emoji-picker caffeine-toggle mic-status]);
# Poll battery level every 30s; battery-monitor no-ops when no battery exists.
systemd.user.services.battery-monitor = {
Unit.Description = "Low-battery OSD and critical notification monitor";
Service = {
Type = "oneshot";
ExecStart = "${scripts.battery-monitor}/bin/battery-monitor";
};
};
systemd.user.timers.battery-monitor = {
Unit.Description = "Poll battery level for low-battery alerts";
Timer = {
OnBootSec = "1min";
OnUnitActiveSec = "30s";
};
Install.WantedBy = ["timers.target"];
};
# Prevent blueman-applet from auto-starting via XDG autostart (we use custom/bluetooth module instead)
xdg.configFile."autostart/blueman.desktop".text = ''
[Desktop Entry]
Hidden=true
'';
wayland.windowManager.hyprland.settings.exec-once = [
"waybar"
];
}
+455
View File
@@ -0,0 +1,455 @@
{
pkgs,
config,
}: let
waybar-osd = pkgs.writeShellApplication {
name = "waybar-osd";
runtimeInputs = with pkgs; [procps coreutils];
text = ''
printf '%s' "$1" > /tmp/waybar-osd
pkill -x -RTMIN+8 waybar 2>/dev/null || true
'';
};
waybar-osd-status = pkgs.writeShellApplication {
name = "waybar-osd-status";
runtimeInputs = with pkgs; [coreutils];
text = ''
file=/tmp/waybar-osd
[ -f "$file" ] || exit 1
mtime=$(stat -c %Y "$file" 2>/dev/null) || exit 1
age=$(( $(date +%s) - mtime ))
if [ "$age" -ge 3 ]; then
rm -f "$file"
exit 1
fi
'';
};
# battery-monitor: low-battery alerts, run by the systemd user timer.
battery-monitor = pkgs.writeShellApplication {
name = "battery-monitor";
runtimeInputs = with pkgs; [waybar-osd libnotify glib coreutils];
text = builtins.readFile ./battery-monitor.sh;
};
updateOsd = ''
${waybar-osd}/bin/waybar-osd "$OSD_TEXT"
'';
volGetText = ''
VOL_RAW=$(${pkgs.wireplumber}/bin/wpctl get-volume @DEFAULT_SINK@)
VOL=$(printf '%s' "$VOL_RAW" | awk '{printf "%d", $2*100}')
if printf '%s' "$VOL_RAW" | grep -q MUTED; then
OSD_TEXT="󰝟 $VOL%"
elif [ "$VOL" -lt 33 ]; then
OSD_TEXT="󰕿 $VOL%"
elif [ "$VOL" -lt 66 ]; then
OSD_TEXT="󰖀 $VOL%"
else
OSD_TEXT="󰕾 $VOL%"
fi
'';
brightGetText = ''
BRIGHT=$(${pkgs.brightnessctl}/bin/brightnessctl -m | awk -F, '{print int($5)}')
if [ "$BRIGHT" -lt 33 ]; then
OSD_TEXT="󰃞 $BRIGHT%"
elif [ "$BRIGHT" -lt 66 ]; then
OSD_TEXT="󰃟 $BRIGHT%"
else
OSD_TEXT="󰃠 $BRIGHT%"
fi
'';
# Resolve $src: the default source, otherwise the first available source.
# Some machines have no default audio source (@DEFAULT_AUDIO_SOURCE@ unresolved).
micSource = ''
src=$(${pkgs.wireplumber}/bin/wpctl inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
if [ -z "$src" ]; then
src=$(${pkgs.pipewire}/bin/pw-dump | ${pkgs.jq}/bin/jq -r \
'[.[] | select(.info.props."media.class"=="Audio/Source") | .id] | .[0] // empty')
fi
'';
# tofi in vertical dmenu mode: the global config is a 36px-tall horizontal
# launcher, unusable for a list, so override the geometry here.
tofiMenu = "${pkgs.tofi}/bin/tofi --horizontal false --anchor center --width 700 --height 500 --margin-top 0 --margin-left 0 --margin-right 0 --num-results 10";
# Name -> glyph table maintained by the nerd-fonts project itself, pinned to
# the same release as the nerd-fonts packages in nixos/fonts.nix.
nerdFontGlyphnames = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/ryanoasis/nerd-fonts/v3.4.0/glyphnames.json";
sha256 = "sha256-4tENI/W/8L1vBnbpsB2XifzcZW3ntJiilVwncW6kQ5w=";
};
nerdFontIconList = pkgs.runCommand "nerd-font-icons.txt" {nativeBuildInputs = [pkgs.jq];} ''
jq -r 'to_entries[] | select(.key != "METADATA") | "\(.value.char) \(.key)"' \
${nerdFontGlyphnames} > "$out"
'';
in {
inherit waybar-osd waybar-osd-status battery-monitor;
bluetoothScript = pkgs.writeShellScript "waybar-bluetooth" ''
jq=${pkgs.jq}/bin/jq
nl=$'\n'
# bluetoothctl hangs without a controller by default always bounded by timeout.
bt() { timeout 3 ${pkgs.bluez}/bin/bluetoothctl "$@" 2>/dev/null; }
powered=$(bt show | awk '/Powered:/ { print $2; exit }')
if [ "$powered" != "yes" ]; then
"$jq" -cn '{ text: "󰂲", class: "off", tooltip: "Bluetooth off" }'
exit 0
fi
tip=""
add_tip() { tip="''${tip:+$tip$nl}$1"; }
count=0
for mac in $(bt devices Connected | awk '{ print $2 }'); do
count=$((count + 1))
info=$(bt info "$mac")
name=$(printf '%s' "$info" | sed -n 's/^[[:space:]]*Name: //p' | head -1)
[ -z "$name" ] && name="$mac"
batt=$(printf '%s' "$info" | sed -n 's/.*Battery Percentage:.*(\([0-9][0-9]*\)).*/\1/p' | head -1)
add_tip "󰂱 $name''${batt:+ · $batt%}"
done
if [ "$count" -gt 0 ]; then
"$jq" -cn --arg tooltip "$tip" '{ text: "󰂰", class: "connected", tooltip: $tooltip }'
else
"$jq" -cn '{ text: "󰂰", class: "on", tooltip: "Bluetooth on" }'
fi
'';
networkScript = pkgs.writeShellScript "waybar-network" ''
nmcli=${pkgs.networkmanager}/bin/nmcli
ip=${pkgs.iproute2}/bin/ip
jq=${pkgs.jq}/bin/jq
nl=$'\n'
text=""
tip=""
class="disconnected"
add_seg() { text="''${text:+$text }$1"; }
add_tip() { tip="''${tip:+$tip$nl}$1"; }
# Ethernet
eth=$("$nmcli" -t -f DEVICE,TYPE,STATE device status 2>/dev/null \
| awk -F: '$2 == "ethernet" && $3 == "connected" { print $1; exit }')
if [ -n "$eth" ]; then
eth_ip=$("$ip" -4 -br addr show "$eth" 2>/dev/null | awk '{ print $3 }' | cut -d/ -f1)
add_seg "󰛳"
class="ethernet"
add_tip "󰛳 Ethernet''${eth_ip:+ · $eth_ip}"
fi
# Wi-Fi
wifi=$("$nmcli" -t -f ACTIVE,SSID,SIGNAL device wifi 2>/dev/null | grep -m1 '^yes:')
if [ -n "$wifi" ]; then
ssid=$(printf '%s' "$wifi" | cut -d: -f2)
signal=$(printf '%s' "$wifi" | cut -d: -f3)
if [ "''${signal:-0}" -ge 80 ]; then icon="󰤨"
elif [ "''${signal:-0}" -ge 60 ]; then icon="󰤥"
elif [ "''${signal:-0}" -ge 40 ]; then icon="󰤢"
elif [ "''${signal:-0}" -ge 20 ]; then icon="󰤟"
else icon="󰤯"
fi
add_seg "$icon"
[ "$class" = "disconnected" ] && class="wifi"
add_tip "$icon ''${ssid:-Wi-Fi}''${signal:+ · $signal%}"
fi
# VPN (nmcli, fallback interfaces)
vpn=$("$nmcli" -t -f TYPE,NAME connection show --active 2>/dev/null \
| awk -F: '$1 == "vpn" || $1 == "wireguard" { print $2; exit }')
if [ -z "$vpn" ]; then
vpn=$("$ip" -br link show 2>/dev/null \
| awk '($2 == "UP" || $2 == "UNKNOWN") && $1 ~ /^(tun|wg|proton|ppp)/ { sub(/@.*/, "", $1); print $1; exit }')
fi
if [ -n "$vpn" ]; then
add_seg "󰦝"
add_tip "󰦝 VPN · $vpn"
fi
if [ -z "$text" ]; then
text="󰤭"
tip="Disconnected"
fi
"$jq" -cn --arg text "$text" --arg class "$class" --arg tooltip "$tip" \
'{ text: $text, class: $class, tooltip: $tooltip }'
'';
vol-up = pkgs.writeShellScriptBin "vol-up" ''
${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 5%+ --limit 1.0
${volGetText}
${updateOsd}
'';
vol-down = pkgs.writeShellScriptBin "vol-down" ''
${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 5%-
${volGetText}
${updateOsd}
'';
vol-mute = pkgs.writeShellScriptBin "vol-mute" ''
${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SINK@ toggle
${volGetText}
${updateOsd}
'';
mic-mute = pkgs.writeShellScriptBin "mic-mute" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
${micSource}
[ -z "$src" ] && exit 0
"$wpctl" set-mute "$src" toggle
if "$wpctl" get-volume "$src" | grep -q MUTED; then
OSD_TEXT="󰍭 Muted"
else
OSD_TEXT="󰍬 Live"
fi
${updateOsd}
'';
mic-status = pkgs.writeShellScriptBin "mic-status" ''
${micSource}
if [ -n "$src" ] && ${pkgs.wireplumber}/bin/wpctl get-volume "$src" | grep -q MUTED; then
echo true
else
echo false
fi
'';
bright-up = pkgs.writeShellScriptBin "bright-up" ''
${pkgs.brightnessctl}/bin/brightnessctl set 5%+
${brightGetText}
${updateOsd}
'';
bright-down = pkgs.writeShellScriptBin "bright-down" ''
${pkgs.brightnessctl}/bin/brightnessctl set 5%-
${brightGetText}
${updateOsd}
'';
wifi-toggle = pkgs.writeShellScriptBin "wifi-toggle" ''
if nmcli radio wifi | grep -q enabled; then
nmcli radio wifi off
else
nmcli radio wifi on
fi
${updateOsd}
'';
bluetooth-toggle = pkgs.writeShellScriptBin "bluetooth-toggle" ''
if bluetoothctl show | grep -q "Powered: yes"; then
bluetoothctl power off
else
bluetoothctl power on
fi
${updateOsd}
'';
waybar-toggle = pkgs.writeShellScriptBin "waybar-toggle" ''
if pidof waybar > /dev/null; then
pkill waybar
else
hyprctl dispatch exec waybar
fi
'';
nightshift-toggle = pkgs.writeShellScriptBin "nightshift-toggle" ''
if pidof "hyprsunset" > /dev/null; then
pkill hyprsunset
OSD_TEXT="󰖔 Night Shift Off"
else
${pkgs.hyprsunset}/bin/hyprsunset -t 4500 &
OSD_TEXT="󰖔 Night Shift On"
fi
${updateOsd}
'';
focus-toggle = pkgs.writeShellScriptBin "focus-toggle" ''
if test -f /tmp/hypr-focus-mode; then
rm /tmp/hypr-focus-mode
OSD_TEXT="󰈈 Focus Off"
${updateOsd}
hyprctl reload
hyprctl dispatch exec waybar
else
touch /tmp/hypr-focus-mode
OSD_TEXT="󰈈 Focus On"
${updateOsd}
pkill waybar || true
hyprctl keyword animations:enabled false
hyprctl keyword general:gaps_in 0
hyprctl keyword general:gaps_out 0
hyprctl keyword decoration:active_opacity 1
hyprctl keyword decoration:inactive_opacity 1
hyprctl keyword decoration:rounding 0
fi
'';
dnd-toggle = pkgs.writeShellScriptBin "dnd-toggle" ''
state=$(${pkgs.swaynotificationcenter}/bin/swaync-client -d)
if [ "$state" = "true" ]; then
OSD_TEXT="󰂛 Do Not Disturb On"
else
OSD_TEXT="󰂚 Do Not Disturb Off"
fi
${updateOsd}
'';
output-cycle = pkgs.writeShellScriptBin "output-cycle" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
jq=${pkgs.jq}/bin/jq
pwdump=${pkgs.pipewire}/bin/pw-dump
# Sink IDs in pw-dump order.
ids=($("$pwdump" | "$jq" -r '.[] | select(.info.props."media.class"=="Audio/Sink") | .id'))
n=''${#ids[@]}
[ "$n" -eq 0 ] && exit 0
cur=$("$wpctl" inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
next_index=0
for i in "''${!ids[@]}"; do
if [ "''${ids[$i]}" = "$cur" ]; then
next_index=$(( (i + 1) % n ))
break
fi
done
next=''${ids[$next_index]}
"$wpctl" set-default "$next"
desc=$("$pwdump" | "$jq" -r --argjson id "$next" '.[] | select(.id==$id) | .info.props."node.description"')
OSD_TEXT="󰓃 ''${desc:-Output}"
${updateOsd}
'';
input-cycle = pkgs.writeShellScriptBin "input-cycle" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
jq=${pkgs.jq}/bin/jq
pwdump=${pkgs.pipewire}/bin/pw-dump
# Source IDs in pw-dump order.
ids=($("$pwdump" | "$jq" -r '.[] | select(.info.props."media.class"=="Audio/Source") | .id'))
n=''${#ids[@]}
[ "$n" -eq 0 ] && exit 0
cur=$("$wpctl" inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
next_index=0
for i in "''${!ids[@]}"; do
if [ "''${ids[$i]}" = "$cur" ]; then
next_index=$(( (i + 1) % n ))
break
fi
done
next=''${ids[$next_index]}
"$wpctl" set-default "$next"
desc=$("$pwdump" | "$jq" -r --argjson id "$next" '.[] | select(.id==$id) | .info.props."node.description"')
OSD_TEXT="󰍬 ''${desc:-Input}"
${updateOsd}
'';
color-pick = pkgs.writeShellScriptBin "color-pick" ''
# hyprpicker -a already copies the color to the clipboard.
color=$(${pkgs.hyprpicker}/bin/hyprpicker -a 2>/dev/null)
if [ -n "$color" ]; then
OSD_TEXT="󰈊 $color"
else
OSD_TEXT="󰈊 Cancelled"
fi
${updateOsd}
'';
screenshot-edit = pkgs.writeShellScriptBin "screenshot-edit" ''
${pkgs.hyprshot}/bin/hyprshot -m region --raw 2>/dev/null \
| ${pkgs.satty}/bin/satty --filename -
'';
record-toggle = pkgs.writeShellScriptBin "record-toggle" ''
if pgrep -x wf-recorder >/dev/null; then
# -INT lets wf-recorder finalize the file cleanly.
pkill -INT -x wf-recorder
OSD_TEXT="󰕧 Recording saved"
else
dir="$HOME/Videos"
mkdir -p "$dir"
file="$dir/rec-$(date +%Y%m%d-%H%M%S).mp4"
${pkgs.wf-recorder}/bin/wf-recorder -f "$file" >/dev/null 2>&1 &
OSD_TEXT="󰑊 Recording"
fi
${updateOsd}
'';
power-cycle = pkgs.writeShellScriptBin "power-cycle" ''
ppd=${pkgs.power-profiles-daemon}/bin/powerprofilesctl
cur=$("$ppd" get)
case "$cur" in
power-saver) next=balanced; icon="󰾅" ;;
balanced) next=performance; icon="󰓅" ;;
performance) next=power-saver; icon="󰌪" ;;
*) next=balanced; icon="󰾅" ;;
esac
"$ppd" set "$next"
OSD_TEXT="$icon ''${next^}"
${updateOsd}
'';
airplane-toggle = pkgs.writeShellScriptBin "airplane-toggle" ''
# Reuse nmcli + bluetoothctl (unprivileged) instead of rfkill.
on=false
nmcli radio wifi 2>/dev/null | grep -q enabled && on=true
bluetoothctl show 2>/dev/null | grep -q "Powered: yes" && on=true
if $on; then
nmcli radio wifi off 2>/dev/null
bluetoothctl power off >/dev/null 2>&1 || true
OSD_TEXT="󰀝 Airplane On"
else
nmcli radio wifi on 2>/dev/null
bluetoothctl power on >/dev/null 2>&1 || true
OSD_TEXT="󰀞 Airplane Off"
fi
${updateOsd}
'';
clipboard-menu = pkgs.writeShellScriptBin "clipboard-menu" ''
list=$(${pkgs.cliphist}/bin/cliphist list)
selected=$(printf '%s\n' "$list" | cut -f2- | ${tofiMenu} --prompt-text "Clipboard: ")
[ -n "$selected" ] && printf '%s\n' "$list" \
| awk -F'\t' -v s="$selected" '$2 == s {print; exit}' \
| ${pkgs.cliphist}/bin/cliphist decode \
| ${pkgs.wl-clipboard}/bin/wl-copy
'';
emoji-picker = pkgs.writeShellScriptBin "emoji-picker" ''
export PATH="${pkgs.wtype}/bin:${pkgs.wl-clipboard}/bin:$PATH"
export BEMOJI_PICKER_CMD="${tofiMenu} --prompt-text 'emoji: '"
# -t types the emoji (wtype), -c also copies it.
exec ${pkgs.bemoji}/bin/bemoji -t -c
'';
icon-picker = pkgs.writeShellScriptBin "icon-picker" ''
selected=$(${tofiMenu} --font "${config.stylix.fonts.monospace.name}" --prompt-text 'icon: ' < ${nerdFontIconList})
[ -z "$selected" ] || icon=$(printf '%s\n' "$selected" | awk '{print $1}')
[ -n "''${icon:-}" ] || exit 0
${pkgs.wtype}/bin/wtype "$icon"
printf '%s' "$icon" | ${pkgs.wl-clipboard}/bin/wl-copy
'';
caffeine-toggle = pkgs.writeShellScriptBin "caffeine-toggle" ''
# Pause hypridle (stay awake) or resume it.
if systemctl --user is-active --quiet hypridle; then
systemctl --user stop hypridle
OSD_TEXT="󰅶 Keep Awake On"
else
systemctl --user start hypridle
OSD_TEXT="󰾫 Keep Awake Off"
fi
${updateOsd}
'';
}
+169
View File
@@ -0,0 +1,169 @@
{
config,
pkgs,
networkScript,
bluetoothScript,
caffeineToggleScript,
osdStatusScript,
nightshiftToggleScript,
...
}: let
gaps-out = config.theme.gaps-out;
c = config.lib.stylix.colors;
in {
programs.waybar.settings = [
{
layer = "top";
position = "top";
height = config.theme.bar-height;
margin = "${toString gaps-out} ${toString gaps-out} 0";
modules-center = ["custom/osd" "custom/osd-sep" "clock" "tray" "hyprland/workspaces" "custom/network" "custom/bluetooth" "battery" "group/drawer"];
# ── Modules ─────────────────────────────────────────────────────────
"hyprland/workspaces" = {
format = "{id}";
all-outputs = true;
move-to-monitor = true;
ignore-workspaces = ["[5-9]" "[1-9][0-9]+"];
on-scroll-down = "${pkgs.hyprland}/bin/hyprctl dispatch workspace e+1";
on-scroll-up = "${pkgs.hyprland}/bin/hyprctl dispatch workspace e-1";
persistent-workspaces."*" = [1 2 3 4];
cursor = true;
};
battery = {
interval = 20;
full-at = 100;
tooltip = true;
format = "{icon} ";
format-charging = " {icon} ";
format-icons = ["" "" "" "" ""];
tooltip-format = "{capacity}% · {time}";
tooltip-format-full = "Full\n{capacity}%";
tooltip-format-charging = "Charging\n{capacity}% · {time}";
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page power";
states = {
warning = 30;
critical = 15;
};
};
"custom/caffeine" = {
exec = "${pkgs.coreutils}/bin/printf '󰅶'";
exec-if = "! systemctl --user is-active --quiet hypridle";
format = "{}";
interval = 5;
on-click = "${caffeineToggleScript}/bin/caffeine-toggle";
tooltip = false;
};
"custom/nightshift" = {
exec = "${pkgs.coreutils}/bin/printf '󰖔'";
exec-if = "${pkgs.procps}/bin/pgrep -x hyprsunset";
format = "{}";
interval = 5;
on-click = "${nightshiftToggleScript}/bin/nightshift-toggle";
tooltip = false;
};
"custom/bluetooth" = {
exec = "${bluetoothScript}";
exec-if = "${pkgs.bluez}/bin/bluetoothctl list 2>/dev/null | grep -q Controller";
return-type = "json";
interval = 5;
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page bluetooth";
};
"custom/osd" = {
exec = "cat /tmp/waybar-osd";
exec-if = "${osdStatusScript}/bin/waybar-osd-status";
signal = 8;
interval = 1;
format = "{}";
};
"custom/osd-sep" = {
exec = "echo '|'";
exec-if = "${osdStatusScript}/bin/waybar-osd-status";
signal = 8;
interval = 1;
format = "{}";
tooltip = false;
};
pulseaudio = {
format = "{icon}";
format-bluetooth = "{icon}";
tooltip-format = "{volume}%";
format-muted = "<span size='12pt'>󰝟</span>";
scroll-step = 2;
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page audio";
format-icons = {
headphone = "";
hands-free = "";
headset = "";
phone = "";
portable = "";
car = "";
default = [
"󰕿"
"󰖀"
"󰕾"
];
};
};
"pulseaudio/slider" = {
min = 0;
max = 100;
cursor = true;
};
"custom/network" = {
exec = "${networkScript}";
return-type = "json";
interval = 10;
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page network";
};
tray = {
icon-size = 13;
spacing = 12;
cursor = true;
};
clock = {
timezone = config.var.timeZone;
tooltip-format = "<tt><small>{calendar}</small></tt>";
format = "{:%H:%M}";
format-alt = "{:%H:%M %d %B %Y}";
calendar = {
mode = "month";
format = {
months = "<span color='#${c.base04}'><b>{}</b></span>";
weekdays = "<span color='#${c.base0A}'><b>{}</b></span>";
days = "<span color='#${c.base05}'>{}</span>";
today = "<span color='#${c.base0D}'><b><u>{}</u></b></span>";
};
};
};
"group/drawer" = {
orientation = "horizontal";
drawer = {
transition-duration = 300;
children-class = "drawer-child";
transition-left-to-right = false;
};
modules = ["custom/arrow-right" "pulseaudio" "custom/nightshift" "custom/caffeine"];
};
"custom/arrow-right" = {
format = " ";
tooltip = false;
cursor = true;
};
}
];
}
+172
View File
@@ -0,0 +1,172 @@
{config, ...}: let
c = config.lib.stylix.colors;
fg = "#${c.base05}";
module-bg = "#${c.base01}";
tooltip-bg = "#${c.base01}";
red = "#${c.base08}";
yellow = "#${c.base0A}";
green = "#${c.base0B}";
blue = "#${c.base0D}";
cyan = "#${c.base0C}";
inactive = "#${c.base03}";
highlight = "#${c.base02}";
font-size = "${toString config.stylix.fonts.sizes.applications}px";
font-size-clock = "${toString (config.stylix.fonts.sizes.applications + 2)}px";
module-padding = "14px";
in {
programs.waybar.style = ''
* {
font-family: '${config.stylix.fonts.sansSerif.name}';
border: none;
border-radius: 0;
min-height: 0;
margin: 0;
padding: 0;
text-shadow: none;
}
#waybar {
font-weight: 700;
background: transparent;
font-size: ${font-size};
color: ${fg};
}
.modules-center {
background: ${module-bg};
border-radius: 100px;
padding: 6px 14px;
box-shadow: none;
}
#clock,
#battery,
#tray,
#workspaces,
#custom-osd,
#custom-network,
#custom-bluetooth,
#custom-caffeine,
#custom-nightshift,
#pulseaudio {
padding: 1px ${module-padding};
}
#custom-arrow-right {
color: ${fg};
padding: 1px 8px;
}
#group-drawer {
padding: 0;
}
#custom-osd-sep {
padding: 0;
color: ${inactive};
}
#clock {
font-size: ${font-size-clock};
}
#workspaces button {
color: ${fg};
font-size: ${font-size};
border-radius: 100px;
padding: 0 3px;
margin: 0;
}
#workspaces button.empty {
color: ${inactive};
}
#workspaces button:hover {
background: transparent;
color: ${fg};
}
#workspaces button.active {
color: ${module-bg};
background: ${blue};
border-radius: 60px;
padding: 0 8px;
margin: 0;
}
#battery {
color: ${green};
}
#battery.charging,
#battery.full {
color: ${green};
}
#battery.critical,
#custom-network.disconnected {
color: ${red};
}
#battery.warning {
color: ${yellow};
}
#custom-network.ethernet,
#custom-network.wifi {
color: ${cyan};
}
#custom-bluetooth {
color: ${blue};
}
#custom-bluetooth.off {
color: ${inactive};
}
#custom-caffeine,
#custom-nightshift {
color: ${yellow};
}
#custom-osd {
font-weight: 700;
color: ${fg};
}
tooltip {
border-radius: 15px;
background: ${tooltip-bg};
}
tooltip label {
padding: 3px 10px;
color: ${fg};
font-weight: 700;
}
.popup * {
box-shadow: none;
outline: none;
border-radius: 10px;
}
menu {
border-radius: 10px;
font-weight: 700;
color: ${fg};
background: ${tooltip-bg};
}
menu > * {
padding: 3px 0px;
}
menu > *:hover {
border-radius: 10px;
background-color: ${highlight};
}
'';
}
+7 -4
View File
@@ -8,15 +8,17 @@
../../nixos/home-manager.nix ../../nixos/home-manager.nix
../../nixos/nix.nix ../../nixos/nix.nix
../../nixos/systemd-boot.nix ../../nixos/systemd-boot.nix
../../nixos/sddm.nix ../../nixos/tuigreet.nix
../../nixos/users.nix ../../nixos/users.nix
../../nixos/utils.nix ../../nixos/utils.nix
../../nixos/hyprland.nix ../../nixos/hyprland.nix
../../nixos/usbguard.nix ../../nixos/usbguard.nix
../../home/programs/helium/system.nix # I hate browser's configuration.. ../../home/programs/gui/helium/system.nix # I hate browser's configuration..
../../nixos/omen.nix # CHANGEME: For my laptop only, remove this (OMEN 16) ../../nixos/omen.nix # CHANGEME: For my laptop only, remove this (OMEN 16)
./wireguard.nix # CHANGEME: For my laptop only
# You should let those lines as is # You should let those lines as is
./hardware-configuration.nix ./hardware-configuration.nix
./variables.nix ./variables.nix
@@ -47,12 +49,13 @@
allow id 03f0:076b serial "" name "USB5734" hash "BshoqybYo0IKgoDORYPRtbhhlmQrYAxPQb2EAm1JsWA=" parent-hash "JHDjLFApQNqijjmuKdJSWH5+1oLL7S6LQ9QHTAk5fTk=" via-port "8-1.3" with-interface 09:00:00 with-connect-type "unknown" allow id 03f0:076b serial "" name "USB5734" hash "BshoqybYo0IKgoDORYPRtbhhlmQrYAxPQb2EAm1JsWA=" parent-hash "JHDjLFApQNqijjmuKdJSWH5+1oLL7S6LQ9QHTAk5fTk=" via-port "8-1.3" with-interface 09:00:00 with-connect-type "unknown"
allow id 0bda:8153 serial "000001000000" name "USB 10/100/1000 LAN" hash "utEnXKJ57kRUbPcGUaNWhEyoOEbLOYAFxvlsyC0PZkk=" parent-hash "JHDjLFApQNqijjmuKdJSWH5+1oLL7S6LQ9QHTAk5fTk=" with-interface { ff:ff:00 02:06:00 0a:00:00 0a:00:00 } with-connect-type "unknown" allow id 0bda:8153 serial "000001000000" name "USB 10/100/1000 LAN" hash "utEnXKJ57kRUbPcGUaNWhEyoOEbLOYAFxvlsyC0PZkk=" parent-hash "JHDjLFApQNqijjmuKdJSWH5+1oLL7S6LQ9QHTAk5fTk=" with-interface { ff:ff:00 02:06:00 0a:00:00 0a:00:00 } with-connect-type "unknown"
allow id 046d:0ab7 serial "2046BAB04T68" name "Blue Microphones" hash "cC6AQ2e1Q/BeFeostpbf1mH2WpoUmt6bhau4NlA3niU=" parent-hash "MSXcPAlZqkpTyZQylOhSIB8eMfST2AzVHV9EbrBGTWc=" with-interface { 01:01:00 01:02:00 01:02:00 01:02:00 01:02:00 01:02:00 01:02:00 03:00:00 } with-connect-type "unknown" allow id 046d:0ab7 serial "2046BAB04T68" name "Blue Microphones" hash "cC6AQ2e1Q/BeFeostpbf1mH2WpoUmt6bhau4NlA3niU=" parent-hash "MSXcPAlZqkpTyZQylOhSIB8eMfST2AzVHV9EbrBGTWc=" with-interface { 01:01:00 01:02:00 01:02:00 01:02:00 01:02:00 01:02:00 01:02:00 03:00:00 } with-connect-type "unknown"
allow id 1532:02a1 serial "" name "Razer Ornata V3" hash "wfuIjBhhGuge8gflyA526SKqKoy8rHJZQZ+2o6usMiE=" parent-hash "MSXcPAlZqkpTyZQylOhSIB8eMfST2AzVHV9EbrBGTWc=" via-port "7-1.3.3" with-interface { 03:01:01 03:00:01 03:00:02 } with-connect-type "unknown"
allow id 13fd:5900 serial "50026B76861EE752 " name "External" hash "l/QvVV5hzZj1z6OUwB/kWl+WnH/7awrdMBoiNVx660M=" parent-hash "MSXcPAlZqkpTyZQylOhSIB8eMfST2AzVHV9EbrBGTWc=" with-interface { 08:06:50 08:06:62 } with-connect-type "unknown" allow id 13fd:5900 serial "50026B76861EE752 " name "External" hash "l/QvVV5hzZj1z6OUwB/kWl+WnH/7awrdMBoiNVx660M=" parent-hash "MSXcPAlZqkpTyZQylOhSIB8eMfST2AzVHV9EbrBGTWc=" with-interface { 08:06:50 08:06:62 } with-connect-type "unknown"
allow id 1532:02a1 name "Razer Ornata V3"
allow id 03f0:066b name "HP USB-C Dock G5"
''; '';
home-manager.users."${config.var.username}" = import ./home.nix; home-manager.users."${config.var.username}" = import ./home.nix;
# Don't touch this # Don't touch this
system.stateVersion = "24.05"; system.stateVersion = "26.05";
} }

Some files were not shown because too many files have changed in this diff Show More