diff options
| author | steven-na <noreply.github@stvnc.dev> | 2026-04-26 11:58:32 -0700 |
|---|---|---|
| committer | steven-na <noreply.github@stvnc.dev> | 2026-04-26 11:58:32 -0700 |
| commit | 4b309f0a5555b5fed5a65ee425dcb6da15421f5b (patch) | |
| tree | b923f4f76df6205ee3099d9bf8072209ff9e8256 | |
Initial commit.
61 files changed, 2072 insertions, 0 deletions
diff --git a/arch/.stowrc b/arch/.stowrc new file mode 100644 index 0000000..9a31e3b --- /dev/null +++ b/arch/.stowrc @@ -0,0 +1 @@ +--target=/home/blake diff --git a/arch/eww/.config/eww/eww.scss b/arch/eww/.config/eww/eww.scss new file mode 100644 index 0000000..7fd3240 --- /dev/null +++ b/arch/eww/.config/eww/eww.scss @@ -0,0 +1,112 @@ +// Colors generated by wallust — see ~/.config/wallust/templates/eww-colors.scss +// Fallback values used until wallust has run at least once +$bg: #1e2121; +$fg: #cdd6f4; +$accent: #89b4fa; +$surface: #313244; +$muted: #6c7086; +$warn: #f38ba8; + +@import "/home/blake/.cache/wallust/eww-colors"; + +* { + font-family: "JetBrainsMono Nerd Font"; + font-size: 12px; + all: unset; +} + +.bar { + background-color: transparentize($bg, 0.4); + color: $fg; + border: none; + box-shadow: none; +} + +// ── Left ─────────────────────────────────────────────────────────────────── + +.left { + padding: 0 8px; +} + +.workspaces { + padding: 0 2px; +} + +.ws { + color: $muted; + padding: 0 5px; +} + +.ws.active { + color: $accent; + font-weight: bold; +} + +// ── Center ───────────────────────────────────────────────────────────────── + +.center { + padding: 0 8px; +} + +.date { + color: $muted; +} + +.clock { + color: $fg; + font-weight: bold; +} + +.music-icon { + color: $accent; +} + +.song { + color: $muted; +} + +// ── Right ────────────────────────────────────────────────────────────────── + +.right { + padding: 0 8px; +} + +.stat { + padding: 0 1px; +} + +.stat-label { + color: $muted; + padding-right: 3px; +} + +.stat-val { + color: $fg; +} + +.stat-val.net { + color: $muted; +} + +.stat-val.warn { + color: $warn; +} + +.stat-btn { + all: unset; +} + +.stat-btn:hover .stat-label, +.stat-btn:hover .stat-val { + color: $accent; +} + +.power-btn { + color: $muted; + padding: 0 4px; + margin-left: 2px; +} + +.power-btn:hover { + color: $warn; +} diff --git a/arch/eww/.config/eww/eww.yuck b/arch/eww/.config/eww/eww.yuck new file mode 100644 index 0000000..8574e1f --- /dev/null +++ b/arch/eww/.config/eww/eww.yuck @@ -0,0 +1,150 @@ +;; ── Listeners (Hyprland IPC) ────────────────────────────────────────────── +;; hyprland-workspaces emits JSON arrays with {id, name, windows, isActive} +;; on every workspace change — single source of truth for list + active state. + +(deflisten workspaces :initial "[]" + `scripts/workspaces`) + +;; ── Polls ────────────────────────────────────────────────────────────────── + +(defpoll clock :interval "1s" + `date +"%-H:%M"`) + +(defpoll date-str :interval "60s" + `date +"%a %b %d"`) + +;; Show the PLAYING source; fall back to any paused one +(defpoll player-status :interval "2s" + `playerctl -a status 2>/dev/null | grep -q "^Playing" && echo "Playing" || playerctl status 2>/dev/null || echo "Stopped"`) + +(defpoll player-song :interval "2s" + `playerctl -a metadata --format "{{status}}||{{ artist }} - {{ title }}" 2>/dev/null | grep "^Playing||" | head -1 | sed 's/^Playing||//' || playerctl metadata --format "{{ artist }} - {{ title }}" 2>/dev/null || echo ""`) + +(defpoll battery-level :interval "30s" :initial "100" + `cat /sys/class/power_supply/BAT0/capacity 2>/dev/null || echo "100"`) + +(defpoll battery-status :interval "10s" :initial "Unknown" + `cat /sys/class/power_supply/BAT0/status 2>/dev/null || echo "Unknown"`) + +(defpoll cpu :interval "3s" + `scripts/cpu`) + +(defpoll ram :interval "5s" + `free | awk '/^Mem/{printf "%d", $3/$2*100}'`) + +(defpoll disk :interval "60s" + `df / | awk 'NR==2{printf "%d", $3/$2*100}'`) + +(defpoll volume :interval "1s" + `pamixer --get-volume 2>/dev/null || echo "0"`) + +;; Use sysfs operstate — works regardless of network manager backend +(defpoll wifi-iface :interval "5s" + `IFACE=$(ls /sys/class/net | grep -m1 '^wl'); [ -n "$IFACE" ] && [ "$(cat /sys/class/net/$IFACE/operstate 2>/dev/null)" = "up" ] && echo "$IFACE" || echo "disconnected"`) + +(defpoll brightness :interval "2s" + `brightnessctl -m 2>/dev/null | awk -F, '{print int($4)}' || echo "100"`) + +(defpoll netspeed :interval "3s" + `scripts/netspeed`) + +;; ── Left: Workspaces + Music ─────────────────────────────────────────────── + +(defwidget workspaces [] + (box :class "workspaces" :space-evenly false :spacing 5 + (for ws in workspaces + (button + :class {ws.active ? "ws active" : "ws"} + :onclick "hyprctl dispatch workspace ${ws.id}" + {ws.id})))) + +(defwidget music [] + (eventbox + :onclick "playerctl play-pause" + (box :class "music" + :space-evenly false :spacing 5 + :visible {player-status != "Stopped" && player-status != ""} + (label :class "music-icon" + :text {player-status == "Playing" ? "▶" : "⏸"}) + (label :class "song" :text player-song :limit-width 30)))) + +;; ── Center: Clock ────────────────────────────────────────────────────────── + +(defwidget center-section [] + (box :class "center" :halign "center" :space-evenly false :spacing 8 + (label :class "date" :text date-str) + (label :class "clock" :text clock))) + +;; ── Right: Stats ─────────────────────────────────────────────────────────── + +(defwidget bright-stat [] + (eventbox + :onscroll "[ '{}' = 'up' ] && brightnessctl set +5% || brightnessctl set 5%-" + (box :class "stat" :space-evenly false :spacing 3 + (label :class "stat-label" :text "bright") + (label :class "stat-val" :text "${brightness}%")))) + +(defwidget audio-stat [] + (eventbox + :onscroll "[ '{}' = 'up' ] && pamixer --increase 5 || pamixer --decrease 5" + (box :class "stat" :space-evenly false :spacing 3 + (label :class "stat-label" :text "audio") + (label :class "stat-val" :text "${volume}%")))) + +(defwidget wifi-stat [] + (eventbox + :onclick "ghostty -e nmtui &" + (box :class "stat" :space-evenly false :spacing 3 + (label :class "stat-label" :text "wifi") + (label :class "stat-val" :text wifi-iface)))) + +(defwidget cpu-stat [] + (eventbox + :onclick "ghostty -e btop &" + (box :class "stat" :space-evenly false :spacing 3 + (label :class "stat-label" :text "cpu") + (label :class "stat-val" :text "${cpu}%")))) + +(defwidget right-section [] + (box :class "right" :halign "end" :space-evenly false :spacing 8 + (bright-stat) + (audio-stat) + (label :class "stat-val net" :text netspeed) + (wifi-stat) + (stat :lbl "bat" :value "${battery-level}%" + :class {battery-level < 20 ? "warn" : ""}) + (stat :lbl "strg" :value "${disk}%") + (stat :lbl "ram" :value "${ram}%") + (cpu-stat) + (button :class "power-btn" :onclick "scripts/powermenu &" "pwr"))) + +;; Plain stat (non-interactive) ───────────────────────────────────────────── + +(defwidget stat [lbl value ?class] + (box :class "stat" :space-evenly false :spacing 3 + (label :class "stat-label" :text lbl) + (label :class {class == "" ? "stat-val" : "stat-val ${class}"} :text value))) + +;; ── Bar ──────────────────────────────────────────────────────────────────── + +(defwidget bar [] + (centerbox :class "bar" :orientation "h" + (box :class "left" :halign "start" :space-evenly false :spacing 12 + (workspaces) + (music)) + (center-section) + (right-section))) + +(defwindow bar + :monitor 0 + :windowtype "dock" + :geometry (geometry + :x "0%" + :y "0%" + :width "100%" + :height "24px" + :anchor "top center") + :stacking "fg" + :exclusive true + :focusable false + (bar)) diff --git a/arch/eww/.config/eww/scripts/active-workspace b/arch/eww/.config/eww/scripts/active-workspace new file mode 100755 index 0000000..21795b9 --- /dev/null +++ b/arch/eww/.config/eww/scripts/active-workspace @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +hyprctl activeworkspace -j | jq '.id' +socat -u UNIX-CONNECT:"${XDG_RUNTIME_DIR}/hypr/${HYPRLAND_INSTANCE_SIGNATURE}/.socket2.sock" STDOUT \ + | while read -r _; do hyprctl activeworkspace -j | jq '.id'; done diff --git a/arch/eww/.config/eww/scripts/active-ws b/arch/eww/.config/eww/scripts/active-ws new file mode 100755 index 0000000..c7b3f3e --- /dev/null +++ b/arch/eww/.config/eww/scripts/active-ws @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +hyprctl activeworkspace | awk '/^workspace/{print $3}' diff --git a/arch/eww/.config/eww/scripts/cpu b/arch/eww/.config/eww/scripts/cpu new file mode 100755 index 0000000..f06ae7b --- /dev/null +++ b/arch/eww/.config/eww/scripts/cpu @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +read -r _ u1 _ s1 id1 _ < /proc/stat +sleep 1 +read -r _ u2 _ s2 id2 _ < /proc/stat +used=$(( (u2+s2) - (u1+s1) )) +total=$(( (u2+s2+id2) - (u1+s1+id1) )) +printf "%d\n" $(( total > 0 ? 100 * used / total : 0 )) diff --git a/arch/eww/.config/eww/scripts/hypr-socket b/arch/eww/.config/eww/scripts/hypr-socket new file mode 100755 index 0000000..9012c17 --- /dev/null +++ b/arch/eww/.config/eww/scripts/hypr-socket @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Stream lines from Hyprland's socket2 IPC.""" +import socket, sys, os + +sock_path = ( + os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{os.getuid()}") + + "/hypr/" + + os.environ["HYPRLAND_INSTANCE_SIGNATURE"] + + "/.socket2.sock" +) + +s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +s.connect(sock_path) + +buf = b"" +while True: + chunk = s.recv(4096) + if not chunk: + break + buf += chunk + while b"\n" in buf: + line, buf = buf.split(b"\n", 1) + sys.stdout.write(line.decode(errors="replace") + "\n") + sys.stdout.flush() diff --git a/arch/eww/.config/eww/scripts/netspeed b/arch/eww/.config/eww/scripts/netspeed new file mode 100755 index 0000000..f5bb25b --- /dev/null +++ b/arch/eww/.config/eww/scripts/netspeed @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +IFACE=$(ip route show default 2>/dev/null | awk '{print $5; exit}') +if [[ -z "$IFACE" ]]; then echo "↓0 ↑0 KB/s"; exit; fi +rx1=$(cat /sys/class/net/"$IFACE"/statistics/rx_bytes 2>/dev/null || echo 0) +tx1=$(cat /sys/class/net/"$IFACE"/statistics/tx_bytes 2>/dev/null || echo 0) +sleep 1 +rx2=$(cat /sys/class/net/"$IFACE"/statistics/rx_bytes 2>/dev/null || echo 0) +tx2=$(cat /sys/class/net/"$IFACE"/statistics/tx_bytes 2>/dev/null || echo 0) +echo "↓$(( (rx2-rx1)/1024 )) ↑$(( (tx2-tx1)/1024 )) KB/s" diff --git a/arch/eww/.config/eww/scripts/powermenu b/arch/eww/.config/eww/scripts/powermenu new file mode 100755 index 0000000..e136674 --- /dev/null +++ b/arch/eww/.config/eww/scripts/powermenu @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +chosen=$(printf "Suspend\nReboot\nShutdown" | bemenu -p " Power") +case "$chosen" in + Suspend) systemctl suspend ;; + Reboot) systemctl reboot ;; + Shutdown) systemctl poweroff ;; +esac diff --git a/arch/eww/.config/eww/scripts/workspaces b/arch/eww/.config/eww/scripts/workspaces new file mode 100755 index 0000000..28571a7 --- /dev/null +++ b/arch/eww/.config/eww/scripts/workspaces @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# hyprland-workspaces streams JSON arrays on every workspace change. +# Filter out special/scratchpad workspaces (negative IDs). +hyprland-workspaces eDP-1 | while IFS= read -r line; do + echo "$line" | jq -c '[.[] | select(.id > 0)]' +done diff --git a/arch/fish/.config/fish/conf.d/aliases.fish b/arch/fish/.config/fish/conf.d/aliases.fish new file mode 100644 index 0000000..cab8bad --- /dev/null +++ b/arch/fish/.config/fish/conf.d/aliases.fish @@ -0,0 +1,17 @@ +alias ls 'eza --icons --group-directories-first' +alias ll 'eza -la --icons --group-directories-first' +alias cat 'bat' +alias grep 'rg' +alias find 'fd' +alias cd 'z' +alias y 'yazi' +alias tl 'tldr' +# alias info 'pinfo' # uncomment once pinfo is installed (AUR: pinfo) + +# Man page shortcuts +abbr -a m1 'man -s 1' +abbr -a m2 'man -s 2' +abbr -a m3 'man -s 3' +abbr -a m5 'man -s 5' +abbr -a m7 'man -s 7' +abbr -a m8 'man -s 8' diff --git a/arch/fish/.config/fish/conf.d/edit-configs.fish b/arch/fish/.config/fish/conf.d/edit-configs.fish new file mode 100644 index 0000000..c085a41 --- /dev/null +++ b/arch/fish/.config/fish/conf.d/edit-configs.fish @@ -0,0 +1,12 @@ +# ── Config editing shortcuts ────────────────────────────────────────────────── +set -l dots ~/dotfiles/arch + +alias envim "nvim $dots/nvim/.config/nvim/" +alias etmux "nvim $dots/tmux/.config/tmux/tmux.conf" +alias ehypr "nvim $dots/hyprland/.config/hypr/" +alias efish "nvim $dots/fish/.config/fish/config.fish" +alias eghostty "nvim $dots/ghostty/.config/ghostty/config" +alias ewwconf "nvim $dots/eww/.config/eww/" +alias emako "nvim $dots/mako/.config/mako/config" +alias ewallust "nvim $dots/wallust/.config/wallust/" +alias edots "nvim $dots/" diff --git a/arch/fish/.config/fish/config.fish b/arch/fish/.config/fish/config.fish new file mode 100644 index 0000000..6c8baba --- /dev/null +++ b/arch/fish/.config/fish/config.fish @@ -0,0 +1,25 @@ +set fish_greeting + +# Auto-attach to tmux on interactive startup (skip if already inside tmux) +# if status is-interactive && not set -q TMUX +# exec tmux new-session +# end + +set -gx EDITOR nvim +set -gx BROWSER zen-browser + +fish_add_path ~/.local/bin + +# Starship prompt +starship init fish | source + +# Zoxide (replaces cd) +zoxide init fish | source + +# Direnv +direnv hook fish | source + +# FZF +# Wallust: set FZF_DEFAULT_OPTS with colors from ~/.cache/wallust/fzf-colors when wiring theming +set -gx FZF_DEFAULT_COMMAND 'fd --type f --hidden --follow --exclude .git' +set -gx FZF_DEFAULT_OPTS '--height 40% --layout=reverse --border' diff --git a/arch/fish/.config/fish/fish_variables b/arch/fish/.config/fish/fish_variables new file mode 100644 index 0000000..612abe8 --- /dev/null +++ b/arch/fish/.config/fish/fish_variables @@ -0,0 +1,4 @@ +# This file contains fish universal variable definitions. +# VERSION: 3.0 +SETUVAR __fish_initialized:4300 +SETUVAR fish_user_paths:/home/blake/\x2elocal/bin diff --git a/arch/ghostty/.config/ghostty/config b/arch/ghostty/.config/ghostty/config new file mode 100644 index 0000000..11decd3 --- /dev/null +++ b/arch/ghostty/.config/ghostty/config @@ -0,0 +1,21 @@ +font-family = JetBrainsMono Nerd Font +font-size = 12 + +scrollback-limit = 10000 + +shell-integration = fish +command = /usr/bin/fish + +window-padding-x = 8 +window-padding-y = 8 + +mouse-hide-while-typing = true + +# Ctrl+Backspace sends C-h by default; remap to C-w (backward-kill-word) +keybind = ctrl+backspace=text:\x17 +confirm-close-surface = false + +background-opacity = 0.85 +background-blur-radius = 20 + +config-file = /home/blake/.cache/wallust/ghostty-colors.conf diff --git a/arch/git/.config/git/config b/arch/git/.config/git/config new file mode 100644 index 0000000..80978cd --- /dev/null +++ b/arch/git/.config/git/config @@ -0,0 +1,21 @@ +[user] + name = "steven-na" + email = "noreply.github@stvnc.dev" + +[core] + editor = nvim + +[init] + defaultBranch = main + +[pull] + rebase = true + +[push] + autoSetupRemote = true + +[merge] + conflictstyle = diff3 + +[diff] + colorMoved = default diff --git a/arch/hyprland/.config/hypr/hypridle.conf b/arch/hyprland/.config/hypr/hypridle.conf new file mode 100644 index 0000000..c6e2ac8 --- /dev/null +++ b/arch/hyprland/.config/hypr/hypridle.conf @@ -0,0 +1,32 @@ +general { + lock_cmd = pidof hyprlock || hyprlock + before_sleep_cmd = loginctl lock-session + after_sleep_cmd = hyprctl dispatch dpms on + ignore_dbus_inhibit = false +} + +# Dim screen after 2.5 min +listener { + timeout = 150 + on-timeout = brightnessctl -s set 10% + on-resume = brightnessctl -r +} + +# Lock after 5 min +listener { + timeout = 300 + on-timeout = loginctl lock-session +} + +# Display off after 5.5 min +listener { + timeout = 330 + on-timeout = hyprctl dispatch dpms off + on-resume = hyprctl dispatch dpms on +} + +# Suspend after 30 min +listener { + timeout = 1800 + on-timeout = systemctl suspend +} diff --git a/arch/hyprland/.config/hypr/hyprland.conf b/arch/hyprland/.config/hypr/hyprland.conf new file mode 100644 index 0000000..65c7338 --- /dev/null +++ b/arch/hyprland/.config/hypr/hyprland.conf @@ -0,0 +1,86 @@ +source = ~/.config/hypr/monitors.conf +source = ~/.config/hypr/theme.conf +source = ~/.config/hypr/keybinds.conf +source = ~/.config/hypr/windowrules.conf + +# NVIDIA +env = WLR_NO_HARDWARE_CURSORS,1 +env = EGL_PLATFORM,wayland +env = OZONE_PLATFORM,wayland +env = XCURSOR_SIZE,24 +env = XCURSOR_THEME,Bibata-Modern-Classic + +general { + layout = dwindle + gaps_in = 3 + gaps_out = 3 + border_size = 2 + # border colors are in theme.conf +} + +dwindle { + pseudotile = true + preserve_split = true +} + +input { + kb_layout = us + follow_mouse = 1 + special_fallthrough = true + touchpad { + natural_scroll = false + } +} + +binds { + movefocus_cycles_fullscreen = 1 +} + +cursor { + no_hardware_cursors = 1 +} + +misc { + disable_hyprland_logo = true + disable_splash_rendering = true + font_family = JetBrainsMono Nerd Font + vfr = 1 + vrr = 1 + enable_swallow = true +} + +decoration { + rounding = 4 + active_opacity = 1.0 + inactive_opacity = 0.92 + blur { + enabled = true + size = 6 + passes = 3 + vibrancy = 0.2 + special = true + new_optimizations = true + } + shadow { + enabled = true + range = 4 + render_power = 3 + } +} + +animations { + enabled = true + bezier = myBezier, 0.05, 0.97, 0.05, 0.97 + animation = windows, 1, 4, myBezier + animation = windowsOut, 1, 4, default, popin 80% + animation = fade, 1, 4, default + animation = workspaces, 1, 4, default +} + +exec-once = awww-daemon +exec-once = mako +exec-once = hypridle +exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 +exec-once = eww daemon && eww open bar +exec-once = bash -c 'sleep 0.5; [ -f ~/.cache/wallust/last-wallpaper ] && ~/.local/bin/set-wallpaper "$(cat ~/.cache/wallust/last-wallpaper)"' +exec-once = spicetify watch -s diff --git a/arch/hyprland/.config/hypr/hyprlock.conf b/arch/hyprland/.config/hypr/hyprlock.conf new file mode 100644 index 0000000..24dd752 --- /dev/null +++ b/arch/hyprland/.config/hypr/hyprlock.conf @@ -0,0 +1,52 @@ +general { + hide_cursor = true + no_fade_in = false + disable_loading_bar = true + ignore_empty_input = true +} + +background { + monitor = + # Wallust: replace with path = ~/.cache/wallust/last-wallpaper + path = screenshot + blur_passes = 3 + blur_size = 7 + brightness = 0.5 +} + +label { + monitor = + text = cmd[update:1000] date +"%-H:%M" + font_size = 72 + font_family = JetBrainsMono Nerd Font + color = rgba(cdd6f4ff) + position = 0, 200 + halign = center + valign = center +} + +label { + monitor = + text = cmd[update:60000] date +"%A, %B %d" + font_size = 18 + font_family = JetBrainsMono Nerd Font + color = rgba(cdd6f4cc) + position = 0, 120 + halign = center + valign = center +} + +input-field { + monitor = + size = 300, 48 + outline_thickness = 2 + outer_color = rgba(cdd6f4ff) + inner_color = rgba(1e1e2ecc) + font_color = rgba(cdd6f4ff) + fade_on_empty = true + placeholder_text = Password + font_family = JetBrainsMono Nerd Font + position = 0, -80 + halign = center + valign = center +} diff --git a/arch/hyprland/.config/hypr/keybinds.conf b/arch/hyprland/.config/hypr/keybinds.conf new file mode 100644 index 0000000..2f00c8f --- /dev/null +++ b/arch/hyprland/.config/hypr/keybinds.conf @@ -0,0 +1,106 @@ +$mainMod = SUPER + +# ── Core ────────────────────────────────────────────────────────────────────── +bind = $mainMod, Q, exec, ghostty +bind = $mainMod, C, killactive +bind = $mainMod, J, togglesplit +bind = $mainMod CTRL, V, togglefloating +bind = $mainMod, F, fullscreen, 1 +bind = $mainMod CTRL, F, fullscreen, 0 +bind = $mainMod SHIFT, L, exec, loginctl lock-session +bind = $mainMod, R, exec, ~/.local/bin/launcher +bind = $mainMod, W, exec, ghostty --class=float-term -e ~/.local/bin/pick-wallpaper +bind = $mainMod SHIFT, F, exec, zen-browser + +# Keyboard pointer modes (wl-kbptr) +bind = $mainMod, G, exec, pkill wl-kbptr || true; wl-kbptr -o modes=floating,click -o mode_floating.source=detect +bind = $mainMod, M, exec, pkill wl-kbptr || true; wl-kbptr -o modes=tile,bisect,click + +# Clipboard +bind = $mainMod SHIFT, V, exec, cliphist list | bemenu | cliphist decode | wl-copy + +# ── Focus movement ──────────────────────────────────────────────────────────── +bind = $mainMod, left, movefocus, l +bind = $mainMod, right, movefocus, r +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d +bind = $mainMod, h, movefocus, l +bind = $mainMod, l, movefocus, r +bind = $mainMod, k, movefocus, u +bind = $mainMod, j, movefocus, d + +# ── Mouse scroll wheel movement ─────────────────────────────────────────────── +binde = $mainMod, B, exec, ydotool mousemove --wheel -- 0 1 +binde = $mainMod, V, exec, ydotool mousemove --wheel -- 0 -1 + +# ── Workspaces ──────────────────────────────────────────────────────────────── +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 + +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 +bind = $mainMod SHIFT, 0, movetoworkspace, 10 + +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# ── Special workspaces (scratchpads) ───────────────────────────────────────── +bind = $mainMod, S, togglespecialworkspace, magic +bind = $mainMod SHIFT, S, movetoworkspace, special:magic + +# ── Screenshots ─────────────────────────────────────────────────────────────── +bind = , Print, exec, grim -g "$(slurp)" - | wl-copy +bind = $mainMod, Print, exec, grim - | wl-copy +bind = $mainMod SHIFT, Print, exec, grim -g "$(hyprctl activewindow -j | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')" - | wl-copy + +# ── Resize submap ───────────────────────────────────────────────────────────── +bind = $mainMod CTRL, R, submap, resize + +submap = resize +binde = , h, resizeactive, -20 0 +binde = , j, resizeactive, 0 20 +binde = , k, resizeactive, 0 -20 +binde = , l, resizeactive, 20 0 +binde = , left, resizeactive, -20 0 +binde = , down, resizeactive, 0 20 +binde = , up, resizeactive, 0 -20 +binde = , right, resizeactive, 20 0 +bind = , Escape, submap, reset +bind = , Return, submap, reset +bind = , catchall, submap, reset +submap = reset + +# ── Mouse window management ─────────────────────────────────────────────────── +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod CTRL, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +# ── Media keys ──────────────────────────────────────────────────────────────── +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPrev, exec, playerctl previous +bindl = , XF86AudioMute, exec, pamixer -t + +bindle = , XF86AudioRaiseVolume, exec, pamixer -i 5 +bindle = , XF86AudioLowerVolume, exec, pamixer -d 5 +bindle = , XF86MonBrightnessUp, exec, brightnessctl set +5% +bindle = , XF86MonBrightnessDown, exec, brightnessctl set 5%- + +bind = $mainMod, F2, exec, brightnessctl -d asus::kbd_backlight set 1- +bind = $mainMod, F3, exec, brightnessctl -d asus::kbd_backlight set +1 +bind = $mainMod, F4, exec, asusctl aura effect --next-mode diff --git a/arch/hyprland/.config/hypr/monitors.conf b/arch/hyprland/.config/hypr/monitors.conf new file mode 100644 index 0000000..6acb585 --- /dev/null +++ b/arch/hyprland/.config/hypr/monitors.conf @@ -0,0 +1,8 @@ +# Laptop screen +monitor = desc:BOE NE160WUM-NX2, 1920x1200@165, 0x0, 1 + +# Fallback for any other connected display +monitor = , preferred, auto, 1 + +# Multi-monitor: uncomment and configure when adding external display +# monitor = desc:YOUR_MONITOR_DESC, 1920x1080@144, auto, 1, transform, 1 diff --git a/arch/hyprland/.config/hypr/theme.conf b/arch/hyprland/.config/hypr/theme.conf new file mode 100644 index 0000000..0107198 --- /dev/null +++ b/arch/hyprland/.config/hypr/theme.conf @@ -0,0 +1,7 @@ +# Theme / color configuration — generated by wallust +# Run set-wallpaper <path> to regenerate +# +# If ~/.cache/wallust/hyprland-colors.conf doesn't exist yet (first boot), +# the fallback colors below are used until you set a wallpaper. + +source = ~/.cache/wallust/hyprland-colors.conf diff --git a/arch/hyprland/.config/hypr/windowrules.conf b/arch/hyprland/.config/hypr/windowrules.conf new file mode 100644 index 0000000..6778846 --- /dev/null +++ b/arch/hyprland/.config/hypr/windowrules.conf @@ -0,0 +1,62 @@ +# ── Spotify transparency ────────────────────────────────────────────────────── +# Barely-noticeable opacity lets Hyprland's compositor blur show wallpaper +# bleed-through behind the CSS rgba panels in the spicetify theme. +windowrule { + name = spotify-transparency + match:class = Spotify + opacity = 0.90 override +} + +# ── Floating terminal (Super+Q with float-term class) ───────────────────────── +windowrule { + name = float-term + match:class = float-term + float = true + center = true + stay_focused = true + size = 900 600 +} + +# ── Wallpaper picker ───────────────────────────────────────────────────────── +windowrule { + name = wallpaper-picker + match:class = wallpaper-picker + float = true + center = true + size = 1200 700 +} + +# ── bemenu launcher window ──────────────────────────────────────────────────── +windowrule { + name = launcher + match:class = launcher + float = true + center = true + size = 800 500 +} + +# ── Suppress maximize requests ──────────────────────────────────────────────── +windowrule { + name = suppress-maximize + match:class = .* + suppress_event = maximize +} + +# ── Fix XWayland drag artifacts ─────────────────────────────────────────────── +windowrule { + name = fix-xwayland-drags + match:class = ^$ + match:title = ^$ + match:xwayland = true + match:float = true + match:fullscreen = false + match:pin = false + no_focus = true +} + +# ── Inhibit idle when fullscreen ───────────────────────────────────────────── +windowrule { + name = no-idle-fullscreen + match:fullscreen = true + idle_inhibit = fullscreen +} diff --git a/arch/install.sh b/arch/install.sh new file mode 100755 index 0000000..c7b24bc --- /dev/null +++ b/arch/install.sh @@ -0,0 +1,191 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: ./install.sh [-y] +# -y Auto-accept all optional component prompts + +AUTO_YES=false +while getopts "y" opt; do + case $opt in + y) AUTO_YES=true ;; + esac +done + +ask() { + # ask <prompt> — returns 0 (yes) or 1 (no). Always yes if -y was passed. + if $AUTO_YES; then return 0; fi + read -rp "$1 [y/N] " ans + [[ "${ans,,}" == "y" ]] +} + +# ── Core WM ─────────────────────────────────────────────────────────────────── +pacman_packages=( + hyprland + hyprlock + hypridle + xdg-desktop-portal-hyprland + xdg-desktop-portal-gtk + polkit-gnome +) + +# ── Audio ───────────────────────────────────────────────────────────────────── +pacman_packages+=( + pipewire + pipewire-alsa + pipewire-pulse + pipewire-jack + wireplumber + pamixer + playerctl + pavucontrol +) + +# ── Display / input ─────────────────────────────────────────────────────────── +pacman_packages+=( + grim + slurp + wl-clipboard + brightnessctl + ydotool + chafa +) + +# ── Notifications ───────────────────────────────────────────────────────────── +pacman_packages+=( + mako + libnotify +) + +# ── Launcher ────────────────────────────────────────────────────────────────── +pacman_packages+=( + bemenu + bemenu-wayland +) + +# ── Shell / CLI ─────────────────────────────────────────────────────────────── +pacman_packages+=( + fish + tmux + starship + zoxide + fzf + ripgrep + fd + bat + eza + btop + yazi + direnv + tealdeer + jq + cliphist +) + +# ── Fonts ───────────────────────────────────────────────────────────────────── +pacman_packages+=( + ttf-jetbrains-mono-nerd + noto-fonts + noto-fonts-emoji + noto-fonts-cjk +) + +# ── GTK / cursor ────────────────────────────────────────────────────────────── +pacman_packages+=( + papirus-icon-theme + gnome-themes-extra + gnome-keyring + gsettings-desktop-schemas +) + +# ── Bluetooth ───────────────────────────────────────────────────────────────── +pacman_packages+=( + bluez + bluez-utils +) + +# ── Network / misc ──────────────────────────────────────────────────────────── +pacman_packages+=( + networkmanager + openssh + wget + socat + curl + git +) + +# ── AUR packages ────────────────────────────────────────────────────────────── +aur_packages=( + ghostty # terminal + sesh # tmux session manager + eww # bar + adw-gtk3 # GTK theme + bibata-cursor-theme + wl-kbptr # keyboard pointer (Super+G / Super+M binds) + pinfo # info page viewer (used in fish aliases) + asusctl # keyboard backlight + wallust # dynamic color generation from wallpaper + hyprland-workspaces # eww workspace widget with active-state JSON + socat # Hyprland IPC streaming (eww deflisten scripts) +) + +# ── Install core ────────────────────────────────────────────────────────────── +echo "==> Installing pacman packages..." +sudo pacman -S --needed "${pacman_packages[@]}" + +echo "==> Installing AUR packages (via yay)..." +yay -S --needed "${aur_packages[@]}" + +# ── Optional: Spotify + Spicetify ──────────────────────────────────────────── +echo "" +if ask "==> Install Spotify + Spicetify (wallust auto-theming)?"; then + yay -S --needed spotify spicetify-cli + + echo "==> Fixing Spotify permissions for Spicetify..." + sudo chmod a+wr /opt/spotify + sudo chmod -R a+wr /opt/spotify/Apps + + echo "==> Applying Spicetify wallust theme..." + spicetify config current_theme wallust color_scheme Base + spicetify backup apply + + echo " Spotify + Spicetify installed and themed." +fi + +# ── Optional: Neovim dev environment ───────────────────────────────────────── +echo "" +if ask "==> Install Neovim dev environment (LSP, formatters, linters)?"; then + sudo pacman -S --needed \ + neovim \ + clang \ + lua-language-server \ + stylua \ + python-black \ + python-isort \ + cppcheck \ + ruff + + yay -S --needed \ + pyright \ + haskell-language-server + + echo "==> Stowing nvim config..." + cd ~/dotfiles/arch && stow nvim + + echo " Neovim dev environment installed." + echo " Open nvim and run :Lazy to install plugins." +fi + +# ── Groups ──────────────────────────────────────────────────────────────────── +# input → ydotool (/dev/uinput access) +# video → brightnessctl (screen + keyboard backlight without sudo) +echo "" +echo "==> Adding $(whoami) to groups: input, video..." +sudo usermod -aG input,video "$(whoami)" + +echo "" +echo "==> Done. Next steps:" +echo " cd ~/dotfiles/arch" +echo " rm ~/.config/hypr/hyprland.conf # remove autogenerated config" +echo " stow hyprland ghostty eww fish mako git scripts wallust spicetify nvim" +echo " chsh -s /usr/bin/fish" +echo " Log out and back in for group changes to take effect" diff --git a/arch/mako/.config/mako/config b/arch/mako/.config/mako/config new file mode 100644 index 0000000..8d9d037 --- /dev/null +++ b/arch/mako/.config/mako/config @@ -0,0 +1,15 @@ +font=JetBrainsMono Nerd Font 12 +border-size=2 +border-radius=4 +padding=8,12 +max-icon-size=48 +default-timeout=5000 +ignore-timeout=1 + +background-color=#211C1A +text-color=#FCF5EA +border-color=#9E7E6D + +[urgency=high] +border-color=#7F5F52 +background-color=#211C1A diff --git a/arch/nvim/.config/nvim/.stylua.toml b/arch/nvim/.config/nvim/.stylua.toml new file mode 100644 index 0000000..e55efd5 --- /dev/null +++ b/arch/nvim/.config/nvim/.stylua.toml @@ -0,0 +1,3 @@ +indent_type = "Spaces" +indent_width = 4 +column_width = 120 diff --git a/arch/nvim/.config/nvim/init.lua b/arch/nvim/.config/nvim/init.lua new file mode 100644 index 0000000..fb4cadd --- /dev/null +++ b/arch/nvim/.config/nvim/init.lua @@ -0,0 +1,27 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.uv.fs_stat(lazypath) then + vim.fn.system({ + "git", "clone", "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +require("options") +require("keymaps") + +require("lazy").setup("plugins", { + performance = { + rtp = { + disabled_plugins = { + "gzip", "matchit", "matchparen", "netrwPlugin", + "tarPlugin", "tohtml", "tutor", "zipPlugin", + }, + }, + }, + install = { colorscheme = { "habamax" } }, + checker = { enabled = false }, + change_detection = { notify = false }, +}) diff --git a/arch/nvim/.config/nvim/lazy-lock.json b/arch/nvim/.config/nvim/lazy-lock.json new file mode 100644 index 0000000..3480e8d --- /dev/null +++ b/arch/nvim/.config/nvim/lazy-lock.json @@ -0,0 +1,30 @@ +{ + "LuaSnip": { "branch": "master", "commit": "a62e1083a3cfe8b6b206e7d3d33a51091df25357" }, + "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, + "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, + "conform.nvim": { "branch": "master", "commit": "dca1a190aa85f9065979ef35802fb77131911106" }, + "fidget.nvim": { "branch": "main", "commit": "889e2e96edef4e144965571d46f7a77bcc4d0ddf" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "fzf-lua": { "branch": "main", "commit": "1ae863c83e0823225b4e041845f10c918d5fb882" }, + "gitsigns.nvim": { "branch": "main", "commit": "6d808f99bd63303646794406e270bd553ad7792e" }, + "hardtime.nvim": { "branch": "main", "commit": "b4e431934af1fe224a3a801f632c008278cb7628" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, + "leap.nvim": { "branch": "main", "commit": "ebecd4c7957770e21abe71f8b2dd34952850033d" }, + "lualine.nvim": { "branch": "master", "commit": "a905eeebc4e63fdc48b5135d3bf8aea5618fb21c" }, + "mini.base16": { "branch": "main", "commit": "800f107b27a00978b0dadd672d6da21a5b12fa9a" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, + "nvim-lint": { "branch": "master", "commit": "eab58b48eb11d7745c11c505e0f3057165902461" }, + "nvim-lspconfig": { "branch": "master", "commit": "8fde495949782bb61c2605174e231d145a048d8c" }, + "nvim-surround": { "branch": "main", "commit": "61319d4bd1c5e336e197defa15bd104c51f0fb29" }, + "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, + "nvim-ufo": { "branch": "main", "commit": "ab3eb124062422d276fae49e0dd63b3ad1062cfc" }, + "oil.nvim": { "branch": "master", "commit": "0fcc83805ad11cf714a949c98c605ed717e0b83e" }, + "promise-async": { "branch": "main", "commit": "119e8961014c9bfaf1487bf3c2a393d254f337e2" }, + "snacks.nvim": { "branch": "main", "commit": "ad9ede6a9cddf16cedbd31b8932d6dcdee9b716e" }, + "undotree": { "branch": "master", "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" }, + "vim-tmux-navigator": { "branch": "master", "commit": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432" }, + "vim-tpipeline": { "branch": "master", "commit": "9c1fc6a9aed96a6ff5f5cb0420e3760e95dfb1c1" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/arch/nvim/.config/nvim/lua/keymaps.lua b/arch/nvim/.config/nvim/lua/keymaps.lua new file mode 100644 index 0000000..2a38a95 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/keymaps.lua @@ -0,0 +1,41 @@ +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +local map = vim.keymap.set + +-- Disable Space in normal/visual (used as leader) +map({ "n", "v" }, "<Space>", "<Nop>", { silent = true }) + +-- Save +map({ "n", "i" }, "<C-s>", "<cmd>w<CR>", { desc = "Save" }) + +-- Clear search highlight +map("n", "<Esc>", "<cmd>nohlsearch<CR>") + +-- Exit terminal mode +map("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Exit terminal" }) + +-- Better up/down on wrapped lines +map({ "n", "v" }, "j", "gj") +map({ "n", "v" }, "k", "gk") + +-- Buffer navigation +map("n", "<S-h>", "<cmd>bprevious<CR>", { desc = "Prev buffer" }) +map("n", "<S-l>", "<cmd>bnext<CR>", { desc = "Next buffer" }) +map("n", "<leader>bd", "<cmd>bdelete<CR>", { desc = "Delete buffer" }) + +-- Splits +map("n", "<leader>sv", "<C-w>v", { desc = "Split vertical" }) +map("n", "<leader>sh", "<C-w>s", { desc = "Split horizontal" }) +map("n", "<leader>se", "<C-w>=", { desc = "Equal splits" }) +map("n", "<leader>sx", "<cmd>close<CR>", { desc = "Close split" }) + +-- Move lines +map("n", "<A-Down>", "<cmd>m .+1<CR>==", { desc = "Move line down" }) +map("n", "<A-Up>", "<cmd>m .-2<CR>==", { desc = "Move line up" }) +map("v", "<A-Down>", ":m '>+1<CR>gv=gv", { desc = "Move selection down" }) +map("v", "<A-Up>", ":m '<-2<CR>gv=gv", { desc = "Move selection up" }) + +-- Stay in visual after indent +map("v", "<", "<gv") +map("v", ">", ">gv") diff --git a/arch/nvim/.config/nvim/lua/options.lua b/arch/nvim/.config/nvim/lua/options.lua new file mode 100644 index 0000000..9a97b4b --- /dev/null +++ b/arch/nvim/.config/nvim/lua/options.lua @@ -0,0 +1,39 @@ +local opt = vim.opt + +-- Line numbers +opt.number = true +opt.relativenumber = true + +-- Indentation +opt.expandtab = true +opt.tabstop = 4 +opt.shiftwidth = 4 +opt.softtabstop = 4 + +-- Visual +opt.cursorline = true +opt.scrolloff = 10 +opt.signcolumn = "yes" +opt.list = true +opt.listchars = { tab = " ", trail = "·", nbsp = "␣" } +opt.termguicolors = true +opt.colorcolumn = "" + +-- Behaviour +opt.swapfile = false +opt.undofile = true +opt.updatetime = 250 +opt.timeoutlen = 300 +opt.splitbelow = true +opt.splitright = true +opt.ignorecase = true +opt.smartcase = true +opt.inccommand = "split" +opt.hlsearch = true +opt.breakindent = true + +-- Folding (nvim-ufo) +opt.foldcolumn = "0" +opt.foldlevel = 99 +opt.foldlevelstart = 99 +opt.foldenable = true diff --git a/arch/nvim/.config/nvim/lua/plugins/colorscheme.lua b/arch/nvim/.config/nvim/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..8198402 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/colorscheme.lua @@ -0,0 +1,74 @@ +return { + "echasnovski/mini.base16", + version = false, + lazy = false, + priority = 1000, + config = function() + local palette_path = vim.fn.expand("~/.cache/wallust/nvim.lua") + + local fallback = { + base00 = "#1e1e2e", base01 = "#181825", base02 = "#313244", + base03 = "#45475a", base04 = "#585b70", base05 = "#cdd6f4", + base06 = "#f5c2e7", base07 = "#b4befe", base08 = "#f38ba8", + base09 = "#fab387", base0A = "#f9e2af", base0B = "#a6e3a1", + base0C = "#94e2d5", base0D = "#89b4fa", base0E = "#cba6f7", + base0F = "#f2cdcd", + } + + local function load_palette() + local ok, p = pcall(dofile, palette_path) + return ok and p or fallback + end + + local transparent_groups = { + "Normal", "NormalNC", "NormalFloat", + "SignColumn", "FoldColumn", "EndOfBuffer", + "LineNr", "CursorLineNr", "CursorLine", + "StatusLine", "StatusLineNC", + "TabLine", "TabLineFill", "TabLineSel", + "VertSplit", "WinSeparator", + "Pmenu", "PmenuSbar", "PmenuThumb", + "FloatBorder", "FloatTitle", + } + + local function apply_transparent() + for _, grp in ipairs(transparent_groups) do + vim.cmd("hi " .. grp .. " guibg=NONE ctermbg=NONE") + end + end + + local function apply(palette) + require("mini.base16").setup({ palette = palette }) + vim.api.nvim_set_hl(0, "LineNr", { fg = palette.base05 }) + vim.api.nvim_set_hl(0, "LineNrAbove", { fg = palette.base05 }) + vim.api.nvim_set_hl(0, "LineNrBelow", { fg = palette.base05 }) + vim.api.nvim_set_hl(0, "CursorLineNr", { fg = palette.base03, bold = true }) + if vim.g.transparent_bg then + apply_transparent() + end + end + + vim.g.transparent_bg = false + apply(load_palette()) + + -- Watch wallust output file and reload automatically + local watcher = vim.uv.new_fs_event() + if watcher then + watcher:start(palette_path, {}, vim.schedule_wrap(function() + apply(load_palette()) + end)) + end + + -- Toggle: wipe background colors so the terminal bg shows through + vim.keymap.set("n", "<leader>tt", function() + vim.g.transparent_bg = not vim.g.transparent_bg + if vim.g.transparent_bg then + apply_transparent() + vim.notify("Background: transparent", vim.log.levels.INFO) + else + apply(load_palette()) + vim.notify("Background: colorscheme", vim.log.levels.INFO) + end + end, { desc = "Toggle transparent background" }) + end, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/completion.lua b/arch/nvim/.config/nvim/lua/plugins/completion.lua new file mode 100644 index 0000000..26ab3b6 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/completion.lua @@ -0,0 +1,40 @@ +return { + { + "saghen/blink.cmp", + version = "*", + dependencies = { "L3MON4D3/LuaSnip", "rafamadriz/friendly-snippets" }, + opts = { + keymap = { + preset = "none", + ["<C-Space>"] = { "show", "show_documentation", "hide_documentation" }, + ["<C-e>"] = { "hide" }, + ["<CR>"] = { "accept", "fallback" }, + ["<Tab>"] = { "select_next", "snippet_forward", "fallback" }, + ["<S-Tab>"] = { "select_prev", "snippet_backward", "fallback" }, + ["<C-b>"] = { "scroll_documentation_up", "fallback" }, + ["<C-f>"] = { "scroll_documentation_down", "fallback" }, + ["<C-n>"] = { "select_next", "fallback" }, + ["<C-p>"] = { "select_prev", "fallback" }, + }, + appearance = { nerd_font_variant = "mono" }, + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + }, + snippets = { preset = "luasnip" }, + completion = { + documentation = { auto_show = true, auto_show_delay_ms = 200 }, + ghost_text = { enabled = true }, + menu = { border = "single" }, + }, + signature = { enabled = true, window = { border = "single" } }, + }, + }, + { + "L3MON4D3/LuaSnip", + event = "InsertEnter", + dependencies = { "rafamadriz/friendly-snippets" }, + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/editor.lua b/arch/nvim/.config/nvim/lua/plugins/editor.lua new file mode 100644 index 0000000..a6ec0e0 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/editor.lua @@ -0,0 +1,73 @@ +return { + -- Motion: s + two chars to jump anywhere + { + url = "https://codeberg.org/andyg/leap.nvim", + keys = { + { "s", "<Plug>(leap)", mode = { "n", "x", "o" }, desc = "Leap" }, + { "S", "<Plug>(leap-from-window)", mode = { "n", "o" }, desc = "Leap from window" }, + }, + }, + -- Enforce good vim habits + { + "m4xshen/hardtime.nvim", + event = "VeryLazy", + dependencies = { "MunifTanjim/nui.nvim" }, + opts = { + max_count = 4, + -- Remove arrows from disabled (completely blocked) and add to + -- restricted (blocked after max_count, same as hjkl) + disabled_keys = { + ["<Up>"] = {}, + ["<Down>"] = {}, + ["<Left>"] = {}, + ["<Right>"] = {}, + }, + restricted_keys = { + ["<Up>"] = { "n", "x" }, + ["<Down>"] = { "n", "x" }, + ["<Left>"] = { "n", "x" }, + ["<Right>"] = { "n", "x" }, + }, + }, + }, + -- Auto-close brackets/quotes + { + "windwp/nvim-autopairs", + event = "InsertEnter", + opts = { check_ts = true }, + }, + -- Folding powered by treesitter/LSP + { + "kevinhwang91/nvim-ufo", + dependencies = { "kevinhwang91/promise-async" }, + event = "BufReadPost", + keys = { + { + "zR", + function() + require("ufo").openAllFolds() + end, + desc = "Open all folds", + }, + { + "zM", + function() + require("ufo").closeAllFolds() + end, + desc = "Close all folds", + }, + }, + opts = { + provider_selector = function() + return { "treesitter", "indent" } + end, + }, + }, + -- Surround text objects: ys, ds, cs + { + "kylechui/nvim-surround", + version = "*", + event = "VeryLazy", + opts = {}, + }, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/extras.lua b/arch/nvim/.config/nvim/lua/plugins/extras.lua new file mode 100644 index 0000000..95366ed --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/extras.lua @@ -0,0 +1,37 @@ +return { + -- Splash screen / dashboard + { + "folke/snacks.nvim", + priority = 1000, + lazy = false, + opts = { + dashboard = { + sections = { + { section = "header" }, + { section = "keys", gap = 1, padding = 1 }, + { section = "startup" }, + }, + }, + }, + }, + -- Undo history tree + { + "mbbill/undotree", + keys = { + { "<leader>u", "<cmd>UndotreeToggle<CR>", desc = "Undo tree" }, + }, + }, + -- Buffer-based file explorer + { + "stevearc/oil.nvim", + lazy = false, + keys = { + { "<leader>e", "<cmd>Oil<CR>", desc = "File explorer" }, + { "-", "<cmd>Oil<CR>", desc = "Open parent dir" }, + }, + opts = { + default_file_explorer = true, + view_options = { show_hidden = true }, + }, + }, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/formatting.lua b/arch/nvim/.config/nvim/lua/plugins/formatting.lua new file mode 100644 index 0000000..912a6a8 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/formatting.lua @@ -0,0 +1,47 @@ +return { + "stevearc/conform.nvim", + event = "BufWritePre", + cmd = { "ConformInfo", "FormatToggle" }, + keys = { + { + "<leader>cF", + function() + vim.g.format_on_save = not vim.g.format_on_save + vim.notify( + "Format on save: " .. (vim.g.format_on_save and "enabled" or "disabled"), + vim.log.levels.INFO, + { title = "conform" } + ) + end, + desc = "Toggle autoformat", + }, + { + "<leader>cf", + function() require("conform").format({ async = true, lsp_fallback = true }) end, + desc = "Format buffer", + }, + }, + config = function() + vim.g.format_on_save = true + + require("conform").setup({ + formatters_by_ft = { + c = { "clang_format" }, + cpp = { "clang_format" }, + python = { "isort", "black" }, + lua = { "stylua" }, + haskell = { "ormolu" }, + }, + format_on_save = function(bufnr) + if not vim.g.format_on_save then return end + if vim.g.disable_autoformat_buf and vim.g.disable_autoformat_buf[bufnr] then return end + return { timeout_ms = 500, lsp_fallback = true } + end, + }) + + vim.api.nvim_create_user_command("FormatToggle", function() + vim.g.format_on_save = not vim.g.format_on_save + vim.notify("Format on save: " .. (vim.g.format_on_save and "on" or "off")) + end, {}) + end, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/fzf.lua b/arch/nvim/.config/nvim/lua/plugins/fzf.lua new file mode 100644 index 0000000..e507348 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/fzf.lua @@ -0,0 +1,23 @@ +return { + "ibhagwan/fzf-lua", + cmd = "FzfLua", + keys = { + { "<leader>ff", "<cmd>FzfLua files<CR>", desc = "Find files" }, + { "<leader>fg", "<cmd>FzfLua live_grep<CR>", desc = "Live grep" }, + { "<leader>fb", "<cmd>FzfLua buffers<CR>", desc = "Buffers" }, + { "<leader>fs", "<cmd>FzfLua grep_cword<CR>", desc = "Grep word under cursor" }, + { "<leader>fr", "<cmd>FzfLua oldfiles<CR>", desc = "Recent files" }, + { "<leader>fc", "<cmd>FzfLua commands<CR>", desc = "Commands" }, + { "<leader>fd", "<cmd>FzfLua diagnostics_document<CR>", desc = "Document diagnostics" }, + { "<leader>/", "<cmd>FzfLua blines<CR>", desc = "Search current buffer" }, + }, + opts = { + winopts = { + height = 0.6, + width = 0.8, + border = "single", + preview = { border = "single" }, + }, + fzf_opts = { ["--cycle"] = true }, + }, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/linting.lua b/arch/nvim/.config/nvim/lua/plugins/linting.lua new file mode 100644 index 0000000..bbbeaa7 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/linting.lua @@ -0,0 +1,17 @@ +return { + "mfussenegger/nvim-lint", + event = { "BufReadPost", "BufWritePost", "InsertLeave" }, + config = function() + require("lint").linters_by_ft = { + c = { "cppcheck" }, + cpp = { "cppcheck" }, + python = { "ruff" }, + } + + vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, { + callback = function() + require("lint").try_lint() + end, + }) + end, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/lsp.lua b/arch/nvim/.config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..17c5c64 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,75 @@ +return { + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "saghen/blink.cmp", + { + "folke/lazydev.nvim", + ft = "lua", + opts = { library = { { path = "luvit-meta/library", words = { "vim%.uv" } } } }, + }, + }, + config = function() + -- nvim 0.11+ API: vim.lsp.config / vim.lsp.enable + -- nvim-lspconfig provides default server configs in its runtime lsp/*.lua files + + local caps = require("blink.cmp").get_lsp_capabilities() + + -- Apply capabilities to all servers + vim.lsp.config("*", { capabilities = caps }) + + -- Server-specific overrides + vim.lsp.config("lua_ls", { + settings = { + Lua = { + diagnostics = { globals = { "vim" } }, + workspace = { checkThirdParty = false }, + }, + }, + }) + + -- Enable servers (default configs come from nvim-lspconfig runtime) + vim.lsp.enable({ "clangd", "pyright", "lua_ls", "hls" }) + + -- Keymaps on attach + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(ev) + local map = function(keys, func, desc) + vim.keymap.set("n", keys, func, { buffer = ev.buf, desc = "LSP: " .. desc }) + end + map("gd", vim.lsp.buf.definition, "Goto definition") + map("gD", vim.lsp.buf.declaration, "Goto declaration") + map("gr", vim.lsp.buf.references, "Goto references") + map("gI", vim.lsp.buf.implementation,"Goto implementation") + map("K", vim.lsp.buf.hover, "Hover docs") + map("<leader>rn", vim.lsp.buf.rename, "Rename") + map("<leader>ca", vim.lsp.buf.code_action, "Code action") + map("[d", vim.diagnostic.goto_prev, "Prev diagnostic") + map("]d", vim.diagnostic.goto_next, "Next diagnostic") + map("<leader>e", vim.diagnostic.open_float, "Show diagnostic") + end, + }) + + vim.diagnostic.config({ + virtual_text = false, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = " ", + [vim.diagnostic.severity.WARN] = " ", + [vim.diagnostic.severity.INFO] = " ", + [vim.diagnostic.severity.HINT] = " ", + }, + }, + float = { border = "single" }, + underline = true, + update_in_insert = false, + }) + end, + }, + { + "j-hui/fidget.nvim", + event = "LspAttach", + opts = { notification = { window = { winblend = 0 } } }, + }, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/nav.lua b/arch/nvim/.config/nvim/lua/plugins/nav.lua new file mode 100644 index 0000000..827da07 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/nav.lua @@ -0,0 +1,16 @@ +return { + "christoomey/vim-tmux-navigator", + cmd = { + "TmuxNavigateLeft", "TmuxNavigateDown", + "TmuxNavigateUp", "TmuxNavigateRight", + }, + keys = { + { "<C-Left>", "<cmd>TmuxNavigateLeft<CR>", desc = "Pane left", mode = { "n", "t" } }, + { "<C-Down>", "<cmd>TmuxNavigateDown<CR>", desc = "Pane down", mode = { "n", "t" } }, + { "<C-Up>", "<cmd>TmuxNavigateUp<CR>", desc = "Pane up", mode = { "n", "t" } }, + { "<C-Right>", "<cmd>TmuxNavigateRight<CR>", desc = "Pane right", mode = { "n", "t" } }, + }, + init = function() + vim.g.tmux_navigator_no_mappings = 1 + end, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/treesitter.lua b/arch/nvim/.config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..b31fd1c --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,34 @@ +return { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + event = { "BufReadPre", "BufNewFile" }, + opts = { + ensure_installed = { + "c", + "cpp", + "python", + "lua", + "haskell", + "vim", + "vimdoc", + "query", + "bash", + "markdown", + "markdown_inline", + "json", + "toml", + "yaml", + }, + highlight = { enable = true }, + indent = { enable = true }, + auto_install = false, + }, + config = function(_, opts) + local ok = pcall(require, "nvim-treesitter.configs") + if ok then + require("nvim-treesitter.configs").setup(opts) + else + require("nvim-treesitter").setup(opts) + end + end, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/ui.lua b/arch/nvim/.config/nvim/lua/plugins/ui.lua new file mode 100644 index 0000000..f0f8a27 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/ui.lua @@ -0,0 +1,105 @@ +return { + -- Statusline + { + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + config = function() + local function make_theme() + local ok, p = pcall(dofile, vim.fn.expand("~/.cache/wallust/nvim.lua")) + if not ok then + p = { base0D = "#89b4fa", base05 = "#cdd6f4", base04 = "#585b70", + base0B = "#a6e3a1", base0E = "#cba6f7", base08 = "#f38ba8", base0A = "#f9e2af" } + end + return { + normal = { a = { fg = p.base0D, bg = "NONE", gui = "bold" }, b = { fg = p.base05, bg = "NONE" }, c = { fg = p.base04, bg = "NONE" } }, + insert = { a = { fg = p.base0B, bg = "NONE", gui = "bold" } }, + visual = { a = { fg = p.base0E, bg = "NONE", gui = "bold" } }, + replace = { a = { fg = p.base08, bg = "NONE", gui = "bold" } }, + command = { a = { fg = p.base0A, bg = "NONE", gui = "bold" } }, + inactive = { a = { fg = p.base04, bg = "NONE" }, b = { fg = p.base04, bg = "NONE" }, c = { fg = p.base04, bg = "NONE" } }, + } + end + + -- lualine.setup() (and every ColorScheme reload of it) asserts + -- laststatus=3. Register the guard first so it catches every future + -- write, then immediately fix the one we're about to trigger. + vim.api.nvim_create_autocmd("OptionSet", { + pattern = "laststatus", + callback = function() + if vim.o.laststatus ~= 0 then + vim.o.laststatus = 0 + end + end, + }) + + require("lualine").setup({ + options = { + theme = make_theme(), + globalstatus = true, + component_separators = { left = "|", right = "|" }, + section_separators = { left = "", right = "" }, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch", "diff", "diagnostics" }, + lualine_c = { { "filename", path = 1 } }, + lualine_x = { "encoding", "filetype" }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + }) + vim.o.laststatus = 0 -- synchronous fix for the setup() call above + + vim.api.nvim_create_autocmd("ColorScheme", { + callback = function() + require("lualine").setup({ options = { theme = make_theme() } }) + vim.o.laststatus = 0 + end, + }) + end, + }, + -- Pipe lualine into the tmux status bar + { + "vimpostor/vim-tpipeline", + event = "VeryLazy", + init = function() + vim.g.tpipeline_restore = 0 -- clear files on exit rather than restore broken format + vim.g.tpipeline_embedopts = {} -- tmux.conf owns status-left/right format + end, + }, + -- Buffer tabs + { + "akinsho/bufferline.nvim", + version = "*", + event = "VeryLazy", + keys = { + { "<leader>bp", "<cmd>BufferLinePick<CR>", desc = "Pick buffer" }, + { "<leader>bo", "<cmd>BufferLineCloseOthers<CR>", desc = "Close others" }, + { "<leader>bc", "<cmd>BufferLinePickClose<CR>", desc = "Close (pick)" }, + }, + opts = { + options = { + mode = "buffers", + show_buffer_close_icons = false, + show_close_icon = false, + separator_style = "thin", + always_show_bufferline = false, + diagnostics = "nvim_lsp", + }, + }, + }, + -- Git signs in the gutter + { + "lewis6991/gitsigns.nvim", + event = { "BufReadPre", "BufNewFile" }, + opts = { + signs = { + add = { text = "▎" }, + change = { text = "▎" }, + delete = { text = "" }, + topdelete = { text = "" }, + changedelete = { text = "▎" }, + }, + }, + }, +} diff --git a/arch/nvim/.config/nvim/lua/plugins/whichkey.lua b/arch/nvim/.config/nvim/lua/plugins/whichkey.lua new file mode 100644 index 0000000..97e8b19 --- /dev/null +++ b/arch/nvim/.config/nvim/lua/plugins/whichkey.lua @@ -0,0 +1,25 @@ +return { + "folke/which-key.nvim", + event = "VeryLazy", + opts = { + icons = { mappings = false }, + delay = 300, + spec = { + { "<leader>f", group = "find" }, + { "<leader>b", group = "buffer" }, + { "<leader>s", group = "split" }, + { "<leader>r", group = "refactor" }, + { "<leader>c", group = "code" }, + { "<leader>cF", desc = "Toggle autoformat" }, + { "<leader>cf", desc = "Format buffer" }, + { "<leader>e", desc = "File explorer" }, + { "<leader>u", desc = "Undo tree" }, + { "<leader>bp", desc = "Pick buffer" }, + { "<leader>bo", desc = "Close others" }, + { "<leader>bc", desc = "Close (pick)" }, + }, + }, + keys = { + { "<leader>?", function() require("which-key").show({ global = false }) end, desc = "Buffer keymaps" }, + }, +} diff --git a/arch/scripts/.local/bin/launcher b/arch/scripts/.local/bin/launcher new file mode 100755 index 0000000..9451d35 --- /dev/null +++ b/arch/scripts/.local/bin/launcher @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Application launcher using bemenu — colors sourced from wallust cache + +FONT="JetBrainsMono Nerd Font 12" + +# Defaults (used until wallust has run at least once) +NB="#1e1e2e" NF="#cdd6f4" SB="#89b4fa" SF="#1e1e2e" +AB="#313244" AF="#cdd6f4" TB="#1e1e2e" TF="#89b4fa" +FB="#1e1e2e" FF="#cdd6f4" + +[ -f ~/.cache/wallust/launcher-colors.sh ] && source ~/.cache/wallust/launcher-colors.sh + +bemenu-run \ + --fn "$FONT" \ + --nb "$NB" \ + --nf "$NF" \ + --sb "$SB" \ + --sf "$SF" \ + --ab "$AB" \ + --af "$AF" \ + --tb "$TB" \ + --tf "$TF" \ + --fb "$FB" \ + --ff "$FF" \ + --list 10 \ + --prompt " " diff --git a/arch/scripts/.local/bin/pick-wallpaper b/arch/scripts/.local/bin/pick-wallpaper new file mode 100755 index 0000000..c96ca4e --- /dev/null +++ b/arch/scripts/.local/bin/pick-wallpaper @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +WALLPAPER_DIR="${HOME}/wallpapers" + +selected=$(find "$WALLPAPER_DIR" -type f \( \ + -name "*.jpg" -o -name "*.jpeg" -o \ + -name "*.png" -o -name "*.webp" \) | sort | \ + fzf --preview 'chafa --size=80x40 {}' \ + --preview-window 'right:60%' \ + --prompt "wallpaper> ") + +[ -n "$selected" ] && ~/.local/bin/set-wallpaper "$selected" diff --git a/arch/scripts/.local/bin/set-wallpaper b/arch/scripts/.local/bin/set-wallpaper new file mode 100755 index 0000000..30b15d8 --- /dev/null +++ b/arch/scripts/.local/bin/set-wallpaper @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail +WALLPAPER="${1:?usage: set-wallpaper <path>}" + +awww img "$WALLPAPER" \ + --transition-type wipe \ + --transition-angle 30 \ + --transition-duration 1 + +wallust run "$WALLPAPER" --ignore-sequence background --ignore-sequence foreground + +gdbus call --session \ + --dest com.mitchellh.ghostty \ + --object-path /com/mitchellh/ghostty \ + --method org.gtk.Actions.Activate \ + "reload-config" "[]" "{}" > /dev/null 2>&1 || true + +hyprctl reload +pkill -x mako || true +mako & +eww reload || true + +# spicetify watch -s picks up color.ini changes automatically. +# Fallback: refresh manually if watch isn't running. +pgrep -f "spicetify watch" > /dev/null || spicetify refresh > /dev/null 2>&1 || true + +# nvim picks up the new palette automatically via a libuv file watcher in colorscheme.lua diff --git a/arch/spicetify/.config/spicetify/Themes/wallust/color.ini b/arch/spicetify/.config/spicetify/Themes/wallust/color.ini new file mode 100644 index 0000000..a0c7209 --- /dev/null +++ b/arch/spicetify/.config/spicetify/Themes/wallust/color.ini @@ -0,0 +1,19 @@ +[Base] +text = FCF5EA +subtext = F2E8D9 +main = 211C1A +main-elevated = 4D4744 +highlight = 4D4744 +highlight-elevated = AAA298 +sidebar = 211C1A +player = 211C1A +card = 4D4744 +shadow = 000000 +selected-row = 4D4744 +button = 9E7E6D +button-active = B9AA93 +button-disabled = AAA298 +tab-active = 4D4744 +notification = 9E7E6D +notification-error = 7F5F52 +misc = AAA298 diff --git a/arch/spicetify/.config/spicetify/Themes/wallust/user.css b/arch/spicetify/.config/spicetify/Themes/wallust/user.css new file mode 100644 index 0000000..8e4e406 --- /dev/null +++ b/arch/spicetify/.config/spicetify/Themes/wallust/user.css @@ -0,0 +1,72 @@ +/* Wallust — auto-updating spicetify theme + Colors come from color.ini (generated by wallust on each wallpaper change). + --spice-rgb-* variables are auto-derived by spicetify from color.ini values. + Transparency: rgba() + backdrop-filter for frosted glass within the window. + The Hyprland opacity windowrule (0.95) makes the window slightly transparent + so wallpaper bleed-through is visible behind the blurred panels. */ + +/* ── Root ─────────────────────────────────────────────────────────────────── */ +html, body { + background: transparent !important; +} + +/* ── Main content area ────────────────────────────────────────────────────── */ +.Root__main-view { + background: rgba(var(--spice-rgb-main), 0.88) !important; + backdrop-filter: blur(20px) saturate(160%); +} + +/* ── Left sidebar / nav ───────────────────────────────────────────────────── */ +.Root__nav-bar, +.root-nav-bar { + background: rgba(var(--spice-rgb-sidebar), 0.88) !important; + backdrop-filter: blur(20px) saturate(160%); +} + +/* ── Bottom now-playing bar ───────────────────────────────────────────────── */ +.Root__now-playing-bar { + background: rgba(var(--spice-rgb-player), 0.92) !important; + backdrop-filter: blur(20px) saturate(160%); + border-top: 1px solid rgba(var(--spice-rgb-highlight), 0.3); +} + +/* ── Top bar ──────────────────────────────────────────────────────────────── */ +.Root__top-bar { + background: rgba(var(--spice-rgb-main), 0.80) !important; + backdrop-filter: blur(20px) saturate(160%); +} + +/* ── Cards ────────────────────────────────────────────────────────────────── */ +.main-card-card, +[data-testid="card-image-hit-area"], +.main-shelf-shelf { + background: rgba(var(--spice-rgb-card), 0.60) !important; + backdrop-filter: blur(8px); + transition: background 0.2s ease; +} + +.main-card-card:hover { + background: rgba(var(--spice-rgb-highlight), 0.70) !important; +} + +/* ── Context menus ────────────────────────────────────────────────────────── */ +.main-contextMenu-menu, +ul[data-radix-popper-content-wrapper] { + background: rgba(var(--spice-rgb-main-elevated), 0.94) !important; + backdrop-filter: blur(24px) saturate(160%); + border: 1px solid rgba(var(--spice-rgb-highlight), 0.25); +} + +/* ── Modals / dialogs ─────────────────────────────────────────────────────── */ +.GenericModal, +.main-genericModal-overlay, +[role="dialog"] { + background: rgba(var(--spice-rgb-main), 0.92) !important; + backdrop-filter: blur(24px); +} + +/* ── Queue / right panel ──────────────────────────────────────────────────── */ +.Root__right-sidebar { + background: rgba(var(--spice-rgb-sidebar), 0.88) !important; + backdrop-filter: blur(20px) saturate(160%); +} diff --git a/arch/tmux/.config/tmux/plugins/tmux-resurrect b/arch/tmux/.config/tmux/plugins/tmux-resurrect new file mode 160000 +Subproject cff343cf9e81983d3da0c8562b01616f12e8d54 diff --git a/arch/tmux/.config/tmux/plugins/tmux-sensible b/arch/tmux/.config/tmux/plugins/tmux-sensible new file mode 160000 +Subproject 25cb91f42d020f675bb0a2ce3fbd3a5d96119ef diff --git a/arch/tmux/.config/tmux/plugins/tmux-yank b/arch/tmux/.config/tmux/plugins/tmux-yank new file mode 160000 +Subproject acfd36e4fcba99f8310a7dfb432111c242fe739 diff --git a/arch/tmux/.config/tmux/plugins/tpm b/arch/tmux/.config/tmux/plugins/tpm new file mode 160000 +Subproject 99469c4a9b1ccf77fade25842dc7bafbc8ce994 diff --git a/arch/tmux/.config/tmux/plugins/vim-tmux-navigator b/arch/tmux/.config/tmux/plugins/vim-tmux-navigator new file mode 160000 +Subproject e41c431a0c7b7388ae7ba341f01a0d217eb3a43 diff --git a/arch/tmux/.config/tmux/tmux.conf b/arch/tmux/.config/tmux/tmux.conf new file mode 100644 index 0000000..38e15a9 --- /dev/null +++ b/arch/tmux/.config/tmux/tmux.conf @@ -0,0 +1,119 @@ +# ── Prefix ──────────────────────────────────────────────────────────────────── +unbind C-b +set -g prefix C-Space +bind C-Space send-prefix + +# ── Core settings ───────────────────────────────────────────────────────────── +set -g default-terminal "tmux-256color" +set -as terminal-overrides ",*:Tc" +set -as terminal-features ",*:RGB" +set -g default-shell /usr/bin/fish +set -g mouse on +set -g base-index 1 +set -g pane-base-index 1 +set -g renumber-windows on +set -g history-limit 50000 +set -sg escape-time 0 +set -g focus-events on +set -g mode-keys emacs + +# ── Splits (open in current directory) ─────────────────────────────────────── +unbind % +unbind '"' +bind v split-window -h -c "#{pane_current_path}" +bind h split-window -v -c "#{pane_current_path}" + +# ── Pane navigation (Ctrl+arrow, no prefix — vim-tmux-navigator aware) ─────── +# Checks if the active pane is running nvim; if so passes the key to nvim, +# otherwise switches tmux panes. Neovim needs matching keybinds — see comment +# at the bottom of this file. +is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ + | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|l?n?vim?x?|fzf)(diff)?$'" + +bind -n C-Left if-shell "$is_vim" 'send-keys C-Left' 'select-pane -L' +bind -n C-Down if-shell "$is_vim" 'send-keys C-Down' 'select-pane -D' +bind -n C-Up if-shell "$is_vim" 'send-keys C-Up' 'select-pane -U' +bind -n C-Right if-shell "$is_vim" 'send-keys C-Right' 'select-pane -R' + +# ── Pane resize (Prefix + Shift+arrow, repeatable) ─────────────────────────── +bind -r S-Up resize-pane -U 5 +bind -r S-Down resize-pane -D 5 +bind -r S-Left resize-pane -L 5 +bind -r S-Right resize-pane -R 5 + +# ── Window navigation (Alt+arrow, no prefix needed) ────────────────────────── +bind -n M-Left previous-window +bind -n M-Right next-window + +# ── Sesh: fuzzy session + directory picker ──────────────────────────────────── +bind S display-popup -E -w 80% -h 70% \ + "sesh connect \$(sesh list | fzf \ + --height 100% \ + --reverse \ + --border \ + --border-label ' sesh ' \ + --prompt ' ' \ + --no-sort)" + +# ── Reload config ───────────────────────────────────────────────────────────── +bind r source-file ~/.config/tmux/tmux.conf \; display " config reloaded" + +# ── Pane transparency — empty style lets ghostty background show through ─────── +set -g window-style '' +set -g window-active-style '' + +# ── Status bar ──────────────────────────────────────────────────────────────── +set -g status on +set -g status-position bottom +set -g status-interval 1 +set -g status-left-length 99 +set -g status-right-length 99 +set -g status-justify centre +set -g status-style "bg=default,fg=default" + +# Left: session name + nvim lualine left sections (mode, branch, diff) +set -g status-left "#[fg=colour4,bold] #S #[default] #(cat #{socket_path}-\#{session_id}-vimbridge)" +set -g status-left-length 80 +# Right: nvim lualine right sections (encoding, filetype, progress, location) +set -g status-right '#(cat #{socket_path}-\#{session_id}-vimbridge-R)' +set -g status-right-length 120 + +# Window list +set -g window-status-format " #I #W " +set -g window-status-current-format "#[fg=colour4,bold,reverse] #I #W " +set -g window-status-separator "" + +# ── Borders ─────────────────────────────────────────────────────────────────── +# colour4 = wallust accent (updates automatically when ghostty palette changes) +set -g pane-border-style "fg=colour0" +set -g pane-active-border-style "fg=colour4" +set -g pane-border-lines single + +# ── Popups / messages ───────────────────────────────────────────────────────── +set -g message-style "bg=colour4,fg=colour0,bold" +set -g popup-border-style "fg=colour4" +set -g popup-border-lines rounded + + +# ── Plugins ─────────────────────────────────────────────────────────────────── +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' +set -g @plugin 'christoomey/vim-tmux-navigator' +set -g @plugin 'tmux-plugins/tmux-yank' +set -g @plugin 'tmux-plugins/tmux-resurrect' + +# Disable vim-tmux-navigator's default C-h/j/k/l bindings (using arrows instead) +set -g @vim-tmux-navigator-no-wrap 1 +set -g @vim_tmux_navigator_no_mappings 1 + +run '~/.tmux/plugins/tpm/tpm' + +# vim-tmux-navigator binds C-h to select-pane -L after TPM loads. +# Unbind it here so Ctrl+Backspace (which sends C-h) passes through to the shell. +unbind -n C-h + +# ── Neovim keybinds (add to your nvim config when ready) ───────────────────── +# vim.keymap.set({'n','t'}, '<C-Left>', '<Cmd>TmuxNavigateLeft<CR>') +# vim.keymap.set({'n','t'}, '<C-Down>', '<Cmd>TmuxNavigateDown<CR>') +# vim.keymap.set({'n','t'}, '<C-Up>', '<Cmd>TmuxNavigateUp<CR>') +# vim.keymap.set({'n','t'}, '<C-Right>', '<Cmd>TmuxNavigateRight<CR>') diff --git a/arch/wallust/.config/wallust/templates/eww-colors.scss b/arch/wallust/.config/wallust/templates/eww-colors.scss new file mode 100644 index 0000000..782b2fa --- /dev/null +++ b/arch/wallust/.config/wallust/templates/eww-colors.scss @@ -0,0 +1,5 @@ +$bg: {{background}}; +$fg: {{foreground}}; +$accent: {{color4}}; +$surface: {{color0}}; +$muted: {{color8}}; diff --git a/arch/wallust/.config/wallust/templates/ghostty-colors.conf b/arch/wallust/.config/wallust/templates/ghostty-colors.conf new file mode 100644 index 0000000..dfa89c5 --- /dev/null +++ b/arch/wallust/.config/wallust/templates/ghostty-colors.conf @@ -0,0 +1,19 @@ +background = {{background}} +foreground = {{foreground}} + +palette = 0={{color0}} +palette = 1={{color1}} +palette = 2={{color2}} +palette = 3={{color3}} +palette = 4={{color4}} +palette = 5={{color5}} +palette = 6={{color6}} +palette = 7={{color7}} +palette = 8={{color8}} +palette = 9={{color9}} +palette = 10={{color10}} +palette = 11={{color11}} +palette = 12={{color12}} +palette = 13={{color13}} +palette = 14={{color14}} +palette = 15={{color15}} diff --git a/arch/wallust/.config/wallust/templates/hyprland-colors.conf b/arch/wallust/.config/wallust/templates/hyprland-colors.conf new file mode 100644 index 0000000..18e7f3d --- /dev/null +++ b/arch/wallust/.config/wallust/templates/hyprland-colors.conf @@ -0,0 +1,10 @@ +general { + col.active_border = rgba({{ color4 | replace("#", "") }}ee) + col.inactive_border = rgba({{ color0 | replace("#", "") }}aa) +} + +decoration { + shadow { + color = rgba({{ background | replace("#", "") }}ee) + } +} diff --git a/arch/wallust/.config/wallust/templates/launcher-colors.sh b/arch/wallust/.config/wallust/templates/launcher-colors.sh new file mode 100644 index 0000000..35b03ee --- /dev/null +++ b/arch/wallust/.config/wallust/templates/launcher-colors.sh @@ -0,0 +1,10 @@ +NB="{{background}}" +NF="{{foreground}}" +SB="{{color4}}" +SF="{{background}}" +AB="{{color0}}" +AF="{{foreground}}" +TB="{{background}}" +TF="{{color4}}" +FB="{{background}}" +FF="{{foreground}}" diff --git a/arch/wallust/.config/wallust/templates/mako.conf b/arch/wallust/.config/wallust/templates/mako.conf new file mode 100644 index 0000000..d5d8382 --- /dev/null +++ b/arch/wallust/.config/wallust/templates/mako.conf @@ -0,0 +1,15 @@ +font=JetBrainsMono Nerd Font 12 +border-size=2 +border-radius=4 +padding=8,12 +max-icon-size=48 +default-timeout=5000 +ignore-timeout=1 + +background-color={{background}} +text-color={{foreground}} +border-color={{color4}} + +[urgency=high] +border-color={{color1}} +background-color={{background}} diff --git a/arch/wallust/.config/wallust/templates/nvim.lua b/arch/wallust/.config/wallust/templates/nvim.lua new file mode 100644 index 0000000..2458113 --- /dev/null +++ b/arch/wallust/.config/wallust/templates/nvim.lua @@ -0,0 +1,19 @@ +-- Generated by wallust — do not edit manually +return { + base00 = "{{background}}", -- bg + base01 = "{{color0}}", -- bg highlight + base02 = "{{color8}}", -- selection + base03 = "{{color8}}", -- comments + base04 = "{{color7}}", -- dark fg + base05 = "{{foreground}}", -- default fg + base06 = "{{color15}}", -- light fg + base07 = "{{color15}}", -- bright white + base08 = "{{color1}}", -- red / errors + base09 = "{{color9}}", -- orange / constants + base0A = "{{color3}}", -- yellow / classes + base0B = "{{color2}}", -- green / strings + base0C = "{{color6}}", -- cyan / support + base0D = "{{color4}}", -- blue / functions + base0E = "{{color5}}", -- purple / keywords + base0F = "{{color13}}", -- brown / embedded +} diff --git a/arch/wallust/.config/wallust/templates/spicetify-colors.ini b/arch/wallust/.config/wallust/templates/spicetify-colors.ini new file mode 100644 index 0000000..65df225 --- /dev/null +++ b/arch/wallust/.config/wallust/templates/spicetify-colors.ini @@ -0,0 +1,19 @@ +[Base] +text = {{ foreground | replace("#", "") }} +subtext = {{ color7 | replace("#", "") }} +main = {{ background | replace("#", "") }} +main-elevated = {{ color0 | replace("#", "") }} +highlight = {{ color0 | replace("#", "") }} +highlight-elevated = {{ color8 | replace("#", "") }} +sidebar = {{ background | replace("#", "") }} +player = {{ background | replace("#", "") }} +card = {{ color0 | replace("#", "") }} +shadow = 000000 +selected-row = {{ color0 | replace("#", "") }} +button = {{ color4 | replace("#", "") }} +button-active = {{ color6 | replace("#", "") }} +button-disabled = {{ color8 | replace("#", "") }} +tab-active = {{ color0 | replace("#", "") }} +notification = {{ color4 | replace("#", "") }} +notification-error = {{ color1 | replace("#", "") }} +misc = {{ color8 | replace("#", "") }} diff --git a/arch/wallust/.config/wallust/wallust.toml b/arch/wallust/.config/wallust/wallust.toml new file mode 100644 index 0000000..ab62dec --- /dev/null +++ b/arch/wallust/.config/wallust/wallust.toml @@ -0,0 +1,14 @@ +backend = "full" +color_space = "lchmixed" +palette = "dark16" +threshold = 11 +check_contrast = true + +[templates] +hyprland = { template = "hyprland-colors.conf", target = "~/.cache/wallust/hyprland-colors.conf" } +mako = { template = "mako.conf", target = "~/.config/mako/config" } +eww = { template = "eww-colors.scss", target = "~/.cache/wallust/eww-colors.scss" } +ghostty = { template = "ghostty-colors.conf", target = "~/.cache/wallust/ghostty-colors.conf" } +launcher = { template = "launcher-colors.sh", target = "~/.cache/wallust/launcher-colors.sh" } +spicetify = { template = "spicetify-colors.ini", target = "~/.config/spicetify/Themes/wallust/color.ini" } +nvim = { template = "nvim.lua", target = "~/.cache/wallust/nvim.lua" } |