Compare commits

..
58 Commits
Author SHA1 Message Date
mathias2784 0d61477072 include kitty noctalia theme 2026-10-31 10:31:07 +01:00
mathias2784 4846325583 hyprpm and binds for hyprtasking 2026-10-28 22:38:31 +01:00
mathias2784 1d654cf470 hyprmod shortcut description 2026-10-28 21:22:27 +01:00
mathias2784 e9ad0175a1 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-10-21 08:45:21 +02:00
mathias2784 093cd97a96 ktouch has floating window 2026-10-21 08:44:43 +02:00
Mathias Schneider f9a44ac5aa some config tweaks 2026-10-19 08:17:24 +02:00
mathias2784 7302e87fa3 noctalia config 2026-10-15 11:28:18 +01:00
mathias2784 4434feed16 skripte 2026-10-15 10:24:18 +01:00
mathias2784 94fa42672c noctalia: start menu command fix 2026-10-15 10:48:11 +02:00
mathias2784 3c1b727a7e caelestia: show weather 2026-10-14 20:43:17 +02:00
mathias2784 c7bf98775b rusr bin on path 2026-10-13 21:22:04 +01:00
mathias2784 590e568061 bitwarden floating 2026-10-13 21:21:36 +01:00
mathias2784 0e7f76200c window rule for keybinds window 2026-10-12 21:11:47 +01:00
mathias2784 30cab18e60 some more hyprland tweaks 2026-10-12 15:15:02 +01:00
mathias2784 e5dd0039a2 yazi tweaks 2026-10-12 11:42:43 +01:00
mathias2784 00e4931d29 some tweaks 2026-10-12 11:40:05 +01:00
mathias2784 e5ce0d0957 remove custom screensavers (let shells handle it) 2026-10-11 22:37:45 +01:00
mathias2784 540baacb15 new and better keybinds window 2026-10-11 22:21:24 +01:00
mathias2784 99b0075ada define floating windows 2026-10-11 22:00:09 +01:00
mathias2784 049e9a9f5e some package fix 2026-10-11 11:52:26 +01:00
mathias2784 1d2878ad81 some package reorganization 2026-10-11 11:28:22 +01:00
mathias2784 60db3ba63c new term packages 2026-10-05 20:59:10 +02:00
mathias2784 51b2cdb6a8 utils setup: add 'code' 2026-09-28 06:39:46 +02:00
mathias2784 b8f3861901 setup/README.md 2026-09-27 21:45:02 +02:00
mathias2784 a2efd03c15 setup: nfs-utils 2026-09-27 21:44:21 +02:00
mathias2784 ad61c53bfc hypr: include hyprmod default artifact, incl. existe guard 2026-09-27 15:25:57 +02:00
mathias2784 a316ad7221 gitignore hyprmod artifacts 2026-09-27 15:21:54 +02:00
mathias2784 e73f49282c hypr: fix noctalia idle 2026-09-27 08:26:15 +02:00
mathias2784 3c0fc3ae6b nvim: auto-closing html tags 2026-09-27 07:33:01 +02:00
mathias2784 dc1a319165 no nextcloud setup during make 2026-09-26 21:54:01 +02:00
mathias2784 1f0bde731e term: some more packages 2026-09-25 22:41:23 +02:00
mathias2784 6208eea2f8 hypr: no hypridle in caelestia 2026-09-25 20:11:03 +02:00
mathias2784 5bc878492e make setup hierarchy changes 2026-09-25 18:26:44 +02:00
mathias2784 73d1297c79 hypr: bugfix in loading envs 2026-09-25 16:26:39 +02:00
mathias2784 10c23c4d24 better env management 2026-09-25 15:57:38 +02:00
mathias2784 77f70e318c hypr fix setup issues 2026-09-25 14:26:30 +02:00
mathias2784 8ec820976f hypr env 2026-09-25 12:02:00 +02:00
mathias2784 6924c1e05e merge hypr-caelestia with conflict resolution 2026-09-25 11:57:58 +02:00
mathias2784 6cd9427b40 noctalia depend on env variable 2026-09-25 11:47:31 +02:00
mathias2784 050efc2b71 hypr setup: install quickshell standalone 2026-09-25 11:44:47 +02:00
mathias2784 8d81e802df Merge branch 'main' into hypr-caelestia 2026-09-24 22:55:09 +02:00
mathias2784 a0e6ad88d1 less transparancy 2026-09-24 22:54:55 +02:00
mathias2784 71cedb7454 starship theme from noctalia 2026-09-24 22:52:44 +02:00
mathias2784 53b763ee4d delete obsolete ensure-env script 2026-09-24 22:51:26 +02:00
mathias2784 5438f786a9 keybind for direct tmux 2026-09-24 20:32:55 +02:00
mathias2784 e80ccf74bb track noctalia 2026-09-24 20:32:19 +02:00
mathias2784 4b9b926c60 fish shortcuts for fd and rg 2026-09-24 17:43:08 +02:00
mathias2784 e499e63a49 screensaver text 2026-09-23 23:41:59 +02:00
mathias2784 df5abce062 merge main incl conflict resolution 2026-09-23 23:36:48 +02:00
mathias2784 aed6d46846 tte screensaver 2026-09-23 23:31:12 +02:00
mathias2784 30619b00ce hyprsaver 2026-09-23 23:05:54 +02:00
mathias2784 545485f3c5 Merge branch 'main' into hypr-caelestia 2026-09-23 21:52:27 +02:00
mathias2784 a8947283a5 .gitignore 2026-09-23 21:51:50 +02:00
mathias2784 496920cbdd refactor 2026-09-23 21:49:06 +02:00
mathias2784 519432d630 hypr: caelestia 2026-09-23 21:21:20 +02:00
mathias2784 15d77eeaca hypr: enrich noctalia config 2026-09-23 19:51:24 +02:00
mathias2784 23d0d1ecd3 hypr: shell commands in dedicated model 2026-09-23 19:32:37 +02:00
mathias2784 1d7ed473f6 hypr: refactor config to a more modular design 2026-09-23 19:04:52 +02:00
69 changed files with 2174 additions and 1457 deletions
+7 -2
View File
@@ -3,10 +3,15 @@ hypr/.config/hypr/env.conf
hypr/.config/hypr/env.sh
hypr/.config/hypr/monitor_setup.lua
# Noctalia template output (shell-owned, regenerated on palette change)
hypr/.config/hypr/noctalia.lua
hypr/.config/kitty/themes/noctalia.conf
# hypr/.config/kitty/themes/noctalia.conf
# Caelestia runtime output (shell-owned, regenerated on scheme change)
hypr/.config/hypr/scheme/
*~lock.*#
lazy-lock.json
fish_variables
term/.config/opencode/cli.json
term/.config/opencode/service.json
hypr/.config/hypr/scheme/current.lua
hypr/.config/hypr/env.lua
hypr/.config/hypr/hyprland-buntes-monster-gui.lua
hypr/.config/hypr/hyprland-gui.lua
+2 -2
View File
@@ -15,7 +15,7 @@ Only entries that would be missed without explicit help are included.
| Task | Command | Why it matters |
|------|---------|----------------|
| **Install required programs** | `bash term/setup.sh` <br>`bash _install_skripte/install_basic_pcks.sh` <br>`bash hypr/setup.sh` <br>`bash _install_skripte/install_kreation_pcks.sh` | These scripts install Neovim, hyprland, VST runtime, and other utilities. Edit `term/packages.txt` to add/remove terminal packages. |
| **Install required programs** | `bash setup/term/setup.sh` <br>`bash setup/basic/setup.sh` <br>`bash setup/hypr/setup.sh` <br>`bash setup/kreation/setup.sh` | These scripts install Neovim, hyprland, VST runtime, and other utilities. Edit `setup/term/packages.txt` to add/remove terminal packages. |
| **Link configuration directories** | `ln -s ~/.dotfiles/hypr/.config/hypr ~/.config/hypr` <br>`ln -s ~/.dotfiles/term/.config/nvim ~/.config/nvim` | The repository expects the configs to live in `~/.config`. |
| **Add VST plugin** | Copy `kreation/.vst3/MT-PowerDrumKit.vst3` into your DAW’s plugins folder (usually `~/.vst`). | The repo contains a pre‑built VST for use in audio software. |
@@ -26,7 +26,7 @@ Only entries that would be missed without explicit help are included.
| Item | Detail |
|------|--------|
| **Wayland compositor** | Requires `hyprland` (and dependencies like `wlroots`). The script `hypr/setup.sh` installs it from `hypr/packages.txt`. |
| **Wayland compositor** | Requires `hyprland` (and dependencies like `wlroots`). The script `setup/hypr/setup.sh` installs it from `setup/hypr/packages.txt`. |
| **MIME defaults** | Run `bash hypr/.config/hypr/scripts/ensure-env.sh` after installing to set environment variables (`$XDG_DATA_HOME`, etc.). |
| **Dolphin file associations** | `bash hypr/.config/hypr/scripts/fix_dolphin_file_associations.sh` must be executed once to register the compositor with KDE. |
| **Portal host override** | `bash hypr/.config/hypr/scripts/portal-host-override.sh` fixes Wayland portal issues on some distros. |
+13 -14
View File
@@ -6,27 +6,26 @@
# Zweige abhaengen. Die uebrigen Ziele haengen nur von basic ab und sind
# untereinander unabhaengig.
basic:
bash basic/setup.sh
stow --ignore='.stow-ignore' --ignore='scripts' --ignore='setup.sh' --ignore='packages.txt' basic
bash setup/basic/setup.sh
stow basic
term: basic
bash term/scripts/setup.sh
stow --ignore='.stow-ignore' --ignore='scripts' --ignore='\.config/tmux/plugins' term
bash setup/term/setup.sh
stow term
utils: basic
bash utils/setup.sh
bash _install_skripte/nextcloud.sh
utils: term
bash setup/utils/setup.sh
hypr: basic
bash hypr/scripts/setup.sh
stow --ignore='.stow-ignore' --ignore='scripts' hypr
hypr: utils
bash setup/hypr/setup.sh
stow hypr
kreation: basic
bash _install_skripte/install_kreation_pcks.sh
kreation: hypr
bash setup/kreation/setup.sh
stow kreation
buntes-monster: hypr kreation
_install_skripte/buntes-monster-links.sh
buntes-monster: kreation
bash setup/buntes-monster-links.sh
# ---------------------------------------------------------------------------
# Testing (see README.md "Testing" and test/ for details)
+26 -12
View File
@@ -8,10 +8,10 @@ Personal configuration files for an Arch Linux workstation (Hyprland + Neovim +
|-----------|----------|
| `basic/` | Base system packages + the **central theme** (`basic/.config/themes` → `~/.config/themes`: Catppuccin Mocha palette, `current` symlink, `switch-theme.sh`/`sync-theme.sh`). All other packages reference it instead of copying colors. |
| `term/` | Fish + kitty + starship + nvim + tmux + yazi + fastfetch + opencode terminal environment |
| `hypr/` | Hyprland compositor config + Noctalia shell config (Catppuccin Mocha) |
| `hypr/` | Hyprland compositor config + selectable Noctalia/Caelestia shell configs |
| `kreation/`| VST plugin (`MT-PowerDrumKit.vst3`) |
| `local_ai/`| Local AI / MCP tooling config |
| `_install_skripte/` | Miscellaneous install helper scripts |
| `setup/` | Install/setup scripts + package lists (one subdir per target, shared helpers in `setup/lib/`; not stowed) |
| `test/` | Docker test harness (lint + smoke tests) |
Each top-level directory is a **stow package**. `stow` symlinks the files from the repository into your home directory (e.g. `term/.config/...` → `~/.config/...`).
@@ -31,7 +31,7 @@ cd ~/.dotfiles
# 2. Install a target and symlink its files
make term # terminal + fish + kitty + nvim
make hypr # Hyprland (also pulls in basic + term)
make hypr # Hyprland + selectable Noctalia/Caelestia shells
make kreation # VST plugin (also pulls in basic)
```
@@ -43,34 +43,48 @@ Run `make <target>` from the repository root. Each target first runs the relevan
| Target | What it does |
|--------|--------------|
| `make term` | Runs `term/setup.sh` (installs terminal packages, sets fish as default shell, clones tmuxifier), then `stow term`. Pulls in `basic`. |
| `make basic` | Runs `basic/setup.sh`: enables multilib, updates the system, installs `yay` if missing, installs the `basic/packages.txt` packages, and sets up Docker (enables/starts the service, adds your user to the `docker` group, verifies the service) |
| `make hypr` | `make basic`, installs Hyprland packages, stows `hypr`, runs the Hyprland setup scripts (`ensure-env.sh`, `portal-host-override.sh`, `fix_dolphin_file_associations.sh`) |
| `make term` | Runs `setup/term/setup.sh` (installs terminal packages, sets fish as default shell, clones tmuxifier), then `stow term`. Pulls in `basic`. |
| `make basic` | Runs `setup/basic/setup.sh`: enables multilib, updates the system, installs `yay` if missing, installs the `setup/basic/packages.txt` packages, and sets up Docker (enables/starts the service, adds your user to the `docker` group, verifies the service) |
| `make hypr` | Runs `make basic`, installs Hyprland plus the Noctalia and Caelestia frontends, creates a local shell selection when needed, stows `hypr`, and runs the portal/file-association integration scripts |
| `make kreation` | `make basic`, installs VST runtime, stows `kreation` |
| `make buntes-monster` | Everything (`basic` + `hypr` + `kreation`), then wires up symlinks |
### Choosing between Noctalia and Caelestia
`make hypr` installs both desktop-shell frontends. Hyprland starts the one selected in `~/.config/hypr/env.lua`:
```lua
return {
shell = "noctalia", -- or "caelestia"
}
```
The local `env.lua` is created from `env.example.lua` on the first setup and is preserved on later runs. After changing the value, log out of and back into Hyprland; the running shell is not replaced live.
Caelestia requires the upstream AUR package `quickshell-git`; the release package `quickshell` must not be installed instead. Do not substitute CachyOS's `noctalia-qs`, even though it provides the virtual `quickshell-git` dependency: its Quickshell parser is not compatible with Caelestia. The package list uses the explicit `aur/quickshell-git` target because `yay --aur` alone may still select a repository provider. `make hypr` then replaces an existing `noctalia-qs` installation transactionally and verifies that `/usr/bin/qs` belongs to `quickshell-git`.
### Managing terminal packages
The terminal package list lives in a single editable file:
```
term/packages.txt
setup/term/packages.txt
```
Add/remove packages on separate lines. Lines starting with `#` are ignored, and you can switch between package sources with section markers:
```
@pacman # install via pacman (default)
@aur # install via yay (AUR)
@aur # use yay's AUR mode; use aur/<pkg> for an explicit source
@npm # install via npm -g
```
The default section is `@pacman`. The AUR helper `yay` is bootstrapped automatically by `basic/setup.sh`.
The default section is `@pacman`. The AUR helper `yay` is bootstrapped automatically by `setup/basic/setup.sh`.
## What the install scripts do
- **`basic/setup.sh`** – enables multilib, updates the system (`pacman -Syu`), ensures `yay` is installed, reads `basic/packages.txt` and installs all packages with `--needed` (skips already-installed ones), and sets up Docker (`sudo systemctl enable --now docker`, adds the current user to the `docker` group, checks the service). Idempotent and safe to re-run.
- **`term/setup.sh`** – reads `term/packages.txt` and installs all packages (pacman/AUR via `yay --needed`, npm via `sudo npm install -g`), sets `fish` as the default shell (`chsh`), clones `tmuxifier`, adds the `git` yazi plugin (skips if already present), and runs `sudo updatedb`. Idempotent and safe to re-run.
- **`setup/basic/setup.sh`** – enables multilib, updates the system (`pacman -Syu`), ensures `yay` is installed, reads `setup/basic/packages.txt` and installs all packages with `--needed` (skips already-installed ones), and sets up Docker (`sudo systemctl enable --now docker`, adds the current user to the `docker` group, checks the service). Idempotent and safe to re-run.
- **`setup/term/setup.sh`** – reads `setup/term/packages.txt` and installs all packages (pacman/AUR via `yay --needed`, npm via `sudo npm install -g`), sets `fish` as the default shell (`chsh`), clones `tmuxifier`, adds the `git` yazi plugin (skips if already present), and runs `sudo updatedb`. Idempotent and safe to re-run.
## Stow: resolving conflicts with existing paths
@@ -138,7 +152,7 @@ There are **two tiers**:
| Target | What it does | Docker required? |
|--------|--------------|------------------|
| `make test-lint` | Fast, offline integrity checks: `bash -n` syntax pass over every script, `shellcheck` (if installed), `packages.txt` marker validation, and Makefile ↔ script/stow-package name consistency. Catches typos like `_install_skripte_install_basic_pcks.sh` (missing `/`). | No |
| `make test-lint` | Fast, offline integrity checks: `bash -n` syntax pass over every script, `shellcheck` (if installed), `packages.txt` marker validation, and Makefile ↔ script/stow-package name consistency. Catches typos like `setup/basic/setuo.sh` (missing `/`). | No |
| `make test-stow` | `stow --simulate` for every stow-able package; fails if a package the Makefile stows doesn't exist (e.g. `stow nvim` — nvim lives under `term/`). | No |
| `make test-shellcheck` | Runs shellcheck over all tracked scripts (shellcheck must be installed). | No |
| `make test-lint-docker` | Builds the `/dev` stage (`archlinux:latest` + shellcheck) and runs `test/lint.sh` inside it. | Yes |
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
sudo pacman -S --needed \
reaper \
guitarix \
kdenlive \
yabridge \
yabridgectl \
obs-studio \
surge-xt \
lsp-plugins \
calf \
dragonfly-reverb
yay -S --needed \
numaplayer
@@ -1,6 +1,6 @@
# Central theme: catppuccin-mocha (Catppuccin Mocha), hyprland $vars.
# Part of basic/.config/themes. Managed file: refresh via
# basic/scripts/fetch-ports.sh
# setup/fetch-ports.sh
# (upstream: catppuccin/hyprland generated mocha.conf).
# Hyprland consumers load it via: source = ~/.config/themes/current/hypr.conf
@@ -1,6 +1,6 @@
# Central theme: catppuccin-mocha (Catppuccin Mocha), kitty colors.
# Part of basic/.config/themes. Managed file: refresh via
# basic/scripts/fetch-ports.sh
# setup/fetch-ports.sh
# (upstream: catppuccin/kitty themes/mocha.conf).
# vim:ft=kitty
-4
View File
@@ -1,4 +0,0 @@
setup.sh
packages.txt
scripts
.stow-ignore
-150
View File
@@ -1,150 +0,0 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SCRIPT_DIR/packages.txt"
# ---------------------------------------------------------------------------
# Enable multilib in /etc/pacman.conf (with a safety backup)
# ---------------------------------------------------------------------------
enable_multilib() {
sudo sed -i.bak '/^#\[multilib\]/,+1 s/^#//' /etc/pacman.conf
}
# ---------------------------------------------------------------------------
# Ensure yay (AUR helper) is installed.
# ---------------------------------------------------------------------------
install_yay() {
if pacman -Q yay &>/dev/null; then
echo "yay bereits installiert; fahre fort."
return
fi
if pacman -Si yay &>/dev/null; then
echo "Installiere yay mit pacman ..."
sudo pacman -S --needed yay
return
fi
echo "installiere yay via git ..."
sudo pacman -S --needed base-devel git
local tmp
tmp="$(mktemp -d)"
git clone https://aur.archlinux.org/yay.git "$tmp/yay"
(
cd "$tmp/yay"
makepkg -si
)
rm -rf "$tmp"
}
# ---------------------------------------------------------------------------
# Read packages.txt, split into pacman / aur / npm sections.
# ---------------------------------------------------------------------------
read_packages() {
local section="pacman"
local current
current=""
while IFS= read -r line || [[ -n "$line" ]]; do
current="${line%%#*}"
current="${current##*( )}"
current="${current%%*( )}"
[[ -z "$current" ]] && continue
case "$current" in
@pacman) section="pacman" ;;
@aur) section="aur" ;;
@npm) section="npm" ;;
*)
case "$section" in
pacman) pacman_pkgs+=("$current") ;;
aur) aur_pkgs+=("$current") ;;
npm) npm_pkgs+=("$current") ;;
esac
;;
esac
done < "$PACKAGES_FILE"
}
declare -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
# ---------------------------------------------------------------------------
# Install sections.
# ---------------------------------------------------------------------------
install_pacman() {
if ((${#pacman_pkgs[@]})); then
echo "==> Installiere Pacman-Pakete: ${pacman_pkgs[*]}"
yay -S --needed "${pacman_pkgs[@]}"
fi
}
install_aur() {
if ((${#aur_pkgs[@]})); then
echo "==> Installiere AUR-Pakete: ${aur_pkgs[*]}"
yay -S --needed "${aur_pkgs[@]}"
fi
}
install_npm() {
if ((${#npm_pkgs[@]})); then
echo "==> Installiere globale npm-Pakete: ${npm_pkgs[*]}"
npm install -g "${npm_pkgs[@]}"
fi
}
# ---------------------------------------------------------------------------
# Docker: Dienst aktivieren/starten, Benutzer in die docker-Gruppe aufnehmen
# und den Dienst verifizieren. (docker selbst wird ueber basic/packages.txt
# als Pacman-Paket installiert.)
# ---------------------------------------------------------------------------
setup_docker() {
if ! command -v docker >/dev/null 2>&1; then
echo "Warnung: docker nicht installiert; ueberspringe Docker-Setup."
return
fi
echo "==> Aktiviere und starte Docker-Dienst ..."
sudo systemctl enable --now docker
# Bei Aufruf via `sudo <script>` ist SUDO_USER der eigentliche Benutzer.
local target_user="${SUDO_USER:-$USER}"
echo "==> Stelle sicher, dass $target_user in der docker-Gruppe ist ..."
if [[ "$target_user" == "root" ]] || id -nG "$target_user" 2>/dev/null | grep -qw docker; then
echo "Benutzer $target_user ist bereits in der docker-Gruppe."
else
sudo usermod -aG docker "$target_user"
echo "Benutzer $target_user zur docker-Gruppe hinzugefuegt; wirksam nach dem naechsten Login."
fi
echo "==> Pruefe Docker-Dienst ..."
if systemctl is-active --quiet docker; then
echo "Docker-Dienst laeuft (Socket: /var/run/docker.sock)."
else
echo "Warnung: Docker-Dienst laeuft nicht; pruefe mit: systemctl status docker"
fi
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
echo "==> Aktiviere multilib ..."
enable_multilib
echo "==> System aktualisieren ..."
sudo pacman -Syu
echo "==> Sicherstelle yay ..."
install_yay
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages
install_pacman
install_aur
install_npm
echo "==> Richte Docker ein ..."
setup_docker
echo "Fertig. Die Basis-Systemumgebung ist eingerichtet."
}
main
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -Eeuo pipefail
SERVER="buntes-monster"
SERVER_IP="192.168.0.4"
MOUNTS=(
"/mnt/anbau:/mnt/anbau"
"/mnt/bilder:/mnt/bilder"
)
# Re-run as root when needed.
if [[ "${EUID}" -ne 0 ]]; then
exec sudo "$0" "$@"
fi
# Preserve ownership for the user who invoked sudo.
OWNER="${SUDO_USER:-${USER}}"
OWNER_UID="$(id -u "$OWNER")"
OWNER_GID="$(id -g "$OWNER")"
for entry in "${MOUNTS[@]}"; do
IFS=":" read -r remote_path local_path <<< "$entry"
# Create the mount point if necessary and give it to the invoking user.
install -d \
-o "$OWNER_UID" \
-g "$OWNER_GID" \
-m 0755 \
"$local_path"
# Do not remount an already-mounted location.
if mountpoint -q "$local_path"; then
echo "Already mounted: $local_path"
continue
fi
echo "Mounting $SERVER:$remote_path at $local_path..."
mount \
-t nfs \
-o rw,sync,addr="$SERVER_IP" \
"$SERVER:$remote_path" \
"$local_path"
echo "Mounted: $local_path"
done
@@ -0,0 +1,2 @@
{
}
@@ -0,0 +1,2 @@
{
}
@@ -0,0 +1,2 @@
{
}
+39
View File
@@ -0,0 +1,39 @@
{
"appearance": {
"transparency": {
"enabled": true
}
},
"background": {
"wallpaperEnabled": true
},
"dashboard": {
"showWeather": true
},
"general": {
"apps": {
"audio": [
"supersonic-desktop"
],
"explorer": [
"dolphin"
],
"playback": [
"celluloid"
],
"terminal": [
"kitty"
]
}
},
"launcher": {
"showOnHover": true,
"useFuzzy": {
"apps": true
},
"vimKeybinds": true
},
"paths": {
"wallpaperDir": "~/nextcloud/Photos/Wallpapers"
}
}
View File
+4
View File
@@ -0,0 +1,4 @@
return {
-- Supported values: "noctalia" or "caelestia".
shell = "noctalia",
}
View File
+44 -714
View File
@@ -1,25 +1,26 @@
-- Central theme (basic/.config/themes): single source of truth for colors.
-- Consumers must use `theme.*` roles, never hardcoded hex, so a future
-- non-Catppuccin theme only adds a new directory. (HyprMod's
-- hyprland-gui.conf may additionally override borders at runtime.)
local theme = dofile(os.getenv("HOME") .. "/.config/themes/current/theme.lua")
local var_color_active_border = theme.border_active
local var_color_inactive_border = theme.border_inactive
local var_color_decoration_shadow = theme.shadow
local var_mainMod = "SUPER"
local var_terminal = "kitty"
local var_fileManager = "dolphin"
local var_menu = "noctalia msg panel-toggle launcher"
local var_screenshot_folder = "~/Bilder/Screenshots/"
require("env")
local config_home = os.getenv("XDG_CONFIG_HOME") or os.getenv("HOME") .. "/.config"
local fid_env = io.open(config_home .. "/hypr/env.lua")
local env = {}
if fid_env then
env = require("env")
else
env = require("env_example")
end
if env.shell ~= "noctalia" and env.shell ~= "caelestia" then
error("Unsupported shell '" .. tostring(env.shell) .. "' in ~/.config/hypr/env.lua; choose 'noctalia' or 'caelestia'")
end
hl.exec_cmd("bash ~/.config/hypr/env.sh")
-- ###############
-- ## MONITORS ###
-- ###############
require("monitor_setup")
-- load default monitor config
require("modules.monitor_setup_default")
-- unscale XWayland
hl.config({
@@ -33,709 +34,38 @@ hl.config({
-- ##################
hl.on("hyprland.start", function()
hl.exec_cmd("noctalia &")
end)
hl.on("hyprland.start", function()
-- start selected shell
if env.shell == "caelestia" then
hl.exec_cmd("caelestia shell -d")
else -- default: "noctalia"
hl.exec_cmd("noctalia &")
end
hl.exec_cmd("sh ~/.config/hypr/scripts/portal-host-override.sh")
hl.exec_cmd("sh ~/.config/hypr/scripts/ensure-mime-defaults.sh")
end)
-- ############################
-- ## ENVIRONMENT VARIABLES ###
-- ############################
-- See https://wiki.hypr.land/Configuring/Environment-variables/
hl.env("XCURSOR_SIZE", "24")
hl.env("HYPRCURSOR_SIZE", "24")
hl.env("XDG_CURRENT_DESKTOP", "Hyprland")
hl.env("XDG_SESSION_DESKTOP", "Hyprland")
hl.env("XDG_SESSION_TYPE", "wayland")
hl.env("XDG_MENU_PREFIX", "plasma-")
hl.env("GTK_USE_PORTAL", "1")
hl.env("GTK_THEME", os.getenv("THEME_GTK") or "Adwaita:dark")
hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1")
hl.env("QT_QPA_PLATFORMTHEME", "kde")
-- ##################
-- ## PERMISSIONS ###
-- ##################
-- ####################
-- ## COLOR SCHEMES ###
-- ####################
-- (Colors come from the central theme via `theme` above; no per-file copies.)
-- ####################
-- ## LOOK AND FEEL ###
-- ####################
-- Refer to https://wiki.hypr.land/Configuring/Variables/
-- https://wiki.hypr.land/Configuring/Variables/#general
hl.config({
general = {
gaps_in = 3,
gaps_out = 4,
border_size = 3,
},
})
-- https://wiki.hypr.land/Configuring/Variables/#variable-types for info about colors
hl.config({
general = {
col = {
active_border = var_color_active_border,
inactive_border = var_color_inactive_border,
},
},
})
-- Set to true enable resizing windows by clicking and dragging on borders and gaps
hl.config({
general = {
resize_on_border = true,
},
})
-- Please see https://wiki.hypr.land/Configuring/Tearing/ before you turn this on
hl.config({
general = {
allow_tearing = false,
layout = "dwindle",
},
})
-- https://wiki.hypr.land/Configuring/Variables/#decoration
hl.config({
decoration = {
rounding = 5,
rounding_power = 2,
},
})
-- Change transparency of focused and unfocused windows
hl.config({
decoration = {
active_opacity = 1.0,
inactive_opacity = 1.0,
shadow = {
enabled = true,
range = 10,
render_power = 3,
color = var_color_decoration_shadow,
},
},
})
-- https://wiki.hypr.land/Configuring/Variables/#blur
hl.config({
decoration = {
blur = {
enabled = true,
size = 10,
passes = 2,
vibrancy = 0.1696,
},
},
})
-- https://wiki.hypr.land/Configuring/Variables/#animations
hl.config({
animations = {
enabled = true,
},
})
-- Default curves, see https://wiki.hypr.land/Configuring/Animations/#curves
-- NAME, X0, Y0, X1, Y1
hl.curve("easeOutQuint", { type = "bezier", points = { { 0.23, 1 }, { 0.32, 1 } } })
hl.curve("easeInOutCubic", { type = "bezier", points = { { 0.65, 0.05 }, { 0.36, 1 } } })
hl.curve("linear", { type = "bezier", points = { { 0, 0 }, { 1, 1 } } })
hl.curve("almostLinear", { type = "bezier", points = { { 0.5, 0.5 }, { 0.75, 1 } } })
hl.curve("quick", { type = "bezier", points = { { 0.15, 0 }, { 0.1, 1 } } })
-- Default animations, see https://wiki.hypr.land/Configuring/Animations/
-- NAME, ONOFF, SPEED, CURVE, [STYLE]
hl.animation({
leaf = "global",
enabled = true,
speed = 10,
bezier = "default",
})
hl.animation({
leaf = "border",
enabled = true,
speed = 5.39,
bezier = "easeOutQuint",
})
hl.animation({
leaf = "windows",
enabled = true,
speed = 4.79,
bezier = "easeOutQuint",
})
hl.animation({
leaf = "windowsIn",
enabled = true,
speed = 4.1,
bezier = "easeOutQuint",
style = "popin 87%",
})
hl.animation({
leaf = "windowsOut",
enabled = true,
speed = 1.49,
bezier = "linear",
style = "popin 87%",
})
hl.animation({
leaf = "fadeIn",
enabled = true,
speed = 1.73,
bezier = "almostLinear",
})
hl.animation({
leaf = "fadeOut",
enabled = true,
speed = 1.46,
bezier = "almostLinear",
})
hl.animation({
leaf = "fade",
enabled = true,
speed = 3.03,
bezier = "quick",
})
hl.animation({
leaf = "layers",
enabled = true,
speed = 3.81,
bezier = "easeOutQuint",
})
hl.animation({
leaf = "layersIn",
enabled = true,
speed = 4,
bezier = "easeOutQuint",
style = "fade",
})
hl.animation({
leaf = "layersOut",
enabled = true,
speed = 1.5,
bezier = "linear",
style = "fade",
})
hl.animation({
leaf = "fadeLayersIn",
enabled = true,
speed = 1.79,
bezier = "almostLinear",
})
hl.animation({
leaf = "fadeLayersOut",
enabled = true,
speed = 1.39,
bezier = "almostLinear",
})
hl.animation({
leaf = "workspaces",
enabled = true,
speed = 1.94,
bezier = "almostLinear",
style = "slide",
})
hl.animation({
leaf = "workspacesIn",
enabled = true,
speed = 1.21,
bezier = "almostLinear",
style = "slide",
})
hl.animation({
leaf = "workspacesOut",
enabled = true,
speed = 1.94,
bezier = "almostLinear",
style = "slide",
})
hl.animation({
leaf = "zoomFactor",
enabled = true,
speed = 7,
bezier = "quick",
})
-- Ref https://wiki.hypr.land/Configuring/Workspace-Rules/
-- "Smart gaps" / "No gaps when only"
-- uncomment all if you wish to use that.
hl.workspace_rule({
workspace = "w[tv1]",
gaps_out = 0,
gaps_in = 0,
})
hl.workspace_rule({
workspace = "f[1]",
gaps_out = 0,
gaps_in = 0,
})
hl.window_rule({
name = "no-gaps-wtv1",
match = {
float = false,
workspace = "w[tv1]",
},
border_size = 0,
rounding = 0,
})
hl.window_rule({
name = "no-gaps-f1",
match = {
float = false,
workspace = "f[1]",
},
border_size = 0,
rounding = 0,
})
-- See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more
hl.config({
dwindle = {
preserve_split = true,
},
})
-- See https://wiki.hypr.land/Configuring/Master-Layout/ for more
hl.config({
master = {
new_status = "master",
},
})
-- https://wiki.hypr.land/Configuring/Variables/#misc
hl.config({
misc = {
force_default_wallpaper = -1,
disable_hyprland_logo = false,
},
})
-- ############
-- ## INPUT ###
-- ############
-- https://wiki.hypr.land/Configuring/Variables/#input
hl.config({
input = {
kb_layout = "de",
kb_variant = "",
kb_model = "",
kb_options = "grp:alt_shift_toggle",
kb_rules = "",
follow_mouse = 1,
numlock_by_default = true,
sensitivity = 0,
touchpad = {
natural_scroll = true,
},
},
})
-- See https://wiki.hypr.land/Configuring/Gestures
hl.gesture({
fingers = 3,
direction = "horizontal",
action = "workspace",
})
-- Example per-device config
-- See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more
hl.device({
name = "epic-mouse-v1",
sensitivity = -0.5,
})
-- ##################
-- ## KEYBINDINGS ###
-- ##################
-- See https://wiki.hypr.land/Configuring/Keywords/
-- Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more
hl.bind(var_mainMod .. " + RETURN", hl.dsp.exec_cmd(var_terminal), { description = "Open terminal (kitty)" })
hl.bind(var_mainMod .. " + Q", hl.dsp.window.close(), { description = "Close focused window" })
-- Session menu (noctalia owns the session panel)
hl.bind(var_mainMod .. " + ESCAPE", hl.dsp.exec_cmd("noctalia msg panel-toggle session"), { description = "Session menu (logout/reboot/shutdown)" })
hl.bind(
var_mainMod .. " + SHIFT + ESCAPE",
hl.dsp.exec_cmd("command -v noctalia >/dev/null 2>&1 && noctalia msg session logout || hyprctl dispatch exit"),
{ description = "Exit Hyprland" }
)
hl.bind(
var_mainMod .. " + CTRL + ESCAPE",
hl.dsp.exec_cmd("noctalia msg session shutdown"),
{ description = "Power off the system" }
)
hl.bind(
var_mainMod .. " + ALT + ESCAPE",
hl.dsp.exec_cmd("noctalia msg session reboot"),
{ description = "Reboot the system" }
)
hl.bind(var_mainMod .. " + E", hl.dsp.exec_cmd(var_fileManager), { description = "Open file manager (dolphin)" })
hl.bind(var_mainMod .. " + V", hl.dsp.window.float({ action = "toggle" }), { description = "Toggle floating window" })
hl.bind(var_mainMod .. " + SPACE", hl.dsp.exec_cmd(var_menu), { description = "Open app launcher (noctalia)" })
hl.bind(var_mainMod .. " + P", hl.dsp.window.pseudo(), { description = "Toggle pseudo-tiling" })
hl.bind(var_mainMod .. " + SHIFT + J", hl.dsp.layout("togglesplit"), { description = "Toggle split layout" })
hl.bind(var_mainMod .. " + I", hl.dsp.exec_cmd("firefox &"), { description = "Open Firefox" })
hl.bind(var_mainMod .. " + n", hl.dsp.exec_cmd("nm-connection-editor"), { description = "Network manager" })
hl.bind(var_mainMod .. " + comma", hl.dsp.exec_cmd("noctalia msg settings-toggle"), { description = "Noctalia settings" })
hl.bind(var_mainMod .. " + S", hl.dsp.exec_cmd("noctalia msg panel-toggle control-center"), { description = "Control center (noctalia)" })
-- Move focus with mainMod or Vim-style
hl.bind(var_mainMod .. " + CTRL + h", hl.dsp.focus({ direction = "left" }), { description = "Focus window left" })
hl.bind(var_mainMod .. " + CTRL + l", hl.dsp.focus({ direction = "right" }), { description = "Focus window right" })
hl.bind(var_mainMod .. " + CTRL + k", hl.dsp.focus({ direction = "up" }), { description = "Focus window up" })
hl.bind(var_mainMod .. " + CTRL + j", hl.dsp.focus({ direction = "down" }), { description = "Focus window down" })
-- Move windows with mainMod or Vim-style
hl.bind(var_mainMod .. " + SHIFT + h", hl.dsp.window.move({ direction = "left" }), { description = "Move window left" })
hl.bind(
var_mainMod .. " + SHIFT + l",
hl.dsp.window.move({ direction = "right" }),
{ description = "Move window right" }
)
hl.bind(var_mainMod .. " + SHIFT + k", hl.dsp.window.move({ direction = "up" }), { description = "Move window up" })
hl.bind(var_mainMod .. " + SHIFT + j", hl.dsp.window.move({ direction = "down" }), { description = "Move window down" })
-- Resize focused window with mainMod + Arrows
hl.bind(
var_mainMod .. " + left",
hl.dsp.window.resize({ x = -10, y = 0, relative = true }),
{ description = "Resize window left" }
)
hl.bind(
var_mainMod .. " + right",
hl.dsp.window.resize({ x = 10, y = 0, relative = true }),
{ description = "Resize window right" }
)
hl.bind(
var_mainMod .. " + up",
hl.dsp.window.resize({ x = 0, y = -10, relative = true }),
{ description = "Resize window up" }
)
hl.bind(
var_mainMod .. " + down",
hl.dsp.window.resize({ x = 0, y = 10, relative = true }),
{ description = "Resize window down" }
)
-- Switch workspaces with mainMod + [0-9]
hl.bind(var_mainMod .. " + 1", hl.dsp.focus({ workspace = 1 }), { description = "Switch to workspace 1" })
hl.bind(var_mainMod .. " + 2", hl.dsp.focus({ workspace = 2 }), { description = "Switch to workspace 2" })
hl.bind(var_mainMod .. " + 3", hl.dsp.focus({ workspace = 3 }), { description = "Switch to workspace 3" })
hl.bind(var_mainMod .. " + 4", hl.dsp.focus({ workspace = 4 }), { description = "Switch to workspace 4" })
hl.bind(var_mainMod .. " + 5", hl.dsp.focus({ workspace = 5 }), { description = "Switch to workspace 5" })
hl.bind(var_mainMod .. " + 6", hl.dsp.focus({ workspace = 6 }), { description = "Switch to workspace 6" })
hl.bind(var_mainMod .. " + 7", hl.dsp.focus({ workspace = 7 }), { description = "Switch to workspace 7" })
hl.bind(var_mainMod .. " + 8", hl.dsp.focus({ workspace = 8 }), { description = "Switch to workspace 8" })
hl.bind(var_mainMod .. " + 9", hl.dsp.focus({ workspace = 9 }), { description = "Switch to workspace 9" })
hl.bind(var_mainMod .. " + 0", hl.dsp.focus({ workspace = 10 }), { description = "Switch to workspace 10" })
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+"), {
repeating = true,
description = "Volume up",
})
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), {
locked = true,
description = "Volume down",
})
-- Move active window to a workspace with mainMod + SHIFT + [0-9]
hl.bind(
var_mainMod .. " + SHIFT + 1",
hl.dsp.window.move({ workspace = 1 }),
{ description = "Move window to workspace 1" }
)
hl.bind(
var_mainMod .. " + SHIFT + 2",
hl.dsp.window.move({ workspace = 2 }),
{ description = "Move window to workspace 2" }
)
hl.bind(
var_mainMod .. " + SHIFT + 3",
hl.dsp.window.move({ workspace = 3 }),
{ description = "Move window to workspace 3" }
)
hl.bind(
var_mainMod .. " + SHIFT + 4",
hl.dsp.window.move({ workspace = 4 }),
{ description = "Move window to workspace 4" }
)
hl.bind(
var_mainMod .. " + SHIFT + 5",
hl.dsp.window.move({ workspace = 5 }),
{ description = "Move window to workspace 5" }
)
hl.bind(
var_mainMod .. " + SHIFT + 6",
hl.dsp.window.move({ workspace = 6 }),
{ description = "Move window to workspace 6" }
)
hl.bind(
var_mainMod .. " + SHIFT + 7",
hl.dsp.window.move({ workspace = 7 }),
{ description = "Move window to workspace 7" }
)
hl.bind(
var_mainMod .. " + SHIFT + 8",
hl.dsp.window.move({ workspace = 8 }),
{ description = "Move window to workspace 8" }
)
hl.bind(
var_mainMod .. " + SHIFT + 9",
hl.dsp.window.move({ workspace = 9 }),
{ description = "Move window to workspace 9" }
)
hl.bind(
var_mainMod .. " + SHIFT + 0",
hl.dsp.window.move({ workspace = 10 }),
{ description = "Move window to workspace 10" }
)
-- # Example special workspace (scratchpad)
-- bind = $mainMod, S, togglespecialworkspace, magic
-- bind = $mainMod SHIFT, S, movetoworkspace, special:magic
-- Scroll through existing workspaces with mainMod + scroll
hl.bind(
var_mainMod .. " + mouse_down",
hl.dsp.focus({ workspace = "e+1" }),
{ description = "Next workspace (scroll down)" }
)
hl.bind(
var_mainMod .. " + mouse_up",
hl.dsp.focus({ workspace = "e-1" }),
{ description = "Previous workspace (scroll up)" }
)
-- Move/resize windows with mainMod + LMB/RMB and dragging
hl.bind(var_mainMod .. " + mouse:272", hl.dsp.window.drag(), {
mouse = true,
description = "Move window with mouse",
})
hl.bind(var_mainMod .. " + mouse:273", hl.dsp.window.resize(), {
mouse = true,
description = "Resize window with mouse",
})
-- Laptop multimedia keys for volume and LCD brightness
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), {
repeating = true,
locked = true,
description = "Volume up (repeat)",
})
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), {
repeating = true,
locked = true,
description = "Volume down (repeat)",
})
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"), {
repeating = true,
locked = true,
description = "Mute audio",
})
hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"), {
repeating = true,
locked = true,
description = "Mute microphone",
})
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"), {
repeating = true,
locked = true,
description = "Brightness up",
})
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"), {
repeating = true,
locked = true,
description = "Brightness down",
})
-- Requires playerctl
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), {
locked = true,
description = "Next track",
})
hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), {
locked = true,
description = "Play/Pause",
})
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), {
locked = true,
description = "Play/Pause",
})
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), {
locked = true,
description = "Previous track",
})
-- Screenshots
hl.bind("PRINT", hl.dsp.exec_cmd("hyprshot -m region --output-folder " .. var_screenshot_folder), {
locked = true,
description = "Screenshot region",
})
hl.bind("CTRL + PRINT", hl.dsp.exec_cmd("hyprshot -m window --output-folder " .. var_screenshot_folder), {
locked = true,
description = "Screenshot window",
})
hl.bind("SHIFT + PRINT", hl.dsp.exec_cmd("hyprshot -m active --output-folder " .. var_screenshot_folder), {
locked = true,
description = "Screenshot active monitor",
})
-- Screenlock (noctalia owns the lock screen)
hl.bind("CTRL + ALT + L", hl.dsp.exec_cmd("noctalia msg session lock"), { locked = true, description = "Lock screen" })
hl.bind(var_mainMod .. " + L", hl.dsp.exec_cmd("noctalia msg session lock"), { locked = true, description = "Lock screen" })
-- Keybind overview popup
hl.bind(
var_mainMod .. " + K",
hl.dsp.exec_cmd("sh ~/.config/hypr/scripts/show-keybinds.sh"),
{ description = "Show keybind overview" }
)
hl.bind(var_mainMod .. " + W", hl.dsp.exec_cmd("noctalia msg panel-toggle wallpaper"), { description = "Wallpaper select (noctalia)" })
-- #############################
-- ## WINDOWS AND WORKSPACES ###
-- #############################
-- See https://wiki.hypr.land/Configuring/Window-Rules/ for more
-- See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules
-- Example windowrules that are useful
-- Ignore maximize requests from all apps. You'll probably like this.
hl.window_rule({
name = "suppress-maximize-events",
match = {
class = ".*",
},
suppress_event = "maximize",
})
-- Fix some dragging issues with XWayland
hl.window_rule({
name = "fix-xwayland-drags",
match = {
class = "^$",
title = "^$",
xwayland = true,
float = true,
fullscreen = false,
pin = false,
},
no_focus = true,
})
-- Hyprland-run windowrule
hl.config({
decoration = {
blur = {
size = 8,
passes = 2,
},
},
})
hl.window_rule({
name = "move-hyprland-run",
match = {
class = "hyprland-run",
},
move = "20 monitor_h-120",
float = true,
})
hl.window_rule({
name = "keybinds-float",
match = {
class = "keybinds",
},
float = true,
size = "900 700",
center = true,
dim_around = true,
})
hl.window_rule({
name = "opacity-kitty-dolphin",
match = {
class = ".*(kitty|dolphin).*",
},
opacity = "0.80 0.70",
})
-- Noctalia shell surfaces: blur bars/panels/dock/notifications and let
-- Noctalia run its own animations (no Hyprland layer animation on top).
hl.layer_rule({
name = "noctalia",
match = {
namespace = "^noctalia-(bar-.+|notification|dock|panel|attached-panel|osd|window-switcher)$",
},
no_anim = true,
ignore_alpha = 0.5,
blur = true,
blur_popups = true,
})
hl.window_rule({
name = "noctalia-settings",
match = {
class = "dev.noctalia.Noctalia",
},
float = true,
size = "1080 920",
})
hl.window_rule({
name = "no-rounding-fullscreen",
match = {
fullscreen = 1,
},
rounding = 0,
border_size = 0,
})
-- windowrule {
-- name = no-rounding-steam-games
-- match:class = ^steam_app_.*$
-- rounding = 0
-- border_size = 0
-- }
-- windowrule {
-- name = no-rounding-gamescope
-- match:class = ^gamescope$
-- rounding = 0
-- border_size = 0
-- }
require("modules.environment_variables")
require("modules.look_and_feel")
require("modules.input")
require("modules.keybinds")
require("modules.windows_and_workspaces")
-- HyprMod managed settings
require("hyprland-gui")
local fid_gui = io.open(config_home .. "/hypr/hyprland-buntes-monster-gui.lua")
if fid_gui then
fid_gui:close()
require("hyprland-buntes-monster-gui")
end
-- For Noctalia Color templates
require("noctalia").apply_theme()
-- For Noctalia Color templates. Noctalia-only: under Caelestia this would
-- otherwise push Noctalia's Catppuccin border colors into the compositor.
if env.shell == "noctalia" then
require("noctalia").apply_theme()
end
-- HyprMod managed settings
local fid_gui2 = io.open(config_home .. "/hypr/hyprland-gui.lua")
if fid_gui2 then
fid_gui2:close()
require("hyprland-gui")
end
@@ -0,0 +1,12 @@
-- See https://wiki.hypr.land/Configuring/Environment-variables/
hl.env("XCURSOR_SIZE", "24")
hl.env("HYPRCURSOR_SIZE", "24")
hl.env("XDG_CURRENT_DESKTOP", "Hyprland")
hl.env("XDG_SESSION_DESKTOP", "Hyprland")
hl.env("XDG_SESSION_TYPE", "wayland")
hl.env("XDG_MENU_PREFIX", "plasma-")
hl.env("GTK_USE_PORTAL", "1")
hl.env("GTK_THEME", os.getenv("THEME_GTK") or "Adwaita:dark")
hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1")
hl.env("QT_QPA_PLATFORMTHEME", "kde")
+33
View File
@@ -0,0 +1,33 @@
-- https://wiki.hypr.land/Configuring/Variables/#input
hl.config({
input = {
kb_layout = "de",
kb_variant = "",
kb_model = "",
kb_options = "grp:alt_shift_toggle",
kb_rules = "",
follow_mouse = 1,
numlock_by_default = true,
sensitivity = 0,
touchpad = {
natural_scroll = true,
},
},
})
-- See https://wiki.hypr.land/Configuring/Gestures
hl.gesture({
fingers = 3,
direction = "horizontal",
action = "workspace",
})
-- Example per-device config
-- See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more
hl.device({
name = "epic-mouse-v1",
sensitivity = -0.5,
})
@@ -0,0 +1,63 @@
-- keybind_registry.lua — wrap hl.bind so every keybind records a runnable
-- action alongside its chord/description.
--
-- Hyprland's Lua API registers binds through hl.bind(keys, dispatcher, opts),
-- and `hyprctl binds -j` reports those as `dispatcher: "__lua"` with an opaque
-- registry reference — the underlying command is not recoverable from the
-- compositor afterwards. This module captures the action at registration time:
--
-- exec(cmd) -> a tagged placeholder for the exec_cmd dispatcher (the final
-- command string is resolved here, so concatenations like
-- "hyprshot ... " .. var.screenshot_folder work automatically)
-- bind(...) -> same signature/behavior as hl.bind; converts the exec
-- placeholder back into a real dispatcher and records the row
-- write(path)-> dump the registry as "keys\x1fdescription\x1fcmd" TSV so the
-- show-keybinds picker can execute the selected entry
--
-- Pure dispatcher binds (hl.dsp.window.close(), hl.dsp.focus(...), ...) pass
-- through unchanged and are recorded with an empty cmd (informational only).
local registry = {}
local M = {}
--- Tag a shell command so bind() knows to turn it into an exec_cmd dispatcher.
function M.exec(cmd)
return { __cmd = cmd }
end
--- Register a keybind like hl.bind, but record it in the registry first.
--- @param keys string final key string (e.g. "SUPER + Q")
--- @param action any M.exec(cmd) or a real dispatcher from hl.dsp.*
--- @param opts? table hl.bind options (description, flags, ...)
function M.bind(keys, action, opts)
opts = opts or {}
local dsp = action
local cmd = ""
if type(action) == "table" and action.__cmd ~= nil then
cmd = action.__cmd
dsp = hl.dsp.exec_cmd(cmd)
end
table.insert(registry, { keys = keys, description = opts.description or "", cmd = cmd })
return hl.bind(keys, dsp, opts)
end
--- Dump the registry as "keys\x1fdescription\x1fcmd" lines (one per bind).
function M.write(path)
local f, err = io.open(path, "w")
if not f then
return nil, err
end
for _, b in ipairs(registry) do
f:write(b.keys, "\x1f", b.description, "\x1f", b.cmd, "\n")
end
f:close()
return registry
end
--- Access the raw registry rows ({keys, description, cmd}).
function M.get()
return registry
end
return M
+248
View File
@@ -0,0 +1,248 @@
local var = require("modules.variables")
local command = require("modules.shell_commands")
local env = require("env")
-- bind/exec wrap hl.bind so each keybind also records a runnable command for
-- the show-keybinds picker (see modules/keybind_registry.lua).
local reg = require("modules.keybind_registry")
local bind = reg.bind
local exec = reg.exec
-- See https://wiki.hypr.land/Configuring/Keywords/
-- Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more
bind(var.mainMod .. " + RETURN", exec(var.terminal), { description = "Open terminal" })
bind(var.mainMod .. " + ALT + RETURN", exec(var.terminal_tmux), { description = "Open tmux in terminal" })
bind(var.mainMod .. " + Q", hl.dsp.window.close(), { description = "Close focused window" })
bind(
var.mainMod .. " + ESCAPE",
exec(command.session),
{ description = "Session menu (logout/reboot/shutdown)" }
)
bind(var.mainMod .. " + SHIFT + ESCAPE", exec(command.logout), { description = "Session: logout" })
bind(var.mainMod .. " + CTRL + ESCAPE", exec(command.shutdown), { description = "Session: power off" })
bind(var.mainMod .. " + ALT + ESCAPE", exec(command.reboot), { description = "Session: reboot" })
bind(var.mainMod .. " + E", exec(var.fileManager), { description = "Open file manager" })
bind(var.mainMod .. " + V", hl.dsp.window.float({ action = "toggle" }), { description = "Floating window toggle" })
bind(var.mainMod .. " + SPACE", exec(command.menu), { description = "Open app launcher" })
bind(var.mainMod .. " + P", hl.dsp.window.pseudo(), { description = "Pseudo-tiling toggle" })
bind(var.mainMod .. " + SHIFT + J", hl.dsp.layout("togglesplit"), { description = "Split layout toggle" })
bind(var.mainMod .. " + I", exec(var.internet_explorer), { description = "Open internet explorer" })
bind(var.mainMod .. " + n", exec("nm-connection-editor"), { description = "Open network manager" })
bind(var.mainMod .. " + comma", exec(command.settings), { description = "Open settings" })
bind(var.mainMod .. " + S", exec(command.control_center), { description = "Open start menu" })
bind(var.mainMod .. " + ALT + H", exec("hyprmod"), {description = "Open hyprmod (hyprland config GUI)"})
bind(var.mainMod .. " + period", exec(command.emoji), { description = "Open emoji picker" })
bind(var.mainMod .. " + ALT + S", exec(var.systemmonitor), {description = "Open systemmonitor"})
bind(var.mainMod .. " + TAB", function()
hl.plugin.hyprtasking.toggle("cursor")
end, { description = "Workspace: overview" })
-- Move focus with mainMod or Vim-style
bind(var.mainMod .. " + CTRL + h", hl.dsp.focus({ direction = "left" }), { description = "Window: focus left" })
bind(var.mainMod .. " + CTRL + l", hl.dsp.focus({ direction = "right" }), { description = "Window: focus right" })
bind(var.mainMod .. " + CTRL + k", hl.dsp.focus({ direction = "up" }), { description = "Window: focus up" })
bind(var.mainMod .. " + CTRL + j", hl.dsp.focus({ direction = "down" }), { description = "Window: focus down" })
-- Move windows with mainMod or Vim-style
bind(var.mainMod .. " + SHIFT + h", hl.dsp.window.move({ direction = "left" }), { description = "Window: move left" })
bind(
var.mainMod .. " + SHIFT + l",
hl.dsp.window.move({ direction = "right" }),
{ description = "Window: move right" }
)
bind(var.mainMod .. " + SHIFT + k", hl.dsp.window.move({ direction = "up" }), { description = "Window: move up" })
bind(var.mainMod .. " + SHIFT + j", hl.dsp.window.move({ direction = "down" }), { description = "Window: move down" })
-- Resize focused window with mainMod + Arrows
bind(
var.mainMod .. " + left",
hl.dsp.window.resize({ x = -10, y = 0, relative = true }),
{ description = "Window: resize left" }
)
bind(
var.mainMod .. " + right",
hl.dsp.window.resize({ x = 10, y = 0, relative = true }),
{ description = "Window: resize right" }
)
bind(
var.mainMod .. " + up",
hl.dsp.window.resize({ x = 0, y = -10, relative = true }),
{ description = "Window: resize up" }
)
bind(
var.mainMod .. " + down",
hl.dsp.window.resize({ x = 0, y = 10, relative = true }),
{ description = "Window: resize down" }
)
-- Switch workspaces with mainMod + [0-9]
bind(var.mainMod .. " + 1", hl.dsp.focus({ workspace = 1 }), { description = "Workspace: switch to 1" })
bind(var.mainMod .. " + 2", hl.dsp.focus({ workspace = 2 }), { description = "Workspace: Switch to 2" })
bind(var.mainMod .. " + 3", hl.dsp.focus({ workspace = 3 }), { description = "Workspace: Switch to 3" })
bind(var.mainMod .. " + 4", hl.dsp.focus({ workspace = 4 }), { description = "Workspace: Switch to 4" })
bind(var.mainMod .. " + 5", hl.dsp.focus({ workspace = 5 }), { description = "Workspace: Switch to 5" })
bind(var.mainMod .. " + 6", hl.dsp.focus({ workspace = 6 }), { description = "Workspace: Switch to 6" })
bind(var.mainMod .. " + 7", hl.dsp.focus({ workspace = 7 }), { description = "Workspace: Switch to 7" })
bind(var.mainMod .. " + 8", hl.dsp.focus({ workspace = 8 }), { description = "Workspace: Switch to 8" })
bind(var.mainMod .. " + 9", hl.dsp.focus({ workspace = 9 }), { description = "Workspace: Switch to 9" })
bind(var.mainMod .. " + 0", hl.dsp.focus({ workspace = 10 }), { description = "Workspace: Switch to 10" })
-- Move active window to a workspace with mainMod + SHIFT + [0-9]
bind(
var.mainMod .. " + SHIFT + 1",
hl.dsp.window.move({ workspace = 1 }),
{ description = "Window: move to workspace 1" }
)
bind(
var.mainMod .. " + SHIFT + 2",
hl.dsp.window.move({ workspace = 2 }),
{ description = "Window: move to workspace 2" }
)
bind(
var.mainMod .. " + SHIFT + 3",
hl.dsp.window.move({ workspace = 3 }),
{ description = "Window: move to workspace 3" }
)
bind(
var.mainMod .. " + SHIFT + 4",
hl.dsp.window.move({ workspace = 4 }),
{ description = "Window: move to workspace 4" }
)
bind(
var.mainMod .. " + SHIFT + 5",
hl.dsp.window.move({ workspace = 5 }),
{ description = "Window: move to workspace 5" }
)
bind(
var.mainMod .. " + SHIFT + 6",
hl.dsp.window.move({ workspace = 6 }),
{ description = "Window: move to workspace 6" }
)
bind(
var.mainMod .. " + SHIFT + 7",
hl.dsp.window.move({ workspace = 7 }),
{ description = "Window: move to workspace 7" }
)
bind(
var.mainMod .. " + SHIFT + 8",
hl.dsp.window.move({ workspace = 8 }),
{ description = "Window: move to workspace 8" }
)
bind(
var.mainMod .. " + SHIFT + 9",
hl.dsp.window.move({ workspace = 9 }),
{ description = "Window: move to workspace 9" }
)
bind(
var.mainMod .. " + SHIFT + 0",
hl.dsp.window.move({ workspace = 10 }),
{ description = "Window: move to workspace 10" }
)
-- # Example special workspace (scratchpad)
-- bind = $mainMod, S, togglespecialworkspace, magic
-- bind = $mainMod SHIFT, S, movetoworkspace, special:magic
-- Scroll through existing workspaces with mainMod + scroll
bind(
var.mainMod .. " + mouse_down",
hl.dsp.focus({ workspace = "e+1" }),
{ description = "Workspace: next (scroll down)" }
)
bind(
var.mainMod .. " + mouse_up",
hl.dsp.focus({ workspace = "e-1" }),
{ description = "Workspace: previous (scroll up)" }
)
-- Move/resize windows with mainMod + LMB/RMB and dragging
bind(var.mainMod .. " + mouse:272", hl.dsp.window.drag(), {
mouse = true,
description = "Window: move with mouse",
})
bind(var.mainMod .. " + mouse:273", hl.dsp.window.resize(), {
mouse = true,
description = "Window: resize with mouse",
})
-- Laptop multimedia keys for volume and LCD brightness
bind("XF86AudioRaiseVolume", exec("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), {
repeating = true,
locked = true,
description = "Media: volume up (repeat)",
})
bind("XF86AudioLowerVolume", exec("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), {
repeating = true,
locked = true,
description = "Media: volume down (repeat)",
})
bind("XF86AudioMute", exec("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"), {
repeating = true,
locked = true,
description = "Media: mute audio",
})
bind("XF86AudioMicMute", exec("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"), {
repeating = true,
locked = true,
description = "Media: mute microphone",
})
bind("XF86MonBrightnessUp", exec("brightnessctl -e4 -n2 set 5%+"), {
repeating = true,
locked = true,
description = "Brightness up",
})
bind("XF86MonBrightnessDown", exec("brightnessctl -e4 -n2 set 5%-"), {
repeating = true,
locked = true,
description = "Brightness down",
})
-- Requires playerctl
bind("XF86AudioNext", exec("playerctl next"), {
locked = true,
description = "Media: next track",
})
bind("XF86AudioPause", exec("playerctl play-pause"), {
locked = true,
description = "Media: play/pause",
})
bind("XF86AudioPlay", exec("playerctl play-pause"), {
locked = true,
description = "Media: play/pause",
})
bind("XF86AudioPrev", exec("playerctl previous"), {
locked = true,
description = "Media: previous track",
})
-- Screenshots
bind("PRINT", exec("hyprshot -m region --output-folder " .. var.screenshot_folder), {
locked = true,
description = "Screenshot region",
})
bind("CTRL + PRINT", exec("hyprshot -m window --output-folder " .. var.screenshot_folder), {
locked = true,
description = "Screenshot window",
})
bind("SHIFT + PRINT", exec("hyprshot -m active --output-folder " .. var.screenshot_folder), {
locked = true,
description = "Screenshot active monitor",
})
bind(var.mainMod .. " + L", exec(command.lock), { locked = true, description = "Lock screen" })
bind(var.mainMod .. " + K", exec(command.keybinds_show), { description = "Keybinds: show overview" })
bind(var.mainMod .. " + W", exec(command.wallpaper_select), { description = "Wallpaper select" })
-- Caelestia extras
if env.shell == "caelestia" then
bind(var.mainMod .. " + SHIFT + V", exec(command.clipboard), { description = "Clipboard history" })
bind(var.mainMod .. " + SHIFT + K", exec(command.show_all), { description = "Toggle utilities" })
bind("CTRL + ALT + C", exec(command.clear_notifications), { description = "Clear notifications" })
end
-- Persist the registry for the show-keybinds picker
-- (scripts/show-keybinds.sh reads this TSV to resolve selected commands).
-- Runs on every config load/reload, keeping the picker in sync with the binds.
reg.write("/tmp/hypr-keybinds.tsv")
+260
View File
@@ -0,0 +1,260 @@
local var = require("modules.variables")
-- Refer to https://wiki.hypr.land/Configuring/Variables/
-- https://wiki.hypr.land/Configuring/Variables/#general
hl.config({
general = {
gaps_in = 3,
gaps_out = 4,
border_size = 3,
},
})
-- https://wiki.hypr.land/Configuring/Variables/#variable-types for info about colors
hl.config({
general = {
col = {
active_border = var.color_active_border,
inactive_border = var.color_inactive_border,
},
},
})
-- Set to true enable resizing windows by clicking and dragging on borders and gaps
hl.config({
general = {
resize_on_border = true,
},
})
-- Please see https://wiki.hypr.land/Configuring/Tearing/ before you turn this on
hl.config({
general = {
allow_tearing = false,
layout = "dwindle",
},
})
-- https://wiki.hypr.land/Configuring/Variables/#decoration
hl.config({
decoration = {
rounding = 5,
rounding_power = 2,
},
})
-- Change transparency of focused and unfocused windows
hl.config({
decoration = {
active_opacity = 1.0,
inactive_opacity = 1.0,
shadow = {
enabled = true,
range = 10,
render_power = 3,
color = var.color_decoration_shadow,
},
},
})
-- https://wiki.hypr.land/Configuring/Variables/#blur
hl.config({
decoration = {
blur = {
enabled = true,
size = 10,
passes = 2,
vibrancy = 0.1696,
},
},
})
-- https://wiki.hypr.land/Configuring/Variables/#animations
hl.config({
animations = {
enabled = true,
},
})
-- Default curves, see https://wiki.hypr.land/Configuring/Animations/#curves
-- NAME, X0, Y0, X1, Y1
hl.curve("easeOutQuint", { type = "bezier", points = { { 0.23, 1 }, { 0.32, 1 } } })
hl.curve("easeInOutCubic", { type = "bezier", points = { { 0.65, 0.05 }, { 0.36, 1 } } })
hl.curve("linear", { type = "bezier", points = { { 0, 0 }, { 1, 1 } } })
hl.curve("almostLinear", { type = "bezier", points = { { 0.5, 0.5 }, { 0.75, 1 } } })
hl.curve("quick", { type = "bezier", points = { { 0.15, 0 }, { 0.1, 1 } } })
-- Default animations, see https://wiki.hypr.land/Configuring/Animations/
-- NAME, ONOFF, SPEED, CURVE, [STYLE]
hl.animation({
leaf = "global",
enabled = true,
speed = 10,
bezier = "default",
})
hl.animation({
leaf = "border",
enabled = true,
speed = 5.39,
bezier = "easeOutQuint",
})
hl.animation({
leaf = "windows",
enabled = true,
speed = 4.79,
bezier = "easeOutQuint",
})
hl.animation({
leaf = "windowsIn",
enabled = true,
speed = 4.1,
bezier = "easeOutQuint",
style = "popin 87%",
})
hl.animation({
leaf = "windowsOut",
enabled = true,
speed = 1.49,
bezier = "linear",
style = "popin 87%",
})
hl.animation({
leaf = "fadeIn",
enabled = true,
speed = 1.73,
bezier = "almostLinear",
})
hl.animation({
leaf = "fadeOut",
enabled = true,
speed = 1.46,
bezier = "almostLinear",
})
hl.animation({
leaf = "fade",
enabled = true,
speed = 3.03,
bezier = "quick",
})
hl.animation({
leaf = "layers",
enabled = true,
speed = 3.81,
bezier = "easeOutQuint",
})
hl.animation({
leaf = "layersIn",
enabled = true,
speed = 4,
bezier = "easeOutQuint",
style = "fade",
})
hl.animation({
leaf = "layersOut",
enabled = true,
speed = 1.5,
bezier = "linear",
style = "fade",
})
hl.animation({
leaf = "fadeLayersIn",
enabled = true,
speed = 1.79,
bezier = "almostLinear",
})
hl.animation({
leaf = "fadeLayersOut",
enabled = true,
speed = 1.39,
bezier = "almostLinear",
})
hl.animation({
leaf = "workspaces",
enabled = true,
speed = 1.94,
bezier = "almostLinear",
style = "slide",
})
hl.animation({
leaf = "workspacesIn",
enabled = true,
speed = 1.21,
bezier = "almostLinear",
style = "slide",
})
hl.animation({
leaf = "workspacesOut",
enabled = true,
speed = 1.94,
bezier = "almostLinear",
style = "slide",
})
hl.animation({
leaf = "zoomFactor",
enabled = true,
speed = 7,
bezier = "quick",
})
-- Ref https://wiki.hypr.land/Configuring/Workspace-Rules/
-- "Smart gaps" / "No gaps when only"
-- uncomment all if you wish to use that.
hl.workspace_rule({
workspace = "w[tv1]",
gaps_out = 0,
gaps_in = 0,
})
hl.workspace_rule({
workspace = "f[1]",
gaps_out = 0,
gaps_in = 0,
})
hl.window_rule({
name = "no-gaps-wtv1",
match = {
float = false,
workspace = "w[tv1]",
},
border_size = 0,
rounding = 0,
})
hl.window_rule({
name = "no-gaps-f1",
match = {
float = false,
workspace = "f[1]",
},
border_size = 0,
rounding = 0,
})
-- See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more
hl.config({
dwindle = {
preserve_split = true,
},
})
-- See https://wiki.hypr.land/Configuring/Master-Layout/ for more
hl.config({
master = {
new_status = "master",
},
})
-- https://wiki.hypr.land/Configuring/Variables/#misc
hl.config({
misc = {
force_default_wallpaper = -1,
disable_hyprland_logo = false,
-- Both *_enables_dpms default to false, so a display left in DPMS-off
-- is unrecoverable without a TTY switch. A keypress should wake it.
key_press_enables_dpms = true,
},
})
@@ -1 +0,0 @@
monitor=,preferred,auto,1.0
@@ -1 +0,0 @@
monitor=,preferred,auto,1.0
@@ -1,9 +0,0 @@
-- monitor=,preferred,auto,1.0
hl.monitor({
output = "",
disabled = false,
mode = "preferred",
position = "auto",
scale = 1.0,
})
@@ -1,18 +0,0 @@
# monitorv2 {
# output = DP-2
# mode = highres highrr
# position = 0x0
# scale = 1.2
# bitdepth = 10
# cm = hdr
# supports_wide_color = 1
# supports_hdr = 1
# sdr_min_luminance = 0.005
# sdr_max_luminance = 200
# min_luminance = 0.002
# max_luminance = 200
# max_avg_luminance = 150
# }
monitor = DP-2, preferred, auto-left, 1.5
monitor = DP-3, preferred, auto-right, 1.0
@@ -1,14 +0,0 @@
hl.monitor({
output = "DP-2",
disabled = false,
mode = "preferred",
position = "auto-left",
scale = 1.5,
})
hl.monitor({
output = "DP-3",
disabled = false,
mode = "preferred",
position = "auto-right",
scale = 1.0,
})
@@ -0,0 +1,36 @@
-- Default
hl.monitor({
output = "",
disabled = false,
mode = "preferred",
position = "auto",
scale = 1.0,
})
-- -- Buntes Monster
-- hl.monitor({
-- output = "DP-2",
-- disabled = false,
-- mode = "preferred",
-- position = "auto-left",
-- scale = 1.5,
-- })
-- hl.monitor({
-- output = "DP-3",
-- disabled = false,
-- mode = "preferred",
-- position = "auto-right",
-- scale = 1.0,
-- })
-- -- Archtop
-- hl.monitor({
-- output = "",
-- disabled = false,
-- mode = "preferred",
-- position = "auto",
-- scale = 1.0,
-- })
@@ -0,0 +1,52 @@
local env = require("env")
local commands = {
session = "",
logout = "",
shutdown = "",
reboot = "",
menu = "",
settings = "",
control_center = "",
lock = "",
wallpaper_select = "",
keybinds_show = "sh ~/.config/hypr/scripts/show-keybinds.sh",
clipboard = "",
clipboard_delete = "",
emoji = "",
show_all = "",
clear_notifications = "",
}
-- Noctalia
if env.shell == "noctalia" then
commands.session = "noctalia msg panel-toggle session"
commands.logout = "command -v noctalia >/dev/null 2>&1 && noctalia msg session logout || hyprctl dispatch exit"
commands.shutdown = "noctalia msg session shutdown"
commands.reboot = "noctalia msg session reboot"
commands.menu = "noctalia msg panel-toggle launcher"
commands.settings = "noctalia msg settings-toggle"
commands.control_center = "noctalia msg panel-toggle control-center"
commands.wallpaper_select = "noctalia msg panel-toggle wallpaper"
commands.lock = "noctalia msg session lock"
commands.emoji = "noctalia msg panel-toggle launcher '/emo '"
-- Caelesia
elseif env.shell == "caelestia" then
commands.session = "caelestia shell drawers toggle session"
commands.logout = "hyprctl dispatch exit"
commands.shutdown = "systemctl poweroff"
commands.reboot = "systemctl reboot"
commands.menu = "caelestia shell drawers toggle launcher"
commands.settings = "caelestia shell drawers toggle dashboard"
commands.control_center = "caelestia shell drawers toggle sidebar"
commands.wallpaper_select = 'caelestia shell drawers toggle launcher && sleep 0.1 && wtype ">wallpaper "'
commands.clipboard = "caelestia clipboard"
commands.clipboard_delete = "caelestia clipboard -d"
commands.emoji = "caelestia emoji -p"
commands.show_all = "caelestia shell drawers toggle utilities"
commands.clear_notifications = "caelestia shell notifs clear"
commands.lock = "caelestia shell lock lock"
end
return commands
+25
View File
@@ -0,0 +1,25 @@
local theme = dofile(os.getenv("HOME") .. "/.config/themes/current/theme.lua")
-- local var_color_active_border = theme.border_active
-- local var_color_inactive_border = theme.border_inactive
-- local var_color_decoration_shadow = theme.shadow
-- local var_mainMod = "SUPER"
-- local var_terminal = "kitty"
-- local var_fileManager = "dolphin"
-- local var_menu = "noctalia msg panel-toggle launcher"
-- local var_screenshot_folder = "~/Bilder/Screenshots/"
local terminal = "kitty"
return {
color_active_border = theme.border_active,
color_inactive_border = theme.border_inactive,
color_decoration_shadow = theme.shadow,
mainMod = "SUPER",
terminal = terminal,
terminal_tmux = terminal .. " -e tmux",
fileManager = terminal .. " -e yazi", -- "dolphin",
screenshot_folder = "~/Bilder/Screenshots/",
internet_explorer = "firefox",
systemmonitor = terminal .. " -e btop",
}
@@ -0,0 +1,115 @@
-- See https://wiki.hypr.land/Configuring/Window-Rules/ for more
-- See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules
-- Example windowrules that are useful
-- Ignore maximize requests from all apps. You'll probably like this.
hl.window_rule({
name = "suppress-maximize-events",
match = {
class = ".*",
},
suppress_event = "maximize",
})
-- Fix some dragging issues with XWayland
hl.window_rule({
name = "fix-xwayland-drags",
match = {
class = "^$",
title = "^$",
xwayland = true,
float = true,
fullscreen = false,
pin = false,
},
no_focus = true,
})
-- Hyprland-run windowrule
hl.config({
decoration = {
blur = {
size = 8,
passes = 2,
},
},
})
hl.window_rule({
name = "move-hyprland-run",
match = {
class = "hyprland-run",
},
move = "20 monitor_h-120",
float = true,
})
hl.window_rule({
name = "keybinds-float",
match = {
class = "keybinds",
},
float = true,
size = "900 700",
center = true,
dim_around = true,
})
hl.window_rule({
name = "opacity-kitty-dolphin",
match = {
class = ".*(kitty|dolphin).*",
},
opacity = "0.90 0.80",
})
hl.window_rule({
match = {
class = ".*keybinds.*",
},
opacity = "0.75 0.50",
})
-- Noctalia shell surfaces: blur bars/panels/dock/notifications and let
-- Noctalia run its own animations (no Hyprland layer animation on top).
hl.layer_rule({
name = "noctalia",
match = {
namespace = "^noctalia-(bar-.+|notification|dock|panel|attached-panel|osd|window-switcher)$",
},
no_anim = true,
ignore_alpha = 0.5,
blur = true,
blur_popups = true,
})
hl.layer_rule({
name = "caelestia",
match = {
namespace = "^caelestia-.*$",
},
no_anim = true,
ignore_alpha = 0.5,
blur = true,
blur_popups = true,
})
hl.window_rule({
name = "noctalia-settings",
match = {
class = "dev.noctalia.Noctalia",
},
float = true,
size = "1080 920",
})
hl.window_rule({
name = "no-rounding-fullscreen",
match = {
fullscreen = 1,
},
rounding = 0,
border_size = 0,
})
hl.window_rule({
name = "floating-windows",
float = true,
match = { class = "(imv|.*hyprmod|.*[Bb]itwarden.*|ktouch)" },
size = "1080 920",
})
+54
View File
@@ -0,0 +1,54 @@
-- Generated by Noctalia
local primary = "rgb(cba6f7)"
local surface = "rgb(1e1e2e)"
local on_surface = "rgb(cdd6f4)"
local secondary = "rgb(fab387)"
local on_secondary = "rgb(11111b)"
local error = "rgb(f38ba8)"
local on_error = "rgb(11111b)"
local function apply_theme()
hl.config({
general = {
col = {
active_border = primary,
inactive_border = surface,
},
},
group = {
col = {
border_active = secondary,
border_inactive = surface,
border_locked_active = error,
border_locked_inactive = surface,
},
groupbar = {
col = {
active = secondary,
inactive = surface,
locked_active = error,
locked_inactive = surface,
},
text_color = on_secondary,
text_color_inactive = on_surface,
text_color_locked_active = on_error,
text_color_locked_inactive = on_surface,
},
},
})
end
return {
colors = {
primary = primary,
surface = surface,
on_surface = on_surface,
secondary = secondary,
on_secondary = on_secondary,
error = error,
on_error = on_error,
},
apply_theme = apply_theme
}
-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env sh
set -eu # Exit immediately if a command exits with a non-zero status, and treat unset variables as an error.
CONF_SOURCE="$HOME/.config/hypr/env.conf.template"
CONF_TARGET="$HOME/.config/hypr/env.conf"
SH_SOURCE="$HOME/.config/hypr/env.sh.template"
SH_TARGET="$HOME/.config/hypr/env.sh"
if [ ! -f "$CONF_TARGET" ]; then
cp "$CONF_SOURCE" "$CONF_TARGET"
echo "Created $CONF_TARGET from template $CONF_SOURCE"
fi
if [ ! -f "$SH_TARGET" ]; then
cp "$SH_SOURCE" "$SH_TARGET"
echo "Created $SH_TARGET from template $SH_SOURCE"
fi
+127 -59
View File
@@ -1,94 +1,162 @@
#!/usr/bin/env bash
# show-keybinds.sh — floating keybind overview popup.
# show-keybinds.sh — fuzzy, executable keybind picker.
#
# Reads the live keybind list from `hyprctl binds -j` and shows it in a
# floating kitty window (single column, sorted A-Z, searchable via less).
# Display-only: wofi/rofi are gone (the Noctalia launcher has no stdin-list
# mode), so picking a row to execute is not wired up.
# SUPER+K opens a floating kitty (class `keybinds`, see
# windows_and_workspaces.lua) running fzf over the keybind list:
# - start typing immediately: the fzf prompt is focused on open
# - arrow keys browse the (filtered) list
# - Enter executes the selected entry's command, then the picker closes
# - Esc closes without action
#
# Note: this config uses the Lua API (hl.bind), so `hyprctl binds -j` reports
# key + modmask + an opaque Lua registry reference instead of a readable
# dispatcher. The human-readable action comes from the `description` option
# added to each hl.bind(...) call - keep those descriptions up to date when
# you change a bind.
# Display data is read live from `hyprctl binds -j`. The command behind each
# entry cannot come from hyprctl — Lua-registered binds report as opaque
# `__lua` dispatchers there — so modules/keybind_registry.lua records every
# command at bind time and writes /tmp/hypr-keybinds.tsv on config load
# ("keys\x1fdescription\x1fcmd" lines). Entries without a recorded command
# (pure dispatchers like window.close) are informational only: Enter closes.
#
# Usage: show-keybinds.sh [--print]
# --print print the formatted list to stdout instead of opening kitty
# (handy for debugging / testing the formatting pipeline)
# Usage: show-keybinds.sh [--print | --internal-pick FILE]
# --print print the formatted list to stdout (debug/testing)
# --internal-pick F run fzf over picker file F and execute the selection
# (spawned by the default mode inside the kitty window)
set -euo pipefail
readonly SEP=$'\x1f'
# modmask bits reported by hyprctl (XKB modifiers), pairwise bit:name in
# display order. See https://wiki.hypr.land/Configuring/Binds/
readonly MOD_ORDER=(64 SUPER 8 ALT 4 CTRL 1 SHIFT 2 CAPS 16 MOD2 32 MOD3 128 MOD5)
readonly SIDECAR=/tmp/hypr-keybinds.tsv
if ! hyprctl binds -j >/dev/null 2>&1; then
echo "hyprctl binds failed - are you inside a Hyprland session?" >&2
# --internal-pick mode: runs INSIDE the floating kitty. fzf over the picker
# list (lines are "cmd\x1fdisplay"), then execute the chosen command and let
# the window close.
if [[ "${1:-}" == "--internal-pick" ]]; then
pick_file="${2:-}"
if [[ -z "$pick_file" || ! -s "$pick_file" ]]; then
echo "show-keybinds: --internal-pick needs an existing picker list file" >&2
exit 1
fi
# `|| rc=$?` keeps `set -e` from aborting before cleanup when fzf is
# cancelled (e.g. Esc) or filters to no match.
rc=0
sel="$(fzf --delimiter "$SEP" --with-nth 2.. --cycle --info=inline \
--prompt 'keybinds> ' --header 'type to filter · Enter executes · Esc closes' \
<"$pick_file")" || rc=$?
rm -f "$pick_file"
if ((rc != 0)) || [[ -z "$sel" ]]; then
exit 0
fi
cmd="${sel%%"$SEP"*}"
if [[ -n "$cmd" ]]; then
# Detach into its own session so the command outlives the picker
# window (kitty/pty teardown would otherwise signal its process group).
setsid -f sh -c "$cmd" >/dev/null 2>&1 </dev/null
fi
exit 0
fi
# ---------------------------------------------------------------------------
# Gather rows: prefer the sidecar (has commands); fall back to live `hyprctl
# binds -j` (display only, e.g. right after a fresh clone without a reload).
# ---------------------------------------------------------------------------
have_sidecar=0
if [[ -s "$SIDECAR" ]]; then
have_sidecar=1
fi
if ((! have_sidecar)) && ! hyprctl binds -j >/dev/null 2>&1; then
echo "show-keybinds: nothing to show: no keybind registry ($SIDECAR) and no Hyprland session" >&2
exit 1
fi
rows=()
cmds=()
keys=()
# modmask\x1fkey\x1fdescription\x1fsubmap\x1farg
# Fields are joined with the unit separator (0x1f): tabs are IFS-whitespace
# and `read` would collapse consecutive tabs, eating empty middle fields
# like the (usually empty) submap. \x1f is not whitespace, so every field
# keeps its position.
while IFS=$'\x1f' read -r modmask key description submap arg; do
# Humanize mouse-button binds.
case "$key" in
if ((have_sidecar)); then
while IFS="$SEP" read -r key description cmd; do
key="${key//mouse:272/LMB}"
key="${key//mouse:273/RMB}"
if [[ -z "$description" ]]; then
description="(no description)"
fi
rows+=("$(printf '%-26s %s' "$key" "$description")")
cmds+=("$cmd")
keys+=("$key")
done <"$SIDECAR"
else
while IFS="$SEP" read -r modmask key description submap; do
case "$key" in
mouse:272) key="LMB" ;;
mouse:273) key="RMB" ;;
esac
esac
# Build the chord, e.g. "SUPER + SHIFT + Q".
chord=""
i=0
while (( i < ${#MOD_ORDER[@]} )); do
bit=${MOD_ORDER[i]}
name=${MOD_ORDER[i + 1]}
if (( modmask & bit )); then
chord+="${name} + "
chord=""
# Rebuild "SUPER + SHIFT + Q" from the modmask bits.
i=0
while ((i < ${#MOD_ORDER[@]})); do
bit=${MOD_ORDER[i]}
name=${MOD_ORDER[i + 1]}
if ((modmask & bit)); then
chord+="${name} + "
fi
i=$((i + 2))
done
chord+="$key"
if [[ -n "$submap" ]]; then
chord="[$submap] $chord"
fi
i=$((i + 2))
done
chord+="$key"
if [[ -n "$submap" ]]; then
chord="[$submap] $chord"
fi
if [[ -n "$description" ]]; then
rows+=("$(printf '%-26s %s' "$chord" "$description")")
else
rows+=("$(printf '%-26s %s' "$chord" "(no description)")")
fi
cmds+=("")
keys+=("$chord")
done < <(hyprctl binds -j | jq -r '.[] | [(.modmask | tostring), .key, .description, .submap] | join("\u001f")')
fi
if [[ -n "$description" ]]; then
rows+=("$(printf '%-26s %s' "$chord" "$description")")
else
rows+=("$(printf '%-26s %s' "$chord" "(no description)")")
fi
done < <(hyprctl binds -j | jq -r '.[] | [(.modmask | tostring), .key, .description, .submap, .arg] | join("\u001f")')
if (( ${#rows[@]} == 0 )); then
echo "No keybinds found." >&2
if ((${#rows[@]} == 0)); then
echo "show-keybinds: no keybinds found." >&2
exit 1
fi
# Drop duplicate chords (e.g. media keys bound twice with different flags),
# then sort alphabetically (A-Z).
mapfile -t rows < <(printf '%s\n' "${rows[@]}" | awk '{ c = $0; sub(/ {2,}.*/, "", c); if (!seen[c]++) print }' | LC_ALL=C sort -f)
# keeping the first occurrence; carry the matching cmd along. Then sort by
# the display column A-Z.
declare -A seen=()
lines=()
for i in "${!rows[@]}"; do
if [[ -z "${seen[${keys[$i]}]:-}" ]]; then
seen["${keys[$i]}"]=1
lines+=("${cmds[$i]}$SEP${rows[$i]}")
fi
done
mapfile -t lines < <(printf '%s\n' "${lines[@]}" | LC_ALL=C sort -f -t "$SEP" -k2.29,2)
if [[ "${1:-}" == "--print" ]]; then
printf '%s\n' "${rows[@]}"
printf '%s\n' "${lines[@]}" | cut -d "$SEP" -f2-
exit 0
fi
# Floating display via kitty (class `keybinds` has a float rule in
# hyprland.lua). Rows go through a temp file rather than a stdin pipe so the
# popup does not depend on kitty forwarding stdin to its child; the previous
# run's file is cleaned up on the next invocation. q closes the window.
rm -f /tmp/keybinds.??????.txt 2>/dev/null || true
# ---------------------------------------------------------------------------
# Default mode: floating kitty + fzf. Rows go through a temp file; the inner
# --internal-pick run removes it when done, stale leftovers get cleaned on the
# next invocation.
# ---------------------------------------------------------------------------
rm -f /tmp/keybinds.??????.list 2>/dev/null || true
list="$(mktemp /tmp/keybinds.XXXXXX.list)"
printf '%s\n' "${lines[@]}" >"$list"
if command -v kitty >/dev/null 2>&1; then
tmp="$(mktemp /tmp/keybinds.XXXXXX.txt)"
printf '%s\n' "${rows[@]}" > "$tmp"
kitty --class keybinds --title Keybinds less -S "$tmp"
kitty --override font_size=16 --class keybinds --title Keybinds "$0" \
--internal-pick "$list"
exit 0
fi
printf '%s\n' "${rows[@]}"
# No kitty: fall back to a plain printout.
printf '%s\n' "${lines[@]}" | cut -d "$SEP" -f2-
rm -f "$list"
+32
View File
@@ -0,0 +1,32 @@
color0 #45475a
color1 #f38ba8
color2 #a6e3a1
color3 #f9e2af
color4 #89b4fa
color5 #f5c2e7
color6 #94e2d5
color7 #a6adc8
color8 #585b70
color9 #f37799
color10 #89d88b
color11 #ebd391
color12 #74a8fc
color13 #f2aede
color14 #6bd7ca
color15 #bac2de
cursor #f5e0dc
cursor_text_color #1e1e2e
background #1e1e2e
foreground #cdd6f4
selection_foreground #cdd6f4
selection_background #585b70
active_border_color #cba6f7
inactive_border_color #313244
url_color #cba6f7
active_tab_foreground #11111b
active_tab_background #cba6f7
inactive_tab_foreground #a3b4eb
inactive_tab_background #313244
cursor_trail_color #a3b4eb
+143 -40
View File
@@ -1,50 +1,153 @@
# Noctalia shell config (hypr/.config/noctalia/config.toml → ~/.config/noctalia/config.toml).
#
# Fresh start: Catppuccin Mocha palette + Noctalia-owned app theming.
# Bar/launcher/control-center/dock run on built-in defaults — explore and
# tune via the Settings UI. GUI edits land in
# ~/.local/state/noctalia/settings.toml and win over this file.
# Validate with: noctalia config validate
[bar.default]
background_opacity = 0.50999998860061169
capsule = true
center = [ "session", "launcher", "control-center", "wallpaper" ]
end = [
"tray",
"notifications",
"network",
"bluetooth",
"volume",
"brightness",
"temp",
"cpu",
"sysmon",
"battery",
"clock"
]
margin_ends = 0
panel_overlap = 0
position = "bottom"
radius = 0
start = [ "workspaces", "media" ]
thickness = 28
[desktop_widgets]
enabled = false
schema_version = 2
widget_order = []
[desktop_widgets.grid]
cell_size = 16
major_interval = 4
visible = true
[desktop_widgets.widget]
[dock]
background_opacity = 0.67999998480081558
[idle]
behavior_order = [ "backlight-dim", "kbd-off", "lock", "screen-off", "suspend" ]
[idle.behavior.backlight-dim]
action = "command"
command = "brightnessctl -s set 10"
enabled = true
resume_command = "brightnessctl -r"
timeout = 300.0
[idle.behavior.kbd-off]
action = "command"
command = "brightnessctl -sd rgb:kbd_backlight set 0"
enabled = true
resume_command = "brightnessctl -rd rgb:kbd_backlight"
timeout = 300.0
[idle.behavior.lock]
action = "lock"
enabled = true
timeout = 900.0
[idle.behavior.screen-off]
action = "screen_off"
enabled = false
timeout = 1800.0
[idle.behavior.suspend]
action = "lock_and_suspend"
enabled = true
timeout = 2700.0
[keybinds]
down = [ "Down", "Ctrl+j" ]
left = [ "Left", "Ctrl+h" ]
right = [ "Right", "Ctrl+l" ]
up = [ "Up", "Ctrl+k" ]
[location]
auto_locate = true
[lockscreen_widgets]
enabled = false
schema_version = 2
widget_order = [ "lockscreen-login-box@eDP-1" ]
[lockscreen_widgets.grid]
cell_size = 16
major_interval = 4
visible = true
[lockscreen_widgets.widget."lockscreen-login-box@eDP-1"]
box_height = 196.0
box_width = 810.0
cx = 960.0
cy = 898.0
output = "eDP-1"
placement_height = 1080.0
placement_width = 1920.0
rotation = 0.0
type = "login_box"
[lockscreen_widgets.widget."lockscreen-login-box@eDP-1".settings]
background_color = "surface_variant"
background_opacity = 0.88
background_radius = 12.0
center_password_text = false
input_opacity = 1.0
input_radius = 6.0
layout = "regular"
show_caps_lock = true
show_keyboard_layout = true
show_login_button = true
show_media = true
show_session_buttons = true
show_unlock_hint = true
show_weather = true
[shell]
font_family = "JetBrainsMono Nerd Font Mono"
telemetry_enabled = true
[shell.panel]
launcher_placement = "attached"
transparency_mode = "glass"
[theme]
builtin = "Catppuccin"
mode = "dark"
shell_mode = "follow"
source = "custom"
custom_palette = "Catppuccin-Mocha"
[theme.templates]
enable_builtin_templates = true
# IDs from `noctalia theme --list-templates`. The `hyprland` template is
# intentionally off: basic/.config/themes owns Hyprland border colors.
builtin_ids = ["kitty", "gtk3", "gtk4", "qt", "kcolorscheme", "starship"]
enable_community_templates = true
community_ids = ["neovim"]
[theme.templates]
builtin_ids = [ "gtk3", "gtk4", "hyprland", "kitty" ]
enable_builtin_templates = true
# Idle behaviors (replaces hypr/.config/hypr/hypridle.conf, same timings:
# dim + kbd off at 5min, lock at 15min, monitors off at 30min, suspend at 45min).
[idle]
behavior_order = ["backlight-dim", "kbd-off", "lock", "screen-off", "suspend"]
[wallpaper]
directory = "/home/mathias/nextcloud/Photos/Wallpapers"
[idle.behavior.backlight-dim]
timeout = 300
action = "command"
command = "brightnessctl -s set 10"
resume_command = "brightnessctl -r"
[wallpaper.default]
path = "/home/mathias/nextcloud/Photos/Wallpapers/eigen/20180318-4825-Teneriffa_LaPalma-2.jpg"
[idle.behavior.kbd-off]
timeout = 300
action = "command"
command = "brightnessctl -sd rgb:kbd_backlight set 0"
resume_command = "brightnessctl -rd rgb:kbd_backlight"
[wallpaper.last]
path = "/home/mathias/nextcloud/Photos/Wallpapers/eigen/20180318-4825-Teneriffa_LaPalma-2.jpg"
[idle.behavior.lock]
timeout = 900
action = "lock"
[wallpaper.monitors.eDP-1]
path = "/home/mathias/nextcloud/Photos/Wallpapers/eigen/20180318-4825-Teneriffa_LaPalma-2.jpg"
[idle.behavior.screen-off]
timeout = 1800
action = "screen_off"
[widget.clock]
format = "{:%Y-%m-%d|%H:%M}"
[idle.behavior.suspend]
timeout = 2700
action = "lock_and_suspend"
[widget.network]
show_label = false
[widget.sysmon]
stat = "gpu_usage"
@@ -1,48 +0,0 @@
{
"dark": {
"mPrimary": "#74c7ec",
"mOnPrimary": "#11111b",
"mSecondary": "#b4befe",
"mOnSecondary": "#11111b",
"mTertiary": "#cba6f7",
"mOnTertiary": "#11111b",
"mError": "#f38ba8",
"mOnError": "#11111b",
"mSurface": "#1e1e2e",
"mOnSurface": "#cdd6f4",
"mSurfaceVariant": "#313244",
"mOnSurfaceVariant": "#a6adc8",
"mOutline": "#45475a",
"mShadow": "#11111b",
"mHover": "#45475a",
"mOnHover": "#cdd6f4",
"terminal": {
"background": "#1e1e2e",
"foreground": "#cdd6f4",
"cursor": "#f5e0dc",
"cursorText": "#1e1e2e",
"selectionBg": "#585b70",
"selectionFg": "#cdd6f4",
"normal": {
"black": "#45475a",
"red": "#f38ba8",
"green": "#a6e3a1",
"yellow": "#f9e2af",
"blue": "#89b4fa",
"magenta": "#cba6f7",
"cyan": "#94e2d5",
"white": "#bac2de"
},
"bright": {
"black": "#585b70",
"red": "#f38ba8",
"green": "#a6e3a1",
"yellow": "#f9e2af",
"blue": "#89b4fa",
"magenta": "#cba6f7",
"cyan": "#94e2d5",
"white": "#a6adc8"
}
}
}
}
-2
View File
@@ -1,2 +0,0 @@
scripts
.stow-ignore
-25
View File
@@ -1,25 +0,0 @@
# ---------------------------------------------------------------------------
# Hyprland compositor package list for hypr/setup.sh
#
# Wayland compositor, screenshot tool and supporting utilities. The desktop
# shell (bar, launcher, notifications, lock screen, wallpaper, idle, session
# menu) is Noctalia, not a set of standalone ecosystem tools.
#
# - Lines starting with '#' and blank lines are ignored.
# - Use "@pacman", "@aur" or "@npm" markers to switch section.
# - The default section is @pacman.
# ---------------------------------------------------------------------------
@pacman
hyprland
xdg-desktop-portal-hyprland
hyprpolkitagent
pantheon-shortcut-overlay
wev
wl-clipboard
hyprshot
brightnessctl
noctalia
@aur
hyprmod
-92
View File
@@ -1,92 +0,0 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SCRIPT_DIR/packages.txt"
# ---------------------------------------------------------------------------
# Read packages.txt, split into pacman / aur / npm sections.
# ---------------------------------------------------------------------------
read_packages() {
local section="pacman"
local current
current=""
while IFS= read -r line || [[ -n "$line" ]]; do
current="${line%%#*}"
current="${current##*( )}"
current="${current%%*( )}"
[[ -z "$current" ]] && continue
case "$current" in
@pacman) section="pacman" ;;
@aur) section="aur" ;;
@npm) section="npm" ;;
*)
case "$section" in
pacman) pacman_pkgs+=("$current") ;;
aur) aur_pkgs+=("$current") ;;
npm) npm_pkgs+=("$current") ;;
esac
;;
esac
done < "$PACKAGES_FILE"
}
declare -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
# ---------------------------------------------------------------------------
# Install sections.
# ---------------------------------------------------------------------------
install_pacman() {
if ((${#pacman_pkgs[@]})); then
echo "==> Installiere Pacman-Pakete: ${pacman_pkgs[*]}"
yay -S --needed "${pacman_pkgs[@]}"
fi
}
install_aur() {
if ((${#aur_pkgs[@]})); then
echo "==> Installiere AUR-Pakete: ${aur_pkgs[*]}"
yay -S --needed "${aur_pkgs[@]}"
fi
}
install_npm() {
if ((${#npm_pkgs[@]})); then
echo "==> Installiere globale npm-Pakete: ${npm_pkgs[*]}"
npm install -g "${npm_pkgs[@]}"
fi
}
# ---------------------------------------------------------------------------
# Post-install: run Hyprland environment & desktop integration scripts.
# ---------------------------------------------------------------------------
run_hypr_scripts() {
local scripts_dir="$SCRIPT_DIR/../.config/hypr/scripts"
echo "==> Fuehre ensure-env.sh aus ..."
bash "$scripts_dir/ensure-env.sh"
echo "==> Fuehre portal-host-override.sh aus ..."
bash "$scripts_dir/portal-host-override.sh"
echo "==> Fuehre fix_dolphin_file_associations.sh aus ..."
bash "$scripts_dir/fix_dolphin_file_associations.sh"
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages
install_pacman
install_aur
install_npm
run_hypr_scripts
echo "Fertig. Hyprland und das Compositor-Okosystem sind eingerichtet."
}
main
+86
View File
@@ -0,0 +1,86 @@
# Notizen
## Buntes-Monster mit NFS verbinden
### Server-Seite (Buntes-Monster)
`nfs-utils` installieren
```bash
sudo pacman -S nfs-utils
```
Datei `/etc/exports` bearbeiten: Zeilen anfügen:
```bash
/mnt/anbau 192.168.0.0/24(rw,sync,no_subtree_check)
/mnt/bilder 192.168.0.0/24(rw,sync,no_subtree_check)
```
Apply exports configuration
```bash
sudo exportfs -rav
```
Or restart the NFS service to reload
```bash
sudo systemctl restart nfs-server
```
Enable NFS Service at Boot
```bash
sudo systemctl enable --now nfs-server
```
### Server-Seite
`nfs-utils` installieren
```bash
sudo pacman -S nfs-utils
```
`/etc/fstab`: Zeilen hinzufügen:
```bash
buntes-monster:/mnt/anbau /mnt/anbau nfs rw,sync,addr=192.168.0.4 0 0
buntes-monster:/mnt/bilder /mnt/bilder nfs rw,sync,addr=192.168.0.4 0 0
```
(Annahmen: IP buntes-monster: 192.168.0.4)
Eiträge hinzufügen. Danach Mounts laden:
```bash
sudo mount -a
```
## FSTAB
`fstab` bearbeiten füt automatische Mounts:
```bash
sudo nvim /etc/fstab
```
Eiträge hinzufügen. Danach Mounts laden:
```bash
sudo mount -a
```
### hidrive
```bash
mathias2784@sftp.hidrive.strato.com:/users/mathias2784 /mnt/hidrive fuse.sshfs defaults,_netdev,IdentityFile=/home/mathias/.ssh/id_ed25519,allow_other 0 0
```
### NAS
```bash
//192.168.0.14/Mathias /mnt/nas/mathias cifs credentials=/home/mathias/.nascred,uid=1000,gid=1000,iocharset=utf8,vers=3.1.1,rsize=65536,wsize=65536,cache=strict,noatime 0 0
//192.168.0.14/Gemeinsam /mnt/nas/gemeinsam cifs credentials=/home/mathias/.nascred,uid=1000,gid=1000,iocharset=utf8,vers=3.1.1,rsize=65536,wsize=65536,cache=strict,noatime 0 0
```
@@ -1,5 +1,5 @@
# ---------------------------------------------------------------------------
# System package list for basic/setup.sh
# System package list for setup/basic/setup.sh
#
# Every other dotfile branch depends on these foundational packages
# (base system, display manager, audio stack, AUR helper).
+68
View File
@@ -0,0 +1,68 @@
#!/bin/bash
set -euo pipefail
SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SETUP_DIR/packages.txt"
# shellcheck source=../lib/common.sh
source "$SETUP_DIR/../lib/common.sh"
# ---------------------------------------------------------------------------
# Docker: Dienst aktivieren/starten, Benutzer in die docker-Gruppe aufnehmen
# und den Dienst verifizieren. (docker selbst wird ueber setup/basic/packages.txt
# als Pacman-Paket installiert.)
# ---------------------------------------------------------------------------
setup_docker() {
if ! command -v docker >/dev/null 2>&1; then
echo "Warnung: docker nicht installiert; ueberspringe Docker-Setup."
return
fi
echo "==> Aktiviere und starte Docker-Dienst ..."
sudo systemctl enable --now docker
# Bei Aufruf via `sudo <script>` ist SUDO_USER der eigentliche Benutzer.
local target_user="${SUDO_USER:-$USER}"
echo "==> Stelle sicher, dass $target_user in der docker-Gruppe ist ..."
if [[ "$target_user" == "root" ]] || id -nG "$target_user" 2>/dev/null | grep -qw docker; then
echo "Benutzer $target_user ist bereits in der docker-Gruppe."
else
sudo usermod -aG docker "$target_user"
echo "Benutzer $target_user zur docker-Gruppe hinzugefuegt; wirksam nach dem naechsten Login."
fi
echo "==> Pruefe Docker-Dienst ..."
if systemctl is-active --quiet docker; then
echo "Docker-Dienst laeuft (Socket: /var/run/docker.sock)."
else
echo "Warnung: Docker-Dienst laeuft nicht; pruefe mit: systemctl status docker"
fi
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
local -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
echo "==> Aktiviere multilib ..."
enable_multilib
echo "==> System aktualisieren ..."
sudo pacman -Syu
echo "==> Sicherstelle yay ..."
ensure_yay
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages "$PACKAGES_FILE" pacman_pkgs aur_pkgs npm_pkgs
install_all_pkgs pacman_pkgs aur_pkgs npm_pkgs
echo "==> Richte Docker ein ..."
setup_docker
echo "Fertig. Die Basis-Systemumgebung ist eingerichtet."
}
main
@@ -1,11 +1,11 @@
#!/bin/bash
# Refresh vendored upstream port files (basic/scripts/fetch-ports.sh).
# Refresh vendored upstream port files (setup/fetch-ports.sh).
#
# This script is intentionally NOT stowed (basic/.stow-ignore) and NOT run
# This script lives outside the stow packages (setup/) and is NOT run
# by the test harness: it contacts the network. Run it manually when you
# want to pull newer upstream Catppuccin ports into the central theme:
#
# bash basic/scripts/fetch-ports.sh
# bash setup/fetch-ports.sh
#
# The central palette (theme.lua / theme.css roles / hypr.conf) remains the
# source of truth; after fetching, re-apply the provenance headers and the
@@ -14,7 +14,7 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEST="$SCRIPT_DIR/../.config/themes/themes/catppuccin-mocha"
DEST="$SCRIPT_DIR/../basic/.config/themes/themes/catppuccin-mocha"
# Pinned upstream revisions (bump deliberately, then run this script).
KITTY_PIN="main"
+39
View File
@@ -0,0 +1,39 @@
# ---------------------------------------------------------------------------
# Hyprland compositor package list for setup/hypr/setup.sh
#
# Wayland compositor, screenshot tool and supporting utilities. Both desktop
# shell frontends are installed: Noctalia and Caelestia. Select the one started
# by Hyprland in hypr/.config/hypr/env.lua.
#
# Caelestia requires the upstream `quickshell-git` build. The explicit
# `aur/` source prefix below is intentional: yay's --aur mode alone can still
# select a repository provider. Do not substitute `noctalia-qs`; although it
# provides `quickshell-git`, that fork is incompatible with Caelestia's
# Quickshell pragmas.
#
# - Lines starting with '#' and blank lines are ignored.
# - Use "@pacman", "@aur" or "@npm" markers to switch section.
# - The default section is @pacman.
# ---------------------------------------------------------------------------
@pacman
hyprland
hypridle
hyprpm
xdg-desktop-portal-hyprland
hyprpolkitagent
pantheon-shortcut-overlay
wev
wl-clipboard
hyprshot
brightnessctl
noctalia
wtype
@aur
hyprmod
caelestia-shell
caelestia-cli
aur/quickshell-git
hyprsaver
python-terminaltexteffects
+99
View File
@@ -0,0 +1,99 @@
#!/bin/bash
set -euo pipefail
SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SETUP_DIR/packages.txt"
# shellcheck source=../lib/common.sh
source "$SETUP_DIR/../lib/common.sh"
# ---------------------------------------------------------------------------
# Create the local shell selection from the tracked example exactly once.
# env.lua is ignored by Git so each machine can keep its own choice.
# ---------------------------------------------------------------------------
ensure_shell_config() {
local config_dir example_file config_file
config_dir="$(repo_root)/hypr/.config/hypr"
example_file="$config_dir/env.example.lua"
config_file="$config_dir/env.lua"
if [[ -e "$config_file" || -L "$config_file" ]]; then
echo "==> Behalte lokale Shell-Auswahl: $config_file"
return
fi
echo "==> Erstelle lokale Shell-Auswahl aus env.example.lua ..."
cp "$example_file" "$config_file"
}
# ---------------------------------------------------------------------------
# Keep Caelestia on upstream Quickshell.
#
# noctalia-qs can satisfy pacman's virtual quickshell-git dependency, but its
# parser is not compatible with Caelestia. The explicit aur/quickshell-git
# target bypasses that provider, then setup verifies that /usr/bin/qs really
# belongs to quickshell-git.
# ---------------------------------------------------------------------------
warn_about_quickshell_provider() {
if pacman -Q noctalia-qs >/dev/null 2>&1; then
log "noctalia-qs ist installiert; die AUR-Transaktion ersetzt es durch quickshell-git."
fi
}
verify_quickshell_runtime() {
local owner
if pacman -Q noctalia-qs >/dev/null 2>&1; then
echo "Fehler: noctalia-qs ist weiterhin installiert; Caelestia benoetigt AUR quickshell-git." >&2
return 1
fi
if ! pacman -Q quickshell-git >/dev/null 2>&1; then
echo "Fehler: AUR-Paket quickshell-git wurde nicht installiert." >&2
return 1
fi
owner="$(pacman -Qoq /usr/bin/qs 2>/dev/null || true)"
if [[ "$owner" != "quickshell-git" ]]; then
echo "Fehler: /usr/bin/qs gehoert zu '$owner' statt zu quickshell-git." >&2
return 1
fi
log "Quickshell-Runtime geprueft: quickshell-git"
}
# ---------------------------------------------------------------------------
# Post-install: run Hyprland environment & desktop integration scripts.
# ---------------------------------------------------------------------------
run_hypr_scripts() {
local scripts_dir
scripts_dir="$(repo_root)/hypr/.config/hypr/scripts"
echo "==> Fuehre portal-host-override.sh aus ..."
bash "$scripts_dir/portal-host-override.sh"
echo "==> Fuehre fix_dolphin_file_associations.sh aus ..."
bash "$scripts_dir/fix_dolphin_file_associations.sh"
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
local -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages "$PACKAGES_FILE" pacman_pkgs aur_pkgs npm_pkgs
warn_about_quickshell_provider
install_all_pkgs pacman_pkgs aur_pkgs npm_pkgs
verify_quickshell_runtime
ensure_shell_config
run_hypr_scripts
echo "Fertig. Hyprland und das Compositor-Okosystem sind eingerichtet."
}
main
+26
View File
@@ -0,0 +1,26 @@
# ---------------------------------------------------------------------------
# Kreation package list for setup/kreation/setup.sh
#
# DAW, video and audio-plugin runtime.
#
# - Lines starting with '#' and blank lines are ignored.
# - Use "@pacman", "@aur" or "@npm" markers to switch section.
# - The default section is @pacman.
# ---------------------------------------------------------------------------
@pacman
reaper
guitarix
kdenlive
yabridge
yabridgectl
obs-studio
surge-xt
lsp-plugins
calf
dragonfly-reverb
darktable
gimp
@aur
numaplayer
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
set -euo pipefail
SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SETUP_DIR/packages.txt"
# shellcheck source=../lib/common.sh
source "$SETUP_DIR/../lib/common.sh"
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
local -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages "$PACKAGES_FILE" pacman_pkgs aur_pkgs npm_pkgs
install_all_pkgs pacman_pkgs aur_pkgs npm_pkgs
echo "Fertig. Kreation-Pakete (DAW, Video, Plugins) sind eingerichtet."
}
main
+126
View File
@@ -0,0 +1,126 @@
#!/bin/bash
# setup/lib/common.sh
#
# Shared helpers for the setup/install scripts under setup/.
# Source this file; do not execute it directly:
#
# SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# # shellcheck source=../lib/common.sh
# source "$SETUP_DIR/../lib/common.sh"
#
# Conventions:
# - The caller owns `set -euo pipefail` and PACKAGES_FILE.
# - Package lists use @pacman (default) / @aur / @npm section markers;
# '#' starts a comment, blank lines are ignored.
# - Set NPM_USE_SUDO=1 before calling install_npm_pkgs when the global
# npm root is root-owned (Arch installs npm to /usr/lib/node_modules).
# Print the repository root (setup/lib/ -> repo root).
repo_root() {
cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd
}
log() {
echo "==> $*"
}
# ---------------------------------------------------------------------------
# Read a packages.txt file, split into pacman / aur / npm sections.
# Usage: read_packages <file> <pacman_array> <aur_array> <npm_array>
# ---------------------------------------------------------------------------
read_packages() {
local file="$1" pacman_ref="$2" aur_ref="$3" npm_ref="$4"
local section="pacman"
local line current
local -n _pacman="$pacman_ref" _aur="$aur_ref" _npm="$npm_ref"
while IFS= read -r line || [[ -n "$line" ]]; do
current="${line%%#*}"
current="${current##*( )}"
current="${current%%*( )}"
[[ -z "$current" ]] && continue
case "$current" in
@pacman) section="pacman" ;;
@aur) section="aur" ;;
@npm) section="npm" ;;
*)
case "$section" in
pacman) _pacman+=("$current") ;;
aur) _aur+=("$current") ;;
npm) _npm+=("$current") ;;
esac
;;
esac
done < "$file"
}
# ---------------------------------------------------------------------------
# Install sections (arrays passed by nameref).
# ---------------------------------------------------------------------------
install_pacman_pkgs() {
local -n _pkgs="$1"
if ((${#_pkgs[@]})); then
log "Installiere Pacman-Pakete: ${_pkgs[*]}"
yay -S --needed "${_pkgs[@]}"
fi
}
install_aur_pkgs() {
local -n _pkgs="$1"
if ((${#_pkgs[@]})); then
log "Installiere AUR-Pakete: ${_pkgs[*]}"
# --aur selects yay's AUR mode. For names that a repository package
# can also provide, use an explicit aur/<package> target in the list.
yay -S --aur --needed "${_pkgs[@]}"
fi
}
install_npm_pkgs() {
local -n _pkgs="$1"
if ((${#_pkgs[@]})); then
log "Installiere globale npm-Pakete: ${_pkgs[*]}"
if [[ "${NPM_USE_SUDO:-0}" == "1" ]]; then
sudo npm install -g "${_pkgs[@]}"
else
npm install -g "${_pkgs[@]}"
fi
fi
}
# Install all three sections at once.
install_all_pkgs() {
install_pacman_pkgs "$1"
install_aur_pkgs "$2"
install_npm_pkgs "$3"
}
# ---------------------------------------------------------------------------
# Enable multilib in /etc/pacman.conf (with a safety backup).
# ---------------------------------------------------------------------------
enable_multilib() {
sudo sed -i.bak '/^#\[multilib\]/,+1 s/^#//' /etc/pacman.conf
}
# ---------------------------------------------------------------------------
# Ensure yay (AUR helper) is installed.
# ---------------------------------------------------------------------------
ensure_yay() {
if pacman -Q yay &>/dev/null; then
echo "yay bereits installiert; fahre fort."
return
fi
if pacman -Si yay &>/dev/null; then
echo "Installiere yay mit pacman ..."
sudo pacman -S --needed yay
return
fi
echo "installiere yay via git ..."
sudo pacman -S --needed base-devel git
local tmp
tmp="$(mktemp -d)"
git clone https://aur.archlinux.org/yay.git "$tmp/yay"
(
cd "$tmp/yay"
makepkg -si
)
rm -rf "$tmp"
}
@@ -1,5 +1,5 @@
# ---------------------------------------------------------------------------
# Terminal package list for term/setup.sh
# Terminal package list for setup/term/setup.sh
#
# Maintenance:
# - Add / remove packages on separate lines.
@@ -37,6 +37,10 @@ fzf
locate
ttf-jetbrains-mono-nerd
ttf-font-awesome
btop
yt-dlp
ffmpeg
jc
@aur
opencode
+14 -62
View File
@@ -1,63 +1,15 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SCRIPT_DIR/packages.txt"
SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SETUP_DIR/packages.txt"
# ---------------------------------------------------------------------------
# Read packages.txt, split into pacman / aur / npm sections.
# ---------------------------------------------------------------------------
read_packages() {
local section="pacman"
local current
current=""
while IFS= read -r line || [[ -n "$line" ]]; do
current="${line%%#*}"
current="${current##*( )}"
current="${current%%*( )}"
[[ -z "$current" ]] && continue
case "$current" in
@pacman) section="pacman" ;;
@aur) section="aur" ;;
@npm) section="npm" ;;
*)
case "$section" in
pacman) pacman_pkgs+=("$current") ;;
aur) aur_pkgs+=("$current") ;;
npm) npm_pkgs+=("$current") ;;
esac
;;
esac
done < "$PACKAGES_FILE"
}
# shellcheck source=../lib/common.sh
source "$SETUP_DIR/../lib/common.sh"
declare -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
# ---------------------------------------------------------------------------
# Install sections.
# ---------------------------------------------------------------------------
install_pacman() {
if ((${#pacman_pkgs[@]})); then
echo "==> Installiere Pacman-Pakete: ${pacman_pkgs[*]}"
yay -S --needed "${pacman_pkgs[@]}"
fi
}
install_aur() {
if ((${#aur_pkgs[@]})); then
echo "==> Installiere AUR-Pakete: ${aur_pkgs[*]}"
yay -S --needed "${aur_pkgs[@]}"
fi
}
install_npm() {
if ((${#npm_pkgs[@]})); then
echo "==> Installiere globale npm-Pakete: ${npm_pkgs[*]}"
# Arch installiert npm nach /usr/lib/node_modules (root-owned),
# daher braucht der globale Install sudo.
sudo npm install -g "${npm_pkgs[@]}"
fi
}
# Arch installiert npm nach /usr/lib/node_modules (root-owned),
# daher braucht der globale Install sudo.
NPM_USE_SUDO=1
# ---------------------------------------------------------------------------
# Post-install configuration.
@@ -131,14 +83,14 @@ add_yazi_git_plugin() {
# Main
# ---------------------------------------------------------------------------
main() {
# Hinweis: multilib, yay und das System-Update werden von
# basic/setup.sh uebernommen (laeuft vor term im Makefile).
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages
local -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
install_pacman
install_aur
install_npm
# Hinweis: multilib, yay und das System-Update werden von
# setup/basic/setup.sh uebernommen (laeuft vor term im Makefile).
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages "$PACKAGES_FILE" pacman_pkgs aur_pkgs npm_pkgs
install_all_pkgs pacman_pkgs aur_pkgs npm_pkgs
set_fish_default_shell
install_tmuxifier
@@ -1,5 +1,5 @@
# ---------------------------------------------------------------------------
# Standalone desktop utility package list for utils/setup.sh
# Standalone desktop utility package list for setup/utils/setup.sh
#
# Programs that are not core to every branch, but are expected on a full
# desktop: office / web / mail / native-app replacements (Wine), the
@@ -11,6 +11,7 @@
# ---------------------------------------------------------------------------
@pacman
firefox
nextcloud-client
thunderbird
ktouch
@@ -20,3 +21,12 @@ wine-mono
wine-gecko
winetricks
rbw
nfs-utils
code
imv
bitwarden
@aur
supersonic-desktop
subtui
localsend
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
set -euo pipefail
SETUP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SETUP_DIR/packages.txt"
# shellcheck source=../lib/common.sh
source "$SETUP_DIR/../lib/common.sh"
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
local -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages "$PACKAGES_FILE" pacman_pkgs aur_pkgs npm_pkgs
install_all_pkgs pacman_pkgs aur_pkgs npm_pkgs
echo "Fertig. Standalone Utilities sind eingerichtet."
}
main
+5
View File
@@ -46,3 +46,8 @@ fi
if command -v fastfetch >/dev/null 2>&1; then
fastfetch --config ~/.config/fastfetch/config.jsonc
fi
# Added by LM Studio CLI (lms)
export PATH="$PATH:/home/mathias/.lmstudio/bin"
# End of LM Studio CLI section
+13
View File
@@ -141,3 +141,16 @@ export HSA_OVERRIDE_GFX_VERSION=11.0.0
export HIP_VISIBLE_DEVICES=0
fish_add_path -m $HOME/.local/bin
# My shortcuts
alias fdh="fd -H"
alias fdhi="fd -HI"
alias rgh="rg --hidden"
alias rghi="rg --hidden --no-ignore"
export PATH="$HOME/.cargo/bin:$PATH"
# Added by LM Studio CLI (lms)
set -gx PATH $PATH /home/mathias/.lmstudio/bin
# End of LM Studio CLI section
+7
View File
@@ -207,6 +207,13 @@ A feature-rich Neovim setup optimized for Python, JSON, and CSV development.
- **Linting**: ESLint LSP (fix with `<leader>fx`, or use `<leader>fA` for fix-all actions)
- **Formatting**: Prettier via `<leader>lf`
### HTML (.html)
- **Auto-close tags**: typing `<div` + `>` inserts `</div>` automatically (`nvim-ts-autotag`)
- **Auto-rename tags**: `ciw` on an opening tag renames the matching closing tag
- **Enter between tags**: expands to indented lines via Treesitter indenting
- **Also applies to**: `.vue`, `.tsx`, `.jsx`, `.svelte`, `.astro`, `.xml`, `.php`, `.hbs`
- **Requires** the Treesitter parser for the filetype (already auto-installed for html/vue/tsx)
### CSV (.csv)
- **Treesitter**: Syntax highlighting
- **No wrap**: Full row visibility
+12 -1
View File
@@ -17,11 +17,22 @@ return {
css = { "prettier" },
scss = { "prettier" },
yaml = { "prettier" },
markdown = { "prettier" },
markdown = { "prettier_markdown" },
sh = { "shfmt" },
bash = { "shfmt" },
rust = { "rustfmt" },
},
formatters = {
prettier_markdown = {
inherit = "prettier",
prepend_args = {
"--prose-wrap",
"always",
"--print-width",
"80",
},
},
},
})
vim.keymap.set({ "n", "v" }, "<leader>lf", function()
@@ -0,0 +1,33 @@
--[[
TS-AUTOTAG.LUA
Auto-close and auto-rename HTML/XML-style tags via Treesitter.
Why this exists: nvim-autopairs (see autopairs.lua) only handles brackets,
quotes and endwise pairs -- it never creates a closing tag. Its only
HTML-aware rule fires on <CR> when a close tag ALREADY exists after the
cursor, so it can re-indent a pair but cannot create one. This plugin
fills that gap: typing `<div` + `>` yields `<div></div>` with the cursor
in between, and `ciw` on an opening tag renames its closing counterpart.
Requires the matching Treesitter parsers. `html`, `vue`, `tsx` and
`javascript` are already in treesitter.lua's `ensure_installed` list, and
the plugin no-ops in filetypes whose parser is missing, so a fresh machine
just needs a restart after the parsers are installed.
]]
return {
"windwp/nvim-ts-autotag",
-- Load events recommended upstream. BufReadPre/BufNewFile is sufficient
-- because the plugin only acts once a filetype's parser is available.
event = { "BufReadPre", "BufNewFile" },
config = function()
require("nvim-ts-autotag").setup({
opts = {
enable_close = true, -- `<div` + `>` -> `<div></div>`
enable_rename = true, -- `ciw` on the open tag renames the close tag
enable_close_on_slash = false, -- a trailing `</` does not autoclose
},
})
end,
}
+1 -1
View File
@@ -63,7 +63,7 @@
"npm": "@ai-sdk/openai-compatible",
"name": "LM Studio (local)",
"options": {
"baseURL": "http://192.168.0.4:1234/v1"
"baseURL": "http://127.0.0.1:1234"
},
"models": {
"qwen3.5-35b-a3b": {
+44 -1
View File
@@ -1,4 +1,5 @@
"$schema" = 'https://starship.rs/config-schema.json'
palette = "noctalia"
format = """
[](red)\
@@ -29,7 +30,6 @@ $character"""
right_format = "$cmd_duration"
palette = 'catppuccin_mocha'
[os]
disabled = false
@@ -202,3 +202,46 @@ base = "#1e1e2e"
mantle = "#181825"
crust = "#11111b"
# >>> NOCTALIA STARSHIP PALETTE >>>
# Noctalia Starship Palette
# Generated by Noctalia - do not edit manually
[palettes.noctalia]
# Standard colors
blue = "#89b4fa"
red = "#f38ba8"
green = "#a6e3a1"
yellow = "#f9e2af"
cyan = "#94e2d5"
magenta = "#f5c2e7"
white = "#a6adc8"
black = "#45475a"
# Extended palette (Catppuccin-compatible names)
rosewater = "#ebd391"
flamingo = "#f37799"
pink = "#f2aede"
mauve = "#f5c2e7"
maroon = "#f37799"
peach = "#ebd391"
teal = "#94e2d5"
sky = "#6bd7ca"
sapphire = "#74a8fc"
lavender = "#f2aede"
# Text shades
text = "#cdd6f4"
subtext1 = "#a6adc8"
subtext0 = "#585b70"
# Surface shades
overlay2 = "#585b70"
overlay1 = "#585b70"
overlay0 = "#45475a"
surface2 = "#45475a"
surface1 = "#45475a"
surface0 = "#1e1e2e"
base = "#1e1e2e"
mantle = "#1e1e2e"
crust = "#1e1e2e"
# <<< NOCTALIA STARSHIP PALETTE <<<
+14
View File
@@ -9,3 +9,17 @@ id = "git"
group = "git"
url = "*/"
run = "git"
[opener]
imv = [
{ run = "imv %s", orphan = true, spread = false, desc = "imv" },
]
mpv = [
{ run = "mpv %s", orphan = true, spread = false, desc = "mpv" },
]
[open]
prepend_rules = [
{ mime = "image/*", use = "imv" },
{ mime = "video/*", use = "mpv" },
]
@@ -1,3 +1 @@
scripts
.stow-ignore
.config/tmux/plugins
+29 -40
View File
@@ -10,7 +10,7 @@
# - `stow --simulate` to prove every stow target resolves
# 2. REAL SMOKE (guarded by RUN_SMOKE=1)
# - resolves every @pacman entry against the repo DB
# - exercises term/setup.sh (pacman + npm) and re-runs it to prove
# - exercises setup/term/setup.sh (pacman + npm) and re-runs it to prove
# idempotency
# - verifies stow actually creates symlinks into $HOME
# AUR + kreation/buntes-monster only run with RUN_FULL=1.
@@ -78,9 +78,7 @@ done
# 1b. stow --simulate for every package the Makefile stows.
while IFS= read -r pkg; do
[[ -z "$pkg" ]] && continue
if stow --simulate --ignore='.stow-ignore' --ignore='scripts' \
--ignore='\.config/tmux/plugins' \
--dir="$REPO" --target="$REPO" "$pkg" 2>"$ERR_LOG"; then
if stow --simulate --dir="$REPO" --target="$REPO" "$pkg" 2>"$ERR_LOG"; then
say_ok "stow --simulate $pkg resolves"
else
say_fail "stow --simulate $pkg (non-existent package or conflict)"
@@ -141,7 +139,7 @@ NOOP
echo "[stub] chsh $*"
exit 0
NOOP
# The AUR section is stripped for the smoke, so term/setup.sh only ever
# The AUR section is stripped for the smoke, so setup/term/setup.sh only ever
# passes repo packages (+ npm) here; route yay through pacman directly.
# --noconfirm is needed because the container isn't interactive.
cat > "$HOME/bin/yay" <<'NOOP'
@@ -154,16 +152,11 @@ NOOP
export PATH="$HOME/bin:$PATH"
# 2c. setup.sh package parsing sanity (mirrors read_packages) for each
# package dir: basic/term/utils/hypr. term/ and hypr/ keep their scripts
# inside scripts/ so stowing the top-level dir only creates .config/ links.
for d in basic term utils hypr; do
if [[ "$d" == "term" || "$d" == "hypr" ]]; then
SETUP_PATH="$d/scripts/setup.sh"
PKG_PATH="$d/scripts/packages.txt"
else
SETUP_PATH="$d/setup.sh"
PKG_PATH="$d/packages.txt"
fi
# setup/$d target. All setup scripts + package lists live in setup/
# (outside the stow packages) and share setup/lib/common.sh.
for d in basic term utils hypr kreation; do
SETUP_PATH="setup/$d/setup.sh"
PKG_PATH="setup/$d/packages.txt"
if ( cd "$REPO" && bash -n "$SETUP_PATH" ); then
say_ok "$SETUP_PATH syntax OK"
else
@@ -189,12 +182,8 @@ NOOP
# AUR-only name (e.g. `rd`) fails here before any install happens.
header "package resolvability (@pacman entries)"
resolv_fail=0
for d in basic term utils hypr; do
if [[ "$d" == "term" || "$d" == "hypr" ]]; then
PKG_PATH="$d/scripts/packages.txt"
else
PKG_PATH="$d/packages.txt"
fi
for d in basic term utils hypr kreation; do
PKG_PATH="setup/$d/packages.txt"
while IFS= read -r pkg; do
[[ -z "$pkg" ]] && continue
if pacman -S --print-format '%n' "$pkg" >/dev/null 2>&1; then
@@ -214,44 +203,46 @@ NOOP
done
# 2d. If network allowed and not skipped, actually install the pacman
# and npm sections of term/setup.sh (mirrors `make term` without AUR;
# the @aur section stays RUN_FULL-gated since it needs yay/AUR builds).
# and npm sections of setup/term/setup.sh (mirrors `make term` without
# AUR; the @aur section stays RUN_FULL-gated since it needs yay/AUR builds).
if [[ "${SKIP_NET:-0}" != "1" ]]; then
header "make term (pacman + npm packages, AUR skipped)"
# Patch packages.txt: keep @pacman and @npm (@npm runs via sudo npm
# in the container), drop @aur so we don't hit AUR builds.
cp "$REPO/term/scripts/packages.txt" "$HOME/packages.txt.full"
cp "$REPO/setup/term/packages.txt" "$HOME/packages.txt.full"
awk '
/^@aur$/{s="skip"}; /^@npm$/{s="npm"}; /^@pacman$/{s="pacman"}
{ if (s!="skip" && NF>0 && $1 !~ /^#/) print }
' "$REPO/term/scripts/packages.txt" > "$HOME/packages.txt.term-smoke"
' "$REPO/setup/term/packages.txt" > "$HOME/packages.txt.term-smoke"
# pacman-only list for verify_packages.sh (npm packages are not in
# the pacman DB).
awk '
/^@aur$/{s="skip"}; /^@npm$/{s="skip"}; /^@pacman$/{s="pacman"}
{ if (s!="skip" && NF>0 && $1 !~ /^#/) print }
' "$REPO/term/scripts/packages.txt" > "$HOME/packages.txt.term-only"
# set a scratch HOME for setup.sh so it doesn't touch the real one.
mkdir -p "$HOME/term"
cp "$REPO/term/scripts/setup.sh" "$HOME/term/setup.sh"
cp "$HOME/packages.txt.term-smoke" "$HOME/term/packages.txt"
' "$REPO/setup/term/packages.txt" > "$HOME/packages.txt.term-only"
# Stage a scratch copy of the term setup incl. setup/lib/common.sh
# (setup.sh sources it via a path relative to its own location).
mkdir -p "$HOME/smoke/term" "$HOME/smoke/lib"
cp "$REPO/setup/term/setup.sh" "$HOME/smoke/term/setup.sh"
cp "$REPO/setup/lib/common.sh" "$HOME/smoke/lib/common.sh"
cp "$HOME/packages.txt.term-smoke" "$HOME/smoke/term/packages.txt"
# chsh is stubbed via $HOME/bin so even `chsh` works without a pty.
setup_ok=0
if ( cd "$HOME/term" && bash setup.sh ) ; then
say_ok "term/setup.sh (pacman+npm) completed"
if ( cd "$HOME/smoke/term" && bash setup.sh ) ; then
say_ok "setup/term/setup.sh (pacman+npm) completed"
setup_ok=1
else
say_fail "term/setup.sh (pacman+npm) failed (exit $?)"
say_fail "setup/term/setup.sh (pacman+npm) failed (exit $?)"
fi
# 2d1. Idempotency probe: a second run must also succeed. Catches
# steps that break on re-runs over an already-populated state (e.g.
# `ya pkg add` failing with "already exists").
if [[ "$setup_ok" == "1" ]]; then
if ( cd "$HOME/term" && bash setup.sh ) ; then
say_ok "term/setup.sh re-run: idempotent"
if ( cd "$HOME/smoke/term" && bash setup.sh ) ; then
say_ok "setup/term/setup.sh re-run: idempotent"
else
say_fail "term/setup.sh re-run failed (exit $?) - not idempotent"
say_fail "setup/term/setup.sh re-run failed (exit $?) - not idempotent"
fi
else
echo " skipping idempotency probe (first run did not complete)"
@@ -279,15 +270,13 @@ NOOP
# 2e. stow --actual into $HOME to prove real symlinks are created.
header "stow real symlinks into \$HOME"
# term/setup.sh may have just re-created the yazi plugin (`ya pkg add`)
# setup/term/setup.sh may have just re-created the yazi plugin (`ya pkg add`)
# as real files. The repo vendors the same plugin under term/.config/yazi,
# so drop the duplicate first, letting stow take ownership of that config.
rm -rf "$HOME/.config/yazi"
for pkg in term hypr kreation local_ai; do
if [[ -d "$REPO/$pkg" ]]; then
if stow --ignore='.stow-ignore' --ignore='scripts' \
--ignore='\.config/tmux/plugins' \
--dir="$REPO" --target="$HOME" "$pkg" 2>"$ERR_LOG"; then
if stow --dir="$REPO" --target="$HOME" "$pkg" 2>"$ERR_LOG"; then
say_ok "stow $pkg into \$HOME"
else
say_fail "stow $pkg into \$HOME"
+98 -23
View File
@@ -31,7 +31,9 @@ say_pass() { printf 'ok: %s\n' "$*"; PASS=$((PASS+1)); }
# Exclusions: never lint tpm or general vendored plugin trees, whose third-party
# scripts may legitimately fail `bash -n` and are not written/maintained here.
EXCLUDE_VENDOR='(/tpm/|/plugins/|/plugins$)'
mapfile -t SCRIPTS < <(git ls-files '*.sh' 2>/dev/null | grep -vE "$EXCLUDE_VENDOR")
mapfile -t SCRIPTS < <(git ls-files '*.sh' 2>/dev/null | grep -vE "$EXCLUDE_VENDOR" | while IFS= read -r script; do
[[ -f "$script" ]] && printf '%s\n' "$script"
done)
if [[ ${#SCRIPTS[@]} -eq 0 ]]; then
mapfile -t SCRIPTS < <(find . -name '*.sh' \
-not -path './.git/*' -not -path '*/.git/*' \
@@ -77,19 +79,14 @@ else
fi
# ---------------------------------------------------------------------------
# 4. packages.txt parsing sanity (mirrors each setup.sh read_packages).
# 4. packages.txt parsing sanity (mirrors setup/lib/common.sh read_packages).
# ---------------------------------------------------------------------------
echo "== Checking packages.txt markers =="
for pkgdir in term basic utils hypr; do
# term/ and hypr/ keep packages.txt + setup.sh inside scripts/ so stowing
# the top-level dir only creates .config/ symlinks.
if [[ "$pkgdir" == "term" || "$pkgdir" == "hypr" ]]; then
PKG_FILE="$pkgdir/scripts/packages.txt"
SETUP_FILE="$pkgdir/scripts/setup.sh"
else
PKG_FILE="$pkgdir/packages.txt"
SETUP_FILE="$pkgdir/setup.sh"
fi
for pkgdir in term basic utils hypr kreation; do
# Setup scripts + package lists live in setup/ (outside the stow
# packages), sharing one parser in setup/lib/common.sh.
PKG_FILE="setup/$pkgdir/packages.txt"
SETUP_FILE="setup/$pkgdir/setup.sh"
if ! [[ -f "$PKG_FILE" ]]; then
say_fail "$PKG_FILE missing"
continue
@@ -99,12 +96,15 @@ for pkgdir in term basic utils hypr; do
else
say_fail "$PKG_FILE missing @pacman marker"
fi
# every @aur/@npm marker must be matched by a real consumer in setup.sh
# every @aur/@npm marker must be matched by a real consumer: either the
# thin setup.sh itself or the shared setup/lib/common.sh it sources.
for marker in '@aur' '@npm'; do
if grep -q "^$marker" "$PKG_FILE"; then
grep -q "$marker" "$SETUP_FILE" \
&& say_pass "$PKG_FILE $marker handled by $SETUP_FILE" \
|| say_fail "$PKG_FILE uses $marker but $SETUP_FILE does not handle it"
if grep -q "$marker" "$SETUP_FILE" || grep -q "$marker" "setup/lib/common.sh"; then
say_pass "$PKG_FILE $marker handled by $SETUP_FILE (via common.sh)"
else
say_fail "$PKG_FILE uses $marker but neither $SETUP_FILE nor setup/lib/common.sh handles it"
fi
else
say_pass "$PKG_FILE has no $marker section"
fi
@@ -112,12 +112,87 @@ for pkgdir in term basic utils hypr; do
done
# ---------------------------------------------------------------------------
# 5. Makefile <-> install script name consistency.
# Catches typos such as `_install_skripte_install_basic_pcks.sh`
# 5. Keep Caelestia on the upstream AUR Quickshell runtime.
# ---------------------------------------------------------------------------
echo "== Checking Quickshell package selection =="
PACKAGE_FILES=()
for pkgdir in term basic utils hypr kreation; do
PACKAGE_FILES+=("setup/$pkgdir/packages.txt")
done
has_package() {
local target="$1" file
shift
for file in "$@"; do
if awk -v target="$target" '
{
sub(/#.*/, "")
gsub(/^[[:space:]]+|[[:space:]]+$/, "")
sub(/^[^/]+\//, "")
}
$0 == target { found = 1 }
END { exit(found ? 0 : 1) }
' "$file"; then
return 0
fi
done
return 1
}
has_aur_package() {
local target="$1" file
shift
for file in "$@"; do
if awk -v target="$target" '
{
sub(/#.*/, "")
gsub(/^[[:space:]]+|[[:space:]]+$/, "")
}
$0 == "@aur" { in_aur = 1; next }
/^@/ { in_aur = 0; next }
in_aur && $0 == target { found = 1 }
END { exit(found ? 0 : 1) }
' "$file"; then
return 0
fi
done
return 1
}
if has_package quickshell "${PACKAGE_FILES[@]}" && has_package quickshell-git "${PACKAGE_FILES[@]}"; then
say_fail "package lists declare both quickshell and quickshell-git"
else
say_pass "no mutually exclusive quickshell packages declared"
fi
if has_package noctalia-qs "${PACKAGE_FILES[@]}"; then
say_fail "package lists must not install noctalia-qs for Caelestia"
else
say_pass "incompatible noctalia-qs provider is not declared"
fi
if has_aur_package aur/quickshell-git "${PACKAGE_FILES[@]}"; then
say_pass "quickshell-git is explicitly selected from the AUR"
else
say_fail "quickshell-git must use the explicit aur/quickshell-git target"
fi
if awk '
/^[[:space:]]*yay[[:space:]]+-S/ && /--aur/ && /--needed/ { found = 1 }
END { exit(found ? 0 : 1) }
' setup/lib/common.sh; then
say_pass "AUR package installation uses yay --aur mode"
else
say_fail "AUR package installation does not use yay --aur mode"
fi
# ---------------------------------------------------------------------------
# 6. Makefile <-> setup script name consistency.
# Catches typos such as `setup/basic/setuo.sh`
# (missing '/') in Makefile targets.
# ---------------------------------------------------------------------------
echo "== Checking Makefile references install scripts that exist =="
# Pull out every `*_install_*_pcks.sh` token mentioned in the Makefile.
echo "== Checking Makefile references setup scripts that exist =="
# Pull out every `setup/...sh` token mentioned in the Makefile.
while IFS= read -r tok; do
[[ -z "$tok" ]] && continue
if [[ -e "$REPO_ROOT/$tok" ]]; then
@@ -125,10 +200,10 @@ while IFS= read -r tok; do
else
say_fail "Makefile references missing script: $tok"
fi
done < <(grep -P '^\t' Makefile | grep -oE '[_A-Za-z0-9/-]*install_[A-Za-z0-9_-]*\.sh' | sort -u)
done < <(grep -P '^\t' Makefile | grep -oE 'setup/[_A-Za-z0-9./-]+\.sh' | sort -u)
# ---------------------------------------------------------------------------
# 6. Makefile <-> stow package name consistency.
# 7. Makefile <-> stow package name consistency.
# Catches bugs such as `stow nvim` when the actual package dir is `term/`.
# ---------------------------------------------------------------------------
echo "== Checking Makefile stow targets reference real package dirs =="
@@ -158,7 +233,7 @@ while IFS= read -r pkg; do
done < <(grep -P '^\t' Makefile | grep -E '\bstow\b' | awk '{print $NF}' | sort -u)
# ---------------------------------------------------------------------------
# 7. Central theme drift guard: no hardcoded theme colors outside
# 8. Central theme drift guard: no hardcoded theme colors outside
# basic/.config/themes (plus declared mirrors). See
# basic/.config/themes/scripts/sync-theme.sh.
# ---------------------------------------------------------------------------
+1 -1
View File
@@ -55,7 +55,7 @@ trap cleanup EXIT
for pkg in "${PACKAGES[@]}"; do
echo "--- stow --simulate: $pkg ---"
if stow --simulate --verbose=1 --ignore='.stow-ignore' --ignore='scripts' --ignore='\.config/tmux/plugins' --dir="$REPO_ROOT" --target="$REPO_ROOT" "$pkg" >/dev/null 2>"$ERR_LOG"; then
if stow --simulate --verbose=1 --dir="$REPO_ROOT" --target="$REPO_ROOT" "$pkg" >/dev/null 2>"$ERR_LOG"; then
echo "ok: stow --simulate '$pkg' resolved without conflicts"
else
echo "FAIL: stow --simulate '$pkg'"
-74
View File
@@ -1,74 +0,0 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SCRIPT_DIR/packages.txt"
# ---------------------------------------------------------------------------
# Read packages.txt, split into pacman / aur / npm sections.
# ---------------------------------------------------------------------------
read_packages() {
local section="pacman"
local current
current=""
while IFS= read -r line || [[ -n "$line" ]]; do
current="${line%%#*}"
current="${current##*( )}"
current="${current%%*( )}"
[[ -z "$current" ]] && continue
case "$current" in
@pacman) section="pacman" ;;
@aur) section="aur" ;;
@npm) section="npm" ;;
*)
case "$section" in
pacman) pacman_pkgs+=("$current") ;;
aur) aur_pkgs+=("$current") ;;
npm) npm_pkgs+=("$current") ;;
esac
;;
esac
done < "$PACKAGES_FILE"
}
declare -a pacman_pkgs=() aur_pkgs=() npm_pkgs=()
# ---------------------------------------------------------------------------
# Install sections.
# ---------------------------------------------------------------------------
install_pacman() {
if ((${#pacman_pkgs[@]})); then
echo "==> Installiere Pacman-Pakete: ${pacman_pkgs[*]}"
yay -S --needed "${pacman_pkgs[@]}"
fi
}
install_aur() {
if ((${#aur_pkgs[@]})); then
echo "==> Installiere AUR-Pakete: ${aur_pkgs[*]}"
yay -S --needed "${aur_pkgs[@]}"
fi
}
install_npm() {
if ((${#npm_pkgs[@]})); then
echo "==> Installiere globale npm-Pakete: ${npm_pkgs[*]}"
npm install -g "${npm_pkgs[@]}"
fi
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
echo "==> Lese Paketliste: $PACKAGES_FILE"
read_packages
install_pacman
install_aur
install_npm
echo "Fertig. Standalone Utilities sind eingerichtet."
}
main