{ config, pkgs, ... }: { home.file.".config/eww/scripts/ascii/ascii_core_layout.sh".file = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # ascii_core_layout.sh # Gets the current Hyprland workspace ID and writes a small ASCII frame # to /tmp/core_layout.txt. # Example output (written to /tmp/core_layout.txt): # ─┐ ┌─ # [ 2 ] # ─┘ └─ # ───────────────────────────────────────────────────────────────────────────── ws=$(hyprctl activeworkspace -j | jq -r '.id') cat < /tmp/core_layout.txt ─┐ ┌─ [ $ws ] ─┘ └─ EOF ''; home.file.".config/eww/scripts/audio/audio_cava_status.sh".file = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # Checks whether the ASCII visualizer output file (/tmp/visualizer.txt) # is actively updating by comparing MD5 hashes between loops. # Outputs simple text. # Called by ascii_audio_status window # ───────────────────────────────────────────────────────────────────────────── VIS_FILE="/tmp/visualizer.txt" HASH_FILE="/tmp/.last_vis_hash" # ── Safety checks ─────────────────────────────────────────────────────────── if [ ! -s "$VIS_FILE" ]; then echo "[ CORE STATUS: ] Standby." exit 0 fi # ── Hash current frame ────────────────────────────────────────────────────── if command -v md5sum >/dev/null 2>&1; then CURRENT=$(md5sum "$VIS_FILE" | awk '{print $1}') elif command -v md5 >/dev/null 2>&1; then # macOS/BSD fallback CURRENT=$(md5 -q "$VIS_FILE") else echo "[ CORE STATUS: ] Unknown (no md5 tool found)" exit 1 fi LAST=$(cat "$HASH_FILE" 2>/dev/null || echo "") # ── Save current hash for next check ────────────────────────────────────── echo "$CURRENT" > "$HASH_FILE" # ── Compare ─────────────────────────────────────────────────────────────── if [ "$CURRENT" = "$LAST" ] && [ -n "$LAST" ]; then echo "[ CORE STATUS: ] Inactive." else echo "[ CORE STATUS: ] Generating visuals." fi ''; home.file.".config/eww/scripts/audio/audio_visualizer.py".text = '' #!/usr/bin/env python3 # ───────────────────────────────────────────────────────────────────────────── # °˖* ૮( • ᴗ 。)っ🍸 pewdiepie/archdaemon/dionysh shhheersh # vers. 1.0 # ───────────────────────────────────────────────────────────────────────────── # Reads /tmp/cava.raw and writes an ASCII‑art file that can be shown by eww, # waybar, or any terminal widget. Can run as exec once in hyprland config. # ───────────────────────────────────────────────────────────────────────────── import argparse import os import signal import sys import time import numpy as np # ── Default visual parameters ─────────────────────────────────────────────── DEFAULT_WIDTH = 64 DEFAULT_HEIGHT = 12 DEFAULT_FPS = 30 DEFAULT_DECAY = 0.92 # lower → longer trails CHARS = [" ", ".", ":", "·", "•", "•"] # ascending intensity def parse_frame(line: str, width: int) -> list[int]: """Turn a semicolon‑separated line from CAVA into a list of ints.""" try: return [int(x) for x in line.strip().split(";") if x][:width] except ValueError: return [0] * width def normalize(vals: list[int]) -> np.ndarray: """Scale values to the range [0, 1].""" arr = np.array(vals, dtype=float) return (arr - arr.min()) / (arr.max() - arr.min() + 1e-5) def get_char_index(val: float) -> int: """Map a normalized value to the appropriate character index.""" return min(int(val * (len(CHARS) - 1)), len(CHARS) - 1) def build_frame(_, history: np.ndarray, height: int, width: int) -> list[str]: """Create the ASCII rows from the decay buffer.""" frame = [[" " for _ in range(width)] for _ in range(height)] for x in range(width): for y in range(height): strength = history[y, x] idx = get_char_index(strength) frame[height - y - 1][x] = CHARS[idx] # No baseline drawing – the “remove” request is satisfied return ["".join(row) for row in frame] def run( cava_path: str, out_path: str, width: int = DEFAULT_WIDTH, height: int = DEFAULT_HEIGHT, fps: int = DEFAULT_FPS, decay: float = DEFAULT_DECAY, ) -> None: """Main loop – read CAVA output, update the decay buffer, write ASCII.""" os.makedirs(os.path.dirname(out_path), exist_ok=True) decay_buffer = np.zeros((height, width), dtype=float) while True: try: with open(cava_path, "r") as f: # read one line at a time from the FIFO line = f.readline() if not line: time.sleep(1.0 / fps) continue except Exception: time.sleep(1.0 / fps) continue # 1️⃣ Parse & normalise values = parse_frame(line, width) values = normalize(values) if values else np.zeros(width) # 2️⃣ Build a binary “bars” matrix for the current frame new_frame = np.zeros((height, width), dtype=float) for i, val in enumerate(values): bar_h = int(val * height) new_frame[:bar_h, i] = 1.0 # 3️⃣ Apply decay (trails) and blend with the new frame decay_buffer = np.maximum(decay_buffer * decay, new_frame) # 4️⃣ Render ASCII and write out ascii_lines = build_frame(values, decay_buffer, height, width) with open(out_path, "w") as out: out.write("\n".join(ascii_lines)) time.sleep(1.0 / fps) def _handle_sigint(signum, frame): """Graceful exit on Ctrl‑C.""" print("\n[+] CAVA ASCII visualizer stopped.") sys.exit(0) def main() -> None: parser = argparse.ArgumentParser( description="CAVA → ASCII visualizer (compatible with eww/widgets)", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument("--cava-path", default="/tmp/cava.raw", help="Path to CAVA raw output file") parser.add_argument("--out-path", default="/tmp/visualizer.txt", help="File where ASCII art will be written") parser.add_argument("--width", type=int, default=DEFAULT_WIDTH, help="Number of columns (match CAVA `bars` setting)") parser.add_argument("--height", type=int, default=DEFAULT_HEIGHT, help="Number of rows in the ASCII canvas") parser.add_argument("--fps", type=int, default=DEFAULT_FPS, help="Refresh rate (frames per second)") parser.add_argument("--decay", type=float, default=DEFAULT_DECAY, help="Trail‑fade factor (0‑1, lower = slower fade)") args = parser.parse_args() signal.signal(signal.SIGINT, _handle_sigint) print("[+] Starting CAVA ASCII visualizer …") run( cava_path=args.cava_path, out_path=args.out_path, width=args.width, height=args.height, fps=args.fps, decay=args.decay, ) if __name__ == "__main__": main() ''; home.file.".config/eww/scripts/bar/bar_render.sh" = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # Converts a numeric percentage (0–100) into an ASCII block bar. # Example: # ./usage_render_bar.sh 73 # ███████▓░░ # ───────────────────────────────────────────────────────────────────────────── usage=$1 # pass percentage as the first argument full="█" half="▓" empty="░" blocks=10 filled=$(( usage * blocks / 100 )) bar="" for ((i=0; i # Example: ./upload_bar.sh 73 # Output (top to bottom): # │ # │ # ╽ # █ # █ # ───────────────────────────────────────────────────────────────────────────── percent=$1 lines=5 # Cap the percent between 0 and 100 if [ "$percent" -gt 100 ]; then percent=100; fi if [ "$percent" -lt 0 ]; then percent=0; fi # Calculate how many rows to fill filled=$((percent * lines / 100)) # Always show at least one block if >0 if (( percent > 0 && filled == 0 )); then filled=1 fi # Draw from top to bottom for ((i=0; i/dev/null \ | grep 'time=' \ | awk -F'time=' '{print int($2)}' \ || echo 0 ''; home.file.".config/eww/scripts/net/ping_latency.sh".text = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # net_ping_latency.sh # Visualizes ping latency as a vertical bar (5 lines). # # Usage: ./net_ping_latency.sh # Example: ./net_ping_latency.sh 120 # Output (top to bottom): # │ # ╽ # █ # █ # █ # ───────────────────────────────────────────────────────────────────────────── ms=$1 lines=5 max_ms=200 # adjust scale (200ms = 100%) # Scale ping ms → percentage percent=$(( ms * 100 / max_ms )) if [ "$percent" -gt 100 ]; then percent=100; fi if [ "$percent" -lt 0 ]; then percent=0; fi # Calculate filled rows filled=$(( (percent * lines + 99) / 100 )) if (( ms > 0 && filled == 0 )); then filled=1 fi for ((i=0; i # Example: ./upload_bar.sh 73 # Output (top to bottom): # │ # │ # ╽ # █ # █ # ───────────────────────────────────────────────────────────────────────────── percent=$1 lines=5 # Cap 0–100 if [ "$percent" -gt 100 ]; then percent=100; fi if [ "$percent" -lt 0 ]; then percent=0; fi # Scale percentage into rows (round up) filled=$(( (percent * lines + 99) / 100 )) # Always show at least one block if >0 if (( percent > 0 && filled == 0 )); then filled=1 fi # Draw from top to bottom for ((i=0; i/dev/null | grep -q "ESTABLISHED"; then # VPN is up → full block bar for ((i=0; i/dev/null | grep -q "ESTABLISHED"; then country=$(curl -s ifconfig.co/country 2>/dev/null) [[ -z "$country" ]] && country="НЕУСТАНОВЛЕНО" echo "[УЗЕЛ] $country" else echo "[НЕТ СВЯЗИ]" fi ''; home.file.".config/eww/scripts/sys/sys_cpu_voltage.sh".text = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # sys_dc_voltage.sh # Reads the VDDNB (SoC / NB voltage) from lm-sensors and prints it in mV. # Requires: lm-sensors (run `sensors-detect` to configure chip readings). # ───────────────────────────────────────────────────────────────────────────── sensors | awk '/vddnb:/ {printf "%s mV\n", $2}' || echo "N/A" ''; home.file.".config/eww/scripts/sys/sys_dc_voltage.sh".text = '' #!/bin/bash # ───────────────────────────────────────────────────────────────────────────── # sys_cpu_voltage.sh # Reads CPU voltage (in0) from lm-sensors and prints it in volts. # Requires: lm-sensors (and sensors-detect configured) # ───────────────────────────────────────────────────────────────────────────── sensors | awk '/in0:/ {print $2 " V"}' || echo "N/A" ''; home.file.".config/eww/scripts/sys/sys_fan_bar.sh".text = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # bar_render.sh # Renders a simple horizontal bar graph from a percentage value. # Example: ./bar_render.sh 75 → ███████░░░ # ───────────────────────────────────────────────────────────────────────────── usage=$1 # percent or normalized value full="█" empty="░" blocks=10 filled=$(( usage * blocks / 100 )) bar="" for ((i=0; i "$cache" # Get RPM if [ "$fan" = "cpu" ]; then rpm=$(sensors | grep -i 'cpu_fan' | awk '{print $2}') elif [ "$fan" = "gpu" ]; then rpm=$(sensors | grep -i 'gpu_fan' | awk '{print $2}') else rpm=0 fi [ -z "$rpm" ] && rpm=0 if [ "$rpm" -eq 0 ]; then echo "|" else echo "${SPIN[$index]}" fi ''; home.file.".config/eww/scripts/sys/sys_gpu_voltage.sh".text = '' #!/bin/bash # ───────────────────────────────────────────────────────────────────────────── # Reads NVIDIA GPU voltage using nvidia-smi and prints it in millivolts. # ───────────────────────────────────────────────────────────────────────────── sensors | awk '/vddgfx/ {print $2 " mV"}' || echo "N/A" ''; home.file.".config/eww/scripts/sys/sys_workspace.sh".text = '' #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # Prints the status of workspaces 1–4 in Hyprland, marking the active one. # Output format: "wsN= [ ACTIVE ]" or "wsN= [INACTIVE]" # ───────────────────────────────────────────────────────────────────────────── # Get active workspace ID (requires jq + hyprctl) CURRENT=$(hyprctl activeworkspace -j 2>/dev/null | jq -r '.id') # Fallback if query fails if [[ -z "$CURRENT" || "$CURRENT" == "null" ]]; then echo "[!] Could not determine active workspace." exit 1 fi for i in {1..4}; do if [[ "$i" -eq "$CURRENT" ]]; then echo "ws${i}= [ ACTIVE ]" else echo "ws${i}= [INACTIVE]" fi done ''; }