initial commit
This commit is contained in:
commit
90cff4f16a
59 changed files with 6855 additions and 0 deletions
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Nix build artifacts
|
||||
result
|
||||
result-*
|
||||
|
||||
# Secrets (never commit these)
|
||||
secrets/
|
||||
*.secret
|
||||
*.key
|
||||
*.pem
|
||||
|
||||
# Editor backups
|
||||
*.backup
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Local overrides
|
||||
local.nix
|
||||
|
||||
# Claude stuff
|
||||
.claude/
|
||||
|
||||
# Quickshell generated theme files (generated by Nix)
|
||||
Hyprland/Quickshell/bar/Theme.qml
|
||||
Hyprland/Quickshell/control-center/Theme.qml
|
||||
|
||||
# nixos-hardware fork (now on GitHub)
|
||||
nixos-hardware-fork/
|
||||
|
||||
# Hyprland wiki
|
||||
hyprland-wiki/
|
||||
|
||||
/st/
|
||||
|
||||
/dwm/
|
||||
409
Hetzner/axiomania.nix
Normal file
409
Hetzner/axiomania.nix
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
networking.hostName = "axiomania";
|
||||
|
||||
# ============================================================================
|
||||
# Firewall
|
||||
# ============================================================================
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 22 80 443 2222 ];
|
||||
allowedUDPPorts = [ 51820 53 ]; # Wireguard, Adguard DNS
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Forgejo
|
||||
# ============================================================================
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
database.type = "sqlite3";
|
||||
settings = {
|
||||
DEFAULT.APP_NAME = "Axiomania Git";
|
||||
|
||||
server = {
|
||||
DOMAIN = "git.axiomania.org";
|
||||
ROOT_URL = "https://git.axiomania.org/";
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
HTTP_PORT = 3000;
|
||||
SSH_DOMAIN = "git.axiomania.org";
|
||||
SSH_PORT = 2222;
|
||||
START_SSH_SERVER = true;
|
||||
};
|
||||
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = true;
|
||||
};
|
||||
|
||||
repository = {
|
||||
DEFAULT_PRIVATE = "private";
|
||||
};
|
||||
|
||||
api = {
|
||||
ENABLE_SWAGGER = false;
|
||||
};
|
||||
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
};
|
||||
|
||||
actions = {
|
||||
ENABLED = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Forgejo Actions Runner
|
||||
# ============================================================================
|
||||
# Requires a registration token from Forgejo.
|
||||
# Generate one: ssh root@178.104.15.221, then:
|
||||
# forgejo-runner register (follow prompts)
|
||||
# Or via Forgejo web UI: Site Administration > Runners > Create Runner
|
||||
# Then put the token in /var/lib/forgejo-runner/token
|
||||
services.gitea-actions-runner.instances.default = {
|
||||
enable = true;
|
||||
name = "axiomania";
|
||||
url = "https://git.axiomania.org";
|
||||
tokenFile = "/var/lib/forgejo-runner/token";
|
||||
labels = [ "native:host" ];
|
||||
hostPackages = with pkgs; [
|
||||
bash
|
||||
coreutils
|
||||
curl
|
||||
gawk
|
||||
git
|
||||
gnused
|
||||
nodejs
|
||||
nix
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Vaultwarden (Bitwarden-compatible password manager)
|
||||
# ============================================================================
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
config = {
|
||||
DOMAIN = "https://vault.axiomania.org";
|
||||
SIGNUPS_ALLOWED = false;
|
||||
ROCKET_ADDRESS = "127.0.0.1";
|
||||
ROCKET_PORT = 8222;
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Navidrome (music streaming)
|
||||
# ============================================================================
|
||||
services.navidrome = {
|
||||
enable = true;
|
||||
settings = {
|
||||
Address = "127.0.0.1";
|
||||
Port = 4533;
|
||||
MusicFolder = "/var/lib/navidrome/music";
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Syncthing (file sync)
|
||||
# ============================================================================
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
openDefaultPorts = true;
|
||||
dataDir = "/var/lib/syncthing";
|
||||
settings.gui.insecureSkipHostcheck = true;
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Attic (Nix binary cache)
|
||||
# ============================================================================
|
||||
# Requires a secret generated on the server:
|
||||
# openssl genrsa -traditional 4096 | base64 -w0 > /var/lib/atticd/token-secret
|
||||
# echo "ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=$(cat /var/lib/atticd/token-secret)" > /etc/atticd.env
|
||||
services.atticd = {
|
||||
enable = true;
|
||||
environmentFile = "/etc/atticd.env";
|
||||
settings = {
|
||||
listen = "[::]:8080";
|
||||
storage = {
|
||||
type = "local";
|
||||
path = "/var/lib/atticd/storage";
|
||||
};
|
||||
garbage-collection = {
|
||||
default-retention-period = "3 months";
|
||||
};
|
||||
chunking = {
|
||||
nar-size-threshold = 65536;
|
||||
min-size = 16384;
|
||||
avg-size = 65536;
|
||||
max-size = 262144;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Kavita (ebook library)
|
||||
# ============================================================================
|
||||
# Generate token on the server:
|
||||
# openssl rand -hex 128 > /var/lib/kavita/token-key
|
||||
services.kavita = {
|
||||
enable = true;
|
||||
settings.Port = 5000;
|
||||
tokenKeyFile = "/var/lib/kavita/token-key";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Audiobookshelf
|
||||
# ============================================================================
|
||||
services.audiobookshelf = {
|
||||
enable = true;
|
||||
port = 8234;
|
||||
host = "127.0.0.1";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Paperless-ngx (document management)
|
||||
# ============================================================================
|
||||
services.paperless = {
|
||||
enable = true;
|
||||
port = 28981;
|
||||
address = "127.0.0.1";
|
||||
domain = "docs.axiomania.org";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Adguard Home (DNS ad blocker)
|
||||
# ============================================================================
|
||||
# Use as DNS server via Wireguard: set DNS = 10.100.0.1 in client config
|
||||
services.adguardhome = {
|
||||
enable = true;
|
||||
port = 3300;
|
||||
host = "127.0.0.1";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# SearXNG (private search engine)
|
||||
# ============================================================================
|
||||
# Generate secret on the server:
|
||||
# echo "SEARX_SECRET=$(openssl rand -hex 32)" > /etc/searx/secrets.env
|
||||
services.searx = {
|
||||
enable = true;
|
||||
redisCreateLocally = true;
|
||||
settings = {
|
||||
server = {
|
||||
bind_address = "127.0.0.1";
|
||||
port = 8888;
|
||||
secret_key = "$SEARX_SECRET";
|
||||
};
|
||||
};
|
||||
environmentFile = "/etc/searx/secrets.env";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Homepage (services dashboard)
|
||||
# ============================================================================
|
||||
services.homepage-dashboard = {
|
||||
enable = true;
|
||||
listenPort = 8082;
|
||||
allowedHosts = "home.axiomania.org";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Matrix Conduit (encrypted messaging)
|
||||
# ============================================================================
|
||||
services.matrix-conduit = {
|
||||
enable = true;
|
||||
settings.global = {
|
||||
server_name = "axiomania.org";
|
||||
port = 6167;
|
||||
address = "127.0.0.1";
|
||||
allow_registration = false;
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Gokapi (file sharing) — disabled due to CVEs in stable
|
||||
# ============================================================================
|
||||
# services.gokapi = {
|
||||
# enable = true;
|
||||
# environment = {
|
||||
# GOKAPI_PORT = 53842;
|
||||
# };
|
||||
# };
|
||||
|
||||
# ============================================================================
|
||||
# Wireguard VPN
|
||||
# ============================================================================
|
||||
# Generate keys on the server:
|
||||
# wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
|
||||
networking.wireguard.interfaces.wg0 = {
|
||||
ips = [ "10.100.0.1/24" ];
|
||||
listenPort = 51820;
|
||||
privateKeyFile = "/etc/wireguard/private.key";
|
||||
peers = [
|
||||
{
|
||||
# Minisforum V3 SE (local NixOS machine)
|
||||
publicKey = "rEsHqzJVnv9AoOIEVTrdEF3x4G6rWxXqHLXTzAx88gc=";
|
||||
allowedIPs = [ "10.100.0.2/32" ];
|
||||
}
|
||||
{
|
||||
# Pixel 5
|
||||
publicKey = "jP+rYdc8qKdNY4l3PDFmGiOA31SnJRgcmQIVu6AJ9EM=";
|
||||
allowedIPs = [ "10.100.0.3/32" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# NAT for Wireguard clients to access the internet
|
||||
networking.nat = {
|
||||
enable = true;
|
||||
externalInterface = "ens3";
|
||||
internalInterfaces = [ "wg0" ];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Nginx reverse proxy + ACME
|
||||
# ============================================================================
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
|
||||
# ── Public services ──
|
||||
virtualHosts."git.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:3000";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."matrix.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:6167";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."cache.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://[::1]:8080";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
# ── VPN-only services (WireGuard clients only) ──
|
||||
virtualHosts."vault.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8222";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."music.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4533";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."sync.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8384";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."books.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:5000";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."audio.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8234";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."docs.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:28981";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."search.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8888";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."home.axiomania.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8082";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
|
||||
};
|
||||
};
|
||||
|
||||
# virtualHosts."share.axiomania.org" = {
|
||||
# enableACME = true;
|
||||
# forceSSL = true;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:53842";
|
||||
# proxyWebsockets = true;
|
||||
# };
|
||||
# };
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "gamma.kinematics@gmail.com";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Packages
|
||||
# ============================================================================
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
htop
|
||||
wireguard-tools
|
||||
];
|
||||
}
|
||||
26
Hetzner/builder.nix
Normal file
26
Hetzner/builder.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
networking.hostName = "builder";
|
||||
|
||||
nix.settings = {
|
||||
max-jobs = "auto";
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://cache.axiomania.org/main"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"main:Uz5F0MbXItVx2XCmBbEAMmQ0T6+DZDgLaXWalh1k++o="
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
tmux
|
||||
attic-client
|
||||
vim
|
||||
htop
|
||||
];
|
||||
}
|
||||
34
Hetzner/common.nix
Normal file
34
Hetzner/common.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{ modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
./disk-config.nix
|
||||
];
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
time.timeZone = "Europe/Berlin";
|
||||
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
efiSupport = true;
|
||||
efiInstallAsRemovable = true;
|
||||
};
|
||||
|
||||
services.qemuGuest.enable = true;
|
||||
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7XcPUNMwpUqXMqhwTlW3YV2BUj0I6efk0LxqFcyYgA gamma.kinematics@gmail.com"
|
||||
];
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "prohibit-password";
|
||||
};
|
||||
};
|
||||
}
|
||||
34
Hetzner/disk-config.nix
Normal file
34
Hetzner/disk-config.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
disko.devices.disk.main = {
|
||||
device = lib.mkDefault "/dev/sda";
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
boot = {
|
||||
size = "1M";
|
||||
type = "EF02"; # BIOS boot partition
|
||||
};
|
||||
esp = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
121
Hetzner/setup.nix
Normal file
121
Hetzner/setup.nix
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
sshKeyPath = "/home/lebowski/.ssh/id_ed25519";
|
||||
sshKeyName = "V3";
|
||||
serverName = "nix-builder";
|
||||
serverType = "ccx43";
|
||||
location = "nbg1";
|
||||
|
||||
sshCmd = "ssh -o StrictHostKeyChecking=no -o BatchMode=yes -i ${sshKeyPath}";
|
||||
|
||||
# Spin up a builder from the NixOS snapshot
|
||||
builder-up = pkgs.writeShellApplication {
|
||||
name = "builder-up";
|
||||
runtimeInputs = with pkgs; [ hcloud openssh ];
|
||||
text = ''
|
||||
SERVER_NAME="${serverName}"
|
||||
SSH_KEY_PATH="${sshKeyPath}"
|
||||
|
||||
# ── Check if server already exists ──
|
||||
if hcloud server describe "$SERVER_NAME" &>/dev/null; then
|
||||
IP=$(hcloud server ip "$SERVER_NAME")
|
||||
echo "Server '$SERVER_NAME' already running at $IP"
|
||||
echo " builder-ssh"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Find snapshot ──
|
||||
SNAPSHOT_ID=$(hcloud image list --type snapshot --selector description="${snapshotDesc}" -o noheader -o columns=id 2>/dev/null | head -1)
|
||||
if [ -z "$SNAPSHOT_ID" ]; then
|
||||
# Fallback: search by description
|
||||
SNAPSHOT_ID=$(hcloud image list --type snapshot -o noheader -o columns=id,description | grep "${snapshotDesc}" | awk '{print $1}' | head -1)
|
||||
fi
|
||||
|
||||
if [ -z "$SNAPSHOT_ID" ]; then
|
||||
echo "ERROR: No snapshot '${snapshotDesc}' found."
|
||||
echo " Create one with: builder-snapshot"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Create server from snapshot ──
|
||||
echo "==> Creating ${serverType} in ${location} from snapshot $SNAPSHOT_ID..."
|
||||
hcloud server create \
|
||||
--name "$SERVER_NAME" \
|
||||
--type "${serverType}" \
|
||||
--image "$SNAPSHOT_ID" \
|
||||
--location "${location}" \
|
||||
--label role=nix-builder \
|
||||
--ssh-key "${sshKeyName}"
|
||||
|
||||
IP=$(hcloud server ip "$SERVER_NAME")
|
||||
|
||||
# ── Wait for SSH ──
|
||||
echo "==> Waiting for SSH..."
|
||||
for i in $(seq 1 30); do
|
||||
if ${sshCmd} "root@''${IP}" true 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
if [ "$i" -eq 30 ]; then
|
||||
echo "ERROR: SSH did not become available after 150s"
|
||||
exit 1
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# ── Update known_hosts ──
|
||||
ssh-keygen -R "$IP" 2>/dev/null || true
|
||||
ssh-keyscan -H "$IP" >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== Builder ready ==="
|
||||
echo " builder-ssh"
|
||||
'';
|
||||
};
|
||||
|
||||
# SSH into the builder
|
||||
builder-ssh = pkgs.writeShellApplication {
|
||||
name = "builder-ssh";
|
||||
runtimeInputs = with pkgs; [ hcloud openssh ];
|
||||
text = ''
|
||||
SERVER_NAME="${serverName}"
|
||||
SSH_KEY_PATH="${sshKeyPath}"
|
||||
|
||||
if ! hcloud server describe "$SERVER_NAME" &>/dev/null; then
|
||||
echo "No server '$SERVER_NAME' found. Run builder-up first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IP=$(hcloud server ip "$SERVER_NAME")
|
||||
ssh -i "$SSH_KEY_PATH" -t "root@$IP" "tmux new-session -A -s build"
|
||||
'';
|
||||
};
|
||||
|
||||
# Tear down the builder
|
||||
builder-down = pkgs.writeShellApplication {
|
||||
name = "builder-down";
|
||||
runtimeInputs = with pkgs; [ hcloud openssh ];
|
||||
text = ''
|
||||
SERVER_NAME="${serverName}"
|
||||
|
||||
if hcloud server describe "$SERVER_NAME" &>/dev/null; then
|
||||
IP=$(hcloud server ip "$SERVER_NAME")
|
||||
echo "==> Deleting '$SERVER_NAME' ($IP)..."
|
||||
hcloud server delete "$SERVER_NAME"
|
||||
ssh-keygen -R "$IP" 2>/dev/null || true
|
||||
echo " Done."
|
||||
else
|
||||
echo "No server '$SERVER_NAME' found."
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [
|
||||
builder-up
|
||||
builder-ssh
|
||||
builder-down
|
||||
pkgs.hcloud
|
||||
];
|
||||
}
|
||||
41
Hyprsuck/home.nix
Normal file
41
Hyprsuck/home.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Hyprsuck home-manager configuration
|
||||
# Unstable extras and autostart
|
||||
{ pkgs-unstable, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hyprland/hyprland.nix
|
||||
./waybar.nix
|
||||
];
|
||||
|
||||
# Screenshot annotation tool
|
||||
programs.swappy = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.swappy;
|
||||
settings.Default = {
|
||||
save_dir = "$HOME/Pictures/Screenshots";
|
||||
save_filename_format = "%F_%T.png";
|
||||
early_exit = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Clipboard history manager
|
||||
services.cliphist = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.cliphist;
|
||||
allowImages = true;
|
||||
};
|
||||
|
||||
# Terminal emulator (Wayland-native)
|
||||
programs.foot = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.foot;
|
||||
};
|
||||
|
||||
# Auto-start Hyprland on tty1
|
||||
programs.bash.profileExtra = ''
|
||||
if [ -z "$WAYLAND_DISPLAY" ] && [ "$XDG_VTNR" = 1 ]; then
|
||||
exec Hyprland
|
||||
fi
|
||||
'';
|
||||
}
|
||||
152
Hyprsuck/hyprland/bindings.nix
Normal file
152
Hyprsuck/hyprland/bindings.nix
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# Hyprland keybindings configuration
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
# Variables
|
||||
"$mod" = "SUPER";
|
||||
"$terminal" = "foot";
|
||||
"$browser" = "zen";
|
||||
|
||||
# Keybindings
|
||||
bind = [
|
||||
# Rofi
|
||||
"$mod, Space, exec, rofi -show system:rofi-system"
|
||||
"$mod ALT, Space, exec, rofi-websearch"
|
||||
|
||||
# Foot terminal - go to workspace 50, launch if not running
|
||||
"$mod, A, exec, hyprctl dispatch workspace 50; hyprctl clients -j | grep -q foot || $terminal"
|
||||
|
||||
# Zed - go to workspace 60, launch if not running
|
||||
"$mod, Z, exec, hyprctl dispatch workspace 60; hyprctl clients -j | grep -q dev.zed.Zed || zeditor"
|
||||
|
||||
# Zen Browser - workspace 70 (DP-3), launch if no browser on that workspace
|
||||
"$mod, B, exec, hyprctl dispatch workspace 70; hyprctl clients -j | jq -e '.[] | select(.class == \"zen-twilight\" and .workspace.id == 70)' > /dev/null || hyprctl dispatch exec [workspace 70 silent] -- $browser"
|
||||
# Zen Browser - workspace 71 (eDP-1), launch new window if no browser on that workspace
|
||||
"$mod ALT, B, exec, hyprctl dispatch workspace 71; hyprctl clients -j | jq -e '.[] | select(.class == \"zen-twilight\" and .workspace.id == 71)' > /dev/null || hyprctl dispatch exec [workspace 71 silent] -- $browser --new-window"
|
||||
|
||||
# Nautilus - go to workspace 80, launch if not running
|
||||
"$mod, N, exec, hyprctl dispatch workspace 80; hyprctl clients -j | grep -q org.gnome.Nautilus || nautilus"
|
||||
|
||||
# Haruna - go to workspace 90
|
||||
"$mod, M, workspace, 90"
|
||||
|
||||
"$mod, Escape, exec, hyprlock"
|
||||
|
||||
# Switch to KiCad workspaces (both monitors)
|
||||
"$mod, K, workspace, 101"
|
||||
"$mod, K, workspace, 102"
|
||||
# Launch KiCad project selector
|
||||
"$mod CTRL, K, exec, kicad-projects"
|
||||
# Launch library editors
|
||||
"$mod, L, exec, kicad-lib-launch"
|
||||
# Show project manager
|
||||
"$mod SHIFT, K, togglespecialworkspace, kicad-pm"
|
||||
# Swap SCH/PCB positions
|
||||
"$mod ALT, K, exec, kicad-swap"
|
||||
# Cycle through project instances
|
||||
"$mod, bracketright, exec, kicad-cycle f"
|
||||
"$mod, bracketleft, exec, kicad-cycle b"
|
||||
|
||||
# FreeCAD - go to workspace 110, launch if not running
|
||||
"$mod, F, exec, hyprctl dispatch workspace 110; hyprctl clients -j | grep -q org.freecad.FreeCAD || env QT_QPA_PLATFORM=xcb FreeCAD --single-instance"
|
||||
|
||||
# Window management
|
||||
"$mod, Q, killactive"
|
||||
"$mod, W, fullscreen"
|
||||
"$mod, R, togglefloating"
|
||||
"$mod, P, pseudo"
|
||||
"$mod, E, togglesplit"
|
||||
|
||||
# Focus movement
|
||||
"$mod, left, movefocus, l"
|
||||
"$mod, right, movefocus, r"
|
||||
"$mod, up, movefocus, u"
|
||||
"$mod, down, movefocus, d"
|
||||
|
||||
# Workspace switching
|
||||
"$mod, 1, workspace, 1"
|
||||
"$mod, 2, workspace, 2"
|
||||
"$mod, 3, workspace, 3"
|
||||
"$mod, 4, workspace, 4"
|
||||
"$mod, 5, workspace, 5"
|
||||
"$mod, 6, workspace, 6"
|
||||
"$mod, 7, workspace, 7"
|
||||
"$mod, 8, workspace, 8"
|
||||
"$mod, 9, workspace, 9"
|
||||
"$mod, 0, workspace, 10"
|
||||
|
||||
# Move window to workspace
|
||||
"$mod SHIFT, 1, movetoworkspace, 1"
|
||||
"$mod SHIFT, 2, movetoworkspace, 2"
|
||||
"$mod SHIFT, 3, movetoworkspace, 3"
|
||||
"$mod SHIFT, 4, movetoworkspace, 4"
|
||||
"$mod SHIFT, 5, movetoworkspace, 5"
|
||||
"$mod SHIFT, 6, movetoworkspace, 6"
|
||||
"$mod SHIFT, 7, movetoworkspace, 7"
|
||||
"$mod SHIFT, 8, movetoworkspace, 8"
|
||||
"$mod SHIFT, 9, movetoworkspace, 9"
|
||||
"$mod SHIFT, 0, movetoworkspace, 10"
|
||||
|
||||
# Special workspace (scratchpad)
|
||||
"$mod, S, togglespecialworkspace, magic"
|
||||
"$mod SHIFT, S, movetoworkspace, special:magic"
|
||||
|
||||
# Exit Hyprland
|
||||
"$mod SHIFT, E, exit"
|
||||
|
||||
# Scroll through workspaces on current monitor (vertical model)
|
||||
"$mod, mouse_down, workspace, m-1"
|
||||
"$mod, mouse_up, workspace, m+1"
|
||||
|
||||
# Keyboard workspace navigation (up/down)
|
||||
"$mod CTRL, up, workspace, m-1"
|
||||
"$mod CTRL, down, workspace, m+1"
|
||||
"$mod CTRL SHIFT, up, movetoworkspace, m-1"
|
||||
"$mod CTRL SHIFT, down, movetoworkspace, m+1"
|
||||
|
||||
# Clipboard history (SUPER+SHIFT+V)
|
||||
"$mod SHIFT, V, exec, cliphist list | rofi -dmenu -p 'Clipboard' | cliphist decode | wl-copy"
|
||||
|
||||
# Screenshot bindings (saves to ~/Pictures/Screenshots/)
|
||||
", Print, exec, mkdir -p ~/Pictures/Screenshots && grimblast --notify copysave area ~/Pictures/Screenshots/$(date +%F_%T).png"
|
||||
"SHIFT, Print, exec, mkdir -p ~/Pictures/Screenshots && grimblast --notify copysave output ~/Pictures/Screenshots/$(date +%F_%T).png"
|
||||
"CTRL, Print, exec, grimblast --notify save area - | swappy -f -"
|
||||
|
||||
# System menu (rofi)
|
||||
"$mod, X, exec, rofi -show system -modes 'system:rofi-system'"
|
||||
|
||||
# On-screen keyboard toggle (for tablet mode)
|
||||
# "$mod, K, exec, pkill wvkbd-mobintl || wvkbd-mobintl"
|
||||
|
||||
# Refresh waybar (for dock/undock)
|
||||
"$mod CTRL, Space, exec, pkill waybar; waybar-start"
|
||||
];
|
||||
|
||||
# Mouse bindings
|
||||
bindm = [
|
||||
"$mod, mouse:272, movewindow"
|
||||
"$mod, mouse:273, resizewindow"
|
||||
];
|
||||
|
||||
# Repeat bindings (hold key for continuous action)
|
||||
binde = [
|
||||
"$mod ALT, left, resizeactive, -20 0"
|
||||
"$mod ALT, right, resizeactive, 20 0"
|
||||
"$mod ALT, up, resizeactive, 0 -20"
|
||||
"$mod ALT, down, resizeactive, 0 20"
|
||||
];
|
||||
|
||||
# Media/hardware key bindings (bindl = works even when locked)
|
||||
bindl = [
|
||||
", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
|
||||
", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
|
||||
];
|
||||
|
||||
# Volume keys with repeat (binde = repeat when held)
|
||||
bindel = [
|
||||
", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+"
|
||||
", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
|
||||
];
|
||||
};
|
||||
}
|
||||
41
Hyprsuck/hyprland/hypridle.nix
Normal file
41
Hyprsuck/hyprland/hypridle.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Hypridle - Idle daemon configuration
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
services.hypridle = {
|
||||
enable = true;
|
||||
package = pkgs.hypridle;
|
||||
settings = {
|
||||
general = {
|
||||
lock_cmd = "pidof hyprlock || hyprlock";
|
||||
before_sleep_cmd = "loginctl lock-session";
|
||||
after_sleep_cmd = "hyprctl dispatch dpms on";
|
||||
};
|
||||
|
||||
listener = [
|
||||
# Dim screen after 2.5 minutes
|
||||
{
|
||||
timeout = 150;
|
||||
on-timeout = "brightnessctl -s set 10";
|
||||
on-resume = "brightnessctl -r";
|
||||
}
|
||||
# Lock after 5 minutes
|
||||
{
|
||||
timeout = 300;
|
||||
on-timeout = "loginctl lock-session";
|
||||
}
|
||||
# Screen off after 5.5 minutes
|
||||
{
|
||||
timeout = 330;
|
||||
on-timeout = "hyprctl dispatch dpms off";
|
||||
on-resume = "hyprctl dispatch dpms on";
|
||||
}
|
||||
# Suspend after 30 minutes
|
||||
{
|
||||
timeout = 1800;
|
||||
on-timeout = "systemctl suspend";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
54
Hyprsuck/hyprland/hyprland.nix
Normal file
54
Hyprsuck/hyprland/hyprland.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Hyprland ecosystem configuration (stable packages)
|
||||
# Core hyprland WM and hypr* tools only
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./bindings.nix
|
||||
./settings.nix
|
||||
./monitors.nix
|
||||
./rules.nix
|
||||
./hyprlock.nix
|
||||
./hypridle.nix
|
||||
./hyprpaper.nix
|
||||
];
|
||||
|
||||
# ============================================================================
|
||||
# Hyprland Window Manager (home-manager config)
|
||||
# ============================================================================
|
||||
# Package/portal set at NixOS level in hyprsuck.nix
|
||||
wayland.windowManager.hyprland = {
|
||||
enable = true;
|
||||
systemd.enable = true;
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Hyprland ecosystem packages (stable)
|
||||
# ============================================================================
|
||||
home.packages = with pkgs; [
|
||||
# Tablet mode
|
||||
iio-hyprland
|
||||
|
||||
# Monitor hotplug
|
||||
hyprland-monitor-attached
|
||||
];
|
||||
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
"iio-hyprland"
|
||||
"hyprland-monitor-attached"
|
||||
];
|
||||
};
|
||||
|
||||
# Polkit authentication agent
|
||||
services.hyprpolkitagent = {
|
||||
enable = true;
|
||||
package = pkgs.hyprpolkitagent;
|
||||
};
|
||||
|
||||
# Blue light filter
|
||||
services.hyprsunset = {
|
||||
enable = true;
|
||||
package = pkgs.hyprsunset;
|
||||
};
|
||||
}
|
||||
39
Hyprsuck/hyprland/hyprlock.nix
Normal file
39
Hyprsuck/hyprland/hyprlock.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Hyprlock - Screen locker configuration
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# Disable Stylix's hyprlock theming (we use screenshot blur)
|
||||
stylix.targets.hyprlock.enable = false;
|
||||
|
||||
programs.hyprlock = {
|
||||
enable = true;
|
||||
package = pkgs.hyprlock;
|
||||
settings = {
|
||||
general = {
|
||||
hide_cursor = true;
|
||||
grace = 5; # seconds before lock takes effect
|
||||
};
|
||||
|
||||
background = [
|
||||
{
|
||||
path = "screenshot";
|
||||
blur_passes = 3;
|
||||
blur_size = 8;
|
||||
}
|
||||
];
|
||||
|
||||
input-field = [
|
||||
{
|
||||
size = "200, 50";
|
||||
position = "0, -80";
|
||||
monitor = "";
|
||||
dots_center = true;
|
||||
fade_on_empty = false;
|
||||
outline_thickness = 2;
|
||||
placeholder_text = "Password...";
|
||||
shadow_passes = 2;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
22
Hyprsuck/hyprland/hyprpaper.nix
Normal file
22
Hyprsuck/hyprland/hyprpaper.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Hyprpaper - Wallpaper manager configuration
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
flakeDir = "${config.home.homeDirectory}/NixOS";
|
||||
in
|
||||
|
||||
{
|
||||
services.hyprpaper = {
|
||||
enable = true;
|
||||
package = pkgs.hyprpaper;
|
||||
settings = {
|
||||
ipc = "on";
|
||||
splash = false;
|
||||
|
||||
# Change the wallpaper filename here
|
||||
preload = [ "${flakeDir}/Wallpapers/Shift.png" ];
|
||||
wallpaper = [ ", ${flakeDir}/Wallpapers/Shift.png" ];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
15
Hyprsuck/hyprland/monitors.nix
Normal file
15
Hyprsuck/hyprland/monitors.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Hyprland monitor configuration
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
# Monitor configuration
|
||||
# eDP-1: Laptop display in portrait mode (rotated 270deg)
|
||||
# DP-3: External monitor in landscape, positioned to the right
|
||||
monitor = [
|
||||
"eDP-1, 1920x1200@60, 0x0, 1.25, transform, 3"
|
||||
"DP-3, 1920x1080@100, 960x-250, 1"
|
||||
", preferred, auto, 1" # Fallback for any other monitor
|
||||
];
|
||||
};
|
||||
}
|
||||
59
Hyprsuck/hyprland/rules.nix
Normal file
59
Hyprsuck/hyprland/rules.nix
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Hyprland window rules and workspace configuration
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
# Window rules (old syntax for Hyprland 0.52.1)
|
||||
windowrule = [
|
||||
"float, class:^(pavucontrol)$"
|
||||
"float, class:^(org.keepassxc.KeePassXC)$"
|
||||
"float, title:^(Picture-in-Picture)$"
|
||||
"pin, title:^(Picture-in-Picture)$"
|
||||
|
||||
# Foot terminal → workspace 50 (DP-3)
|
||||
"workspace 50 silent, class:^(foot)$"
|
||||
|
||||
# Zed → workspace 60 (DP-3)
|
||||
"workspace 60 silent, class:^(dev.zed.Zed)$"
|
||||
|
||||
# FreeCAD → workspace 110 (DP-3)
|
||||
"workspace 110 silent, class:^(org.freecad.FreeCAD)$"
|
||||
|
||||
# Nautilus → workspace 80 (eDP-1)
|
||||
"workspace 80 silent, class:^(org.gnome.Nautilus)$"
|
||||
|
||||
# Haruna → workspace 104, tabbed/grouped
|
||||
"workspace 90 silent, class:^(org.kde.haruna)$"
|
||||
"group set, class:^(org.kde.haruna)$"
|
||||
|
||||
# Schematic/Symbol Editor → workspace 102 (eDP-1), maximized, grouped
|
||||
"workspace 102 silent, class:^(KiCad|kicad)$, title:.*Schematic Editor.*"
|
||||
"maximize, class:^(KiCad|kicad)$, title:.*Schematic Editor.*"
|
||||
"group set, class:^(KiCad|kicad)$, title:.*Schematic Editor.*"
|
||||
"workspace 102 silent, class:^(KiCad|kicad)$, title:.*Symbol Editor.*"
|
||||
"maximize, class:^(KiCad|kicad)$, title:.*Symbol Editor.*"
|
||||
"group set, class:^(KiCad|kicad)$, title:.*Symbol Editor.*"
|
||||
|
||||
# PCB/Footprint Editor → workspace 101 (DP-3), maximized, grouped
|
||||
"workspace 101 silent, class:^(KiCad|kicad)$, title:.*PCB Editor.*"
|
||||
"maximize, class:^(KiCad|kicad)$, title:.*PCB Editor.*"
|
||||
"group set, class:^(KiCad|kicad)$, title:.*PCB Editor.*"
|
||||
"workspace 101 silent, class:^(KiCad|kicad)$, title:.*Footprint Editor.*"
|
||||
"maximize, class:^(KiCad|kicad)$, title:.*Footprint Editor.*"
|
||||
"group set, class:^(KiCad|kicad)$, title:.*Footprint Editor.*"
|
||||
];
|
||||
|
||||
# Workspace rules
|
||||
workspace = [
|
||||
"50, monitor:eDP-1, defaultName:terminal"
|
||||
"60, monitor:DP-3, defaultName:code"
|
||||
"70, monitor:DP-3, defaultName:browser"
|
||||
"71, monitor:eDP-1, defaultName:browser"
|
||||
"80, monitor:eDP-1, defaultName:files"
|
||||
"90, monitor:DP-3, defaultName:video"
|
||||
"101, monitor:DP-3, defaultName:kicad_prim"
|
||||
"102, monitor:eDP-1, defaultName:kicad_sec"
|
||||
"110, monitor:DP-3, defaultName:freecad"
|
||||
];
|
||||
};
|
||||
}
|
||||
81
Hyprsuck/hyprland/settings.nix
Normal file
81
Hyprsuck/hyprland/settings.nix
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Hyprland general settings
|
||||
# Input, appearance, layout, gestures, misc
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
# Input configuration
|
||||
input = {
|
||||
kb_layout = "us";
|
||||
numlock_by_default = true;
|
||||
|
||||
follow_mouse = 1;
|
||||
sensitivity = 0;
|
||||
|
||||
touchpad = {
|
||||
natural_scroll = true;
|
||||
};
|
||||
};
|
||||
|
||||
# General settings
|
||||
general = {
|
||||
gaps_in = 5;
|
||||
gaps_out = 5;
|
||||
border_size = 2;
|
||||
layout = "dwindle";
|
||||
};
|
||||
|
||||
# Decoration
|
||||
decoration = {
|
||||
rounding = 10;
|
||||
# blur = {
|
||||
# enabled = true;
|
||||
# size = 3;
|
||||
# passes = 1;
|
||||
# };
|
||||
# shadow = {
|
||||
# enabled = true;
|
||||
# range = 4;
|
||||
# render_power = 3;
|
||||
# };
|
||||
};
|
||||
|
||||
# Animations
|
||||
animations = {
|
||||
enabled = true;
|
||||
# bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";
|
||||
animation = [
|
||||
# "windows, 1, 7, myBezier"
|
||||
# "windowsOut, 1, 7, default, popin 80%"
|
||||
# "border, 1, 10, default"
|
||||
# "fade, 1, 7, default"
|
||||
"workspaces, 1, 4, default, slidevert"
|
||||
];
|
||||
};
|
||||
|
||||
# Layout settings
|
||||
dwindle = {
|
||||
pseudotile = true;
|
||||
preserve_split = true;
|
||||
};
|
||||
|
||||
# Gestures (Hyprland 0.51+ new syntax)
|
||||
gestures = {
|
||||
workspace_swipe_distance = 500;
|
||||
workspace_swipe_invert = false;
|
||||
workspace_swipe_create_new = false;
|
||||
};
|
||||
|
||||
# New gesture bindings (replaces workspace_swipe)
|
||||
# Vertical 3-finger swipe for workspace switching
|
||||
gesture = [
|
||||
"3, vertical, workspace"
|
||||
];
|
||||
|
||||
# Misc
|
||||
misc = {
|
||||
force_default_wallpaper = 0;
|
||||
disable_hyprland_logo = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
23
Hyprsuck/hyprsuck.nix
Normal file
23
Hyprsuck/hyprsuck.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Hyprsuck configuration entry point
|
||||
# Wayland compositor setup with Hyprland
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# ============================================================================
|
||||
# Hyprland - NixOS level config
|
||||
# ============================================================================
|
||||
programs.hyprland = {
|
||||
enable = true;
|
||||
package = pkgs.hyprland;
|
||||
portalPackage = pkgs.xdg-desktop-portal-hyprland;
|
||||
xwayland.enable = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Screenshot tool for Hyprland
|
||||
grimblast
|
||||
|
||||
# Tablet mode
|
||||
wvkbd
|
||||
];
|
||||
}
|
||||
219
Hyprsuck/waybar.nix
Normal file
219
Hyprsuck/waybar.nix
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
# Waybar - Dynamic config based on connected monitors
|
||||
# Docked (DP-3): external gets workspaces+clock, internal gets workspaces
|
||||
# Undocked: internal gets workspaces+clock
|
||||
{ pkgs-unstable, pkgs, ... }:
|
||||
|
||||
let
|
||||
workspaceIcons = {
|
||||
"terminal" = "";
|
||||
"code" = "";
|
||||
"browser" = "";
|
||||
"files" = "";
|
||||
"video" = "";
|
||||
"kicad_prim" = "";
|
||||
"kicad_sec" = "";
|
||||
"freecad" = "";
|
||||
};
|
||||
|
||||
sharedStyle = ''
|
||||
* {
|
||||
font-family: "JetBrainsMono Nerd Font Mono", monospace;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.modules-left,
|
||||
.modules-center,
|
||||
.modules-right {
|
||||
background: alpha(@theme_bg_color, 0.8);
|
||||
border-radius: 8px;
|
||||
padding: 2px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
window#waybar.right .modules-center {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
window#waybar.left .modules-center {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
#workspaces {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.modules-center #workspaces button,
|
||||
.modules-left #workspaces button,
|
||||
.modules-right #workspaces button {
|
||||
padding: 1px 2px;
|
||||
min-width: 14px;
|
||||
min-height: 12px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: none;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.modules-center #workspaces button label,
|
||||
.modules-left #workspaces button label,
|
||||
.modules-right #workspaces button label {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.modules-center #workspaces button.active,
|
||||
.modules-left #workspaces button.active,
|
||||
.modules-right #workspaces button.active {
|
||||
color: @base0D;
|
||||
border-bottom: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.modules-center #workspaces button.active label,
|
||||
.modules-left #workspaces button.active label,
|
||||
.modules-right #workspaces button.active label {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
#clock {
|
||||
padding: 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
'';
|
||||
|
||||
# JSON config for docked mode (DP-3 primary)
|
||||
dockedConfig = builtins.toJSON [
|
||||
# DP-3: workspaces on right
|
||||
{
|
||||
name = "dp3-workspaces";
|
||||
output = "DP-3";
|
||||
layer = "top";
|
||||
exclusive = false;
|
||||
passthrough = true;
|
||||
position = "right";
|
||||
margin-right = 0;
|
||||
modules-center = [ "hyprland/workspaces" ];
|
||||
"hyprland/workspaces" = {
|
||||
format = "{icon}";
|
||||
format-icons = workspaceIcons;
|
||||
show-special = false;
|
||||
persistent-workspaces = { };
|
||||
};
|
||||
}
|
||||
|
||||
# DP-3: clock on left
|
||||
{
|
||||
name = "dp3-clock";
|
||||
output = "DP-3";
|
||||
layer = "top";
|
||||
exclusive = false;
|
||||
passthrough = true;
|
||||
position = "left";
|
||||
margin-left = 0;
|
||||
modules-center = [ "clock" ];
|
||||
clock = {
|
||||
format = "{:%H\n%M}";
|
||||
tooltip-format = "{:%A, %B %d, %Y}";
|
||||
};
|
||||
}
|
||||
|
||||
# eDP-1: workspaces on left (secondary)
|
||||
{
|
||||
name = "edp1-workspaces";
|
||||
output = "eDP-1";
|
||||
layer = "top";
|
||||
exclusive = false;
|
||||
passthrough = true;
|
||||
position = "left";
|
||||
margin-left = 0;
|
||||
modules-center = [ "hyprland/workspaces" ];
|
||||
"hyprland/workspaces" = {
|
||||
format = "{icon}";
|
||||
format-icons = workspaceIcons;
|
||||
show-special = false;
|
||||
persistent-workspaces = { };
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# JSON config for undocked mode (eDP-1 only)
|
||||
undockedConfig = builtins.toJSON [
|
||||
# eDP-1: workspaces on right
|
||||
{
|
||||
name = "edp1-workspaces";
|
||||
output = "eDP-1";
|
||||
layer = "top";
|
||||
exclusive = false;
|
||||
passthrough = true;
|
||||
position = "right";
|
||||
margin-right = 0;
|
||||
modules-center = [ "hyprland/workspaces" ];
|
||||
"hyprland/workspaces" = {
|
||||
format = "{icon}";
|
||||
format-icons = workspaceIcons;
|
||||
show-special = false;
|
||||
persistent-workspaces = { };
|
||||
};
|
||||
}
|
||||
|
||||
# eDP-1: clock on left
|
||||
{
|
||||
name = "edp1-clock";
|
||||
output = "eDP-1";
|
||||
layer = "top";
|
||||
exclusive = false;
|
||||
passthrough = true;
|
||||
position = "left";
|
||||
margin-left = 0;
|
||||
modules-center = [ "clock" ];
|
||||
clock = {
|
||||
format = "{:%H\n%M}";
|
||||
tooltip-format = "{:%A, %B %d, %Y}";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Simple startup script - check for DP-3 and load appropriate config
|
||||
startupScript = ''
|
||||
sleep 1
|
||||
CONFIG_DIR="$HOME/.config/waybar"
|
||||
|
||||
if hyprctl monitors -j | grep -q '"name": "DP-3"'; then
|
||||
waybar -c "$CONFIG_DIR/config-docked.jsonc" &
|
||||
else
|
||||
waybar -c "$CONFIG_DIR/config-undocked.jsonc" &
|
||||
fi
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
# Waybar - disable systemd, we manage startup ourselves
|
||||
programs.waybar = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.waybar;
|
||||
systemd.enable = false;
|
||||
style = sharedStyle;
|
||||
};
|
||||
|
||||
# Write config files (style via programs.waybar.style to avoid conflict)
|
||||
home.file.".config/waybar/config-docked.jsonc".text = dockedConfig;
|
||||
home.file.".config/waybar/config-undocked.jsonc".text = undockedConfig;
|
||||
|
||||
# Waybar startup script
|
||||
home.packages = [
|
||||
(pkgs.writeShellScriptBin "waybar-start" startupScript)
|
||||
];
|
||||
|
||||
# Start waybar
|
||||
wayland.windowManager.hyprland.settings.exec-once = [
|
||||
"waybar-start"
|
||||
];
|
||||
}
|
||||
44
KiCad/Scripts/kicad-cycle.sh
Normal file
44
KiCad/Scripts/kicad-cycle.sh
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env bash
|
||||
# Cycle through KiCad windows/projects
|
||||
# Usage: kicad-cycle [f|b] (forward/backward, default: f)
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
DIRECTION="${1:-f}"
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Main
|
||||
# ==============================================================================
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
# Hyprland: Cycle through groups on both workspaces
|
||||
hyprctl dispatch workspace 101
|
||||
hyprctl dispatch changegroupactive "$DIRECTION"
|
||||
hyprctl dispatch workspace 102
|
||||
hyprctl dispatch changegroupactive "$DIRECTION"
|
||||
else
|
||||
# Ensure we're on kicad tag on both monitors first
|
||||
kicad-show
|
||||
|
||||
# Determine focus direction
|
||||
FOCUS_CMD="focus-next"
|
||||
[[ "$DIRECTION" == "b" ]] && FOCUS_CMD="focus-prev"
|
||||
|
||||
if [[ $(autorandr --detected) != "mobile" ]]; then
|
||||
# Multi-monitor: cycle on both monitors
|
||||
echo "mon-prim" > /tmp/dwm.fifo
|
||||
echo "$FOCUS_CMD" > /tmp/dwm.fifo
|
||||
echo "mon-sec" > /tmp/dwm.fifo
|
||||
echo "$FOCUS_CMD" > /tmp/dwm.fifo
|
||||
else
|
||||
# Single monitor: just cycle windows
|
||||
echo "$FOCUS_CMD" > /tmp/dwm.fifo
|
||||
fi
|
||||
fi
|
||||
103
KiCad/Scripts/kicad-launch.sh
Normal file
103
KiCad/Scripts/kicad-launch.sh
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#!/usr/bin/env bash
|
||||
# Launch KiCad with managed window layout
|
||||
# Usage: kicad-launch <project.kicad_pro>
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Main
|
||||
# ==============================================================================
|
||||
PROJECT="${1:-}"
|
||||
if [[ -z "$PROJECT" ]]; then
|
||||
echo "Usage: kicad-launch <project.kicad_pro>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROJECT_NAME=$(basename "$PROJECT" .kicad_pro)
|
||||
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
# Hyprland: Use special workspace for PM
|
||||
hyprctl dispatch workspace 102
|
||||
hyprctl dispatch togglespecialworkspace kicad-pm
|
||||
hyprctl dispatch exec "[workspace special:kicad-pm silent]" -- env GDK_BACKEND=x11 kicad "$PROJECT"
|
||||
|
||||
# Wait for project manager window
|
||||
PM_ADDR=""
|
||||
for i in {1..50}; do
|
||||
PM_ADDR=$(hyprctl clients -j | jq -r --arg name "$PROJECT_NAME" \
|
||||
'.[] | select(.class == "KiCad" and (.title | test($name))) | .address' 2>/dev/null | head -1)
|
||||
[[ -n "$PM_ADDR" ]] && break
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
if [[ -z "$PM_ADDR" ]]; then
|
||||
hyprctl dispatch togglespecialworkspace kicad-pm
|
||||
echo "Failed to find KiCad project manager window"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Focus PM and open PCB editor
|
||||
hyprctl dispatch focuswindow "address:$PM_ADDR"
|
||||
sleep 0.25
|
||||
xdotool key ctrl+p
|
||||
sleep 0.25
|
||||
|
||||
# Hide special workspace
|
||||
hyprctl dispatch togglespecialworkspace kicad-pm
|
||||
|
||||
# Focus PCB editor and open schematic
|
||||
sleep 2
|
||||
hyprctl dispatch workspace 101
|
||||
sleep 0.25
|
||||
xdotool key ctrl+e
|
||||
sleep 0.25
|
||||
|
||||
# Switch to KiCad workspaces
|
||||
hyprctl dispatch workspace 101
|
||||
hyprctl dispatch workspace 102
|
||||
|
||||
else
|
||||
# dwm: Launch KiCad, window rules handle placement
|
||||
# Tag 16 = kicad-pm, Tag 17 = kicad (sch/pcb), Tag 18 = kicad-aux (mobile)
|
||||
|
||||
# Detect profile
|
||||
PROFILE=$(autorandr --detected 2>/dev/null || echo "mobile")
|
||||
|
||||
# Switch to PM tag and launch
|
||||
[[ "$PROFILE" != "mobile" ]] && echo "mon-sec" > /tmp/dwm.fifo
|
||||
echo "kicad-pm" > /tmp/dwm.fifo
|
||||
kicad "$PROJECT" &
|
||||
|
||||
# Wait for PM, open PCB editor
|
||||
sleep 1
|
||||
sleep 0.25
|
||||
xdotool key ctrl+p
|
||||
|
||||
# Wait for PCB Editor
|
||||
sleep 2
|
||||
[[ "$PROFILE" != "mobile" ]] && echo "mon-prim" > /tmp/dwm.fifo
|
||||
echo "kicad" > /tmp/dwm.fifo
|
||||
|
||||
if [[ "$PROFILE" == "mobile" ]]; then
|
||||
# Mobile: retag PCB to tag 18 (kicad-aux)
|
||||
# PCB landed on tag 17, focus it, retag to 18, follow
|
||||
xdotool search --name "PCB Editor" windowactivate --sync
|
||||
sleep 0.25
|
||||
echo "tag 18" > /tmp/dwm.fifo
|
||||
echo "kicad-aux" > /tmp/dwm.fifo
|
||||
fi
|
||||
|
||||
# Focus PCB Editor, open Schematic
|
||||
sleep 0.25
|
||||
xdotool key ctrl+e
|
||||
fi
|
||||
45
KiCad/Scripts/kicad-lib-launch.sh
Normal file
45
KiCad/Scripts/kicad-lib-launch.sh
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env bash
|
||||
# Open Symbol + Footprint editors from running schematic/PCB editors
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
PROFILE=$(autorandr --detected 2>/dev/null || echo "mobile")
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Main
|
||||
# ==============================================================================
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
# Hyprland: Focus workspaces and send keys
|
||||
hyprctl dispatch workspace 101
|
||||
sleep 0.25
|
||||
xdotool key ctrl+u # Open Footprint Editor from PCB
|
||||
|
||||
sleep 2
|
||||
|
||||
hyprctl dispatch workspace 102
|
||||
sleep 0.25
|
||||
xdotool key ctrl+i # Open Symbol Editor from Schematic
|
||||
else
|
||||
# Focus PCB Editor, open Footprint Editor
|
||||
[[ "$PROFILE" != "mobile" ]] && echo "mon-prim" > /tmp/dwm.fifo
|
||||
echo "kicad" > /tmp/dwm.fifo
|
||||
sleep 0.25
|
||||
xdotool key ctrl+u
|
||||
|
||||
sleep 0.5
|
||||
|
||||
# Focus right monitor, Schematic Editor, open Symbol Editor
|
||||
[[ "$PROFILE" != "mobile" ]] && echo "mon-sec" > /tmp/dwm.fifo
|
||||
echo "kicad" > /tmp/dwm.fifo
|
||||
sleep 0.25
|
||||
xdotool key ctrl+i
|
||||
fi
|
||||
63
KiCad/Scripts/kicad-projects.sh
Normal file
63
KiCad/Scripts/kicad-projects.sh
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rofi KiCad project launcher
|
||||
# Two-step: select folder, then select project
|
||||
# Works with both Hyprland and dwm
|
||||
|
||||
# Define project folders: "Display Name|/path/to/folder"
|
||||
PROJECT_FOLDERS=(
|
||||
"CNC|/data/3D-Printer/Electronics/PCBs"
|
||||
"Keyboard|/data/Keyboard/PCB"
|
||||
"eGPU|/data/eGPU"
|
||||
)
|
||||
|
||||
# Step 1: Select project folder
|
||||
FOLDER_MENU=""
|
||||
for entry in "${PROJECT_FOLDERS[@]}"; do
|
||||
FOLDER_MENU+="${entry%%|*}\n"
|
||||
done
|
||||
|
||||
SELECTED_FOLDER=$(echo -e "$FOLDER_MENU" | rofi -dmenu -p "KiCad Folder" -i)
|
||||
[ -z "$SELECTED_FOLDER" ] && exit 0
|
||||
|
||||
# Get the path for selected folder
|
||||
FOLDER_PATH=""
|
||||
for entry in "${PROJECT_FOLDERS[@]}"; do
|
||||
name="${entry%%|*}"
|
||||
path="${entry#*|}"
|
||||
if [ "$name" = "$SELECTED_FOLDER" ]; then
|
||||
FOLDER_PATH="$path"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -z "$FOLDER_PATH" ] && exit 1
|
||||
|
||||
# Step 2: Find .kicad_pro files in selected folder
|
||||
# Sort by path length (shallowest first) to handle submodule duplicates
|
||||
mapfile -t PROJECTS < <(find "$FOLDER_PATH" -name "*.kicad_pro" -type f 2>/dev/null | awk '{print length, $0}' | sort -n | cut -d' ' -f2-)
|
||||
|
||||
if [ ${#PROJECTS[@]} -eq 0 ]; then
|
||||
rofi -e "No KiCad projects found in $FOLDER_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build menu with duplicate filtering (keep shallowest path for each project name)
|
||||
declare -A SEEN_PROJECTS
|
||||
MENU=""
|
||||
for project in "${PROJECTS[@]}"; do
|
||||
name=$(basename "$project" .kicad_pro)
|
||||
# Skip if we've already seen this project name (deeper path = submodule)
|
||||
if [ -z "${SEEN_PROJECTS[$name]}" ]; then
|
||||
SEEN_PROJECTS[$name]="$project"
|
||||
MENU+="$name\n"
|
||||
fi
|
||||
done
|
||||
|
||||
# Show rofi menu
|
||||
SELECTED=$(echo -e "$MENU" | rofi -dmenu -p "Project" -i)
|
||||
[ -z "$SELECTED" ] && exit 0
|
||||
|
||||
# Launch selected project
|
||||
PROJECT_PATH="${SEEN_PROJECTS[$SELECTED]}"
|
||||
if [ -n "$PROJECT_PATH" ]; then
|
||||
kicad-launch "$PROJECT_PATH"
|
||||
fi
|
||||
31
KiCad/Scripts/kicad-show.sh
Normal file
31
KiCad/Scripts/kicad-show.sh
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
# Show KiCad tag on both monitors
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Main
|
||||
# ==============================================================================
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
hyprctl dispatch workspace 101
|
||||
hyprctl dispatch workspace 102
|
||||
else
|
||||
if [[ $(autorandr --detected) != "mobile" ]]; then
|
||||
# Multi-monitor: set kicad tag on both monitors
|
||||
echo "mon-prim" > /tmp/dwm.fifo
|
||||
echo "kicad" > /tmp/dwm.fifo
|
||||
echo "mon-sec" > /tmp/dwm.fifo
|
||||
echo "kicad" > /tmp/dwm.fifo
|
||||
else
|
||||
# Single monitor: just switch to kicad tag
|
||||
echo "kicad" > /tmp/dwm.fifo
|
||||
fi
|
||||
fi
|
||||
23
KiCad/Scripts/kicad-swap.sh
Normal file
23
KiCad/Scripts/kicad-swap.sh
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
# Swap KiCad workspaces between monitors
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Main
|
||||
# ==============================================================================
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
hyprctl dispatch swapactiveworkspaces DP-3 eDP-1
|
||||
else
|
||||
# Ensure we're on kicad tag on both monitors first
|
||||
kicad-show
|
||||
echo "mon-swap" > /tmp/dwm.fifo
|
||||
fi
|
||||
20
KiCad/kicad.nix
Normal file
20
KiCad/kicad.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# KiCad configuration and scripts
|
||||
# Works with both Hyprland (Wayland) and dwm (X11)
|
||||
{ pkgs-stable, ... }:
|
||||
|
||||
let
|
||||
scriptsDir = ./Scripts;
|
||||
in
|
||||
{
|
||||
home.packages = with pkgs-stable; [
|
||||
kicad
|
||||
|
||||
# Custom scripts
|
||||
(writeShellScriptBin "kicad-launch" (builtins.readFile "${scriptsDir}/kicad-launch.sh"))
|
||||
(writeShellScriptBin "kicad-projects" (builtins.readFile "${scriptsDir}/kicad-projects.sh"))
|
||||
(writeShellScriptBin "kicad-show" (builtins.readFile "${scriptsDir}/kicad-show.sh"))
|
||||
(writeShellScriptBin "kicad-swap" (builtins.readFile "${scriptsDir}/kicad-swap.sh"))
|
||||
(writeShellScriptBin "kicad-cycle" (builtins.readFile "${scriptsDir}/kicad-cycle.sh"))
|
||||
(writeShellScriptBin "kicad-lib-launch" (builtins.readFile "${scriptsDir}/kicad-lib-launch.sh"))
|
||||
];
|
||||
}
|
||||
86
Rofi/Scripts/favorites.sh
Normal file
86
Rofi/Scripts/favorites.sh
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rofi Favorites - Reads Zen/Firefox bookmarks directly from SQLite
|
||||
# Supports folder navigation with ROFI_DATA state tracking
|
||||
# Works with both Hyprland and dwm (no WM-specific code)
|
||||
|
||||
PLACES_DB="$HOME/.zen/default/places.sqlite"
|
||||
TEMP_DB="/tmp/rofi-bookmarks.sqlite"
|
||||
STATE="${ROFI_DATA:-3}" # 3 = Bookmarks Toolbar folder ID
|
||||
SELECTION="$1"
|
||||
|
||||
# Copy database to avoid lock issues (browser keeps it locked)
|
||||
cp "$PLACES_DB" "$TEMP_DB" 2>/dev/null
|
||||
|
||||
show_folder() {
|
||||
local folder_id="$1"
|
||||
echo -en "\0data\x1f${folder_id}\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
|
||||
# Show back option if not at root
|
||||
[[ "$folder_id" != "3" ]] && echo " .."
|
||||
|
||||
# Query bookmarks in this folder
|
||||
# type 1 = bookmark, type 2 = folder
|
||||
sqlite3 -separator '|' "$TEMP_DB" "
|
||||
SELECT
|
||||
b.id,
|
||||
b.type,
|
||||
COALESCE(b.title, ''),
|
||||
COALESCE(p.url, '')
|
||||
FROM moz_bookmarks b
|
||||
LEFT JOIN moz_places p ON b.fk = p.id
|
||||
WHERE b.parent = $folder_id
|
||||
AND b.title IS NOT NULL
|
||||
AND b.title != ''
|
||||
ORDER BY b.position;
|
||||
" | while IFS='|' read -r id type title url; do
|
||||
if [[ "$type" == "2" ]]; then
|
||||
# Folder
|
||||
echo -en " ${title}\0info\x1ffolder:${id}\n"
|
||||
elif [[ "$type" == "1" && -n "$url" ]]; then
|
||||
# Bookmark
|
||||
echo -en " ${title}\0info\x1f${url}\n"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
handle_selection() {
|
||||
local info="$ROFI_INFO"
|
||||
|
||||
# Back/parent
|
||||
if [[ "$SELECTION" == " .." ]]; then
|
||||
parent=$(sqlite3 "$TEMP_DB" "SELECT parent FROM moz_bookmarks WHERE id = $STATE;")
|
||||
[[ -z "$parent" || "$parent" == "0" || "$parent" == "1" ]] && parent=3
|
||||
show_folder "$parent"
|
||||
return
|
||||
fi
|
||||
|
||||
# Folder - navigate into it
|
||||
if [[ "$info" == folder:* ]]; then
|
||||
local folder_id="${info#folder:}"
|
||||
show_folder "$folder_id"
|
||||
return
|
||||
fi
|
||||
|
||||
# URL - open it
|
||||
if [[ -n "$info" && "$info" != folder:* ]]; then
|
||||
coproc (xdg-open "$info" &)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
show_folder "$STATE"
|
||||
}
|
||||
|
||||
# Check if database exists
|
||||
if [[ ! -f "$PLACES_DB" ]]; then
|
||||
echo " No Zen browser profile found"
|
||||
echo " Expected: ~/.zen/default/places.sqlite"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Main entry
|
||||
if [[ -z "$SELECTION" ]]; then
|
||||
show_folder "$STATE"
|
||||
else
|
||||
handle_selection
|
||||
fi
|
||||
46
Rofi/Scripts/max30.sh
Normal file
46
Rofi/Scripts/max30.sh
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rofi Max30 mode - list and open video files with custom names
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
VIDEOS=(
|
||||
"Max Out Cardio|/data-bis/Insanity MAX 30/Max Out Cardio.mkv"
|
||||
"Max Out Power|/data-bis/Insanity MAX 30/Max Out Power.mkv"
|
||||
"Max Out Sweat|/data-bis/Insanity MAX 30/Max Out Sweat.mkv"
|
||||
"Max Out Strength|/data-bis/Insanity MAX 30/Max Out Strength.mkv"
|
||||
"Friday Fight #2|/data-bis/Insanity MAX 30/Friday Fight Round 2.mkv"
|
||||
)
|
||||
|
||||
# If no argument, list video names
|
||||
if [ -z "$1" ]; then
|
||||
for entry in "${VIDEOS[@]}"; do
|
||||
echo "${entry%%|*}"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If argument provided, find and open the matching video
|
||||
SELECTED="$1"
|
||||
for entry in "${VIDEOS[@]}"; do
|
||||
name="${entry%%|*}"
|
||||
path="${entry#*|}"
|
||||
if [ "$name" = "$SELECTED" ]; then
|
||||
setsid xdg-open "$path" >/dev/null 2>&1 &
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
hyprctl dispatch workspace 90 >/dev/null 2>&1
|
||||
else
|
||||
# Focus primary monitor first if not on mobile (single monitor) profile
|
||||
[[ $(autorandr --detected) != "mobile" ]] && echo "mon-prim" > /tmp/dwm.fifo
|
||||
echo "video" > /tmp/dwm.fifo
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
317
Rofi/Scripts/system.sh
Normal file
317
Rofi/Scripts/system.sh
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rofi System Menu - as rofi mode with inline submenus
|
||||
# Uses ROFI_DATA for state tracking between calls
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
STATE="${ROFI_DATA:-main}"
|
||||
SELECTION="$1"
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Helper Functions
|
||||
# ==============================================================================
|
||||
|
||||
get_volume() { wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null | awk '{print int($2*100)}'; }
|
||||
get_mic_volume() { wpctl get-volume @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | awk '{print int($2*100)}'; }
|
||||
is_muted() { wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null | grep -q MUTED && echo "yes" || echo "no"; }
|
||||
is_mic_muted() { wpctl get-volume @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | grep -q MUTED && echo "yes" || echo "no"; }
|
||||
get_brightness_internal() { brightnessctl -m 2>/dev/null | cut -d',' -f4 | tr -d '%'; }
|
||||
get_brightness_external() {
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
local val=$(busctl --user get-property rs.wl-gammarelay /outputs/DP_3 rs.wl.gammarelay Brightness 2>/dev/null | awk '{print $2}')
|
||||
echo "${val:-1}" | awk '{print int($1*100)}'
|
||||
else
|
||||
# X11: Use xrandr gamma (approximate)
|
||||
local gamma=$(xrandr --verbose | grep -A5 "DP-3" | grep "Brightness" | awk '{print $2}' 2>/dev/null)
|
||||
echo "${gamma:-1}" | awk '{print int($1*100)}'
|
||||
fi
|
||||
}
|
||||
get_power_profile() { powerprofilesctl get 2>/dev/null || echo "balanced"; }
|
||||
|
||||
get_default_sink_id() {
|
||||
wpctl inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | head -1 | awk '{print $2}' | tr -d ','
|
||||
}
|
||||
|
||||
get_default_source_id() {
|
||||
wpctl inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | head -1 | awk '{print $2}' | tr -d ','
|
||||
}
|
||||
|
||||
get_sinks() {
|
||||
local default_id=$(get_default_sink_id)
|
||||
pw-cli list-objects Node 2>/dev/null | awk '
|
||||
/^[[:space:]]*id [0-9]+/ { id = $2; gsub(",", "", id) }
|
||||
/node.description = / { gsub(/.*node.description = "|"$/, ""); desc = $0 }
|
||||
/media.class = "Audio\/Sink"/ { print id "|" desc }
|
||||
' | while IFS='|' read -r id desc; do
|
||||
if [[ "$id" == "$default_id" ]]; then
|
||||
echo "✓ ${desc}|${id}"
|
||||
else
|
||||
echo "${desc}|${id}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
get_sources() {
|
||||
local default_id=$(get_default_source_id)
|
||||
pw-cli list-objects Node 2>/dev/null | awk '
|
||||
/^[[:space:]]*id [0-9]+/ { id = $2; gsub(",", "", id) }
|
||||
/node.description = / { gsub(/.*node.description = "|"$/, ""); desc = $0 }
|
||||
/media.class = "Audio\/Source"/ { print id "|" desc }
|
||||
' | while IFS='|' read -r id desc; do
|
||||
if [[ "$id" == "$default_id" ]]; then
|
||||
echo "✓ ${desc}|${id}"
|
||||
else
|
||||
echo "${desc}|${id}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Menu Display Functions
|
||||
# ==============================================================================
|
||||
|
||||
show_main() {
|
||||
echo -en "\0data\x1fmain\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
echo " Sound"
|
||||
echo " Brightness"
|
||||
echo " WiFi"
|
||||
echo " Bluetooth"
|
||||
echo " Power Profile"
|
||||
echo " Power"
|
||||
}
|
||||
|
||||
show_sound() {
|
||||
echo -en "\0data\x1fsound\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
local vol=$(get_volume)
|
||||
local mic=$(get_mic_volume)
|
||||
local muted=$(is_muted)
|
||||
local mic_muted=$(is_mic_muted)
|
||||
local vol_icon=""; [[ "$muted" == "yes" ]] && vol_icon=""
|
||||
local mic_icon=""; [[ "$mic_muted" == "yes" ]] && mic_icon=""
|
||||
|
||||
echo "$vol_icon Volume: ${vol}%"
|
||||
echo " Volume +5%"
|
||||
echo " Volume -5%"
|
||||
echo " Output Device"
|
||||
echo "$mic_icon Mic: ${mic}%"
|
||||
echo " Mic +5%"
|
||||
echo " Mic -5%"
|
||||
echo " Input Device"
|
||||
echo " Back"
|
||||
}
|
||||
|
||||
show_output() {
|
||||
echo -en "\0data\x1foutput\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
get_sinks | while IFS='|' read -r name id; do
|
||||
echo -en " ${name}\0info\x1f${id}\n"
|
||||
done
|
||||
echo " Back"
|
||||
}
|
||||
|
||||
show_input() {
|
||||
echo -en "\0data\x1finput\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
get_sources | while IFS='|' read -r name id; do
|
||||
echo -en " ${name}\0info\x1f${id}\n"
|
||||
done
|
||||
echo " Back"
|
||||
}
|
||||
|
||||
show_brightness() {
|
||||
echo -en "\0data\x1fbrightness\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
local internal=$(get_brightness_internal)
|
||||
local external=$(get_brightness_external)
|
||||
|
||||
echo " Internal: ${internal}%"
|
||||
echo " Internal +5%"
|
||||
echo " Internal -5%"
|
||||
echo " External: ${external}%"
|
||||
echo " External +5%"
|
||||
echo " External -5%"
|
||||
echo " Back"
|
||||
}
|
||||
|
||||
show_power_profile() {
|
||||
echo -en "\0data\x1fprofile\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
local current=$(get_power_profile)
|
||||
local perf="" bal="" saver=""
|
||||
[[ "$current" == "performance" ]] && perf="✓ "
|
||||
[[ "$current" == "balanced" ]] && bal="✓ "
|
||||
[[ "$current" == "power-saver" ]] && saver="✓ "
|
||||
|
||||
echo "${perf} Performance"
|
||||
echo "${bal} Balanced"
|
||||
echo "${saver} Power Saver"
|
||||
echo " Edit Tuning"
|
||||
echo " Back"
|
||||
}
|
||||
|
||||
show_power() {
|
||||
echo -en "\0data\x1fpower\n"
|
||||
echo -en "\0keep-selection\x1ftrue\n"
|
||||
echo " Shutdown"
|
||||
echo " Reboot"
|
||||
echo " Logout"
|
||||
echo " Lock"
|
||||
echo " Back"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Action Handlers
|
||||
# ==============================================================================
|
||||
|
||||
handle_main() {
|
||||
case "$SELECTION" in
|
||||
*"Sound"*) show_sound ;;
|
||||
*"Brightness"*) show_brightness ;;
|
||||
*"WiFi"*) coproc (rofi-network-manager &); exit 0 ;;
|
||||
*"Bluetooth"*) coproc (rofi-bluetooth &); exit 0 ;;
|
||||
*"Power Profile"*) show_power_profile ;;
|
||||
*"Power"*) show_power ;;
|
||||
*) show_main ;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_sound() {
|
||||
case "$SELECTION" in
|
||||
*"Volume:"*) wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle; show_sound ;;
|
||||
*"Volume +5%"*) wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ -l 1.0; show_sound ;;
|
||||
*"Volume -5%"*) wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-; show_sound ;;
|
||||
*"Output Device"*) show_output ;;
|
||||
*"Mic:"*) wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle; show_sound ;;
|
||||
*"Mic +5%"*) wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%+ -l 1.0; show_sound ;;
|
||||
*"Mic -5%"*) wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%-; show_sound ;;
|
||||
*"Input Device"*) show_input ;;
|
||||
*"Back"*) show_main ;;
|
||||
*) show_sound ;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_output() {
|
||||
case "$SELECTION" in
|
||||
*"Back"*) show_sound ;;
|
||||
*)
|
||||
[[ -n "$ROFI_INFO" ]] && wpctl set-default "$ROFI_INFO"
|
||||
show_output
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_input() {
|
||||
case "$SELECTION" in
|
||||
*"Back"*) show_sound ;;
|
||||
*)
|
||||
[[ -n "$ROFI_INFO" ]] && wpctl set-default "$ROFI_INFO"
|
||||
show_input
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_brightness() {
|
||||
case "$SELECTION" in
|
||||
*"Internal +5%"*) brightnessctl -q set +5%; show_brightness ;;
|
||||
*"Internal -5%"*) brightnessctl -q set 5%-; show_brightness ;;
|
||||
*"External +5%"*)
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
current=$(get_brightness_external)
|
||||
new=$((current + 5)); [[ $new -gt 100 ]] && new=100
|
||||
val=$(echo "scale=2; $new/100" | bc)
|
||||
busctl --user set-property rs.wl-gammarelay /outputs/DP_3 rs.wl.gammarelay Brightness d "$val" 2>/dev/null
|
||||
else
|
||||
current=$(get_brightness_external)
|
||||
new=$((current + 5)); [[ $new -gt 100 ]] && new=100
|
||||
val=$(echo "scale=2; $new/100" | bc)
|
||||
xrandr --output DP-3 --brightness "$val" 2>/dev/null
|
||||
fi
|
||||
show_brightness ;;
|
||||
*"External -5%"*)
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
current=$(get_brightness_external)
|
||||
new=$((current - 5)); [[ $new -lt 5 ]] && new=5
|
||||
val=$(echo "scale=2; $new/100" | bc)
|
||||
busctl --user set-property rs.wl-gammarelay /outputs/DP_3 rs.wl.gammarelay Brightness d "$val" 2>/dev/null
|
||||
else
|
||||
current=$(get_brightness_external)
|
||||
new=$((current - 5)); [[ $new -lt 5 ]] && new=5
|
||||
val=$(echo "scale=2; $new/100" | bc)
|
||||
xrandr --output DP-3 --brightness "$val" 2>/dev/null
|
||||
fi
|
||||
show_brightness ;;
|
||||
*"Back"*) show_main ;;
|
||||
*) show_brightness ;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_power_profile() {
|
||||
case "$SELECTION" in
|
||||
# systemd path watcher auto-applies power-tuning on profile change
|
||||
*"Performance"*) powerprofilesctl set performance; show_power_profile ;;
|
||||
*"Balanced"*) powerprofilesctl set balanced; show_power_profile ;;
|
||||
*"Power Saver"*) powerprofilesctl set power-saver; show_power_profile ;;
|
||||
*"Edit Tuning"*) coproc (zeditor "$HOME/NixOS/ryzenadj.nix" &); exit 0 ;;
|
||||
*"Back"*) show_main ;;
|
||||
*) show_power_profile ;;
|
||||
esac
|
||||
}
|
||||
|
||||
handle_power() {
|
||||
case "$SELECTION" in
|
||||
*"Shutdown"*) systemctl poweroff ;;
|
||||
*"Reboot"*) systemctl reboot ;;
|
||||
*"Logout"*)
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
hyprctl dispatch exit
|
||||
else
|
||||
pkill -x dwm
|
||||
fi
|
||||
;;
|
||||
*"Lock"*)
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
hyprlock & exit 0
|
||||
else
|
||||
slock & exit 0
|
||||
fi
|
||||
;;
|
||||
*"Back"*) show_main ;;
|
||||
*) show_power ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Main Entry Point
|
||||
# ==============================================================================
|
||||
|
||||
if [[ -z "$SELECTION" ]]; then
|
||||
case "$STATE" in
|
||||
sound) show_sound ;;
|
||||
output) show_output ;;
|
||||
input) show_input ;;
|
||||
brightness) show_brightness ;;
|
||||
profile) show_power_profile ;;
|
||||
power) show_power ;;
|
||||
*) show_main ;;
|
||||
esac
|
||||
else
|
||||
case "$STATE" in
|
||||
sound) handle_sound ;;
|
||||
output) handle_output ;;
|
||||
input) handle_input ;;
|
||||
brightness) handle_brightness ;;
|
||||
profile) handle_power_profile ;;
|
||||
power) handle_power ;;
|
||||
*) handle_main ;;
|
||||
esac
|
||||
fi
|
||||
86
Rofi/Scripts/websearch.sh
Normal file
86
Rofi/Scripts/websearch.sh
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rofi web search - with DuckDuckGo result preview
|
||||
# Supports both Hyprland (Wayland) and dwm (X11)
|
||||
|
||||
# ==============================================================================
|
||||
# Environment Detection
|
||||
# ==============================================================================
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
WM="hyprland"
|
||||
else
|
||||
WM="dwm"
|
||||
fi
|
||||
|
||||
switch_to_browser() {
|
||||
if [[ "$WM" == "hyprland" ]]; then
|
||||
hyprctl dispatch workspace 70
|
||||
else
|
||||
# Focus primary monitor first if not on mobile (single monitor) profile
|
||||
[[ $(autorandr --detected) != "mobile" ]] && echo "mon-prim" > /tmp/dwm.fifo
|
||||
echo "browser" > /tmp/dwm.fifo
|
||||
fi
|
||||
}
|
||||
|
||||
# Step 1: Query input (no list)
|
||||
QUERY=$(echo "" | rofi -dmenu -p "Search : " -l 0)
|
||||
[ -z "$QUERY" ] && exit 0
|
||||
|
||||
# Check if input looks like a URL - open directly
|
||||
if echo "$QUERY" | grep -qE '\.(com|org|net|io|dev|co|me|gov|edu|app|xyz|info)(/|$)'; then
|
||||
# Add https:// if no protocol specified
|
||||
[[ "$QUERY" =~ ^https?:// ]] || QUERY="https://$QUERY"
|
||||
switch_to_browser
|
||||
xdg-open "$QUERY"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Step 2: Engine selection (DuckDuckGo first)
|
||||
ENGINE=$(printf " DuckDuckGo\n Google\n MyNixOS\n Nixpkgs\n NerdFonts" | rofi -dmenu -p "Engine : " -no-custom -l 5)
|
||||
[ -z "$ENGINE" ] && exit 0
|
||||
|
||||
# Remove icon prefix
|
||||
ENGINE="${ENGINE#* }"
|
||||
|
||||
ENCODED=$(echo "$QUERY" | sed 's/ /%20/g; s/&/%26/g; s/?/%3F/g; s/=/%3D/g')
|
||||
|
||||
case "$ENGINE" in
|
||||
"DuckDuckGo")
|
||||
# Fetch top 5 results using ddgr
|
||||
RESULTS=$(ddgr --json -n 5 "$QUERY" 2>/dev/null | jq -r '.[] | "\(.title)\t\(.url)"')
|
||||
|
||||
if [ -z "$RESULTS" ]; then
|
||||
# Fallback to direct search if no results
|
||||
switch_to_browser
|
||||
xdg-open "https://duckduckgo.com/?q=$ENCODED"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show results in rofi (title only)
|
||||
TITLES=$(echo "$RESULTS" | cut -f1)
|
||||
SELECTED=$(echo "$TITLES" | rofi -dmenu -p "Results : " -l 5)
|
||||
[ -z "$SELECTED" ] && exit 0
|
||||
|
||||
# Get URL for selected title
|
||||
URL=$(echo "$RESULTS" | grep "^$SELECTED " | cut -f2)
|
||||
if [ -n "$URL" ]; then
|
||||
switch_to_browser
|
||||
xdg-open "$URL"
|
||||
fi
|
||||
;;
|
||||
"Google")
|
||||
switch_to_browser
|
||||
xdg-open "https://www.google.com/search?q=$ENCODED"
|
||||
;;
|
||||
"MyNixOS")
|
||||
switch_to_browser
|
||||
xdg-open "https://mynixos.com/search?q=$ENCODED"
|
||||
;;
|
||||
"Nixpkgs")
|
||||
switch_to_browser
|
||||
xdg-open "https://search.nixos.org/packages?query=$ENCODED"
|
||||
;;
|
||||
"NerdFonts")
|
||||
switch_to_browser
|
||||
xdg-open "https://www.nerdfonts.com/cheat-sheet?q=$ENCODED"
|
||||
;;
|
||||
esac
|
||||
162
Rofi/rofi.nix
Normal file
162
Rofi/rofi.nix
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
# Rofi configuration and scripts
|
||||
# Works with both Hyprland (Wayland) and dwm (X11)
|
||||
{
|
||||
pkgs-stable,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
scriptsDir = ./Scripts;
|
||||
|
||||
# Detect if we're in Wayland or X11 based on session type
|
||||
# This is evaluated at build time, so we need runtime detection in scripts
|
||||
isWayland = config.wayland.windowManager.hyprland.enable or false;
|
||||
|
||||
# Terminal varies by environment
|
||||
terminal = if isWayland then "foot" else "st";
|
||||
in
|
||||
{
|
||||
# Wayland-specific packages (only when using Hyprland)
|
||||
home.packages =
|
||||
with pkgs-stable;
|
||||
[
|
||||
rofi-bluetooth
|
||||
rofi-network-manager
|
||||
ddgr
|
||||
brightnessctl
|
||||
bc
|
||||
sqlite
|
||||
|
||||
# Custom scripts (environment-aware)
|
||||
(writeShellScriptBin "rofi-websearch" (builtins.readFile "${scriptsDir}/websearch.sh"))
|
||||
(writeShellScriptBin "rofi-max30" (builtins.readFile "${scriptsDir}/max30.sh"))
|
||||
(writeShellScriptBin "rofi-system" (builtins.readFile "${scriptsDir}/system.sh"))
|
||||
(writeShellScriptBin "rofi-favorites" (builtins.readFile "${scriptsDir}/favorites.sh"))
|
||||
]
|
||||
++ (
|
||||
if isWayland then
|
||||
[
|
||||
wl-gammarelay-rs
|
||||
]
|
||||
else
|
||||
[
|
||||
]
|
||||
);
|
||||
|
||||
# Start wl-gammarelay-rs on Hyprland
|
||||
wayland.windowManager.hyprland.settings = lib.mkIf isWayland {
|
||||
exec-once = [ "wl-gammarelay-rs" ];
|
||||
};
|
||||
|
||||
programs.rofi = {
|
||||
enable = true;
|
||||
package = pkgs-stable.rofi;
|
||||
terminal = terminal;
|
||||
|
||||
plugins = with pkgs-stable; [
|
||||
rofi-calc
|
||||
rofi-emoji
|
||||
];
|
||||
|
||||
modes = [
|
||||
"system:rofi-system"
|
||||
"favorites:rofi-favorites"
|
||||
"drun"
|
||||
"calc"
|
||||
"emoji"
|
||||
"max30:rofi-max30"
|
||||
];
|
||||
|
||||
extraConfig = {
|
||||
show-icons = true;
|
||||
display-system = "";
|
||||
display-favorites = "";
|
||||
display-drun = "";
|
||||
display-calc = "";
|
||||
display-emoji = "";
|
||||
display-max30 = "";
|
||||
drun-display-format = "{name}";
|
||||
scroll-method = 0;
|
||||
disable-history = false;
|
||||
sidebar-mode = false;
|
||||
sort = true;
|
||||
sorting-method = "fzf";
|
||||
matching = "fuzzy";
|
||||
|
||||
kb-primary-paste = "Control+V,Shift+Insert";
|
||||
kb-secondary-paste = "Control+v,Insert";
|
||||
kb-secondary-copy = "Control+c";
|
||||
kb-clear-line = "Control+w";
|
||||
kb-move-front = "Control+a";
|
||||
kb-move-end = "Control+e";
|
||||
kb-move-word-back = "Alt+b,Control+Left";
|
||||
kb-move-word-forward = "Alt+f,Control+Right";
|
||||
kb-move-char-back = "Control+b";
|
||||
kb-move-char-forward = "Control+f";
|
||||
kb-remove-word-back = "Control+Alt+h,Control+BackSpace";
|
||||
kb-remove-word-forward = "Control+Alt+d";
|
||||
kb-remove-char-forward = "Delete,Control+d";
|
||||
kb-remove-char-back = "BackSpace,Shift+BackSpace,Control+h";
|
||||
kb-remove-to-eol = "";
|
||||
kb-remove-to-sol = "Control+u";
|
||||
kb-accept-entry = "Return,KP_Enter";
|
||||
kb-accept-custom = "Control+Return";
|
||||
kb-accept-custom-alt = "Control+Shift+Return";
|
||||
kb-accept-alt = "Shift+Return";
|
||||
kb-delete-entry = "Shift+Delete";
|
||||
kb-mode-next = "Right";
|
||||
kb-mode-previous = "Left";
|
||||
kb-mode-complete = "Control+l";
|
||||
kb-row-left = "Control+Page_Up";
|
||||
kb-row-right = "Control+Page_Down";
|
||||
kb-row-up = "Up";
|
||||
kb-row-down = "Down";
|
||||
kb-row-tab = "";
|
||||
kb-element-next = "Tab";
|
||||
kb-element-prev = "ISO_Left_Tab";
|
||||
kb-page-prev = "Page_Up";
|
||||
kb-page-next = "Page_Down";
|
||||
kb-row-first = "Home,KP_Home";
|
||||
kb-row-last = "End,KP_End";
|
||||
kb-row-select = "Control+space";
|
||||
kb-screenshot = "Alt+S";
|
||||
kb-ellipsize = "Alt+period";
|
||||
kb-toggle-case-sensitivity = "grave,dead_grave";
|
||||
kb-toggle-sort = "Alt+grave";
|
||||
kb-cancel = "Escape";
|
||||
};
|
||||
|
||||
theme =
|
||||
let
|
||||
mkLiteral = value: {
|
||||
_type = "literal";
|
||||
value = value;
|
||||
};
|
||||
in
|
||||
{
|
||||
window = {
|
||||
width = mkLiteral "300px";
|
||||
location = mkLiteral "center";
|
||||
# border-radius = mkLiteral "12px";
|
||||
border = mkLiteral "2px solid";
|
||||
border-color = mkLiteral "@border-color";
|
||||
};
|
||||
listview = {
|
||||
lines = 8;
|
||||
fixed-height = false;
|
||||
};
|
||||
element = {
|
||||
padding = mkLiteral "8px";
|
||||
# border-radius = mkLiteral "6px";
|
||||
};
|
||||
# "element selected" = {
|
||||
# border-radius = mkLiteral "6px";
|
||||
# };
|
||||
inputbar = {
|
||||
padding = mkLiteral "8px";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
92
Suckless/dwm/api.nix
Normal file
92
Suckless/dwm/api.nix
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
# dwm fifo API - control dwm via named pipe
|
||||
# Usage: echo "command" > /tmp/dwm.fifo
|
||||
{ lib }:
|
||||
|
||||
{
|
||||
config = ''
|
||||
/* dwmfifo - control dwm via named pipe */
|
||||
static const char *dwmfifo = "/tmp/dwm.fifo";
|
||||
static Command commands[] = {
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* TAG NAVIGATION - Semantic names matching workflow
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "view", view, .parse = parsetag }, /* Generic: view 5 */
|
||||
{ "view-all", view, {.ui = ~0} }, /* All tags */
|
||||
{ "view-prev", viewprev, {0} }, /* Previous tag */
|
||||
{ "view-next", viewnext, {0} }, /* Next tag */
|
||||
|
||||
/* Semantic tag shortcuts (matching tags.nix) */
|
||||
{ "terminal", view, {.ui = 1 << 9} }, /* Tag 10: */
|
||||
{ "files", view, {.ui = 1 << 10} }, /* Tag 11: */
|
||||
{ "video", view, {.ui = 1 << 11} }, /* Tag 12: */
|
||||
{ "browser", view, {.ui = 1 << 12} }, /* Tag 13: */
|
||||
{ "code", view, {.ui = 1 << 13} }, /* Tag 14: */
|
||||
{ "freecad", view, {.ui = 1 << 14} }, /* Tag 15: */
|
||||
{ "kicad-pm", view, {.ui = 1 << 15} }, /* Tag 16: (project manager) */
|
||||
{ "kicad", view, {.ui = 1 << 16} }, /* Tag 17: (sch/pcb) */
|
||||
{ "kicad-aux", view, {.ui = 1 << 17} }, /* Tag 18: (pcb mobile) */
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* MONITOR CONTROL - Primary (left) / Secondary (right)
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "mon-prim", focusnthmon, {.i = 1} }, /* Focus primary monitor */
|
||||
{ "mon-sec", focusnthmon, {.i = 0} }, /* Focus secondary monitor */
|
||||
{ "mon-send-prim", tagnthmon, {.i = 1} }, /* Send window to primary */
|
||||
{ "mon-send-sec", tagnthmon, {.i = 0} }, /* Send window to secondary */
|
||||
{ "mon-swap", swapmon, {0} }, /* Swap monitor contents */
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* WINDOW MANAGEMENT
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "focus-next", focusstack, {.i = +1} }, /* Next window in stack */
|
||||
{ "focus-prev", focusstack, {.i = -1} }, /* Previous window */
|
||||
{ "focus", focusstack, .parse = parseplusminus },/* Generic: focus +2 */
|
||||
{ "kill", killclient, {0} }, /* Close window */
|
||||
{ "zoom", zoom, {0} }, /* Promote to master */
|
||||
{ "float", togglefloating, {0} }, /* Toggle floating */
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* LAYOUT
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "layout-tile", setlayout, {.v = &layouts[0]} },
|
||||
{ "layout-float", setlayout, {.v = &layouts[1]} },
|
||||
{ "layout-mono", setlayout, {.v = &layouts[2]} },
|
||||
{ "layout-toggle", setlayout, {0} }, /* Cycle layouts */
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* MASTER AREA
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "master-inc", incnmaster, {.i = +1} },
|
||||
{ "master-dec", incnmaster, {.i = -1} },
|
||||
{ "mfact", setmfact, .parse = parseplusminus },/* mfact +0.05 */
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* TAG MANAGEMENT
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "toggleview", toggleview, .parse = parsetag },
|
||||
{ "tag", tag, .parse = parsetag },
|
||||
{ "toggletag", toggletag, .parse = parsetag },
|
||||
{ "tagmon", tagmon, .parse = parseplusminus },
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* ADVANCED (window targeting)
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "viewwin", viewwin, .parse = parsexid }, /* Focus by X window ID */
|
||||
{ "viewname", viewname, .parse = parsestr }, /* Focus by name */
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* SPAWNS
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "spawn-term", spawn, {.v = termcmd} },
|
||||
{ "spawn-browser", spawn, {.v = browsercmd} },
|
||||
{ "spawn-rofi", spawn, {.v = roficmd} },
|
||||
{ "spawn-files", spawn, {.v = filescmd} },
|
||||
{ "spawn-editor", spawn, {.v = editorcmd} },
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
* SESSION
|
||||
* ═══════════════════════════════════════════════════════════════════════ */
|
||||
{ "quit", quit, {0} },
|
||||
};
|
||||
'';
|
||||
}
|
||||
39
Suckless/dwm/appearance.nix
Normal file
39
Suckless/dwm/appearance.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# dwm appearance settings (colors, fonts, borders, gaps)
|
||||
# Integrates with Stylix for consistent theming
|
||||
{ config, lib }:
|
||||
|
||||
let
|
||||
colors = config.lib.stylix.colors;
|
||||
fonts = config.stylix.fonts;
|
||||
in
|
||||
{
|
||||
config = ''
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 2; /* border pixel of windows */
|
||||
static const unsigned int gappx = 5; /* gaps between windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
static const int showbar = 0; /* 0 means no bar (holdbar shows on key hold) */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
/* Display modes of the tab bar: never shown, always shown, shown only in */
|
||||
/* monocle mode in the presence of several windows. */
|
||||
/* Modes after showtab_nmodes are disabled. */
|
||||
enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always};
|
||||
static const int showtab = showtab_auto; /* Default tab bar show mode */
|
||||
static const int toptab = False; /* False means bottom tab bar */
|
||||
|
||||
static const char *fonts[] = { "${fonts.monospace.name}:size=${toString fonts.sizes.terminal}" };
|
||||
static const char dmenufont[] = "${fonts.monospace.name}:size=${toString fonts.sizes.terminal}";
|
||||
static const char col_gray1[] = "#${colors.base00}";
|
||||
static const char col_gray2[] = "#${colors.base01}";
|
||||
static const char col_gray3[] = "#${colors.base04}";
|
||||
static const char col_gray4[] = "#${colors.base05}";
|
||||
static const char col_cyan[] = "#${colors.base0D}";
|
||||
static const char *colors[][3] = {
|
||||
/* fg bg border */
|
||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||
};
|
||||
'';
|
||||
}
|
||||
1779
Suckless/dwm/dwm-lebowski.patch
Normal file
1779
Suckless/dwm/dwm-lebowski.patch
Normal file
File diff suppressed because it is too large
Load diff
100
Suckless/dwm/dwm.nix
Normal file
100
Suckless/dwm/dwm.nix
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# dwm window manager configuration
|
||||
#
|
||||
# =============================================================================
|
||||
# Patch Development Notes
|
||||
# =============================================================================
|
||||
#
|
||||
# Base: dwm 6.6 (matches nixpkgs)
|
||||
# Clone: ~/NixOS/dwm
|
||||
#
|
||||
# Clean & Build Commands:
|
||||
# cd ~/NixOS/dwm
|
||||
# git reset --hard 6.6
|
||||
# rm -f config.h drw.o dwm dwm.o util.o
|
||||
# nix-shell -p xorg.libX11 xorg.libXft xorg.libXinerama xorg.libXcursor pkg-config gnumake gcc
|
||||
# make clean && make
|
||||
#
|
||||
# Generate patch after all patches applied:
|
||||
# git diff 6.6 > ~/NixOS/Suckless/dwm/dwm-lebowski.patch
|
||||
#
|
||||
# =============================================================================
|
||||
# Patches (apply in order):
|
||||
# =============================================================================
|
||||
#
|
||||
# 1. pertag - Per-tag layouts (applied separately, then tab)
|
||||
# 2. tab - Tabbed monocle bar
|
||||
# 3. fullgaps - Simple gaps between windows
|
||||
# 4. holdbar-modkey - Show bar while holding mod key
|
||||
# 5. hide_vacant_tags - Only show occupied tags
|
||||
# 6. bardwmlogo - DWM logo in bar
|
||||
# 7. cursorwarp - Cursor follows focus
|
||||
# 8. alwayscenter - Float windows spawn centered
|
||||
# 9. swapmonitors - Swap tagsets between monitors
|
||||
# 10. adjacenttag - Navigate tags with arrows (skipvacant)
|
||||
# 11. accessnthmonitor - Focus/send to specific monitor by number
|
||||
# 12. dwmfifo - Control dwm via named pipe
|
||||
# 13. xcursor - Use system Xcursor theme (Stylix)
|
||||
# 14. actualfullscreen
|
||||
#
|
||||
# Custom additions:
|
||||
# - def_layouts array for per-tag default layouts
|
||||
#
|
||||
# =============================================================================
|
||||
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
appearance = import ./appearance.nix { inherit config lib; };
|
||||
tags = import ./tags.nix { inherit lib; };
|
||||
rules = import ./rules.nix { inherit lib; };
|
||||
layouts = import ./layouts.nix { inherit lib; };
|
||||
keybindings = import ./keybindings.nix { inherit lib; };
|
||||
api = import ./api.nix { inherit lib; };
|
||||
|
||||
configDefH = ''
|
||||
${appearance.config}
|
||||
|
||||
${tags.config}
|
||||
|
||||
${rules.config}
|
||||
|
||||
${layouts.config}
|
||||
|
||||
${keybindings.config}
|
||||
|
||||
${api.config}
|
||||
'';
|
||||
in
|
||||
{
|
||||
services.xserver.windowManager.dwm = {
|
||||
enable = true;
|
||||
package =
|
||||
(pkgs.dwm.override {
|
||||
conf = configDefH;
|
||||
}).overrideAttrs
|
||||
(old: {
|
||||
patches = [ ./dwm-lebowski.patch ];
|
||||
buildInputs = old.buildInputs ++ [ pkgs.xorg.libXcursor ];
|
||||
});
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellScriptBin "vieworspawn" ''
|
||||
mon=$1; tag=$2; class=$3; shift 3
|
||||
# Focus monitor if multi-monitor setup (0=secondary, 1=primary)
|
||||
if [[ $(${pkgs.autorandr}/bin/autorandr --detected) != "mobile" ]]; then
|
||||
[[ "$mon" == "0" ]] && echo "mon-sec" > /tmp/dwm.fifo || echo "mon-prim" > /tmp/dwm.fifo
|
||||
fi
|
||||
echo "view $tag" > /tmp/dwm.fifo
|
||||
sleep 0.02
|
||||
if ! ${pkgs.xdotool}/bin/xdotool search --class "$class" >/dev/null 2>&1; then
|
||||
exec "$@"
|
||||
fi
|
||||
'')
|
||||
];
|
||||
}
|
||||
181
Suckless/dwm/keybindings.nix
Normal file
181
Suckless/dwm/keybindings.nix
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# dwm keybindings
|
||||
{ lib }:
|
||||
|
||||
{
|
||||
config = ''
|
||||
/* key definitions */
|
||||
#define MODKEY Mod4Mask
|
||||
#define TAGKEYS(KEY,TAG) \
|
||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||
#define HOLDKEY 0xffeb // 0 - disable; 0xffe9 - Mod1Mask; 0xffeb - Mod4Mask (Super)
|
||||
|
||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
|
||||
/* commands */
|
||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
||||
static const char *roficmd[] = { "rofi", "-show", "system", NULL };
|
||||
static const char *rofiwebcmd[] = { "rofi-websearch", NULL };
|
||||
static const char *browsercmd[] = { "zen-twilight", NULL };
|
||||
static const char *lockcmd[] = { "slock", NULL };
|
||||
static const char *kicadshowcmd[] = { "kicad-show", NULL };
|
||||
static const char *kicadprojectscmd[] = { "kicad-projects", NULL };
|
||||
static const char *kicadlibcmd[] = { "kicad-lib-launch", NULL };
|
||||
static const char *kicadswapcmd[] = { "kicad-swap", NULL };
|
||||
static const char *kicadcyclefcmd[] = { "kicad-cycle", "f", NULL };
|
||||
static const char *kicadcyclebcmd[] = { "kicad-cycle", "b", NULL };
|
||||
static const char *screenshotcmd[] = { "flameshot", "gui", NULL };
|
||||
static const char *screenshotfullcmd[] = { "flameshot", "full", "--path", "/home/lebowski/Pictures/Screenshots", NULL };
|
||||
static const char *cliphistcmd[] = { "sh", "-c", "greenclip print | rofi -dmenu -p Clipboard | xclip -selection clipboard", NULL };
|
||||
static const char *volmutecmd[] = { "wpctl", "set-mute", "@DEFAULT_AUDIO_SINK@", "toggle", NULL };
|
||||
static const char *micmutecmd[] = { "wpctl", "set-mute", "@DEFAULT_AUDIO_SOURCE@", "toggle", NULL };
|
||||
static const char *volupcmd[] = { "sh", "-c", "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+", NULL };
|
||||
static const char *voldowncmd[] = { "wpctl", "set-volume", "@DEFAULT_AUDIO_SINK@", "5%-", NULL };
|
||||
|
||||
/* vieworspawn: monitor, tag (1-based), class, cmd... */
|
||||
static const char *termvos[] = { "vieworspawn", "0", "10", "st-256color", "st", NULL };
|
||||
static const char *filesvos[] = { "vieworspawn", "0", "11", "Thunar", "thunar", NULL };
|
||||
static const char *editorvos[] = { "vieworspawn", "1", "14", "dev.zed.Zed", "zeditor", NULL };
|
||||
static const char *freecadvos[] = { "vieworspawn", "1", "15", "FreeCAD", "FreeCAD", "--single-instance", NULL };
|
||||
static const char *bambuvos[] = { "vieworspawn", "1", "19", "BambuStudio", "bambu-studio", NULL };
|
||||
|
||||
/* fallback spawn commands */
|
||||
static const char *termcmd[] = { "st", NULL };
|
||||
static const char *filescmd[] = { "thunar", NULL };
|
||||
static const char *editorcmd[] = { "zeditor", NULL };
|
||||
static const char *freecadcmd[] = { "FreeCAD", "--single-instance", NULL };
|
||||
static const char *bambucmd[] = { "bambu-studio", NULL };
|
||||
|
||||
static const Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
|
||||
/* Rofi */
|
||||
{ MODKEY, XK_space, spawn, {.v = roficmd } },
|
||||
{ MODKEY|Mod1Mask, XK_space, spawn, {.v = rofiwebcmd } },
|
||||
|
||||
/* Terminal */
|
||||
{ MODKEY, XK_a, spawn, {.v = termvos } },
|
||||
{ MODKEY|ShiftMask, XK_a, spawn, {.v = termcmd } },
|
||||
|
||||
/* Zed (code) */
|
||||
{ MODKEY, XK_z, spawn, {.v = editorvos } },
|
||||
{ MODKEY|ShiftMask, XK_z, spawn, {.v = editorcmd } },
|
||||
|
||||
/* Zen Browser (web) */
|
||||
{ MODKEY, XK_x, view, {.ui = 1 << 12 } },
|
||||
{ MODKEY|ShiftMask, XK_x, spawn, {.v = browsercmd } },
|
||||
|
||||
/* Thunar (files) */
|
||||
{ MODKEY, XK_n, spawn, {.v = filesvos } },
|
||||
{ MODKEY|ShiftMask, XK_n, spawn, {.v = filescmd } },
|
||||
|
||||
/* Video */
|
||||
{ MODKEY, XK_m, view, {.ui = 1 << 11 } },
|
||||
|
||||
/* Lock */
|
||||
{ MODKEY, XK_Escape, spawn, {.v = lockcmd } },
|
||||
|
||||
/* KiCad */
|
||||
{ MODKEY, XK_k, spawn, {.v = kicadshowcmd } },
|
||||
{ MODKEY|ShiftMask, XK_k, spawn, {.v = kicadprojectscmd } },
|
||||
{ MODKEY, XK_l, spawn, {.v = kicadlibcmd } },
|
||||
{ MODKEY|ControlMask, XK_k, view, {.ui = 1 << 15 } },
|
||||
{ MODKEY|Mod1Mask, XK_k, spawn, {.v = kicadswapcmd } },
|
||||
{ MODKEY, XK_bracketright, spawn, {.v = kicadcyclefcmd } },
|
||||
{ MODKEY, XK_bracketleft, spawn, {.v = kicadcyclebcmd } },
|
||||
|
||||
/* FreeCAD */
|
||||
{ MODKEY, XK_f, spawn, {.v = freecadvos } },
|
||||
{ MODKEY|ShiftMask, XK_f, spawn, {.v = freecadcmd } },
|
||||
|
||||
/* Bambu Studio */
|
||||
{ MODKEY, XK_p, spawn, {.v = bambuvos } },
|
||||
{ MODKEY|ShiftMask, XK_p, spawn, {.v = bambucmd } },
|
||||
|
||||
/* Window management */
|
||||
{ MODKEY, XK_q, killclient, {0} },
|
||||
{ MODKEY, XK_e, togglefloating, {0} },
|
||||
{ MODKEY, XK_w, togglefullscr, {0} },
|
||||
{ MODKEY, XK_t, tabmode, {-1} },
|
||||
|
||||
/* Focus movement - stack */
|
||||
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||
{ MODKEY|ShiftMask, XK_j, focusstack, {.i = -1 } },
|
||||
|
||||
/* Adjacent tags - Up/Down */
|
||||
{ MODKEY, XK_Up, viewprev, {0} },
|
||||
{ MODKEY, XK_Down, viewnext, {0} },
|
||||
{ MODKEY|ShiftMask, XK_Up, tagtoprev, {0} },
|
||||
{ MODKEY|ShiftMask, XK_Down, tagtonext, {0} },
|
||||
|
||||
/* Move to monitor */
|
||||
{ MODKEY, XK_Left, focusnthmon, {.i = 1 } },
|
||||
{ MODKEY, XK_Right, focusnthmon, {.i = 0 } },
|
||||
{ MODKEY|ShiftMask, XK_Left, tagnthmon, {.i = 1 } },
|
||||
{ MODKEY|ShiftMask, XK_Right, tagnthmon, {.i = 0 } },
|
||||
|
||||
/* Swap monitors */
|
||||
{ MODKEY|ShiftMask, XK_apostrophe, swapmon, {0} },
|
||||
|
||||
/* Resize master */
|
||||
{ MODKEY|Mod1Mask, XK_Left, setmfact, {.f = -0.05} },
|
||||
{ MODKEY|Mod1Mask, XK_Right, setmfact, {.f = +0.05} },
|
||||
|
||||
/* Tags */
|
||||
TAGKEYS( XK_1, 0)
|
||||
TAGKEYS( XK_2, 1)
|
||||
TAGKEYS( XK_3, 2)
|
||||
TAGKEYS( XK_4, 3)
|
||||
TAGKEYS( XK_5, 4)
|
||||
TAGKEYS( XK_6, 5)
|
||||
TAGKEYS( XK_7, 6)
|
||||
TAGKEYS( XK_8, 7)
|
||||
TAGKEYS( XK_9, 8)
|
||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||
|
||||
/* Clipboard */
|
||||
{ MODKEY|ShiftMask, XK_v, spawn, {.v = cliphistcmd } },
|
||||
|
||||
/* Screenshots */
|
||||
{ 0, XK_Print, spawn, {.v = screenshotcmd } },
|
||||
{ ShiftMask, XK_Print, spawn, {.v = screenshotfullcmd } },
|
||||
|
||||
/* Media keys */
|
||||
{ 0, XF86XK_AudioMute, spawn, {.v = volmutecmd } },
|
||||
{ 0, XF86XK_AudioMicMute, spawn, {.v = micmutecmd } },
|
||||
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = volupcmd } },
|
||||
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = voldowncmd } },
|
||||
|
||||
/* Holdbar */
|
||||
{ 0, HOLDKEY, holdbar, {0} },
|
||||
};
|
||||
|
||||
/* button definitions */
|
||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||
static const Button buttons[] = {
|
||||
/* click event mask button function argument */
|
||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||
{ ClkTagBar, 0, Button1, view, {0} },
|
||||
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||
{ ClkTabBar, 0, Button1, focuswin, {0} },
|
||||
/* Scroll through tags with Mod+scroll */
|
||||
{ ClkRootWin, MODKEY, Button4, viewprev, {0} },
|
||||
{ ClkRootWin, MODKEY, Button5, viewnext, {0} },
|
||||
{ ClkClientWin, MODKEY, Button4, viewprev, {0} },
|
||||
{ ClkClientWin, MODKEY, Button5, viewnext, {0} },
|
||||
};
|
||||
'';
|
||||
}
|
||||
49
Suckless/dwm/layouts.nix
Normal file
49
Suckless/dwm/layouts.nix
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# dwm layouts
|
||||
{ lib }:
|
||||
|
||||
let
|
||||
# Layout indices: 0 = tile, 1 = floating, 2 = monocle
|
||||
defLayouts = [
|
||||
0 # index 0: all-tags view
|
||||
0 # tag 1
|
||||
0 # tag 2
|
||||
0 # tag 3
|
||||
0 # tag 4
|
||||
0 # tag 5
|
||||
0 # tag 6
|
||||
0 # tag 7
|
||||
0 # tag 8
|
||||
0 # tag 9
|
||||
2 # tag 10: terminal
|
||||
2 # tag 11: files
|
||||
2 # tag 12: video
|
||||
2 # tag 13: web/browser
|
||||
2 # tag 14: code
|
||||
2 # tag 15: freecad
|
||||
2 # tag 16: kicad project manager
|
||||
2 # tag 17: kicad (sch/pcb editors)
|
||||
2 # tag 18: kicad-aux (pcb/footprint mobile)
|
||||
2 # tag 19: bambu studio
|
||||
];
|
||||
defLayoutsStr = lib.concatMapStringsSep ", " toString defLayouts;
|
||||
in
|
||||
{
|
||||
config = ''
|
||||
/* layout(s) */
|
||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
|
||||
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
{ "[]=", tile }, /* 0: first entry is default */
|
||||
{ "><>", NULL }, /* 1: floating */
|
||||
{ "[M]", monocle }, /* 2: monocle (tabbed) */
|
||||
};
|
||||
|
||||
/* default layout per tag */
|
||||
/* 0 = tile, 1 = floating, 2 = monocle */
|
||||
static int def_layouts[1 + LENGTH(tags)] = { ${defLayoutsStr} };
|
||||
'';
|
||||
}
|
||||
41
Suckless/dwm/rules.nix
Normal file
41
Suckless/dwm/rules.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# dwm window rules
|
||||
# Tag mapping: 1<<9=term, 1<<10=files, 1<<11=video, 1<<12=web, 1<<13=code,
|
||||
# 1<<14=freecad, 1<<15=kicad-pm, 1<<16=kicad, 1<<17=kicad-aux
|
||||
{ lib }:
|
||||
|
||||
{
|
||||
config = ''
|
||||
static const Rule rules[] = {
|
||||
/* xprop(1):
|
||||
* WM_CLASS(STRING) = instance, class
|
||||
* WM_NAME(STRING) = title
|
||||
*/
|
||||
/* class instance title tags mask isfloating monitor */
|
||||
{ "Polkit-gnome-authentication-agent-1", NULL, NULL, 0, 1, -1 },
|
||||
{ "KeePassXC", NULL, NULL, 0, 1, -1 },
|
||||
{ NULL, NULL, "Picture-in-Picture", 0, 1, -1 },
|
||||
{ "slint-viewer", NULL, NULL, 0, 1, -1 },
|
||||
{ "LVGL Simulator", NULL, NULL, 0, 1, -1 },
|
||||
{ NULL, NULL, "Axium Browser", 0, 1, -1 },
|
||||
{ NULL, NULL, "Axium", 0, 1, -1 },
|
||||
{ NULL, NULL, "Fex", 0, 1, -1 },
|
||||
{ NULL, NULL, "@", 0, 1, -1 },
|
||||
{ NULL, NULL, "OSM", 0, 1, -1 },
|
||||
{ NULL, NULL, "YouNix", 0, 1, -1 },
|
||||
{ "st-256color", NULL, NULL, 1 << 9, 0, 0 }, /* terminal */
|
||||
{ "Thunar", NULL, NULL, 1 << 10, 0, 0 }, /* files */
|
||||
{ "haruna", NULL, NULL, 1 << 11, 0, 1 }, /* video */
|
||||
{ "zen-twilight", NULL, "Zen Twilight", 1 << 12, 0, 1 }, /* web */
|
||||
{ "dev.zed.Zed", NULL, NULL, 1 << 13, 0, 1 }, /* code */
|
||||
{ "FreeCAD", NULL, "Expression editor", 0, 1, -1 }, /* freecad formula popup */
|
||||
{ "FreeCAD", NULL, "Insert length", 0, 1, -1 }, /* freecad dimension popup */
|
||||
{ "FreeCAD", NULL, NULL, 1 << 14, 0, 1 }, /* freecad */
|
||||
{ "KiCad", NULL, "KiCad 9", 1 << 15, 0, 0 }, /* kicad-pm: tag 16 */
|
||||
{ "KiCad", NULL, "Schematic Editor", 1 << 16, 0, 0 }, /* kicad: tag 17, mon 0 */
|
||||
{ "KiCad", NULL, "Symbol Editor", 1 << 16, 0, 0 }, /* kicad: tag 17, mon 0 */
|
||||
{ "KiCad", NULL, "PCB Editor", 1 << 16, 0, 1 }, /* kicad: tag 17, mon 1 */
|
||||
{ "KiCad", NULL, "Footprint Editor", 1 << 16, 0, 1 }, /* kicad: tag 17, mon 1 */
|
||||
{ "BambuStudio", NULL, NULL, 1 << 18, 0, 1 }, /* bambu studio */
|
||||
};
|
||||
'';
|
||||
}
|
||||
33
Suckless/dwm/tags.nix
Normal file
33
Suckless/dwm/tags.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# dwm tag names (Nerd Font icons for special workspaces)
|
||||
{ lib }:
|
||||
|
||||
let
|
||||
tags = [
|
||||
"1"
|
||||
"2"
|
||||
"3"
|
||||
"4"
|
||||
"5"
|
||||
"6"
|
||||
"7"
|
||||
"8"
|
||||
"9"
|
||||
"" # 10: terminal
|
||||
"" # 11: files
|
||||
"" # 12: video
|
||||
"" # 13: web/browser
|
||||
"" # 14: code
|
||||
"" # 15: freecad
|
||||
"" # 16: kicad project manager
|
||||
"" # 17: kicad (sch/pcb editors)
|
||||
"" # 18: kicad-aux (pcb/footprint mobile)
|
||||
"" # 19: bambu studio
|
||||
];
|
||||
tagsStr = lib.concatMapStringsSep ", " (t: ''"${t}"'') tags;
|
||||
in
|
||||
{
|
||||
config = ''
|
||||
/* tagging */
|
||||
static const char *tags[] = { ${tagsStr} };
|
||||
'';
|
||||
}
|
||||
144
Suckless/home.nix
Normal file
144
Suckless/home.nix
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# Suckless home-manager configuration
|
||||
# X11-specific settings that integrate with home-manager
|
||||
{ pkgs-stable, ... }:
|
||||
|
||||
{
|
||||
# Monitor management
|
||||
programs.autorandr = {
|
||||
enable = true;
|
||||
package = pkgs-stable.autorandr;
|
||||
hooks.postswitch = {
|
||||
"set-xft-dpi" = "echo 'Xft.dpi: 96' | xrdb -merge";
|
||||
"set-wallpaper" = ''
|
||||
case "$AUTORANDR_CURRENT_PROFILE" in
|
||||
docked)
|
||||
xwallpaper --output eDP-1 --zoom ~/NixOS/Wallpapers/pearl.jpg --output DP-3 --zoom ~/NixOS/Wallpapers/siege.png
|
||||
;;
|
||||
mobile)
|
||||
xwallpaper --output eDP-1 --zoom ~/NixOS/Wallpapers/siege.png
|
||||
;;
|
||||
esac
|
||||
'';
|
||||
};
|
||||
profiles = {
|
||||
"docked" = {
|
||||
fingerprint = {
|
||||
eDP-1 = "00ffffffffffff002c831207000000001d220104a51e1378025645935e5b9325185054000000010101010101010101010101010101010f3c80a070b0204018303c002ebd10000018000000000000000000000000000000000000000000000000000000000000000000000000000000fe004b443134304e3336333041303100df";
|
||||
DP-3 = "00ffffffffffff0061a906b00100000025220103803c2278afa545ad504da6260c5054a5cb0081809500a9c0b300d1c0010101010101023a801871382d40582c450055502100001e000000ff0035333738323030303434353132000000fd0030a561ba3c000a202020202020000000fc005032374642422d52410a20202001c0020319b349010311130414051f90e200ca67030c00100038448e4480a070382d40582c450055502100001e605980a0703814403024350055502100001c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050";
|
||||
};
|
||||
config = {
|
||||
DP-3 = {
|
||||
enable = true;
|
||||
primary = false;
|
||||
mode = "1920x1080";
|
||||
rate = "75.00";
|
||||
dpi = 96;
|
||||
position = "0x180";
|
||||
};
|
||||
eDP-1 = {
|
||||
enable = true;
|
||||
primary = true;
|
||||
mode = "1920x1200";
|
||||
rate = "60.00";
|
||||
dpi = 96;
|
||||
position = "1920x0";
|
||||
rotate = "left";
|
||||
scale = {
|
||||
x = 0.75;
|
||||
y = 0.75;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
"mobile" = {
|
||||
fingerprint = {
|
||||
eDP-1 = "00ffffffffffff002c831207000000001d220104a51e1378025645935e5b9325185054000000010101010101010101010101010101010f3c80a070b0204018303c002ebd10000018000000000000000000000000000000000000000000000000000000000000000000000000000000fe004b443134304e3336333041303100df";
|
||||
};
|
||||
config = {
|
||||
eDP-1 = {
|
||||
enable = true;
|
||||
primary = true;
|
||||
mode = "1920x1200";
|
||||
rate = "60.00";
|
||||
dpi = 96;
|
||||
position = "0x0";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
services.autorandr = {
|
||||
enable = true;
|
||||
package = pkgs-stable.autorandr;
|
||||
};
|
||||
|
||||
# Screenshots
|
||||
services.flameshot = {
|
||||
enable = true;
|
||||
package = pkgs-stable.flameshot;
|
||||
};
|
||||
|
||||
# Touchpad gestures (for mobile mode)
|
||||
home.file.".config/libinput-gestures.conf".text = ''
|
||||
# 3-finger up/down: tag navigation
|
||||
gesture swipe up 3 sh -c 'echo "view-prev" > /tmp/dwm.fifo'
|
||||
gesture swipe down 3 sh -c 'echo "view-next" > /tmp/dwm.fifo'
|
||||
|
||||
# 3-finger left/right: window cycling
|
||||
gesture swipe left 3 sh -c 'echo "focus-prev" > /tmp/dwm.fifo'
|
||||
gesture swipe right 3 sh -c 'echo "focus-next" > /tmp/dwm.fifo'
|
||||
|
||||
# 4-finger up/down: layout
|
||||
gesture swipe up 4 sh -c 'echo "layout-mono" > /tmp/dwm.fifo'
|
||||
gesture swipe down 4 sh -c 'echo "layout-tile" > /tmp/dwm.fifo'
|
||||
|
||||
# Pinch: rofi system menu / view all
|
||||
gesture pinch in rofi -show system
|
||||
gesture pinch out sh -c 'echo "view-all" > /tmp/dwm.fifo'
|
||||
'';
|
||||
|
||||
# X11 startup script
|
||||
home.file.".xinitrc".text = ''
|
||||
# D-Bus environment for GTK apps (fixes slow first launch)
|
||||
dbus-update-activation-environment --systemd DBUS_SESSION_BUS_ADDRESS DISPLAY XAUTHORITY
|
||||
|
||||
# Apply monitor profile
|
||||
autorandr --change --default mobile
|
||||
|
||||
# Disable DPMS and screen blanking
|
||||
xset s off
|
||||
xset -dpms
|
||||
xset s noblank
|
||||
|
||||
# Numlock on
|
||||
numlockx
|
||||
|
||||
# Status bar
|
||||
slstatus &
|
||||
|
||||
# Compositor
|
||||
# picom &
|
||||
|
||||
# Touchpad gestures
|
||||
libinput-gestures-setup start &
|
||||
|
||||
# Auto-rotate
|
||||
auto-rotate &
|
||||
|
||||
# KeePassXC (minimized, ready for browser extension)
|
||||
keepassxc --minimized &
|
||||
|
||||
# Create dwmfifo for IPC
|
||||
mkfifo /tmp/dwm.fifo 2>/dev/null || true
|
||||
|
||||
# Start dwm
|
||||
exec dwm
|
||||
'';
|
||||
|
||||
# Auto-start X11/dwm on tty1
|
||||
programs.bash.profileExtra = ''
|
||||
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]; then
|
||||
exec startx
|
||||
fi
|
||||
'';
|
||||
}
|
||||
93
Suckless/slstatus.nix
Normal file
93
Suckless/slstatus.nix
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# slstatus - suckless status bar
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
# Dynamic icon scripts
|
||||
batteryScript = pkgs.writeShellScript "slstatus-battery" ''
|
||||
perc=$(cat /sys/class/power_supply/BATT/capacity 2>/dev/null || echo "0")
|
||||
status=$(cat /sys/class/power_supply/BATT/status 2>/dev/null || echo "Unknown")
|
||||
|
||||
if [ "$status" = "Charging" ]; then icon=""
|
||||
elif [ "$perc" -ge 90 ]; then icon=""
|
||||
elif [ "$perc" -ge 80 ]; then icon=""
|
||||
elif [ "$perc" -ge 70 ]; then icon=""
|
||||
elif [ "$perc" -ge 60 ]; then icon=""
|
||||
elif [ "$perc" -ge 50 ]; then icon=""
|
||||
elif [ "$perc" -ge 40 ]; then icon=""
|
||||
elif [ "$perc" -ge 30 ]; then icon=""
|
||||
elif [ "$perc" -ge 20 ]; then icon=""
|
||||
elif [ "$perc" -ge 10 ]; then icon=""
|
||||
else icon=""
|
||||
fi
|
||||
|
||||
printf "%s %s%%" "$icon" "$perc"
|
||||
'';
|
||||
|
||||
mouseScript = pkgs.writeShellScript "slstatus-mouse" ''
|
||||
perc=$(cat /sys/class/power_supply/hidpp_battery_0/capacity 2>/dev/null || echo "")
|
||||
[ -z "$perc" ] && exit 0
|
||||
printf " %s%%" "$perc"
|
||||
'';
|
||||
|
||||
volumeScript = pkgs.writeShellScript "slstatus-volume" ''
|
||||
vol=$(${pkgs.wireplumber}/bin/wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null)
|
||||
muted=$(echo "$vol" | grep -c MUTED)
|
||||
perc=$(echo "$vol" | awk '{printf "%.0f", $2*100}')
|
||||
|
||||
if [ "$muted" -eq 1 ]; then icon=""
|
||||
elif [ "$perc" -ge 66 ]; then icon=""
|
||||
elif [ "$perc" -ge 33 ]; then icon=""
|
||||
else icon=""
|
||||
fi
|
||||
|
||||
printf "%s %s%%" "$icon" "$perc"
|
||||
'';
|
||||
|
||||
wifiScript = pkgs.writeShellScript "slstatus-wifi" ''
|
||||
essid=$(cat /sys/class/net/wlp2s0/wireless/../uevent 2>/dev/null | grep INTERFACE | cut -d= -f2)
|
||||
essid=$(${pkgs.iw}/bin/iw dev wlp2s0 link 2>/dev/null | grep SSID | awk '{print $2}')
|
||||
[ -z "$essid" ] && exit 0
|
||||
|
||||
perc=$(awk 'NR==3 {printf "%.0f", $3*100/70}' /proc/net/wireless 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$perc" -ge 75 ]; then icon=""
|
||||
elif [ "$perc" -ge 50 ]; then icon=""
|
||||
elif [ "$perc" -ge 25 ]; then icon=""
|
||||
else icon=""
|
||||
fi
|
||||
|
||||
printf "%s %s %s%%" "$icon" "$essid" "$perc"
|
||||
'';
|
||||
|
||||
config = ''
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* interval between updates (in ms) */
|
||||
const unsigned int interval = 1000;
|
||||
|
||||
/* text to show if no value can be retrieved */
|
||||
static const char unknown_str[] = "";
|
||||
|
||||
/* maximum output string length */
|
||||
#define MAXLEN 512
|
||||
|
||||
static const struct arg args[] = {
|
||||
/* function format argument */
|
||||
{ cpu_freq, " %s/", NULL },
|
||||
{ cpu_perc, "%s%% | ", NULL },
|
||||
{ ram_used, " %s/", NULL },
|
||||
{ ram_perc, "%s%% | ", NULL },
|
||||
{ temp, " %s°C | ", "/sys/class/thermal/thermal_zone0/temp" },
|
||||
{ run_command, "%s | ", "${wifiScript}" },
|
||||
{ run_command, "%s | ", "${volumeScript}" },
|
||||
{ run_command, "%s | ", "${batteryScript}" },
|
||||
{ run_command, "%s | ", "${mouseScript}" },
|
||||
{ datetime, " %s ", "%d/%m %H:%M:%S" },
|
||||
};
|
||||
'';
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [
|
||||
(pkgs.slstatus.override { conf = config; })
|
||||
];
|
||||
}
|
||||
46
Suckless/st/appearance.nix
Normal file
46
Suckless/st/appearance.nix
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# st appearance settings
|
||||
{ config, lib }:
|
||||
|
||||
let
|
||||
colors = config.lib.stylix.colors;
|
||||
fonts = config.stylix.fonts;
|
||||
in
|
||||
{
|
||||
font = "${fonts.monospace.name}:pixelsize=${
|
||||
toString (fonts.sizes.terminal + 6)
|
||||
}:antialias=true:autohint=true";
|
||||
alpha = "0.9";
|
||||
|
||||
colorsSed = ''
|
||||
sed -i '/static const char \*colorname\[\]/,/^};/c\
|
||||
static const char *colorname[] = {\
|
||||
/* 8 normal colors */\
|
||||
"#${colors.base00}",\
|
||||
"#${colors.base08}",\
|
||||
"#${colors.base0B}",\
|
||||
"#${colors.base0A}",\
|
||||
"#${colors.base0D}",\
|
||||
"#${colors.base0E}",\
|
||||
"#${colors.base0C}",\
|
||||
"#${colors.base05}",\
|
||||
\
|
||||
/* 8 bright colors */\
|
||||
"#${colors.base03}",\
|
||||
"#${colors.base08}",\
|
||||
"#${colors.base0B}",\
|
||||
"#${colors.base0A}",\
|
||||
"#${colors.base0D}",\
|
||||
"#${colors.base0E}",\
|
||||
"#${colors.base0C}",\
|
||||
"#${colors.base07}",\
|
||||
\
|
||||
[255] = 0,\
|
||||
\
|
||||
/* more colors can be added after 255 to use with DefaultXX */\
|
||||
"#${colors.base04}", /* 256: cursor */\
|
||||
"#${colors.base03}", /* 257: reverse cursor */\
|
||||
"#${colors.base05}", /* 258: foreground */\
|
||||
"#${colors.base00}", /* 259: background */\
|
||||
};' config.def.h
|
||||
'';
|
||||
}
|
||||
69
Suckless/st/st.nix
Normal file
69
Suckless/st/st.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# st terminal configuration
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
appearance = import ./appearance.nix { inherit config lib; };
|
||||
in
|
||||
{
|
||||
nixpkgs.overlays = [(final: prev: {
|
||||
st = prev.st.overrideAttrs (oldAttrs: {
|
||||
buildInputs = oldAttrs.buildInputs ++ [ final.harfbuzz ];
|
||||
patches = (oldAttrs.patches or []) ++ [
|
||||
# Scrollback (ringbuffer + float + mouse)
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/scrollback/st-scrollback-ringbuffer-0.9.2.diff";
|
||||
sha256 = "1r23q4mi5bkam49ld5c3ccwaa1li7bbjx0ndjgm207p02az9h4cn";
|
||||
})
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/scrollback/st-scrollback-float-0.9.2.diff";
|
||||
sha256 = "01r1gdgkcpf9194257myjnr5nn1fj1baj13wjm9rf2nclbagifgm";
|
||||
})
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/scrollback/st-scrollback-mouse-0.9.2.diff";
|
||||
sha256 = "068s5rjvvw2174y34i5xxvpw4jvjy58akd1kgf025h1153hmf7jy";
|
||||
})
|
||||
# Alpha (transparency)
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/alpha/st-alpha-20240814-a0274bc.diff";
|
||||
sha256 = "0hld9dwkk7i1f0z0k9biigx2g4wzlqa2yb7vdn5rrf6ymr5nlbsn";
|
||||
})
|
||||
# Anysize (no gaps)
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/anysize/st-expected-anysize-0.9.diff";
|
||||
sha256 = "04gvkf80lhaiwyv3m7fdkf81msf8al1kfb7inx1bf02ygx9152v2";
|
||||
})
|
||||
# Bold is not bright
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/bold-is-not-bright/st-bold-is-not-bright-20190127-3be4cf1.diff";
|
||||
sha256 = "1cpap2jz80n90izhq5fdv2cvg29hj6bhhvjxk40zkskwmjn6k49j";
|
||||
})
|
||||
# Clipboard
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/clipboard/st-clipboard-0.8.3.diff";
|
||||
sha256 = "1h1nwilwws02h2lnxzmrzr69lyh6pwsym21hvalp9kmbacwy6p0g";
|
||||
})
|
||||
# Ligatures (scrollback-ringbuffer variant)
|
||||
(final.fetchurl {
|
||||
url = "https://st.suckless.org/patches/ligatures/0.9.3/st-ligatures-scrollback-ringbuffer-20251007-0.9.3.diff";
|
||||
sha256 = "0c2w1p0siafiyarfx6skdighwzw29d1mydpjfrwgrvdsywwyq2di";
|
||||
})
|
||||
];
|
||||
postPatch = (oldAttrs.postPatch or "") + ''
|
||||
# Font
|
||||
substituteInPlace config.def.h \
|
||||
--replace '"Liberation Mono:pixelsize=12:antialias=true:autohint=true"' \
|
||||
'"${appearance.font}"'
|
||||
|
||||
# Alpha
|
||||
substituteInPlace config.def.h \
|
||||
--replace 'float alpha = 0.8;' \
|
||||
'float alpha = ${appearance.alpha};'
|
||||
|
||||
# Colors
|
||||
${appearance.colorsSed}
|
||||
'';
|
||||
});
|
||||
})];
|
||||
|
||||
environment.systemPackages = [ pkgs.st ];
|
||||
}
|
||||
121
Suckless/suckless.nix
Normal file
121
Suckless/suckless.nix
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# Suckless configuration entry point
|
||||
# X11 window manager setup with dwm, st, and related tools
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./dwm/dwm.nix
|
||||
./st/st.nix
|
||||
./slstatus.nix
|
||||
];
|
||||
|
||||
# ============================================================================
|
||||
# X11 Display Server
|
||||
# ============================================================================
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
|
||||
# Keyboard layout
|
||||
xkb.layout = "us";
|
||||
|
||||
displayManager.startx.enable = true;
|
||||
|
||||
# Auto-lock after 10 minutes of inactivity
|
||||
xautolock = {
|
||||
enable = true;
|
||||
time = 10;
|
||||
locker = "${pkgs.slock}/bin/slock";
|
||||
};
|
||||
};
|
||||
|
||||
# Input (libinput)
|
||||
services.libinput.enable = true;
|
||||
|
||||
# Tablet/stylus support
|
||||
services.xserver.wacom.enable = true;
|
||||
|
||||
# Accelerometer for auto-rotation
|
||||
hardware.sensor.iio.enable = true;
|
||||
|
||||
# ============================================================================
|
||||
# Screen Locker
|
||||
# ============================================================================
|
||||
programs.slock = {
|
||||
enable = true;
|
||||
package = pkgs.slock;
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# XDG Portal for X11
|
||||
# ============================================================================
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
||||
config.common.default = "gtk";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# X11 ecosystem packages
|
||||
# ============================================================================
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Clipboard
|
||||
xclip
|
||||
|
||||
# Wallpaper
|
||||
xwallpaper
|
||||
|
||||
# Numlock on startup
|
||||
numlockx
|
||||
|
||||
# Touchpad gestures
|
||||
libinput-gestures
|
||||
|
||||
# Auto-rotate based on accelerometer (with wallpaper switching, mobile only)
|
||||
(writeShellScriptBin "auto-rotate" ''
|
||||
export DISPLAY=''${DISPLAY:-:0}
|
||||
WALLPAPER_DIR="$HOME/NixOS/Wallpapers"
|
||||
|
||||
${iio-sensor-proxy}/bin/monitor-sensor | while read -r line; do
|
||||
# Skip rotation when docked (would mess up monitor positions)
|
||||
[[ $(${autorandr}/bin/autorandr --detected) != "mobile" ]] && continue
|
||||
|
||||
case "$line" in
|
||||
*"normal"*)
|
||||
${xorg.xrandr}/bin/xrandr --output eDP-1 --rotate normal
|
||||
${xwallpaper}/bin/xwallpaper --output eDP-1 --zoom "$WALLPAPER_DIR/siege.png"
|
||||
;;
|
||||
*"left-up"*)
|
||||
${xorg.xrandr}/bin/xrandr --output eDP-1 --rotate left
|
||||
${xwallpaper}/bin/xwallpaper --output eDP-1 --zoom "$WALLPAPER_DIR/pearl.jpg"
|
||||
;;
|
||||
*"right-up"*)
|
||||
${xorg.xrandr}/bin/xrandr --output eDP-1 --rotate right
|
||||
${xwallpaper}/bin/xwallpaper --output eDP-1 --zoom "$WALLPAPER_DIR/pearl.jpg"
|
||||
;;
|
||||
*"bottom-up"*)
|
||||
${xorg.xrandr}/bin/xrandr --output eDP-1 --rotate inverted
|
||||
${xwallpaper}/bin/xwallpaper --output eDP-1 --zoom "$WALLPAPER_DIR/siege.png"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
'')
|
||||
];
|
||||
|
||||
# ============================================================================
|
||||
# Polkit authentication agent
|
||||
# ============================================================================
|
||||
security.polkit.enable = true;
|
||||
systemd.user.services.polkit-gnome-authentication-agent-1 = {
|
||||
description = "polkit-gnome-authentication-agent-1";
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
wants = [ "graphical-session.target" ];
|
||||
after = [ "graphical-session.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 1;
|
||||
TimeoutStopSec = 10;
|
||||
};
|
||||
};
|
||||
}
|
||||
BIN
Wallpapers/Shift.png
Executable file
BIN
Wallpapers/Shift.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 573 KiB |
BIN
Wallpapers/caesar.png
Normal file
BIN
Wallpapers/caesar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4 MiB |
BIN
Wallpapers/norse.png
Normal file
BIN
Wallpapers/norse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
BIN
Wallpapers/pearl.jpg
Normal file
BIN
Wallpapers/pearl.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3 MiB |
BIN
Wallpapers/shift_base.png
Executable file
BIN
Wallpapers/shift_base.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 606 KiB |
BIN
Wallpapers/siege.png
Normal file
BIN
Wallpapers/siege.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 MiB |
176
configuration.nix
Executable file
176
configuration.nix
Executable file
|
|
@ -0,0 +1,176 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./stylix.nix
|
||||
# ./Hyprsuck/hyprsuck.nix
|
||||
./Suckless/suckless.nix
|
||||
./ryzenadj.nix
|
||||
# ./virtualisation.nix
|
||||
# ./Hetzner/setup.nix
|
||||
];
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
# Axium binary caches
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://axium.cachix.org"
|
||||
"https://cache.axiomania.org/main"
|
||||
];
|
||||
|
||||
http-connections = 128;
|
||||
max-substitution-jobs = 128;
|
||||
max-jobs = "auto";
|
||||
|
||||
trusted-public-keys = [
|
||||
"axium.cachix.org-1:BfzPfRTbbCYmaQrVLSWchgsR4ScA9ZCZ389FyWspUH8="
|
||||
"main:Uz5F0MbXItVx2XCmBbEAMmQ0T6+DZDgLaXWalh1k++o="
|
||||
];
|
||||
};
|
||||
|
||||
nix.distributedBuilds = true;
|
||||
|
||||
# Required for home-manager xdg.portal with useUserPackages
|
||||
environment.pathsToLink = [
|
||||
"/share/applications"
|
||||
"/share/xdg-desktop-portal"
|
||||
];
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.loader.systemd-boot.configurationLimit = 10;
|
||||
boot.loader.timeout = 1;
|
||||
|
||||
networking.hostName = "v3";
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
hardware.bluetooth.enable = true;
|
||||
|
||||
time.timeZone = "Asia/Ho_Chi_Minh";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
i18n.extraLocaleSettings = {
|
||||
LC_ADDRESS = "en_US.UTF-8";
|
||||
LC_IDENTIFICATION = "en_US.UTF-8";
|
||||
LC_MEASUREMENT = "en_US.UTF-8";
|
||||
LC_MONETARY = "en_US.UTF-8";
|
||||
LC_NAME = "en_US.UTF-8";
|
||||
LC_NUMERIC = "en_US.UTF-8";
|
||||
LC_PAPER = "en_US.UTF-8";
|
||||
LC_TELEPHONE = "en_US.UTF-8";
|
||||
LC_TIME = "en_US.UTF-8";
|
||||
};
|
||||
|
||||
services.getty.autologinUser = "lebowski";
|
||||
|
||||
programs.nix-ld.enable = true;
|
||||
|
||||
services.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
|
||||
users.users.lebowski = {
|
||||
isNormalUser = true;
|
||||
description = "Antoine Lespinasse";
|
||||
extraGroups = [
|
||||
"networkmanager"
|
||||
"wheel"
|
||||
"input"
|
||||
];
|
||||
};
|
||||
|
||||
# GVfs - for Nautilus trash, network shares, MTP devices
|
||||
services.gvfs.enable = true;
|
||||
|
||||
# UPower - battery/power device monitoring
|
||||
services.upower.enable = true;
|
||||
|
||||
# Power Profiles Daemon - power management (performance/balanced/power-saver)
|
||||
services.power-profiles-daemon.enable = true;
|
||||
|
||||
# System packages (stable for core tools)
|
||||
environment.systemPackages = with pkgs; [
|
||||
wget
|
||||
git
|
||||
bat
|
||||
btop
|
||||
ncdu
|
||||
nmap
|
||||
neofetch
|
||||
xdotool
|
||||
jq
|
||||
attic-client
|
||||
wireguard-tools
|
||||
sox
|
||||
|
||||
ffmpegthumbnailer
|
||||
gdk-pixbuf
|
||||
librsvg
|
||||
evince
|
||||
libgsf
|
||||
libjxl
|
||||
libavif
|
||||
|
||||
# Disk utilities
|
||||
gparted
|
||||
gnome-disk-utility
|
||||
|
||||
# Image / PDF viewers
|
||||
kdePackages.gwenview
|
||||
kdePackages.okular
|
||||
|
||||
# File browser
|
||||
xfce.thunar
|
||||
xfce.thunar-volman
|
||||
xfce.tumbler # thumbnails
|
||||
];
|
||||
|
||||
# ============================================================================
|
||||
# WireGuard VPN profiles
|
||||
# ============================================================================
|
||||
# Generate keys: wg genkey | sudo tee /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
|
||||
# Then add the public key as a peer on the VPS.
|
||||
# Start/stop: sudo systemctl start/stop wg-quick-wg-services / wg-quick-wg-vpn
|
||||
|
||||
# Profile 1: Internal services only (split tunnel)
|
||||
networking.wg-quick.interfaces.wg-services = {
|
||||
autostart = false;
|
||||
address = [ "10.100.0.2/24" ];
|
||||
privateKeyFile = "/etc/wireguard/private.key";
|
||||
peers = [{
|
||||
publicKey = "F2hvz4vx9VrM6IZ2zMUG2FMPMCMwmfxGH9qocbe4q3U=";
|
||||
endpoint = "178.104.15.221:51820";
|
||||
allowedIPs = [ "10.100.0.0/24" "178.104.15.221/32" ];
|
||||
persistentKeepalive = 25;
|
||||
}];
|
||||
};
|
||||
|
||||
# Profile 2: Full VPN + AdGuard DNS ad-blocking
|
||||
networking.wg-quick.interfaces.wg-vpn = {
|
||||
autostart = false;
|
||||
address = [ "10.100.0.2/24" ];
|
||||
dns = [ "10.100.0.1" ];
|
||||
privateKeyFile = "/etc/wireguard/private.key";
|
||||
peers = [{
|
||||
publicKey = "F2hvz4vx9VrM6IZ2zMUG2FMPMCMwmfxGH9qocbe4q3U=";
|
||||
endpoint = "178.104.15.221:51820";
|
||||
allowedIPs = [ "0.0.0.0/0" ];
|
||||
persistentKeepalive = 25;
|
||||
}];
|
||||
};
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
420
flake.lock
generated
Executable file
420
flake.lock
generated
Executable file
|
|
@ -0,0 +1,420 @@
|
|||
{
|
||||
"nodes": {
|
||||
"base16": {
|
||||
"inputs": {
|
||||
"fromYaml": "fromYaml"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755819240,
|
||||
"narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=",
|
||||
"owner": "SenchoPens",
|
||||
"repo": "base16.nix",
|
||||
"rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "SenchoPens",
|
||||
"repo": "base16.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"base16-fish": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1765809053,
|
||||
"narHash": "sha256-XCUQLoLfBJ8saWms2HCIj4NEN+xNsWBlU1NrEPcQG4s=",
|
||||
"owner": "tomyun",
|
||||
"repo": "base16-fish",
|
||||
"rev": "86cbea4dca62e08fb7fd83a70e96472f92574782",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tomyun",
|
||||
"repo": "base16-fish",
|
||||
"rev": "86cbea4dca62e08fb7fd83a70e96472f92574782",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"base16-helix": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1760703920,
|
||||
"narHash": "sha256-m82fGUYns4uHd+ZTdoLX2vlHikzwzdu2s2rYM2bNwzw=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-helix",
|
||||
"rev": "d646af9b7d14bff08824538164af99d0c521b185",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-helix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"base16-vim": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1732806396,
|
||||
"narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-vim",
|
||||
"rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-vim",
|
||||
"rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773889306,
|
||||
"narHash": "sha256-PAqwnsBSI9SVC2QugvQ3xeYCB0otOwCacB1ueQj2tgw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "5ad85c82cc52264f4beddc934ba57f3789f28347",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"firefox-gnome-theme": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1764873433,
|
||||
"narHash": "sha256-1XPewtGMi+9wN9Ispoluxunw/RwozuTRVuuQOmxzt+A=",
|
||||
"owner": "rafaelmardojai",
|
||||
"repo": "firefox-gnome-theme",
|
||||
"rev": "f7ffd917ac0d253dbd6a3bf3da06888f57c69f92",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rafaelmardojai",
|
||||
"repo": "firefox-gnome-theme",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"stylix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767609335,
|
||||
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fromYaml": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1731966426,
|
||||
"narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=",
|
||||
"owner": "SenchoPens",
|
||||
"repo": "fromYaml",
|
||||
"rev": "106af9e2f715e2d828df706c386a685698f3223b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "SenchoPens",
|
||||
"repo": "fromYaml",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gnome-shell": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.gnome.org",
|
||||
"lastModified": 1767737596,
|
||||
"narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=",
|
||||
"owner": "GNOME",
|
||||
"repo": "gnome-shell",
|
||||
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.gnome.org",
|
||||
"owner": "GNOME",
|
||||
"ref": "gnome-49",
|
||||
"repo": "gnome-shell",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774738535,
|
||||
"narHash": "sha256-2jfBEZUC67IlnxO5KItFCAd7Oc+1TvyV/jQlR+2ykGQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "769e07ef8f4cf7b1ec3b96ef015abec9bc6b1e2a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1766517411,
|
||||
"narHash": "sha256-qilXvRpeyefgLRl1oyitQsacWGP5TrWf7f6V+KOUt38=",
|
||||
"owner": "GammaKinematics",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "b1dfc15a77366c8f163af12b8b3c5f4d4f56812c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "GammaKinematics",
|
||||
"repo": "nixos-hardware",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1774388614,
|
||||
"narHash": "sha256-tFwzTI0DdDzovdE9+Ras6CUss0yn8P9XV4Ja6RjA+nU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1073dad219cb244572b74da2b20c7fe39cb3fa9e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-25.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1774386573,
|
||||
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nur": {
|
||||
"inputs": {
|
||||
"flake-parts": [
|
||||
"stylix",
|
||||
"flake-parts"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"stylix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767810917,
|
||||
"narHash": "sha256-ZKqhk772+v/bujjhla9VABwcvz+hB2IaRyeLT6CFnT0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "dead29c804adc928d3a69dfe7f9f12d0eec1f1a4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"disko": "disko",
|
||||
"home-manager": "home-manager",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"stylix": "stylix",
|
||||
"zen-browser": "zen-browser"
|
||||
}
|
||||
},
|
||||
"stylix": {
|
||||
"inputs": {
|
||||
"base16": "base16",
|
||||
"base16-fish": "base16-fish",
|
||||
"base16-helix": "base16-helix",
|
||||
"base16-vim": "base16-vim",
|
||||
"firefox-gnome-theme": "firefox-gnome-theme",
|
||||
"flake-parts": "flake-parts",
|
||||
"gnome-shell": "gnome-shell",
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
],
|
||||
"nur": "nur",
|
||||
"systems": "systems",
|
||||
"tinted-foot": "tinted-foot",
|
||||
"tinted-kitty": "tinted-kitty",
|
||||
"tinted-schemes": "tinted-schemes",
|
||||
"tinted-tmux": "tinted-tmux",
|
||||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774124764,
|
||||
"narHash": "sha256-Poz9WTjiRlqZIf197CrMMJfTifZhrZpbHFv0eU1Nhtg=",
|
||||
"owner": "nix-community",
|
||||
"repo": "stylix",
|
||||
"rev": "e31c79f571c5595a155f84b9d77ce53a84745494",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "stylix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-foot": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1726913040,
|
||||
"narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-foot",
|
||||
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-foot",
|
||||
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-kitty": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1735730497,
|
||||
"narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-kitty",
|
||||
"rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-kitty",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-schemes": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767710407,
|
||||
"narHash": "sha256-+W1EB79Jl0/gm4JqmO0Nuc5C7hRdp4vfsV/VdzI+des=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "schemes",
|
||||
"rev": "2800e2b8ac90f678d7e4acebe4fa253f602e05b2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "schemes",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-tmux": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767489635,
|
||||
"narHash": "sha256-e6nnFnWXKBCJjCv4QG4bbcouJ6y3yeT70V9MofL32lU=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-tmux",
|
||||
"rev": "3c32729ccae99be44fe8a125d20be06f8d7d8184",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-tmux",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-zed": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767488740,
|
||||
"narHash": "sha256-wVOj0qyil8m+ouSsVZcNjl5ZR+1GdOOAooAatQXHbuU=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-zed",
|
||||
"rev": "11abb0b282ad3786a2aae088d3a01c60916f2e40",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-zed",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"zen-browser": {
|
||||
"inputs": {
|
||||
"home-manager": [
|
||||
"home-manager"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774708879,
|
||||
"narHash": "sha256-rTYvYkQL69/YkZB+MRA/IaX1qJ1lPx5KXoQS2/9+7Mw=",
|
||||
"owner": "0xc000022070",
|
||||
"repo": "zen-browser-flake",
|
||||
"rev": "d01d23c798cceef42307d5789bfbce70515e8800",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "0xc000022070",
|
||||
"repo": "zen-browser-flake",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
112
flake.nix
Executable file
112
flake.nix
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
description = "NixOS - AL";
|
||||
|
||||
inputs = {
|
||||
# Stable nixpkgs for core system (kernel, boot, virtualization)
|
||||
nixpkgs.url = "nixpkgs/nixos-25.11";
|
||||
|
||||
# Unstable nixpkgs for desktop/dev tools
|
||||
nixpkgs-unstable.url = "nixpkgs/nixos-unstable";
|
||||
|
||||
# Home Manager
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
|
||||
# Zen Browser
|
||||
zen-browser = {
|
||||
url = "github:0xc000022070/zen-browser-flake";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
inputs.home-manager.follows = "home-manager";
|
||||
};
|
||||
|
||||
# Hardware-specific optimizations (fork with Minisforum V3 SE support)
|
||||
nixos-hardware.url = "github:GammaKinematics/nixos-hardware";
|
||||
|
||||
# Stylix - system-wide theming
|
||||
stylix = {
|
||||
url = "github:nix-community/stylix";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
|
||||
# Disko - declarative disk partitioning (for VPS)
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
nixpkgs-unstable,
|
||||
home-manager,
|
||||
zen-browser,
|
||||
...
|
||||
}@inputs:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
|
||||
|
||||
# Stable pkgs for CAD/manufacturing (more reliable builds)
|
||||
pkgs-stable = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
|
||||
# Unstable pkgs for home-manager / desktop / dev
|
||||
pkgs-unstable = import nixpkgs-unstable {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
# ── Hetzner VPS ──
|
||||
nixosConfigurations.axiomania = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
inputs.disko.nixosModules.disko
|
||||
./Hetzner/axiomania.nix
|
||||
];
|
||||
};
|
||||
|
||||
# ── Hetzner ephemeral builder ──
|
||||
nixosConfigurations.builder = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
inputs.disko.nixosModules.disko
|
||||
./Hetzner/builder.nix
|
||||
];
|
||||
};
|
||||
|
||||
# ── Local: Minisforum V3 SE ──
|
||||
nixosConfigurations.v3 = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
specialArgs = { inherit inputs; };
|
||||
|
||||
modules = [
|
||||
inputs.stylix.nixosModules.stylix
|
||||
inputs.nixos-hardware.nixosModules.minisforum-v3-se
|
||||
|
||||
./configuration.nix
|
||||
|
||||
home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager = {
|
||||
useGlobalPkgs = false;
|
||||
useUserPackages = true;
|
||||
extraSpecialArgs = {
|
||||
inherit inputs pkgs-unstable pkgs-stable;
|
||||
};
|
||||
users.lebowski = import ./home.nix;
|
||||
backupFileExtension = "backup";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
68
git.nix
Normal file
68
git.nix
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{ pkgs-stable, ... }:
|
||||
|
||||
{
|
||||
# ============================================================================
|
||||
# Git Configuration
|
||||
# ============================================================================
|
||||
programs.git = {
|
||||
enable = true;
|
||||
package = pkgs-stable.git;
|
||||
|
||||
settings = {
|
||||
user.name = "GammaKinematics";
|
||||
user.email = "gamma.kinematics@gmail.com";
|
||||
init.defaultBranch = "main";
|
||||
pull.rebase = true;
|
||||
push.autoSetupRemote = true;
|
||||
# Use SSH for GitHub
|
||||
url."ssh://git@github.com/".insteadOf = "https://github.com/";
|
||||
};
|
||||
|
||||
# Delta - better diff viewer
|
||||
# delta = {
|
||||
# enable = true;
|
||||
# options = {
|
||||
# navigate = true;
|
||||
# light = false;
|
||||
# line-numbers = true;
|
||||
# };
|
||||
# };
|
||||
|
||||
# Aliases
|
||||
# aliases = {
|
||||
# co = "checkout";
|
||||
# br = "branch";
|
||||
# ci = "commit";
|
||||
# st = "status";
|
||||
# lg = "log --oneline --graph --decorate";
|
||||
# };
|
||||
|
||||
# SSH signing (for verified commits)
|
||||
# signing = {
|
||||
# key = "~/.ssh/id_ed25519.pub";
|
||||
# signByDefault = true;
|
||||
# };
|
||||
# extraConfig.gpg.format = "ssh";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# SSH Configuration
|
||||
# ============================================================================
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
"github.com" = {
|
||||
host = "github.com";
|
||||
identityFile = "~/.ssh/id_ed25519";
|
||||
identitiesOnly = true;
|
||||
};
|
||||
# Add more hosts as needed
|
||||
# "gitlab.com" = {
|
||||
# host = "gitlab.com";
|
||||
# identityFile = "~/.ssh/id_ed25519";
|
||||
# identitiesOnly = true;
|
||||
# };
|
||||
};
|
||||
};
|
||||
}
|
||||
73
hardware-configuration.nix
Executable file
73
hardware-configuration.nix
Executable file
|
|
@ -0,0 +1,73 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"nvme"
|
||||
"xhci_pci"
|
||||
"thunderbolt"
|
||||
"usb_storage"
|
||||
"usbhid"
|
||||
"uas"
|
||||
"sd_mod"
|
||||
"rtsx_pci_sdmmc"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/ea496278-ae69-48b0-9edb-b351b9620829";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/C267-DCFD";
|
||||
fsType = "vfat";
|
||||
options = [
|
||||
"fmask=0077"
|
||||
"dmask=0077"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/data" = {
|
||||
device = "/dev/disk/by-label/DATA";
|
||||
fsType = "ntfs";
|
||||
options = [
|
||||
"rw"
|
||||
"uid=1000"
|
||||
"gid=100"
|
||||
"umask=022"
|
||||
"nofail"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/data-bis" = {
|
||||
device = "/dev/disk/by-label/DATA-bis";
|
||||
fsType = "ntfs";
|
||||
options = [
|
||||
"rw"
|
||||
"uid=1000"
|
||||
"gid=100"
|
||||
"umask=022"
|
||||
"nofail"
|
||||
];
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
141
home.nix
Normal file
141
home.nix
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
{
|
||||
config,
|
||||
pkgs-unstable,
|
||||
pkgs-stable,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
flakeDir = "${config.home.homeDirectory}/NixOS";
|
||||
in
|
||||
|
||||
{
|
||||
# Fix home-manager xresources bug: pkgs.xrdb doesn't exist, should be xorg.xrdb
|
||||
nixpkgs.overlays = [ (final: prev: { xrdb = prev.xorg.xrdb; }) ];
|
||||
|
||||
# Disable xresources - Stylix enables it by default but we don't need it (ST uses compile-time colors)
|
||||
stylix.targets.xresources.enable = false;
|
||||
|
||||
imports = [
|
||||
./git.nix
|
||||
./zed.nix
|
||||
./zen.nix
|
||||
./Rofi/rofi.nix
|
||||
./KiCad/kicad.nix
|
||||
|
||||
# ./Hyprsuck/home.nix
|
||||
./Suckless/home.nix # Uncomment for dwm (and comment Hyprsuck)
|
||||
];
|
||||
|
||||
home.username = "lebowski";
|
||||
home.homeDirectory = "/home/lebowski";
|
||||
|
||||
# Let Home Manager manage itself
|
||||
programs.home-manager.enable = true;
|
||||
|
||||
# ============================================================================
|
||||
# User Packages (stable by default, unstable for bleeding-edge tools)
|
||||
# ============================================================================
|
||||
home.packages = with pkgs-stable; [
|
||||
# Media & Creative
|
||||
haruna
|
||||
krita
|
||||
xournalpp
|
||||
|
||||
# Office & Productivity
|
||||
libreoffice-fresh
|
||||
|
||||
# CAD & Manufacturing
|
||||
freecad
|
||||
bambu-studio
|
||||
|
||||
# Dev tools (unstable for latest features)
|
||||
pkgs-unstable.claude-code
|
||||
pkgs-unstable.hcloud
|
||||
];
|
||||
|
||||
# ============================================================================
|
||||
# GTK Icon Theme
|
||||
# ============================================================================
|
||||
gtk.iconTheme = {
|
||||
package = pkgs-stable.papirus-icon-theme;
|
||||
name = "Papirus-Dark";
|
||||
};
|
||||
gtk.gtk4.theme = null;
|
||||
|
||||
# ============================================================================
|
||||
# Notifications (shared between Hyprland and dwm)
|
||||
# ============================================================================
|
||||
services.dunst = {
|
||||
enable = true;
|
||||
package = pkgs-stable.dunst;
|
||||
settings.global.timeout = 3;
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Shell Aliases
|
||||
# ============================================================================
|
||||
home.shellAliases = {
|
||||
# NixOS rebuild shortcuts
|
||||
nrs = "sudo nixos-rebuild switch --flake ${flakeDir}";
|
||||
nrb = "sudo nixos-rebuild boot --flake ${flakeDir}";
|
||||
nrt = "sudo nixos-rebuild test --flake ${flakeDir}";
|
||||
|
||||
# Nix utilities
|
||||
nfu = "nix flake update --flake ${flakeDir}";
|
||||
ncg = "sudo nix-collect-garbage -d";
|
||||
nso = "nix store optimise";
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Optional: Additional program configurations
|
||||
# ============================================================================
|
||||
|
||||
# --- Bash shell ---
|
||||
programs.bash = {
|
||||
enable = true;
|
||||
package = pkgs-stable.bash;
|
||||
};
|
||||
|
||||
# --- KeePassXC ---
|
||||
programs.keepassxc = {
|
||||
enable = true;
|
||||
package = pkgs-stable.keepassxc;
|
||||
};
|
||||
|
||||
programs.foliate = {
|
||||
enable = true;
|
||||
package = pkgs-stable.foliate;
|
||||
};
|
||||
|
||||
# --- SSH ---
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
package = pkgs-stable.openssh;
|
||||
|
||||
matchBlocks = {
|
||||
"*" = {
|
||||
addKeysToAgent = "yes";
|
||||
serverAliveInterval = 60;
|
||||
controlMaster = "auto";
|
||||
controlPersist = "10m";
|
||||
};
|
||||
"git.axiomania.org" = {
|
||||
port = 2222;
|
||||
};
|
||||
"vps" = {
|
||||
hostname = "178.104.15.221";
|
||||
user = "root";
|
||||
identityFile = "~/.ssh/id_ed25519";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# Disable version check - we intentionally use unstable home-manager with stable nixpkgs
|
||||
# Note: This may cause issues if home-manager uses features not yet in stable
|
||||
home.enableNixpkgsReleaseCheck = false;
|
||||
|
||||
home.stateVersion = "25.11";
|
||||
}
|
||||
181
ryzenadj.nix
Normal file
181
ryzenadj.nix
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# RyzenAdj power tuning configuration
|
||||
# Provides power-tuning script for Minisforum V3 SE power profile management
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
# Power profiles (values in mW for power, °C for temp)
|
||||
profiles = {
|
||||
saver = {
|
||||
stapm = 15000;
|
||||
fast = 18000;
|
||||
slow = 16000;
|
||||
temp = 80;
|
||||
};
|
||||
balanced = {
|
||||
stapm = 22500;
|
||||
fast = 30000;
|
||||
slow = 25000;
|
||||
temp = 90;
|
||||
};
|
||||
performance = {
|
||||
stapm = 30000;
|
||||
fast = 40000;
|
||||
slow = 35000;
|
||||
temp = 100;
|
||||
};
|
||||
compile = {
|
||||
stapm = 40000;
|
||||
fast = 50000;
|
||||
slow = 45000;
|
||||
temp = 100;
|
||||
};
|
||||
};
|
||||
|
||||
configFile = pkgs.writeText "power-tuning-config.json" (builtins.toJSON profiles);
|
||||
|
||||
power-tuning = pkgs.writeShellScriptBin "power-tuning" ''
|
||||
CONFIG_FILE="${configFile}"
|
||||
COMPILE_FLAG="/tmp/.power-tuning-compile-mode"
|
||||
|
||||
# Read a profile from config
|
||||
get_profile() {
|
||||
local profile="$1"
|
||||
${pkgs.jq}/bin/jq -r ".$profile" "$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Apply ryzenadj settings
|
||||
apply_settings() {
|
||||
local profile="$1"
|
||||
local settings
|
||||
settings=$(get_profile "$profile")
|
||||
|
||||
if [[ "$settings" == "null" ]]; then
|
||||
echo "Error: Profile '$profile' not found in config"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local stapm fast slow temp
|
||||
stapm=$(echo "$settings" | ${pkgs.jq}/bin/jq -r '.stapm')
|
||||
fast=$(echo "$settings" | ${pkgs.jq}/bin/jq -r '.fast')
|
||||
slow=$(echo "$settings" | ${pkgs.jq}/bin/jq -r '.slow')
|
||||
temp=$(echo "$settings" | ${pkgs.jq}/bin/jq -r '.temp')
|
||||
|
||||
echo "Applying $profile: STAPM=''${stapm}mW Fast=''${fast}mW Slow=''${slow}mW Temp=''${temp}°C"
|
||||
|
||||
${pkgs.ryzenadj}/bin/ryzenadj \
|
||||
--stapm-limit="$stapm" \
|
||||
--fast-limit="$fast" \
|
||||
--slow-limit="$slow" \
|
||||
--tctl-temp="$temp" \
|
||||
2>&1
|
||||
}
|
||||
|
||||
# Get current power profile from power-profiles-daemon
|
||||
get_current_ppd_profile() {
|
||||
local profile
|
||||
profile=$(${pkgs.power-profiles-daemon}/bin/powerprofilesctl get 2>/dev/null)
|
||||
|
||||
case "$profile" in
|
||||
"power-saver") echo "saver" ;;
|
||||
"balanced") echo "balanced" ;;
|
||||
"performance") echo "performance" ;;
|
||||
*) echo "balanced" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check if compile mode is active
|
||||
is_compile_mode() {
|
||||
[[ -f "$COMPILE_FLAG" ]]
|
||||
}
|
||||
|
||||
# Main command handling
|
||||
case "''${1:-apply}" in
|
||||
apply)
|
||||
if is_compile_mode; then
|
||||
echo "Compile mode active, using compile profile"
|
||||
apply_settings "compile"
|
||||
else
|
||||
profile=$(get_current_ppd_profile)
|
||||
echo "Current PPD profile: $profile"
|
||||
apply_settings "$profile"
|
||||
fi
|
||||
;;
|
||||
|
||||
compile-on)
|
||||
touch "$COMPILE_FLAG"
|
||||
echo "Compile mode enabled"
|
||||
apply_settings "compile"
|
||||
;;
|
||||
|
||||
compile-off)
|
||||
rm -f "$COMPILE_FLAG"
|
||||
echo "Compile mode disabled"
|
||||
profile=$(get_current_ppd_profile)
|
||||
apply_settings "$profile"
|
||||
;;
|
||||
|
||||
status)
|
||||
echo "=== Power Tuning Status ==="
|
||||
echo "Config file: $CONFIG_FILE"
|
||||
echo "PPD Profile: $(${pkgs.power-profiles-daemon}/bin/powerprofilesctl get 2>/dev/null || echo 'unknown')"
|
||||
echo "Compile mode: $(is_compile_mode && echo 'ON' || echo 'OFF')"
|
||||
echo ""
|
||||
echo "Current presets:"
|
||||
${pkgs.jq}/bin/jq '.' "$CONFIG_FILE"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: power-tuning {apply|compile-on|compile-off|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
'';
|
||||
in
|
||||
{
|
||||
# Kernel module for SMU access
|
||||
hardware.cpu.amd.ryzen-smu.enable = true;
|
||||
|
||||
# Permissions for ryzenadj to access SMU
|
||||
systemd.tmpfiles.rules = [
|
||||
"z /sys/kernel/ryzen_smu_drv/smn 0660 root wheel -"
|
||||
"z /sys/kernel/ryzen_smu_drv/smu_args 0660 root wheel -"
|
||||
"z /sys/kernel/ryzen_smu_drv/mp1_smu_cmd 0660 root wheel -"
|
||||
"z /sys/kernel/ryzen_smu_drv/rsmu_cmd 0660 root wheel -"
|
||||
];
|
||||
|
||||
environment.systemPackages = [
|
||||
power-tuning
|
||||
pkgs.ryzenadj
|
||||
];
|
||||
|
||||
# Apply power tuning on boot and when power profile changes
|
||||
systemd.services.power-tuning = {
|
||||
description = "Apply RyzenAdj power tuning";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "power-profiles-daemon.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${power-tuning}/bin/power-tuning apply";
|
||||
};
|
||||
};
|
||||
|
||||
# Re-apply when power profile changes
|
||||
systemd.services.power-tuning-on-profile-change = {
|
||||
description = "Apply RyzenAdj on power profile change";
|
||||
after = [ "power-profiles-daemon.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${power-tuning}/bin/power-tuning apply";
|
||||
};
|
||||
};
|
||||
|
||||
# Path trigger to watch for profile changes
|
||||
systemd.paths.power-tuning-watch = {
|
||||
description = "Watch for power profile changes";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig = {
|
||||
PathChanged = "/sys/firmware/acpi/platform_profile";
|
||||
Unit = "power-tuning-on-profile-change.service";
|
||||
};
|
||||
};
|
||||
}
|
||||
53
stylix.nix
Normal file
53
stylix.nix
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
stylix = {
|
||||
enable = true;
|
||||
enableReleaseChecks = false;
|
||||
|
||||
polarity = "dark";
|
||||
|
||||
# Catppuccin Mocha theme
|
||||
base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml";
|
||||
|
||||
# Wallpaper (used for color scheme generation)
|
||||
image = ./Wallpapers/siege.png;
|
||||
|
||||
# Cursor
|
||||
cursor = {
|
||||
package = pkgs.bibata-cursors;
|
||||
name = "Bibata-Modern-Ice";
|
||||
size = 20;
|
||||
};
|
||||
|
||||
# Fonts
|
||||
fonts = {
|
||||
monospace = {
|
||||
package = pkgs.nerd-fonts.jetbrains-mono;
|
||||
name = "JetBrainsMono Nerd Font";
|
||||
};
|
||||
sansSerif = {
|
||||
package = pkgs.dejavu_fonts;
|
||||
name = "DejaVu Sans";
|
||||
};
|
||||
serif = {
|
||||
package = pkgs.dejavu_fonts;
|
||||
name = "DejaVu Serif";
|
||||
};
|
||||
emoji = {
|
||||
package = pkgs.noto-fonts-color-emoji;
|
||||
name = "Noto Color Emoji";
|
||||
};
|
||||
sizes = {
|
||||
terminal = 11;
|
||||
applications = 11;
|
||||
desktop = 11;
|
||||
};
|
||||
};
|
||||
|
||||
# Opacity settings
|
||||
opacity = {
|
||||
terminal = 0.9;
|
||||
};
|
||||
};
|
||||
}
|
||||
19
virtualisation.nix
Normal file
19
virtualisation.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Libvirt/QEMU virtualisation
|
||||
programs.virt-manager.enable = true;
|
||||
users.groups.libvirtd.members = [ "lebowski" ];
|
||||
virtualisation.libvirtd.enable = true;
|
||||
virtualisation.spiceUSBRedirection.enable = true;
|
||||
|
||||
# Docker
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
# Use the rootless mode - run Docker daemon as non-root user
|
||||
rootless = {
|
||||
enable = true;
|
||||
setSocketVariable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
73
zed.nix
Normal file
73
zed.nix
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Zed Editor configuration
|
||||
{ pkgs-unstable, ... }:
|
||||
|
||||
{
|
||||
|
||||
programs.zed-editor = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.zed-editor;
|
||||
|
||||
# This populates the userSettings "auto_install_extensions"
|
||||
extensions = [
|
||||
"nix"
|
||||
"odin"
|
||||
"astro"
|
||||
"slint"
|
||||
"dockerfile"
|
||||
"docker-compose"
|
||||
"latex"
|
||||
"make"
|
||||
"log"
|
||||
"csv"
|
||||
];
|
||||
|
||||
# Everything inside of these brackets are Zed options
|
||||
userSettings = {
|
||||
# Disable all AI features (including Claude Code ACP agents)
|
||||
disable_ai = true;
|
||||
|
||||
# Disable collaboration/AI features
|
||||
assistant = { enabled = false; };
|
||||
collaboration_panel = { button = false; };
|
||||
chat_panel = { button = false; };
|
||||
notification_panel = { button = false; };
|
||||
title_bar = { show_sign_in = false; };
|
||||
|
||||
# Hide UI panels
|
||||
diagnostics = { button = false; };
|
||||
debugger = { button = false; };
|
||||
|
||||
# Disable edit predictions completely
|
||||
features = { edit_prediction_provider = "none"; };
|
||||
show_edit_predictions = false;
|
||||
|
||||
hour_format = "hour24";
|
||||
auto_update = false;
|
||||
|
||||
terminal = {
|
||||
alternate_scroll = "off";
|
||||
blinking = "off";
|
||||
copy_on_select = true;
|
||||
dock = "right";
|
||||
line_height = "comfortable";
|
||||
shell = "system";
|
||||
toolbar = {
|
||||
title = true; # Shows terminal title (e.g. "zsh" or running command) in panel header
|
||||
};
|
||||
working_directory = "current_project_directory";
|
||||
};
|
||||
|
||||
vim_mode = false;
|
||||
|
||||
base_keymap = "VSCode";
|
||||
|
||||
show_whitespaces = "selection";
|
||||
|
||||
# Disable all language servers globally
|
||||
enable_language_server = false;
|
||||
|
||||
# Disable Claude Code integration (prevents auto-launching claude-code-acp)
|
||||
context_servers = { };
|
||||
};
|
||||
};
|
||||
}
|
||||
322
zen.nix
Normal file
322
zen.nix
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
{ config, lib, pkgs-unstable, inputs, ... }:
|
||||
|
||||
{
|
||||
# Workaround for https://github.com/0xc000022070/zen-browser-flake/issues/285
|
||||
# The twilight module generates profiles.ini as a read-only nix store symlink,
|
||||
# which Zen can't write to, so it ignores it and creates a random-prefix profile.
|
||||
# This replaces the symlink with a mutable copy.
|
||||
home.activation.fixZenProfiles = lib.hm.dag.entryAfter ["linkGeneration"] ''
|
||||
ZEN_DIR="$HOME/.zen"
|
||||
if [ -L "$ZEN_DIR/profiles.ini" ]; then
|
||||
REAL=$(readlink -f "$ZEN_DIR/profiles.ini")
|
||||
rm "$ZEN_DIR/profiles.ini"
|
||||
cp "$REAL" "$ZEN_DIR/profiles.ini"
|
||||
chmod u+w "$ZEN_DIR/profiles.ini"
|
||||
fi
|
||||
'';
|
||||
# Tell Stylix which Zen profiles to theme
|
||||
stylix.targets.zen-browser.profileNames = [ "default" ];
|
||||
|
||||
imports = [
|
||||
inputs.zen-browser.homeModules.twilight
|
||||
];
|
||||
|
||||
# Set Zen as default browser for all relevant MIME types
|
||||
xdg.mimeApps = let
|
||||
associations = builtins.listToAttrs (map (name: {
|
||||
inherit name;
|
||||
value = let
|
||||
zen-browser = config.programs.zen-browser.package;
|
||||
in
|
||||
zen-browser.meta.desktopFileName;
|
||||
}) [
|
||||
"application/x-extension-shtml"
|
||||
"application/x-extension-xhtml"
|
||||
"application/x-extension-html"
|
||||
"application/x-extension-xht"
|
||||
"application/x-extension-htm"
|
||||
"x-scheme-handler/unknown"
|
||||
"x-scheme-handler/mailto"
|
||||
"x-scheme-handler/chrome"
|
||||
"x-scheme-handler/about"
|
||||
"x-scheme-handler/https"
|
||||
"x-scheme-handler/http"
|
||||
"application/xhtml+xml"
|
||||
"application/json"
|
||||
"text/plain"
|
||||
"text/html"
|
||||
]);
|
||||
in {
|
||||
associations.added = associations;
|
||||
defaultApplications = associations;
|
||||
};
|
||||
|
||||
programs.zen-browser = {
|
||||
enable = true;
|
||||
|
||||
# Native Messaging Hosts - required for KeePassXC browser integration
|
||||
nativeMessagingHosts = [ pkgs-unstable.keepassxc ];
|
||||
|
||||
policies = let
|
||||
# Helper to lock preferences
|
||||
mkLockedAttrs = builtins.mapAttrs (_: value: {
|
||||
Value = value;
|
||||
Status = "locked";
|
||||
});
|
||||
|
||||
# Helper to create extension install URL
|
||||
mkPluginUrl = id: "https://addons.mozilla.org/firefox/downloads/latest/${id}/latest.xpi";
|
||||
|
||||
# Helper to create extension entry with options
|
||||
mkExtensionEntry = {
|
||||
id,
|
||||
pinned ? false,
|
||||
private_browsing ? true,
|
||||
}: let
|
||||
base = {
|
||||
install_url = mkPluginUrl id;
|
||||
installation_mode = "force_installed";
|
||||
inherit private_browsing;
|
||||
};
|
||||
in
|
||||
if pinned
|
||||
then base // { default_area = "navbar"; }
|
||||
else base;
|
||||
|
||||
# Helper to process extension settings
|
||||
mkExtensionSettings = builtins.mapAttrs (_: entry:
|
||||
if builtins.isAttrs entry
|
||||
then entry
|
||||
else mkExtensionEntry { id = entry; });
|
||||
in {
|
||||
# App behavior
|
||||
DisableAppUpdate = true;
|
||||
DontCheckDefaultBrowser = true;
|
||||
DisableFeedbackCommands = true;
|
||||
|
||||
# Privacy & Telemetry
|
||||
DisableTelemetry = true;
|
||||
DisableFirefoxStudies = true;
|
||||
DisablePocket = true;
|
||||
|
||||
# Autofill
|
||||
AutofillAddressEnabled = true;
|
||||
AutofillCreditCardEnabled = false;
|
||||
OfferToSaveLogins = false;
|
||||
|
||||
# Tracking Protection
|
||||
EnableTrackingProtection = {
|
||||
Value = true;
|
||||
Locked = true;
|
||||
Cryptomining = true;
|
||||
Fingerprinting = true;
|
||||
};
|
||||
|
||||
# Clean up on shutdown (fresh instance)
|
||||
SanitizeOnShutdown = {
|
||||
Cache = true;
|
||||
Cookies = false; # Keep logins
|
||||
Downloads = true;
|
||||
FormData = true;
|
||||
History = false; # Keep history
|
||||
Sessions = false; # Keep tabs on restart
|
||||
SiteSettings = false;
|
||||
OfflineApps = true;
|
||||
Locked = true;
|
||||
};
|
||||
|
||||
# Extensions
|
||||
ExtensionSettings = mkExtensionSettings {
|
||||
# uBlock Origin - ad blocker (pinned to navbar)
|
||||
"uBlock0@raymondhill.net" = mkExtensionEntry {
|
||||
id = "ublock-origin";
|
||||
pinned = true;
|
||||
private_browsing = true;
|
||||
};
|
||||
# KeePassXC - password manager (pinned to navbar)
|
||||
"keepassxc-browser@keepassxc.org" = mkExtensionEntry {
|
||||
id = "keepassxc-browser";
|
||||
pinned = true;
|
||||
private_browsing = true;
|
||||
};
|
||||
|
||||
# --- Privacy & Security ---
|
||||
"{74145f27-f039-47ce-a470-a662b129930a}" = "clearurls"; # Remove tracking from URLs
|
||||
"jid1-BoFifL9Vbdl2zQ@jetpack" = "decentraleyes"; # Local CDN emulation
|
||||
"{3579f63b-d8ee-424f-bbb6-6d0ce3285e6a}" = "chameleon-ext"; # Spoof browser profile
|
||||
|
||||
# --- GitHub ---
|
||||
"{a4c4eda4-fb84-4a84-b4a1-f7c1cbf2a1ad}" = "refined-github-"; # GitHub enhancements
|
||||
"{85860b32-02a8-431a-b2b1-40fbd64c9c69}" = "github-file-icons"; # File icons in GitHub
|
||||
"github-repository-size@pranavmangal" = "gh-repo-size"; # Show repo size
|
||||
|
||||
# --- YouTube ---
|
||||
"{762f9885-5a13-4abd-9c77-433dcd38b8fd}" = "return-youtube-dislikes";
|
||||
};
|
||||
|
||||
# Locked preferences
|
||||
Preferences = mkLockedAttrs {
|
||||
"browser.aboutConfig.showWarning" = false;
|
||||
"browser.tabs.warnOnClose" = false;
|
||||
"media.videocontrols.picture-in-picture.video-toggle.enabled" = true;
|
||||
|
||||
# Translation (auto-translate all languages except en/fr)
|
||||
"browser.translations.enable" = true;
|
||||
"browser.translations.panelShown" = true;
|
||||
"browser.translations.automaticallyPopup" = true;
|
||||
"browser.translations.alwaysTranslateLanguages" = "ar,bg,cs,da,de,el,es,et,fi,hu,id,it,ja,ko,lt,lv,nl,no,pl,pt,ro,ru,sk,sl,sv,th,tr,uk,vi,zh";
|
||||
"browser.translations.neverTranslateLanguages" = "en,fr";
|
||||
|
||||
# Privacy (balanced - removed slow options)
|
||||
"privacy.spoof_english" = 1;
|
||||
"network.cookie.cookieBehavior" = 5;
|
||||
"dom.battery.enabled" = false;
|
||||
|
||||
# Performance & Speed
|
||||
"gfx.webrender.all" = true;
|
||||
"layers.acceleration.force-enabled" = true;
|
||||
"network.http.http3.enabled" = true;
|
||||
"network.dns.disablePrefetch" = false;
|
||||
"network.prefetch-next" = true;
|
||||
"browser.sessionstore.interval" = 60000; # Less frequent session saves (60s)
|
||||
"browser.cache.memory.enable" = true;
|
||||
"browser.cache.memory.capacity" = 524288; # 512MB memory cache
|
||||
"content.notify.interval" = 100000;
|
||||
"ui.submenuDelay" = 0; # Instant submenus
|
||||
|
||||
# Disable animations for snappiness
|
||||
"toolkit.cosmeticAnimations.enabled" = false;
|
||||
"browser.fullscreen.animate" = false;
|
||||
};
|
||||
};
|
||||
|
||||
profiles.default = {
|
||||
# Zen-specific settings
|
||||
settings = {
|
||||
"zen.workspaces.continue-where-left-off" = true; # Restore tabs
|
||||
"zen.workspaces.natural-scroll" = true;
|
||||
"zen.view.compact.hide-tabbar" = true;
|
||||
"zen.view.compact.hide-toolbar" = true;
|
||||
"zen.view.compact.animate-sidebar" = false;
|
||||
"zen.welcome-screen.seen" = true;
|
||||
"zen.urlbar.behavior" = "float";
|
||||
|
||||
# Restore previous session
|
||||
"browser.startup.page" = 3; # Restore previous session
|
||||
"browser.sessionstore.resume_from_crash" = true;
|
||||
};
|
||||
|
||||
# --- Bookmarks ---
|
||||
bookmarks = {
|
||||
force = true;
|
||||
settings = [
|
||||
{
|
||||
name = "Dev";
|
||||
toolbar = true;
|
||||
bookmarks = [
|
||||
{ name = "GitHub"; url = "https://github.com"; }
|
||||
{ name = "NixOS Wiki"; url = "https://wiki.nixos.org/"; }
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# --- Containers ---
|
||||
# containersForce = true;
|
||||
# containers = {
|
||||
# Personal = { color = "blue"; icon = "fingerprint"; id = 1; };
|
||||
# Work = { color = "orange"; icon = "briefcase"; id = 2; };
|
||||
# Shopping = { color = "yellow"; icon = "dollar"; id = 3; };
|
||||
# Banking = { color = "green"; icon = "dollar"; id = 4; };
|
||||
# };
|
||||
|
||||
# --- Workspaces/Spaces ---
|
||||
# spacesForce = true;
|
||||
# spaces = {
|
||||
# "Default" = {
|
||||
# id = "generate-your-own-uuid"; # Use: uuidgen
|
||||
# icon = "🏠";
|
||||
# position = 1000;
|
||||
# };
|
||||
# "Work" = {
|
||||
# id = "generate-your-own-uuid";
|
||||
# icon = "💼";
|
||||
# position = 1001;
|
||||
# # container = containers."Work".id; # Link to container
|
||||
# theme = {
|
||||
# type = "gradient";
|
||||
# colors = [
|
||||
# {
|
||||
# red = 100;
|
||||
# green = 150;
|
||||
# blue = 200;
|
||||
# algorithm = "floating";
|
||||
# type = "explicit-lightness";
|
||||
# }
|
||||
# ];
|
||||
# opacity = 0.5;
|
||||
# texture = 0.3;
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
|
||||
# --- Pinned tabs ---
|
||||
# pinsForce = true;
|
||||
# pins = {
|
||||
# "GitHub" = {
|
||||
# id = "generate-your-own-uuid";
|
||||
# # workspace = spaces."Work".id;
|
||||
# url = "https://github.com";
|
||||
# position = 100;
|
||||
# isEssential = false;
|
||||
# };
|
||||
# };
|
||||
|
||||
# --- Search engines ---
|
||||
search = {
|
||||
force = true;
|
||||
default = "google";
|
||||
engines = let
|
||||
nixIcon = "${pkgs-unstable.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
|
||||
in {
|
||||
"Nix Packages" = {
|
||||
urls = [{
|
||||
template = "https://search.nixos.org/packages";
|
||||
params = [
|
||||
{ name = "type"; value = "packages"; }
|
||||
{ name = "channel"; value = "unstable"; }
|
||||
{ name = "query"; value = "{searchTerms}"; }
|
||||
];
|
||||
}];
|
||||
icon = nixIcon;
|
||||
definedAliases = [ "np" ];
|
||||
};
|
||||
"Nix Options" = {
|
||||
urls = [{
|
||||
template = "https://search.nixos.org/options";
|
||||
params = [
|
||||
{ name = "channel"; value = "unstable"; }
|
||||
{ name = "query"; value = "{searchTerms}"; }
|
||||
];
|
||||
}];
|
||||
icon = nixIcon;
|
||||
definedAliases = [ "no" ];
|
||||
};
|
||||
"Home Manager Options" = {
|
||||
urls = [{
|
||||
template = "https://home-manager-options.extranix.com/";
|
||||
params = [
|
||||
{ name = "query"; value = "{searchTerms}"; }
|
||||
{ name = "release"; value = "master"; }
|
||||
];
|
||||
}];
|
||||
icon = nixIcon;
|
||||
definedAliases = [ "hm" ];
|
||||
};
|
||||
# Hide unwanted default engines
|
||||
"bing".metaData.hidden = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue