From 665ce577516546840268cf54a48569ed2aca315c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Wed, 29 Oct 2025 00:06:12 +0100 Subject: [PATCH] A new start --- .editorconfig | 34 ++ .gitconfig | 16 + .gitignore | 55 +++ .hushlogin | 0 .init/alias.sh | 17 + .init/bin/.gitkeep | 0 .init/bin/artifact_github_download.sh | 477 +++++++++++++++++++++ .init/bin/mime_mp4_gif.sh | 592 ++++++++++++++++++++++++++ .init/eval.sh | 13 + .init/export.sh | 5 + .init/functions.sh | 116 +++++ .init/hooks/.gitkeep | 0 .init/init.sh | 41 ++ .init/links.sh | 1 + .init/path.sh | 66 +++ .init/source.sh | 28 ++ .init/start.sh | 26 ++ .init/trap.sh | 13 + .last_pwd | 1 + .nvmrc | 1 + .p10k.zsh | 193 +++++++++ .pre-commit-config.yaml | 5 + .prettierignore | 5 + .prettierrc | 16 + .python-version | 1 + .rubocop.yml | 267 ++++++++++++ .ruby-version | 1 + .vscode/settings.json | 49 +++ .zlogin | 0 .zlogout | 0 .zprofile | 2 + .zshenv | 1 + .zshrc | 130 ++++++ CLAUDE.md | 137 ++++++ Gemfile | 7 + README.md | 478 +++++++++++++++++++++ arty.yml | 65 +++ biome.json | 34 ++ ecosystem.config.js | 9 + eslint.config.mts | 14 + playbook.yml | 288 +++++++++++++ requirements.txt | 1 + 42 files changed, 3205 insertions(+) create mode 100755 .editorconfig create mode 100755 .gitconfig create mode 100755 .gitignore create mode 100644 .hushlogin create mode 100755 .init/alias.sh create mode 100644 .init/bin/.gitkeep create mode 100755 .init/bin/artifact_github_download.sh create mode 100755 .init/bin/mime_mp4_gif.sh create mode 100755 .init/eval.sh create mode 100755 .init/export.sh create mode 100755 .init/functions.sh create mode 100644 .init/hooks/.gitkeep create mode 100755 .init/init.sh create mode 100755 .init/links.sh create mode 100755 .init/path.sh create mode 100755 .init/source.sh create mode 100755 .init/start.sh create mode 100755 .init/trap.sh create mode 100644 .last_pwd create mode 100644 .nvmrc create mode 100644 .p10k.zsh create mode 100644 .pre-commit-config.yaml create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .python-version create mode 100644 .rubocop.yml create mode 100644 .ruby-version create mode 100644 .vscode/settings.json create mode 100755 .zlogin create mode 100755 .zlogout create mode 100755 .zprofile create mode 100644 .zshenv create mode 100644 .zshrc create mode 100644 CLAUDE.md create mode 100644 Gemfile create mode 100755 README.md create mode 100644 arty.yml create mode 100644 biome.json create mode 100644 ecosystem.config.js create mode 100644 eslint.config.mts create mode 100644 playbook.yml create mode 100644 requirements.txt diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 00000000..fea95f20 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,34 @@ +# EditorConfig is awesome: https://editorconfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_size = 2 + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{js,py}] +charset = utf-8 + +# 4 space indentation +[*.py] +indent_style = space +indent_size = 4 + +# Tab indentation (no size specified) +[Makefile] +indent_style = tab + +# Indentation override for all JS under lib directory +[lib/**.js] +indent_style = space +indent_size = 2 + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 2 diff --git a/.gitconfig b/.gitconfig new file mode 100755 index 00000000..171aee8e --- /dev/null +++ b/.gitconfig @@ -0,0 +1,16 @@ +[user] + name = Sebastian Krüger + email = valknar@pivoine.art +[filter "lfs"] + clean = git-lfs clean -- %f + smudge = git-lfs smudge -- %f + process = git-lfs filter-process + required = true +[core] + editor = nano +[init] + defaultBranch = main +[alias] + squash-all = "!f(){ git reset $(git commit-tree \"HEAD^{tree}\" \"$@\");};f" +[push] + autoSetupRemote = true diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..3c37208d --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +# Ignore everything +* + +# But not these files. +!CLAUDE.md +!.gitignore +!.gitconfig +!.gitmodules +!README.md +!.editorconfig +!*.env +!.prettierrc +!.prettierignore +!package.json +!pnpm-workspace.yaml +!.nvmrc +!.ruby-version +!.python-version +!.pre-commit-config.yaml +!.rubocop.yml +!requirements.txt +!Gemfile +!ecosystem.config.js +!playbook.yml +!.p10k.zsh +!crates.yml +!flatpaks.yml +!eslint.config.mts +!.zprofile +!.zlogout +!.zlogin +!.zshrc +!.zshenv +!.hushlogin +!.last_pwd +!biome.json +!arty.yml + +!/.github/ +!/.github/** + +!/.init/ +!/.init/** + +!.vscode/ +!.vscode/settings.json +!.vscode/tasks.json + +# Ignore so we won't commit these in the allowed dirctories. +.DS_Store +*.log* +*.db* +*.vscdb* +*.sqlite* +*.bnk* diff --git a/.hushlogin b/.hushlogin new file mode 100644 index 00000000..e69de29b diff --git a/.init/alias.sh b/.init/alias.sh new file mode 100755 index 00000000..1d72f6a8 --- /dev/null +++ b/.init/alias.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +alias ri='source ~/.init/init.sh' + +# git +alias g0='git add . && git diff --quiet && git diff --cached --quiet' +alias g1='git reset $(git commit-tree "HEAD^{tree}" -m "A new start")' +alias g2='git log --format=%B -n 1 HEAD | head -n 1' + +# rsync +alias rs='rsync --rsync-path="sudo rsync" -avzhe ssh' + +# serve static files +alias ss='python -m http.server 8000 -d' + +# download youtube mp3 +alias yt='yt-dlp -x --audio-format mp3' diff --git a/.init/bin/.gitkeep b/.init/bin/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.init/bin/artifact_github_download.sh b/.init/bin/artifact_github_download.sh new file mode 100755 index 00000000..d7ea1b61 --- /dev/null +++ b/.init/bin/artifact_github_download.sh @@ -0,0 +1,477 @@ +#!/usr/bin/env bash + +############################################################################# +# GitHub Artifact Downloader +# +# Download and extract GitHub Actions artifacts with style +# +# Usage: +# artifact_github_download.sh [OPTIONS] +# +# Arguments: +# REPO GitHub repository (owner/repo) +# +# Options: +# -n, --name NAME Artifact name to download (preselect) +# -o, --output DIR Output directory (default: current directory) +# -h, --help Show this help message +# +# Examples: +# artifact_github_download.sh valknarness/awesome +# artifact_github_download.sh valknarness/awesome -n awesome-database-latest +# artifact_github_download.sh valknarness/awesome -o ~/downloads +############################################################################# + +set -euo pipefail + +# ============================================================================ +# Color Definitions +# ============================================================================ + +# Check if terminal supports colors +if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then + COLORS=$(tput colors 2>/dev/null || echo 0) + if [[ $COLORS -ge 8 ]]; then + # Standard colors + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + YELLOW=$(tput setaf 3) + BLUE=$(tput setaf 4) + MAGENTA=$(tput setaf 5) + CYAN=$(tput setaf 6) + WHITE=$(tput setaf 7) + + # Bright colors + BRIGHT_GREEN=$(tput setaf 10 2>/dev/null || tput setaf 2) + BRIGHT_YELLOW=$(tput setaf 11 2>/dev/null || tput setaf 3) + BRIGHT_BLUE=$(tput setaf 12 2>/dev/null || tput setaf 4) + BRIGHT_MAGENTA=$(tput setaf 13 2>/dev/null || tput setaf 5) + BRIGHT_CYAN=$(tput setaf 14 2>/dev/null || tput setaf 6) + + # Text formatting + BOLD=$(tput bold) + DIM=$(tput dim 2>/dev/null || echo "") + RESET=$(tput sgr0) + else + RED="" GREEN="" YELLOW="" BLUE="" MAGENTA="" CYAN="" WHITE="" + BRIGHT_GREEN="" BRIGHT_YELLOW="" BRIGHT_BLUE="" BRIGHT_MAGENTA="" BRIGHT_CYAN="" + BOLD="" DIM="" RESET="" + fi +else + RED="" GREEN="" YELLOW="" BLUE="" MAGENTA="" CYAN="" WHITE="" + BRIGHT_GREEN="" BRIGHT_YELLOW="" BRIGHT_BLUE="" BRIGHT_MAGENTA="" BRIGHT_CYAN="" + BOLD="" DIM="" RESET="" +fi + +# ============================================================================ +# Logging Functions +# ============================================================================ + +log_info() { + echo -e "${BRIGHT_BLUE}${BOLD}ℹ${RESET} ${CYAN}$*${RESET}" >&2 +} + +log_success() { + echo -e "${BRIGHT_GREEN}${BOLD}✓${RESET} ${GREEN}$*${RESET}" >&2 +} + +log_warning() { + echo -e "${BRIGHT_YELLOW}${BOLD}⚠${RESET} ${YELLOW}$*${RESET}" >&2 +} + +log_error() { + echo -e "${RED}${BOLD}✗${RESET} ${RED}$*${RESET}" >&2 +} + +log_step() { + echo -e "${BRIGHT_MAGENTA}${BOLD}▸${RESET} ${MAGENTA}$*${RESET}" >&2 +} + +log_header() { + local text="$*" + local length=${#text} + local line=$(printf '═%.0s' $(seq 1 $length)) + echo "" >&2 + echo -e "${BRIGHT_CYAN}${BOLD}╔${line}╗${RESET}" >&2 + echo -e "${BRIGHT_CYAN}${BOLD}║${RESET}${BOLD}${WHITE}${text}${RESET}${BRIGHT_CYAN}${BOLD}║${RESET}" >&2 + echo -e "${BRIGHT_CYAN}${BOLD}╚${line}╝${RESET}" >&2 + echo "" >&2 +} + +log_data() { + local label="$1" + local value="$2" + echo -e " ${DIM}${label}:${RESET} ${BOLD}${value}${RESET}" >&2 +} + +# ============================================================================ +# Helper Functions +# ============================================================================ + +check_dependencies() { + local missing=() + + if ! command -v gh &> /dev/null; then + missing+=("gh (GitHub CLI)") + fi + + if ! command -v jq &> /dev/null; then + missing+=("jq") + fi + + if ! command -v unzip &> /dev/null; then + missing+=("unzip") + fi + + if [[ ${#missing[@]} -gt 0 ]]; then + log_error "Missing required dependencies:" + for dep in "${missing[@]}"; do + echo -e " ${RED}•${RESET} ${dep}" + done + exit 1 + fi +} + +check_gh_auth() { + if ! gh auth status &> /dev/null; then + log_error "Not authenticated with GitHub CLI" + log_info "Run: ${BOLD}gh auth login${RESET}" + exit 1 + fi +} + +show_help() { + cat << EOF +${BOLD}${BRIGHT_CYAN}GitHub Artifact Downloader${RESET} + +${BOLD}USAGE:${RESET} + $(basename "$0") ${CYAN}${RESET} [${YELLOW}OPTIONS${RESET}] + +${BOLD}ARGUMENTS:${RESET} + ${CYAN}REPO${RESET} GitHub repository (${DIM}owner/repo${RESET}) + +${BOLD}OPTIONS:${RESET} + ${YELLOW}-n, --name NAME${RESET} Artifact name to download (preselect) + ${YELLOW}-o, --output DIR${RESET} Output directory (default: current directory) + ${YELLOW}-h, --help${RESET} Show this help message + +${BOLD}EXAMPLES:${RESET} + ${DIM}# Interactive mode - list and select artifacts${RESET} + $(basename "$0") valknarness/awesome + + ${DIM}# Preselect artifact by name${RESET} + $(basename "$0") valknarness/awesome -n awesome-database-latest + + ${DIM}# Download to specific directory${RESET} + $(basename "$0") valknarness/awesome -o ~/downloads + + ${DIM}# Combine options${RESET} + $(basename "$0") valknarness/awesome -n awesome-database-latest -o ~/downloads + +EOF +} + +format_size() { + local bytes=$1 + if (( bytes < 1024 )); then + echo "${bytes}B" + elif (( bytes < 1048576 )); then + awk "BEGIN {printf \"%.1fKB\", $bytes/1024}" + elif (( bytes < 1073741824 )); then + awk "BEGIN {printf \"%.1fMB\", $bytes/1048576}" + else + awk "BEGIN {printf \"%.2fGB\", $bytes/1073741824}" + fi +} + +format_date() { + local iso_date="$1" + if command -v date &> /dev/null; then + if date --version &> /dev/null 2>&1; then + # GNU date + date -d "$iso_date" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$iso_date" + else + # BSD date (macOS) + date -j -f "%Y-%m-%dT%H:%M:%SZ" "$iso_date" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$iso_date" + fi + else + echo "$iso_date" + fi +} + +# ============================================================================ +# Main Functions +# ============================================================================ + +list_artifacts() { + local repo="$1" + + log_step "Fetching artifacts from ${BOLD}${repo}${RESET}..." + + # First check if there are any artifacts using gh's built-in jq + local count + count=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + --jq '.artifacts | length' \ + "/repos/${repo}/actions/artifacts?per_page=100" 2>/dev/null) + + if [[ -z "$count" ]]; then + log_error "Failed to fetch artifacts from repository" + log_info "Please check that:" + echo " • The repository ${BOLD}${repo}${RESET} exists and you have access" + echo " • GitHub Actions is enabled for this repository" + exit 1 + fi + + if [[ "$count" -eq 0 ]]; then + log_warning "No artifacts found in repository ${BOLD}${repo}${RESET}" + log_info "This repository may not have any workflow runs that produced artifacts" + exit 0 + fi + + # Now fetch the full JSON response + local artifacts_json + artifacts_json=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/${repo}/actions/artifacts?per_page=100" 2>/dev/null) + + echo "$artifacts_json" +} + +select_artifact() { + local artifacts_json="$1" + local preselect_name="$2" + + # Parse artifacts + local artifacts + artifacts=$(echo "$artifacts_json" | jq -r '.artifacts[] | + "\(.id)|\(.name)|\(.size_in_bytes)|\(.created_at)|\(.workflow_run.id)"') + + # If preselect name is provided, find matching artifact + if [[ -n "$preselect_name" ]]; then + local selected + selected=$(echo "$artifacts" | grep -F "|${preselect_name}|" | head -1) + + if [[ -z "$selected" ]]; then + log_error "Artifact '${BOLD}${preselect_name}${RESET}' not found" + log_info "Available artifacts:" + echo "$artifacts" | while IFS='|' read -r id name size created workflow; do + echo " ${CYAN}•${RESET} ${name}" + done + exit 1 + fi + + echo "$selected" + return 0 + fi + + # Interactive selection + log_info "Available artifacts:" + echo "" + + local i=1 + local -a artifact_array + + while IFS='|' read -r id name size created workflow; do + artifact_array+=("$id|$name|$size|$created|$workflow") + local formatted_size=$(format_size "$size") + local formatted_date=$(format_date "$created") + + printf " ${BOLD}${YELLOW}[%2d]${RESET} ${BRIGHT_CYAN}%s${RESET}\n" "$i" "$name" + printf " ${DIM}Size: ${RESET}%s ${DIM}Created: ${RESET}%s\n" "$formatted_size" "$formatted_date" + echo "" + + ((i++)) + done <<< "$artifacts" + + # Prompt for selection + local selection + while true; do + echo -n -e "${BRIGHT_MAGENTA}${BOLD}�${RESET} ${MAGENTA}Select artifact [1-$((i-1))]:${RESET} " + read -r selection + + if [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -lt "$i" ]]; then + break + else + log_warning "Invalid selection. Please enter a number between 1 and $((i-1))" + fi + done + + echo "${artifact_array[$((selection-1))]}" +} + +download_artifact() { + local repo="$1" + local artifact_id="$2" + local artifact_name="$3" + local output_dir="$4" + + log_step "Downloading artifact ${BOLD}${artifact_name}${RESET}..." + + # Create output directory if it doesn't exist + mkdir -p "$output_dir" + + # Download artifact using gh + local zip_file="${output_dir}/${artifact_name}.zip" + + if gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/${repo}/actions/artifacts/${artifact_id}/zip" \ + > "$zip_file" 2>/dev/null; then + + log_success "Downloaded to ${BOLD}${zip_file}${RESET}" + echo "$zip_file" + else + log_error "Failed to download artifact" + exit 1 + fi +} + +extract_artifact() { + local zip_file="$1" + local output_dir="$2" + + log_step "Extracting archive..." + + # Create extraction directory + local extract_dir="${output_dir}/$(basename "$zip_file" .zip)" + mkdir -p "$extract_dir" + + if unzip -q "$zip_file" -d "$extract_dir"; then + log_success "Extracted to ${BOLD}${extract_dir}${RESET}" + + # Show extracted files + log_info "Extracted files:" + find "$extract_dir" -type f -exec basename {} \; | while read -r file; do + echo " ${GREEN}•${RESET} ${file}" + done + + # Remove zip file + rm "$zip_file" + log_info "Cleaned up zip file" + + echo "$extract_dir" + else + log_error "Failed to extract archive" + exit 1 + fi +} + +# ============================================================================ +# Main Script +# ============================================================================ + +main() { + local repo="" + local artifact_name="" + local output_dir="." + + # Parse arguments + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -n|--name) + artifact_name="$2" + shift 2 + ;; + -o|--output) + output_dir="$2" + shift 2 + ;; + -*) + log_error "Unknown option: $1" + echo "" + show_help + exit 1 + ;; + *) + if [[ -z "$repo" ]]; then + repo="$1" + else + log_error "Unexpected argument: $1" + echo "" + show_help + exit 1 + fi + shift + ;; + esac + done + + # Validate required arguments + if [[ -z "$repo" ]]; then + log_error "Repository argument is required" + echo "" + show_help + exit 1 + fi + + # Validate repository format + if [[ ! "$repo" =~ ^[^/]+/[^/]+$ ]]; then + log_error "Invalid repository format. Expected: ${BOLD}owner/repo${RESET}" + exit 1 + fi + + # Show header + log_header "GitHub Artifact Downloader" + + # Check dependencies + log_step "Checking dependencies..." + check_dependencies + log_success "All dependencies found" + + # Check GitHub authentication + log_step "Checking GitHub authentication..." + check_gh_auth + log_success "Authenticated with GitHub" + + echo "" + log_data "Repository" "${BRIGHT_CYAN}${repo}${RESET}" + if [[ -n "$artifact_name" ]]; then + log_data "Artifact" "${BRIGHT_YELLOW}${artifact_name}${RESET}" + fi + log_data "Output" "${BRIGHT_GREEN}${output_dir}${RESET}" + echo "" + + # List artifacts + local artifacts_json + artifacts_json=$(list_artifacts "$repo") + + # Select artifact + local selected + selected=$(select_artifact "$artifacts_json" "$artifact_name") + + IFS='|' read -r artifact_id name size created workflow <<< "$selected" + + echo "" + log_info "Selected artifact:" + log_data " Name" "${BRIGHT_CYAN}${name}${RESET}" + log_data " Size" "$(format_size "$size")" + log_data " Created" "$(format_date "$created")" + echo "" + + # Download artifact + local zip_file + zip_file=$(download_artifact "$repo" "$artifact_id" "$name" "$output_dir") + + # Extract artifact + local extract_dir + extract_dir=$(extract_artifact "$zip_file" "$output_dir") + + # Success summary + echo "" + log_header "Download Complete!" + log_data "Location" "${BOLD}${extract_dir}${RESET}" + echo "" + + log_success "All done! 🎉" +} + +# Run main function +main "$@" diff --git a/.init/bin/mime_mp4_gif.sh b/.init/bin/mime_mp4_gif.sh new file mode 100755 index 00000000..752d2484 --- /dev/null +++ b/.init/bin/mime_mp4_gif.sh @@ -0,0 +1,592 @@ +#!/usr/bin/env bash + +# mime_mp4_gif.sh - Advanced MP4 to Animated GIF converter +# Converts MP4 videos to GIFs with sophisticated keyframe extraction, +# interpolation algorithms, and scheduling distributions + +set -euo pipefail + +# Default values +KEYFRAMES=10 +INPUT_SCHEDULES=1 +TRANSITION="linear" +SCHEDULE="uniform" +MAGIC="none" +KEYFRAME_DURATION=100 +INPUT_FILE="" +OUTPUT_FILE="" +VERBOSE=false + +# Color codes for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Available algorithms +TRANSITIONS=("linear" "sinoid" "cubic" "quadratic" "exponential" "bounce" "elastic") +SCHEDULES=("uniform" "front-load" "back-load" "center-peak" "edge-peak" "fibonacci" "golden-ratio") +MAGICS=("none" "psychedelic" "dither-bloom" "edge-glow" "temporal-blur" "chromatic-shift" "vaporwave") + +############################################################################# +# Helper Functions +############################################################################# + +print_usage() { + cat << EOF +Usage: $(basename "$0") [OPTIONS] INPUT_FILE [OUTPUT_FILE] + +Convert MP4 videos to animated GIFs with advanced frame extraction algorithms. + +Arguments: + INPUT_FILE Input MP4 video file (required) + OUTPUT_FILE Output GIF file (optional, defaults to INPUT_FILE.gif) + +Options: + -k, --keyframes N Number of keyframes to extract (default: 10) + -d, --keyframe-duration MS Duration of each frame in milliseconds (default: 100) + Valid range: 1-30000 ms + Lower values = faster animation + Higher values = slower animation + -i, --input-schedules N Number of input schedules (default: 1) + 1 schedule = entire video duration + N schedules = divide video into N segments + -t, --transition TYPE Interpolation function for frame timing + Available: ${TRANSITIONS[*]} + (default: linear) + -s, --schedule TYPE Algorithm to distribute keyframes across schedules + Available: ${SCHEDULES[*]} + (default: uniform) + -m, --magic TYPE Apply magical effects to the GIF + Available: ${MAGICS[*]} + (default: none) + -v, --verbose Enable verbose output + -h, --help Show this help message + +Examples: + # Basic conversion with 15 keyframes + $(basename "$0") -k 15 video.mp4 + + # Fast animation with 50ms per frame + $(basename "$0") -k 20 -d 50 video.mp4 + + # Slow animation with 500ms per frame + $(basename "$0") -k 10 -d 500 video.mp4 + + # Use sinusoidal transition with center-peak distribution + $(basename "$0") -t sinoid -s center-peak -k 20 video.mp4 + + # Apply psychedelic magic with fibonacci distribution + $(basename "$0") -m psychedelic -s fibonacci -k 13 video.mp4 trippy.gif + + # Complex: 3 schedules with cubic interpolation and edge glow + $(basename "$0") -i 3 -t cubic -s front-load -m edge-glow -k 30 video.mp4 + +EOF +} + +log_info() { + echo -e "${BLUE}[INFO]${NC} $*" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $*" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $*" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $*" >&2 +} + +verbose_log() { + if [[ "$VERBOSE" == "true" ]]; then + log_info "$@" + fi +} + +validate_enum() { + local value="$1" + local array_name="$2" + local -n arr=$array_name + + for item in "${arr[@]}"; do + if [[ "$value" == "$item" ]]; then + return 0 + fi + done + return 1 +} + +############################################################################# +# Mathematical Functions +############################################################################# + +# Calculate transition weight based on interpolation type +# Input: progress (0.0 to 1.0), Returns: weighted value (0.0 to 1.0) +calculate_transition() { + local progress="$1" + local type="$2" + + case "$type" in + linear) + echo "$progress" + ;; + sinoid) + # Smooth sinusoidal easing + awk -v p="$progress" 'BEGIN { print (1 - cos(p * 3.14159265359)) / 2 }' + ;; + cubic) + # Cubic easing in-out + awk -v p="$progress" 'BEGIN { + if (p < 0.5) + print 4 * p * p * p; + else + print 1 - ((-2 * p + 2) ^ 3) / 2; + }' + ;; + quadratic) + # Quadratic easing + awk -v p="$progress" 'BEGIN { + if (p < 0.5) + print 2 * p * p; + else + print 1 - ((-2 * p + 2) ^ 2) / 2; + }' + ;; + exponential) + # Exponential easing + awk -v p="$progress" 'BEGIN { + if (p == 0) print 0; + else if (p == 1) print 1; + else if (p < 0.5) print (2 ^ (20 * p - 10)) / 2; + else print (2 - (2 ^ (-20 * p + 10))) / 2; + }' + ;; + bounce) + # Bouncing effect + awk -v p="$progress" 'BEGIN { + n1 = 7.5625; d1 = 2.75; + x = 1 - p; + if (x < 1/d1) result = n1 * x * x; + else if (x < 2/d1) { x -= 1.5/d1; result = n1 * x * x + 0.75; } + else if (x < 2.5/d1) { x -= 2.25/d1; result = n1 * x * x + 0.9375; } + else { x -= 2.625/d1; result = n1 * x * x + 0.984375; } + print 1 - result; + }' + ;; + elastic) + # Elastic spring effect + awk -v p="$progress" 'BEGIN { + c4 = (2 * 3.14159265359) / 3; + if (p == 0) print 0; + else if (p == 1) print 1; + else if (p < 0.5) print -(2 ^ (20 * p - 10) * sin((20 * p - 11.125) * c4)) / 2; + else print (2 ^ (-20 * p + 10) * sin((20 * p - 11.125) * c4)) / 2 + 1; + }' + ;; + *) + echo "$progress" + ;; + esac +} + +# Generate keyframe distribution based on schedule type +generate_schedule_distribution() { + local num_frames="$1" + local schedule_type="$2" + local -n result_array=$3 + + case "$schedule_type" in + uniform) + for ((i=0; i/dev/null + done +} + +apply_magic_effects() { + local magic_type="$1" + local temp_dir="$2" + + if [[ "$magic_type" == "none" ]]; then + return 0 + fi + + verbose_log "Applying magic effect: $magic_type" + + case "$magic_type" in + psychedelic) + for frame in "$temp_dir"/*.png; do + ffmpeg -v quiet -i "$frame" -vf "hue=s=3:h=sin(2*PI*t)*360" \ + "${frame}.tmp.png" 2>/dev/null && mv "${frame}.tmp.png" "$frame" + done + ;; + dither-bloom) + for frame in "$temp_dir"/*.png; do + ffmpeg -v quiet -i "$frame" -vf "format=gbrp,split[a][b],[a]negate[c],[b][c]blend=all_mode=xor,noise=alls=20:allf=t" \ + "${frame}.tmp.png" 2>/dev/null && mv "${frame}.tmp.png" "$frame" + done + ;; + edge-glow) + for frame in "$temp_dir"/*.png; do + ffmpeg -v quiet -i "$frame" -vf "edgedetect=low=0.1:high=0.3,negate,hue=s=2" \ + "${temp_dir}/edges_$(basename "$frame")" + ffmpeg -v quiet -i "$frame" -i "${temp_dir}/edges_$(basename "$frame")" \ + -filter_complex "[0:v][1:v]blend=all_mode=addition:all_opacity=0.5" \ + "${frame}.tmp.png" 2>/dev/null && mv "${frame}.tmp.png" "$frame" + rm "${temp_dir}/edges_$(basename "$frame")" + done + ;; + temporal-blur) + # Create motion blur effect + local frames=("$temp_dir"/*.png) + for i in "${!frames[@]}"; do + local prev_idx=$((i > 0 ? i - 1 : 0)) + local next_idx=$((i < ${#frames[@]} - 1 ? i + 1 : ${#frames[@]} - 1)) + + ffmpeg -v quiet -i "${frames[$prev_idx]}" -i "${frames[$i]}" -i "${frames[$next_idx]}" \ + -filter_complex "[0:v][1:v][2:v]blend=all_mode=average" \ + "${frames[$i]}.tmp.png" 2>/dev/null && mv "${frames[$i]}.tmp.png" "${frames[$i]}" + done + ;; + chromatic-shift) + for frame in "$temp_dir"/*.png; do + ffmpeg -v quiet -i "$frame" -vf "rgbashift=rh=5:bh=-5" \ + "${frame}.tmp.png" 2>/dev/null && mv "${frame}.tmp.png" "$frame" + done + ;; + vaporwave) + for frame in "$temp_dir"/*.png; do + ffmpeg -v quiet -i "$frame" -vf "curves=vintage,hue=h=300:s=1.5,eq=saturation=1.5:contrast=1.2" \ + "${frame}.tmp.png" 2>/dev/null && mv "${frame}.tmp.png" "$frame" + done + ;; + esac +} + +create_gif() { + local temp_dir="$1" + local output="$2" + local frame_delay="$3" + + verbose_log "Creating animated GIF with ${frame_delay}ms per frame..." + + # Convert milliseconds to centiseconds (GIF delay unit) + local delay_cs + delay_cs=$(awk -v ms="$frame_delay" 'BEGIN { print int(ms / 10) }') + + # Ensure minimum delay of 1 centisecond + if [[ $delay_cs -lt 1 ]]; then + delay_cs=1 + fi + + # Calculate input framerate (frames are read at this rate) + # For GIF delay, we want 1000ms / frame_delay fps + local fps + fps=$(awk -v ms="$frame_delay" 'BEGIN { printf "%.2f", 1000.0 / ms }') + + verbose_log "Frame delay: ${delay_cs} centiseconds (${frame_delay}ms), FPS: ${fps}" + + # Generate palette for better color quality + ffmpeg -v error -pattern_type glob -i "${temp_dir}/frame_*.png" \ + -vf "scale=480:-1:flags=lanczos,palettegen=stats_mode=diff" \ + -y "${temp_dir}/palette.png" + + # Create GIF using palette with specified frame delay + ffmpeg -v error -framerate "$fps" -pattern_type glob -i "${temp_dir}/frame_*.png" -i "${temp_dir}/palette.png" \ + -filter_complex "[0:v]scale=480:-1:flags=lanczos[scaled];[scaled][1:v]paletteuse=dither=bayer:bayer_scale=5" \ + -gifflags +transdiff -y "$output" +} + +############################################################################# +# Main Processing +############################################################################# + +process_video() { + local input="$INPUT_FILE" + local output="$OUTPUT_FILE" + + # Validate input file + if [[ ! -f "$input" ]]; then + log_error "Input file not found: $input" + exit 1 + fi + + # Get video duration + local duration + duration=$(get_video_duration "$input") + verbose_log "Video duration: ${duration}s" + + # Calculate schedule duration + local schedule_duration + schedule_duration=$(awk -v d="$duration" -v s="$INPUT_SCHEDULES" 'BEGIN { print d / s }') + verbose_log "Schedule duration: ${schedule_duration}s (${INPUT_SCHEDULES} schedule(s))" + + # Generate frame distribution + local -a distribution + generate_schedule_distribution "$KEYFRAMES" "$SCHEDULE" distribution + + verbose_log "Using schedule: $SCHEDULE" + verbose_log "Using transition: $TRANSITION" + + # Calculate actual timestamps with transition function + local -a timestamps + for i in "${!distribution[@]}"; do + local base_time="${distribution[$i]}" + local weighted_time + weighted_time=$(calculate_transition "$base_time" "$TRANSITION") + + # Map to video duration considering input schedules + local actual_time + actual_time=$(awk -v w="$weighted_time" -v d="$duration" 'BEGIN { print w * d }') + + # Ensure we don't exceed video duration + timestamps[$i]=$(awk -v t="$actual_time" -v d="$duration" 'BEGIN { + if (t > d) print d; + else print t; + }') + done + + # Create temporary directory + local temp_dir + temp_dir=$(mktemp -d) + trap "rm -rf '$temp_dir'" EXIT + + # Extract frames + extract_frames "$input" "$duration" timestamps "$temp_dir" + + # Apply magic effects + apply_magic_effects "$MAGIC" "$temp_dir" + + # Create GIF with specified frame duration + create_gif "$temp_dir" "$output" "$KEYFRAME_DURATION" + + log_success "GIF created successfully: $output" + + # Show file size + local size + size=$(du -h "$output" | cut -f1) + log_info "Output size: $size" +} + +############################################################################# +# Command Line Parsing +############################################################################# + +parse_arguments() { + while [[ $# -gt 0 ]]; do + case "$1" in + -k|--keyframes) + KEYFRAMES="$2" + shift 2 + ;; + -d|--keyframe-duration) + KEYFRAME_DURATION="$2" + shift 2 + ;; + -i|--input-schedules) + INPUT_SCHEDULES="$2" + shift 2 + ;; + -t|--transition) + TRANSITION="$2" + if ! validate_enum "$TRANSITION" TRANSITIONS; then + log_error "Invalid transition type: $TRANSITION" + log_error "Available: ${TRANSITIONS[*]}" + exit 1 + fi + shift 2 + ;; + -s|--schedule) + SCHEDULE="$2" + if ! validate_enum "$SCHEDULE" SCHEDULES; then + log_error "Invalid schedule type: $SCHEDULE" + log_error "Available: ${SCHEDULES[*]}" + exit 1 + fi + shift 2 + ;; + -m|--magic) + MAGIC="$2" + if ! validate_enum "$MAGIC" MAGICS; then + log_error "Invalid magic type: $MAGIC" + log_error "Available: ${MAGICS[*]}" + exit 1 + fi + shift 2 + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -h|--help) + print_usage + exit 0 + ;; + -*) + log_error "Unknown option: $1" + print_usage + exit 1 + ;; + *) + if [[ -z "$INPUT_FILE" ]]; then + INPUT_FILE="$1" + elif [[ -z "$OUTPUT_FILE" ]]; then + OUTPUT_FILE="$1" + else + log_error "Too many arguments" + print_usage + exit 1 + fi + shift + ;; + esac + done + + # Validate required arguments + if [[ -z "$INPUT_FILE" ]]; then + log_error "Input file is required" + print_usage + exit 1 + fi + + # Set default output file + if [[ -z "$OUTPUT_FILE" ]]; then + OUTPUT_FILE="${INPUT_FILE%.*}.gif" + fi + + # Validate numeric arguments + if ! [[ "$KEYFRAMES" =~ ^[0-9]+$ ]] || [[ "$KEYFRAMES" -lt 2 ]]; then + log_error "Keyframes must be a positive integer >= 2" + exit 1 + fi + + if ! [[ "$KEYFRAME_DURATION" =~ ^[0-9]+$ ]] || [[ "$KEYFRAME_DURATION" -lt 1 ]] || [[ "$KEYFRAME_DURATION" -gt 30000 ]]; then + log_error "Keyframe duration must be an integer between 1 and 30000 milliseconds" + exit 1 + fi + + if ! [[ "$INPUT_SCHEDULES" =~ ^[0-9]+$ ]] || [[ "$INPUT_SCHEDULES" -lt 1 ]]; then + log_error "Input schedules must be a positive integer >= 1" + exit 1 + fi +} + +############################################################################# +# Entry Point +############################################################################# + +main() { + parse_arguments "$@" + + log_info "Starting MP4 to GIF conversion..." + log_info "Configuration:" + log_info " Input: $INPUT_FILE" + log_info " Output: $OUTPUT_FILE" + log_info " Keyframes: $KEYFRAMES" + log_info " Frame Duration: ${KEYFRAME_DURATION}ms" + log_info " Schedules: $INPUT_SCHEDULES" + log_info " Transition: $TRANSITION" + log_info " Schedule: $SCHEDULE" + log_info " Magic: $MAGIC" + + process_video +} + +# Run main function +main "$@" diff --git a/.init/eval.sh b/.init/eval.sh new file mode 100755 index 00000000..12fda0ad --- /dev/null +++ b/.init/eval.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if command -v oh-my-posh 2>&1 >/dev/null; then + eval "$(! oh-my-posh init zsh --config=~/worker.omp.json)" +fi + +if command -v rbenv 2>&1 >/dev/null; then + eval "$(rbenv init - --no-rehash zsh)" +fi + +if command -v pyenv 2>&1 >/dev/null; then + eval "$(pyenv init --path)" +fi \ No newline at end of file diff --git a/.init/export.sh b/.init/export.sh new file mode 100755 index 00000000..790a544d --- /dev/null +++ b/.init/export.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +export NVM_DIR="$HOME/.nvm" +export REPOS_DIR="$HOME/repos" +export CHORE_CHORE="chore: chore" \ No newline at end of file diff --git a/.init/functions.sh b/.init/functions.sh new file mode 100755 index 00000000..44626801 --- /dev/null +++ b/.init/functions.sh @@ -0,0 +1,116 @@ +#!/bin/bash + + +is_ssh() { + IS_SSH=$(cat /proc/$PPID/status | head -1 | cut -f2) + if [ "$_IS_SSH" = "sshd-session" ]; then + return 1 + else + return 0 + fi +} + +_home_push() { + git add -A + git commit -m "${1:-$CHORE_CHORE}" + git push $2 $3 +} + +_home_pull() { + [ -n $(is_ssh) ] && git checkout $HOME/.last_pwd + git stash + git pull $1 $2 + git stash pop +} + +_site_deploy_jekyll() { + cd "$HOME/repos/$1" + rm -rf _site + JEKYLL_ENV=production bundle exec jekyll build + rsync -avzhe ssh _site/ "pi@hive:$DOCKER_STORAGE_DIR/staticwebserver/hosts/$1/" --delete + cd - +} + +_site_deploy_nuxt() { + cd "$HOME/repos/$1" + rm -rf .output + npm run generate + rsync -avzhe ssh .output/public/ "pi@hive:$DOCKER_STORAGE_DIR/staticwebserver/hosts/$1/" --delete + cd - +} + +_site_deploy_static() { + cd "$HOME/repos/$1" + rsync -avzhe ssh src/ "pi@hive:$DOCKER_STORAGE_DIR/staticwebserver/hosts/$1/" --delete + cd - +} + +_site_run_jekyll() { + cd "$HOME/repos/$1" + bundle exec jekyll serve --livereload + cd - +} + +_site_run_nuxt() { + cd "$HOME/repos/$1" + npm run dev + cd - +} + +_site_run_static() { + cd "$HOME/repos/$1" + python -m http.server 8000 -d src + cd - +} + +batch_file_sequence() { + a=0 + for i in *.$2; do + new=$(printf "$1-%03d.$2" "$a") + mv -i -- "$i" "$new" + let a="$a+1" + done +} + +batch_image_webp() { + find . -type f -regex ".*\.\(jpg\|jpeg\|png\)" -exec mogrify -format webp {} \; -print + find . -type f -regex ".*\.\(jpg\|jpeg\|png\)" -exec rm {} \; -print +} + +batch_video_x264() { + find . -type f -regex ".*\.\(mp4\)" -exec ffmpeg -i {} -vcodec libx264 -crf 24 "{}.mp4" \; -print + find . -type f -regex ".+mp4\.mp4" -exec python3 -c "import os;os.rename('{}', '{}'[:-4])" \; -print +} + +_image_description() { + identify -verbose $1 | grep ImageDescription | sed "s/ exif:ImageDescription: //" +} + +_image_optimize() { + i_x4 && cp -rf x4/* . && i_x05 && cp -rf x05/* . && _file_sequence $1 webp && mv $1-000.webp $1.webp + _image_description *.png + rm -rf *.png x4 x05 +} + +_video_optimize() { + filename=$(basename -- "$1") + extension="${filename##*.}" + filename="${filename%.*}" + ffmpeg -y -i $1 -vf "setpts=1.25*PTS" -r 24 "$filename.mp4" +} + +function _over_subdirs { + _PWD=$PWD + . $PWD/.env + for D in $(find . -mindepth 1 -maxdepth 1 -type d); do + cd "$D" && $1 + cd $_PWD + done +} + +_join_by() { + local d=${1-} f=${2-} + if shift 2; then + printf %s "$f" "${@/#/$d}" + fi +} diff --git a/.init/hooks/.gitkeep b/.init/hooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.init/init.sh b/.init/init.sh new file mode 100755 index 00000000..ec189fc3 --- /dev/null +++ b/.init/init.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +if [ -f "$HOME/.init/path.sh" ] ; then + . "$HOME/.init/path.sh" +fi + +if [ -f "$HOME/.init/export.sh" ] ; then + . "$HOME/.init/export.sh" +fi + +if [ -f "$HOME/.init/alias.sh" ] ; then + . "$HOME/.init/alias.sh" +fi + +if [ -f "$HOME/.init/source.sh" ] ; then + . "$HOME/.init/source.sh" +fi + +if [ -f "$HOME/.init/functions.sh" ] ; then + . "$HOME/.init/functions.sh" +fi + +if [ -f "$HOME/.init/links.sh" ] ; then + . "$HOME/.init/links.sh" +fi + +if [ -f "$HOME/.init/source.sh" ] ; then + . "$HOME/.init/source.sh" +fi + +if [ -f "$HOME/.init/eval.sh" ] ; then + . "$HOME/.init/eval.sh" +fi + +if [ -f "$HOME/.init/trap.sh" ] ; then + . "$HOME/.init/trap.sh" +fi + +if [ -f "$HOME/.init/start.sh" ] ; then + . "$HOME/.init/start.sh" +fi \ No newline at end of file diff --git a/.init/links.sh b/.init/links.sh new file mode 100755 index 00000000..a9bf588e --- /dev/null +++ b/.init/links.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/.init/path.sh b/.init/path.sh new file mode 100755 index 00000000..9ff000fd --- /dev/null +++ b/.init/path.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +if [ -d "$HOME/bin" ]; then + export PATH="$HOME/bin:$PATH" +fi + +if [ -d "$HOME/.local/bin" ]; then + export PATH="$HOME/.local/bin:$PATH" +fi + +if [ -d "$HOME/.rvm/bin" ]; then + export PATH="$HOME/.rvm/bin:$PATH" +fi + +if [ -d "$HOME/repos/flutter/bin" ]; then + export PATH="$HOME/repos/flutter/bin:$PATH" +fi + +if [ -d "$HOME/.rbenv/bin" ]; then + export PATH="$PATH:$HOME/.rbenv/bin" +fi + +if [ -d "$HOME/.pyenv/bin" ]; then + export PYENV_ROOT="$HOME/.pyenv" + export PATH="$PYENV_ROOT/bin:$PATH" +fi + +if [ -d "$HOME/.cargo/bin" ]; then + export PATH="$PATH:$HOME/.cargo/bin" +fi + +if [ -d "/opt/Upscayl/resources/bin" ]; then + export PATH="$PATH:/opt/Upscayl/resources/bin" +fi + +if [ -d "/usr/local/go/bin" ]; then + export PATH="$PATH:/usr/local/go/bin" +fi + +if [ -d "$HOME/go/bin" ]; then + export PATH="$PATH:$HOME/go/bin" +fi + +if [ -d "$HOME/node_modules/.bin" ]; then + export PATH="$PATH:$HOME/node_modules/.bin" +fi + +if [ -d "$HOME/miniconda3/bin" ]; then + export PATH="$PATH:$HOME/miniconda3/bin" +fi + +if [ -d "$HOME/.local/share/flatpak/exports/share" ] ; then + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.local/share/flatpak/exports/share" +fi + +if [ -d "/var/lib/flatpak/exports/share" ] ; then + export XDG_DATA_DIRS="$XDG_DATA_DIRS:/var/lib/flatpak/exports/share" +fi + +if [ -d "$HOME/.init/bin" ] ; then + export PATH="$PATH:$HOME/.init/bin" +fi + +if [ -d "$HOME/Projects/kompose" ] ; then + export PATH="$PATH:$HOME/Projects/kompose" +fi diff --git a/.init/source.sh b/.init/source.sh new file mode 100755 index 00000000..17071812 --- /dev/null +++ b/.init/source.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +if [ -n "$BASH_VERSION" ]; then + # include .bashrc if it exists + if [ -f "$HOME/.bashrc" ]; then + . "$HOME/.bashrc" + fi +fi + +if [ -s "$NVM_DIR/nvm.sh" ] ; then + . "$NVM_DIR/nvm.sh" +fi + +if [ -s "$NVM_DIR/bash_completion" ] ; then + . "$NVM_DIR/bash_completion" +fi + +if [ -s "$HOME/.rvm/scripts/rvm" ] ; then + . "$HOME/.rvm/scripts/rvm" +fi + +if [ -s "$HOME/.cargo/env" ] ; then + . "$HOME/.cargo/env" +fi + +# if [ -s "$HOME/.gvm/scripts/gvm" ]; then +# . "$HOME/.gvm/scripts/gvm" +# fi diff --git a/.init/start.sh b/.init/start.sh new file mode 100755 index 00000000..4d9a1cf3 --- /dev/null +++ b/.init/start.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +ssh-add &>/dev/null + +# SSH_ENV="$HOME/.ssh/agent-environment" + +# function start_agent { +# echo "Initialising new SSH agent..." +# /usr/bin/ssh-agent | sed 's/^echo/#echo/' >"$SSH_ENV" +# echo succeeded +# chmod 600 "$SSH_ENV" +# . "$SSH_ENV" >/dev/null +# /usr/bin/ssh-add; +# } + +# # Source SSH settings, if applicable + +# if [ -f "$SSH_ENV" ]; then +# . "$SSH_ENV" >/dev/null +# #ps $SSH_AGENT_PID doesn't work under Cygwin +# ps -ef | grep $SSH_AGENT_PID | grep ssh-agent$ >/dev/null || { +# start_agent +# } +# else +# start_agent +# fi diff --git a/.init/trap.sh b/.init/trap.sh new file mode 100755 index 00000000..bf943c61 --- /dev/null +++ b/.init/trap.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +TRAPINT() { +} + +TRAPQUIT() { +} + +TRAPTERM() { +} + +TRAPEXIT() { +} \ No newline at end of file diff --git a/.last_pwd b/.last_pwd new file mode 100644 index 00000000..598c5651 --- /dev/null +++ b/.last_pwd @@ -0,0 +1 @@ +repos/sexy.pivoine.art diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..f62f0b29 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v20.19.1 diff --git a/.p10k.zsh b/.p10k.zsh new file mode 100644 index 00000000..b9a4ffba --- /dev/null +++ b/.p10k.zsh @@ -0,0 +1,193 @@ +# Generated by Powerlevel10k configuration wizard on 2025-09-04 at 02:33 CEST. +# Based on romkatv/powerlevel10k/config/p10k-pure.zsh, checksum 07533. +# Wizard options: nerdfont-v3 + powerline, small icons, pure, snazzy, 24h time, 1 line, +# compact, instant_prompt=verbose. +# Type `p10k configure` to generate another config. +# +# Config file for Powerlevel10k with the style of Pure (https://github.com/sindresorhus/pure). +# +# Differences from Pure: +# +# - Git: +# - `@c4d3ec2c` instead of something like `v1.4.0~11` when in detached HEAD state. +# - No automatic `git fetch` (the same as in Pure with `PURE_GIT_PULL=0`). +# +# Apart from the differences listed above, the replication of Pure prompt is exact. This includes +# even the questionable parts. For example, just like in Pure, there is no indication of Git status +# being stale; prompt symbol is the same in command, visual and overwrite vi modes; when prompt +# doesn't fit on one line, it wraps around with no attempt to shorten it. +# +# If you like the general style of Pure but not particularly attached to all its quirks, type +# `p10k configure` and pick "Lean" style. This will give you slick minimalist prompt while taking +# advantage of Powerlevel10k features that aren't present in Pure. + +# Temporarily change options. +'builtin' 'local' '-a' 'p10k_config_opts' +[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') +[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') +[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') +'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' + +() { + emulate -L zsh -o extended_glob + + # Unset all configuration options. + unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' + + # Zsh >= 5.1 is required. + [[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return + + # Prompt colors. + local grey='242' + local red='#FF5C57' + local yellow='#F3F99D' + local blue='#57C7FF' + local magenta='#FF6AC1' + local cyan='#9AEDFE' + local white='#F1F1F0' + + # Left prompt segments. + typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( + context # user@host + dir # current directory + vcs # git status + command_execution_time # previous command duration + # virtualenv # python virtual environment + prompt_char # prompt symbol + ) + + # Right prompt segments. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=( + # command_execution_time # previous command duration + # virtualenv # python virtual environment + # context # user@host + time # current time + ) + + # Basic style options that define the overall prompt look. + typeset -g POWERLEVEL9K_BACKGROUND= # transparent background + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= # no surrounding whitespace + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' # separate segments with a space + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol + typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION= # no segment icons + + # Add an empty line before each prompt except the first. This doesn't emulate the bug + # in Pure that makes prompt drift down whenever you use the Alt-C binding from fzf or similar. + typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false + + # Magenta prompt symbol if the last command succeeded. + typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS}_FOREGROUND=$magenta + # Red prompt symbol if the last command failed. + typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS}_FOREGROUND=$red + # Default prompt symbol. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION='❯' + # Prompt symbol in command vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION='❮' + # Prompt symbol in visual vi mode is the same as in command mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='❮' + # Prompt symbol in overwrite vi mode is the same as in command mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=false + + # Grey Python Virtual Environment. + typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=$grey + # Don't show Python version. + typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false + typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER= + + # Blue current directory. + typeset -g POWERLEVEL9K_DIR_FOREGROUND=$blue + + # Context format when root: user@host. The first part white, the rest grey. + typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE="%F{$white}%n%f%F{$grey}@%m%f" + # Context format when not root: user@host. The whole thing grey. + typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE="%F{$grey}%n@%m%f" + # Don't show context unless root or in SSH. + typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION= + + # Show previous command duration only if it's >= 5s. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=5 + # Don't show fractional seconds. Thus, 7s rather than 7.3s. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 + # Duration format: 1d 2h 3m 4s. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' + # Yellow previous command duration. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=$yellow + + # Grey Git prompt. This makes stale prompts indistinguishable from up-to-date ones. + typeset -g POWERLEVEL9K_VCS_FOREGROUND=$grey + + # Disable async loading indicator to make directories that aren't Git repositories + # indistinguishable from large Git repositories without known state. + typeset -g POWERLEVEL9K_VCS_LOADING_TEXT= + + # Don't wait for Git status even for a millisecond, so that prompt always updates + # asynchronously when Git state changes. + typeset -g POWERLEVEL9K_VCS_MAX_SYNC_LATENCY_SECONDS=0 + + # Cyan ahead/behind arrows. + typeset -g POWERLEVEL9K_VCS_{INCOMING,OUTGOING}_CHANGESFORMAT_FOREGROUND=$cyan + # Don't show remote branch, current tag or stashes. + typeset -g POWERLEVEL9K_VCS_GIT_HOOKS=(vcs-detect-changes git-untracked git-aheadbehind) + # Don't show the branch icon. + typeset -g POWERLEVEL9K_VCS_BRANCH_ICON= + # When in detached HEAD state, show @commit where branch normally goes. + typeset -g POWERLEVEL9K_VCS_COMMIT_ICON='@' + # Don't show staged, unstaged, untracked indicators. + typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED}_ICON= + # Show '*' when there are staged, unstaged or untracked files. + typeset -g POWERLEVEL9K_VCS_DIRTY_ICON='*' + # Show '⇣' if local branch is behind remote. + typeset -g POWERLEVEL9K_VCS_INCOMING_CHANGES_ICON=':⇣' + # Show '⇡' if local branch is ahead of remote. + typeset -g POWERLEVEL9K_VCS_OUTGOING_CHANGES_ICON=':⇡' + # Don't show the number of commits next to the ahead/behind arrows. + typeset -g POWERLEVEL9K_VCS_{COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=1 + # Remove space between '⇣' and '⇡' and all trailing spaces. + typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${${${P9K_CONTENT/⇣* :⇡/⇣⇡}// }//:/ }' + + # Grey current time. + typeset -g POWERLEVEL9K_TIME_FOREGROUND=$grey + # Format for the current time: 09:51:02. See `man 3 strftime`. + typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}' + # If set to true, time will update when you hit enter. This way prompts for the past + # commands will contain the start times of their commands rather than the end times of + # their preceding commands. + typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false + + # Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt + # when accepting a command line. Supported values: + # + # - off: Don't change prompt when accepting a command line. + # - always: Trim down prompt when accepting a command line. + # - same-dir: Trim down prompt when accepting a command line unless this is the first command + # typed after changing current working directory. + typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off + + # Instant prompt mode. + # + # - off: Disable instant prompt. Choose this if you've tried instant prompt and found + # it incompatible with your zsh configuration files. + # - quiet: Enable instant prompt and don't print warnings when detecting console output + # during zsh initialization. Choose this if you've read and understood + # https://github.com/romkatv/powerlevel10k#instant-prompt. + # - verbose: Enable instant prompt and print a warning when detecting console output during + # zsh initialization. Choose this if you've never tried instant prompt, haven't + # seen the warning, or if you are unsure what this all means. + typeset -g POWERLEVEL9K_INSTANT_PROMPT=off + + # Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized. + # For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload + # can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you + # really need it. + typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=off + + # If p10k is already loaded, reload configuration. + # This works even with POWERLEVEL9K_DISABLE_HOT_RELOAD=true. + (( ! $+functions[p10k] )) || p10k reload +} + +# Tell `p10k configure` which file it should overwrite. +typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a} + +(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} +'builtin' 'unset' 'p10k_config_opts' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..19fb890a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +fail_fast: false +default_stages: [pre-commit] +repos: + - repo: local + hooks: [] diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..082123b9 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Ignore artifacts: +build +coverage + +repos/hydejack/**/*.html diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..9b2ee4b1 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxSingleQuote": true, + "printWidth": 80, + "proseWrap": "always", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false +} diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..1d4830ee --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10.17 diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..ef60f700 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,267 @@ +AllCops: + NewCops: enable + +Gemspec/AddRuntimeDependency: # new in 1.65 + Enabled: true +Gemspec/DeprecatedAttributeAssignment: # new in 1.30 + Enabled: true +Gemspec/DevelopmentDependencies: # new in 1.44 + Enabled: true +Gemspec/RequireMFA: # new in 1.23 + Enabled: true +Layout/LineContinuationLeadingSpace: # new in 1.31 + Enabled: true +Layout/LineContinuationSpacing: # new in 1.31 + Enabled: true +Layout/LineEndStringConcatenationIndentation: # new in 1.18 + Enabled: true +Layout/SpaceBeforeBrackets: # new in 1.7 + Enabled: true +Lint/AmbiguousAssignment: # new in 1.7 + Enabled: true +Lint/AmbiguousOperatorPrecedence: # new in 1.21 + Enabled: true +Lint/AmbiguousRange: # new in 1.19 + Enabled: true +Lint/ArrayLiteralInRegexp: # new in 1.71 + Enabled: true +Lint/ConstantOverwrittenInRescue: # new in 1.31 + Enabled: true +Lint/ConstantReassignment: # new in 1.70 + Enabled: true +Lint/CopDirectiveSyntax: # new in 1.72 + Enabled: true +Lint/DeprecatedConstants: # new in 1.8 + Enabled: true +Lint/DuplicateBranch: # new in 1.3 + Enabled: true +Lint/DuplicateMagicComment: # new in 1.37 + Enabled: true +Lint/DuplicateMatchPattern: # new in 1.50 + Enabled: true +Lint/DuplicateRegexpCharacterClassElement: # new in 1.1 + Enabled: true +Lint/DuplicateSetElement: # new in 1.67 + Enabled: true +Lint/EmptyBlock: # new in 1.1 + Enabled: true +Lint/EmptyClass: # new in 1.3 + Enabled: true +Lint/EmptyInPattern: # new in 1.16 + Enabled: true +Lint/HashNewWithKeywordArgumentsAsDefault: # new in 1.69 + Enabled: true +Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21 + Enabled: true +Lint/ItWithoutArgumentsInBlock: # new in 1.59 + Enabled: true +Lint/LambdaWithoutLiteralBlock: # new in 1.8 + Enabled: true +Lint/LiteralAssignmentInCondition: # new in 1.58 + Enabled: true +Lint/MixedCaseRange: # new in 1.53 + Enabled: true +Lint/NoReturnInBeginEndBlocks: # new in 1.2 + Enabled: true +Lint/NonAtomicFileOperation: # new in 1.31 + Enabled: true +Lint/NumberedParameterAssignment: # new in 1.9 + Enabled: true +Lint/NumericOperationWithConstantResult: # new in 1.69 + Enabled: true +Lint/OrAssignmentToConstant: # new in 1.9 + Enabled: true +Lint/RedundantDirGlobSort: # new in 1.8 + Enabled: true +Lint/RedundantRegexpQuantifiers: # new in 1.53 + Enabled: true +Lint/RedundantTypeConversion: # new in 1.72 + Enabled: true +Lint/RefinementImportMethods: # new in 1.27 + Enabled: true +Lint/RequireRangeParentheses: # new in 1.32 + Enabled: true +Lint/RequireRelativeSelfPath: # new in 1.22 + Enabled: true +Lint/SharedMutableDefault: # new in 1.70 + Enabled: true +Lint/SuppressedExceptionInNumberConversion: # new in 1.72 + Enabled: true +Lint/SymbolConversion: # new in 1.9 + Enabled: true +Lint/ToEnumArguments: # new in 1.1 + Enabled: true +Lint/TripleQuotes: # new in 1.9 + Enabled: true +Lint/UnescapedBracketInRegexp: # new in 1.68 + Enabled: true +Lint/UnexpectedBlockArity: # new in 1.5 + Enabled: true +Lint/UnmodifiedReduceAccumulator: # new in 1.1 + Enabled: true +Lint/UselessConstantScoping: # new in 1.72 + Enabled: true +Lint/UselessDefined: # new in 1.69 + Enabled: true +Lint/UselessNumericOperation: # new in 1.66 + Enabled: true +Lint/UselessRescue: # new in 1.43 + Enabled: true +Lint/UselessRuby2Keywords: # new in 1.23 + Enabled: true +Metrics/CollectionLiteralLength: # new in 1.47 + Enabled: true +Naming/BlockForwarding: # new in 1.24 + Enabled: true +Security/CompoundHash: # new in 1.28 + Enabled: true +Security/IoMethods: # new in 1.22 + Enabled: true +Style/AmbiguousEndlessMethodDefinition: # new in 1.68 + Enabled: true +Style/ArgumentsForwarding: # new in 1.1 + Enabled: true +Style/ArrayIntersect: # new in 1.40 + Enabled: true +Style/BitwisePredicate: # new in 1.68 + Enabled: true +Style/CollectionCompact: # new in 1.2 + Enabled: true +Style/CombinableDefined: # new in 1.68 + Enabled: true +Style/ComparableBetween: # new in 1.74 + Enabled: true +Style/ComparableClamp: # new in 1.44 + Enabled: true +Style/ConcatArrayLiterals: # new in 1.41 + Enabled: true +Style/DataInheritance: # new in 1.49 + Enabled: true +Style/DigChain: # new in 1.69 + Enabled: true +Style/DirEmpty: # new in 1.48 + Enabled: true +Style/DocumentDynamicEvalDefinition: # new in 1.1 + Enabled: true +Style/EmptyHeredoc: # new in 1.32 + Enabled: true +Style/EndlessMethod: # new in 1.8 + Enabled: true +Style/EnvHome: # new in 1.29 + Enabled: true +Style/ExactRegexpMatch: # new in 1.51 + Enabled: true +Style/FetchEnvVar: # new in 1.28 + Enabled: true +Style/FileEmpty: # new in 1.48 + Enabled: true +Style/FileNull: # new in 1.69 + Enabled: true +Style/FileRead: # new in 1.24 + Enabled: true +Style/FileTouch: # new in 1.69 + Enabled: true +Style/FileWrite: # new in 1.24 + Enabled: true +Style/HashConversion: # new in 1.10 + Enabled: true +Style/HashExcept: # new in 1.7 + Enabled: true +Style/HashFetchChain: # new in 1.75 + Enabled: true +Style/HashSlice: # new in 1.71 + Enabled: true +Style/IfWithBooleanLiteralBranches: # new in 1.9 + Enabled: true +Style/InPatternThen: # new in 1.16 + Enabled: true +Style/ItAssignment: # new in 1.70 + Enabled: true +Style/ItBlockParameter: # new in 1.75 + Enabled: true +Style/KeywordArgumentsMerging: # new in 1.68 + Enabled: true +Style/MagicCommentFormat: # new in 1.35 + Enabled: true +Style/MapCompactWithConditionalBlock: # new in 1.30 + Enabled: true +Style/MapIntoArray: # new in 1.63 + Enabled: true +Style/MapToHash: # new in 1.24 + Enabled: true +Style/MapToSet: # new in 1.42 + Enabled: true +Style/MinMaxComparison: # new in 1.42 + Enabled: true +Style/MultilineInPatternThen: # new in 1.16 + Enabled: true +Style/NegatedIfElseCondition: # new in 1.2 + Enabled: true +Style/NestedFileDirname: # new in 1.26 + Enabled: true +Style/NilLambda: # new in 1.3 + Enabled: true +Style/NumberedParameters: # new in 1.22 + Enabled: true +Style/NumberedParametersLimit: # new in 1.22 + Enabled: true +Style/ObjectThen: # new in 1.28 + Enabled: true +Style/OpenStructUse: # new in 1.23 + Enabled: true +Style/OperatorMethodCall: # new in 1.37 + Enabled: true +Style/QuotedSymbols: # new in 1.16 + Enabled: true +Style/RedundantArgument: # new in 1.4 + Enabled: true +Style/RedundantArrayConstructor: # new in 1.52 + Enabled: true +Style/RedundantConstantBase: # new in 1.40 + Enabled: true +Style/RedundantCurrentDirectoryInPath: # new in 1.53 + Enabled: true +Style/RedundantDoubleSplatHashBraces: # new in 1.41 + Enabled: true +Style/RedundantEach: # new in 1.38 + Enabled: true +Style/RedundantFilterChain: # new in 1.52 + Enabled: true +Style/RedundantFormat: # new in 1.72 + Enabled: true +Style/RedundantHeredocDelimiterQuotes: # new in 1.45 + Enabled: true +Style/RedundantInitialize: # new in 1.27 + Enabled: true +Style/RedundantInterpolationUnfreeze: # new in 1.66 + Enabled: true +Style/RedundantLineContinuation: # new in 1.49 + Enabled: true +Style/RedundantRegexpArgument: # new in 1.53 + Enabled: true +Style/RedundantRegexpConstructor: # new in 1.52 + Enabled: true +Style/RedundantSelfAssignmentBranch: # new in 1.19 + Enabled: true +Style/RedundantStringEscape: # new in 1.37 + Enabled: true +Style/ReturnNilInPredicateMethodDefinition: # new in 1.53 + Enabled: true +Style/SafeNavigationChainLength: # new in 1.68 + Enabled: true +Style/SelectByRegexp: # new in 1.22 + Enabled: true +Style/SendWithLiteralMethodName: # new in 1.64 + Enabled: true +Style/SingleLineDoEndBlock: # new in 1.57 + Enabled: true +Style/StringChars: # new in 1.12 + Enabled: true +Style/SuperArguments: # new in 1.64 + Enabled: true +Style/SuperWithArgsParentheses: # new in 1.58 + Enabled: true +Style/SwapValues: # new in 1.1 + Enabled: true +Style/YAMLFileRead: # new in 1.53 + Enabled: true diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..47b322c9 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.4.1 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..14846432 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,49 @@ +{ + "explorer.excludeGitIgnore": false, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[ignore]": { + "editor.defaultFormatter": "foxundermoon.shell-format" + }, + "[shellscript]": { + "editor.defaultFormatter": "mkhl.shfmt" + }, + "[xml]": { + "editor.defaultFormatter": "trunk.io" + }, + "[html]": { + "editor.defaultFormatter": "trunk.io" + }, + "[javascript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[markdown]": { + "editor.defaultFormatter": "trunk.io" + }, + "[typescript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[yaml]": { + "editor.defaultFormatter": "kennylong.kubernetes-yaml-formatter" + }, + "[dockercompose]": { + "editor.defaultFormatter": "ms-azuretools.vscode-containers" + }, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode" + }, + "[css]": { + "editor.defaultFormatter": "vscode.css-language-features" + }, + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features" + }, + "[rust]": { + "editor.defaultFormatter": "rust-lang.rust-analyzer" + }, + "[jsonc]": { + "editor.defaultFormatter": "vscode.json-language-features" + }, + "[vue]": { + "editor.defaultFormatter": "Vue.volar" + } +} diff --git a/.zlogin b/.zlogin new file mode 100755 index 00000000..e69de29b diff --git a/.zlogout b/.zlogout new file mode 100755 index 00000000..e69de29b diff --git a/.zprofile b/.zprofile new file mode 100755 index 00000000..139597f9 --- /dev/null +++ b/.zprofile @@ -0,0 +1,2 @@ + + diff --git a/.zshenv b/.zshenv new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.zshenv @@ -0,0 +1 @@ + diff --git a/.zshrc b/.zshrc new file mode 100644 index 00000000..6b44a9db --- /dev/null +++ b/.zshrc @@ -0,0 +1,130 @@ +if [ -f "$HOME/.init/init.sh" ] ; then + . "$HOME/.init/init.sh" +fi +# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. +# Initialization code that may require console input (password prompts, [y/n] +# confirmations, etc.) must go above this block; everything else may go below. +if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then + source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" +fi + +# If you come from bash you might have to change your $PATH. +# export PATH=$HOME/bin:$HOME/.local/bin:/usr/local/bin:$PATH + +# Path to your Oh My Zsh installation. +export ZSH="$HOME/.oh-my-zsh" + +# Set name of the theme to load --- if set to "random", it will +# load a random theme each time Oh My Zsh is loaded, in which case, +# to know which specific one was loaded, run: echo $RANDOM_THEME +# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes +ZSH_THEME="powerlevel10k/powerlevel10k" + +# Set list of themes to pick from when loading at random +# Setting this variable when ZSH_THEME=random will cause zsh to load +# a theme from this variable instead of looking in $ZSH/themes/ +# If set to an empty array, this variable will have no effect. +# ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) + +# Uncomment the following line to use case-sensitive completion. +# CASE_SENSITIVE="true" + +# Uncomment the following line to use hyphen-insensitive completion. +# Case-sensitive completion must be off. _ and - will be interchangeable. +# HYPHEN_INSENSITIVE="true" + +# Uncomment one of the following lines to change the auto-update behavior +# zstyle ':omz:update' mode disabled # disable automatic updates +# zstyle ':omz:update' mode auto # update automatically without asking +# zstyle ':omz:update' mode reminder # just remind me to update when it's time + +# Uncomment the following line to change how often to auto-update (in days). +# zstyle ':omz:update' frequency 13 + +# Uncomment the following line if pasting URLs and other text is messed up. +# DISABLE_MAGIC_FUNCTIONS="true" + +# Uncomment the following line to disable colors in ls. +# DISABLE_LS_COLORS="true" + +# Uncomment the following line to disable auto-setting terminal title. +# DISABLE_AUTO_TITLE="true" + +# Uncomment the following line to enable command auto-correction. +# ENABLE_CORRECTION="true" + +# Uncomment the following line to display red dots whilst waiting for completion. +# You can also set it to another string to have that shown instead of the default red dots. +# e.g. COMPLETION_WAITING_DOTS="%F{yellow}waiting...%f" +# Caution: this setting can cause issues with multiline prompts in zsh < 5.7.1 (see #5765) +# COMPLETION_WAITING_DOTS="true" + +# Uncomment the following line if you want to disable marking untracked files +# under VCS as dirty. This makes repository status check for large repositories +# much, much faster. +# DISABLE_UNTRACKED_FILES_DIRTY="true" + +# Uncomment the following line if you want to change the command execution time +# stamp shown in the history command output. +# You can set one of the optional three formats: +# "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" +# or set a custom format using the strftime function format specifications, +# see 'man strftime' for details. +# HIST_STAMPS="mm/dd/yyyy" + +# Would you like to use another custom folder than $ZSH/custom? +# ZSH_CUSTOM=/path/to/new-custom-folder + +# Which plugins would you like to load? +# Standard plugins can be found in $ZSH/plugins/ +# Custom plugins may be added to $ZSH_CUSTOM/plugins/ +# Example format: plugins=(rails git textmate ruby lighthouse) +# Add wisely, as too many plugins slow down shell startup. +plugins=(git pm2 gh sudo ssh ruby rust python node github rsync nvm rbenv pyenv docker docker-compose qrcode zsh-autosuggestions zsh-syntax-highlighting zsh-interactive-cd zsh-navigation-tools) + +source $ZSH/oh-my-zsh.sh + +# User configuration + +# export MANPATH="/usr/local/man:$MANPATH" + +# You may need to manually set your language environment +# export LANG=en_US.UTF-8 + +# Preferred editor for local and remote sessions +# if [[ -n $SSH_CONNECTION ]]; then +# export EDITOR='vim' +# else +# export EDITOR='nvim' +# fi + +# Compilation flags +# export ARCHFLAGS="-arch $(uname -m)" + +# Set personal aliases, overriding those provided by Oh My Zsh libs, +# plugins, and themes. Aliases can be placed here, though Oh My Zsh +# users are encouraged to define aliases within a top-level file in +# the $ZSH_CUSTOM folder, with .zsh extension. Examples: +# - $ZSH_CUSTOM/aliases.zsh +# - $ZSH_CUSTOM/macos.zsh +# For a full list of active aliases, run `alias`. +# +# Example aliases +# alias zshconfig="mate ~/.zshrc" +# alias ohmyzsh="mate ~/.oh-my-zsh" + +# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh. +[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh + + +# _home_pull + +cd "$HOME/$(cat $HOME/.last_pwd)" &>/dev/null + +# pnpm +export PNPM_HOME="/home/valknar/.local/share/pnpm" +case ":$PATH:" in + *":$PNPM_HOME:"*) ;; + *) export PATH="$PNPM_HOME:$PATH" ;; +esac +# pnpm end diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..6f3f9e44 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,137 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +This is a personal home directory repository managed as a git repository with selective tracking via `.gitignore`. The repository tracks dotfiles and configuration for a Debian development environment supporting Node.js, Python, Ruby, Rust, and Go development. + +## Key Architecture + +### Initialization System +Shell initialization is managed through `.init/init.sh`, which sources modular configuration: +- `.init/path.sh` - PATH environment setup for all language toolchains +- `.init/alias.sh` - Custom shell aliases +- `.init/functions.sh` - Custom shell functions for deployment and media processing +- `.init/export.sh`, `.init/source.sh`, `.init/eval.sh` - Additional environment setup + +### Arty Configuration +`arty.yml` defines the repository structure using Arty (artifact/repository manager): +- **references**: Git subrepositories to clone into specific paths +- **envs**: Environment profiles (dev/prod) for selective repository management +- Manages both development projects and language version managers (nvm, rbenv, pyenv, gvm) + +### Ansible Provisioning +`playbook.yml` is an Ansible playbook for system setup: +- Installs and configures language runtimes (Node, Python, Ruby, Rust, Go) +- Sets up Docker, PostgreSQL 18, and development tools +- Configures Zsh with Oh-My-Zsh and Powerlevel10k theme +- Manages system packages via apt + +### Git Selective Tracking +The `.gitignore` uses an inverted pattern (ignore everything, then selectively allow): +- Tracks only specific dotfiles and configuration files +- Allows `.github/`, `.init/`, `.vscode/` directories +- Excludes logs, databases, and temporary files + +## Development Environment + +### Language Version Management +- **Node.js**: Managed by nvm, version specified in `.nvmrc` +- **Ruby**: Managed by rbenv, version in `.ruby-version` +- **Python**: Managed by pyenv, version in `.python-version` +- **Rust**: Via rustup (`.cargo/`, `.rustup/`) +- **Go**: Via gvm (`.gvm/`) + +### Shell Environment +- **Shell**: Zsh with Oh-My-Zsh framework +- **Theme**: Powerlevel10k (`.p10k.zsh`) +- **Plugins**: git, pm2, gh, docker, language-specific plugins, zsh-autosuggestions, zsh-syntax-highlighting + +## Common Commands + +### Environment Setup +```bash +# Reinitialize shell environment +ri # alias for: source ~/.init/init.sh + +# Bootstrap system (run as user, prompts for sudo) +sudo -u $USER ansible-playbook -K playbook.yml + +# Run specific Ansible tags +ansible-playbook --tags node,python,ruby -K playbook.yml +``` + +### Arty Repository Management +```bash +# Debug Arty configuration +pnpm arty debug + +# Clone/update repositories based on environment +pnpm arty sync --env dev +``` + +### Git Workflow +```bash +# Stage all changes and check if clean +g0 # alias for: git add . && git diff --quiet && git diff --cached --quiet + +# Reset to single commit +g1 # alias for: git reset $(git commit-tree "HEAD^{tree}" -m "A new start") + +# Get last commit message +g2 # alias for: git log --format=%B -n 1 HEAD | head -n 1 +``` + +### Code Quality +```bash +# Python pre-commit hooks (configured in .pre-commit-config.yaml) +pre-commit run --all-files + +# Ruby style checking +rubocop + +# Node.js linting +pnpm eslint +``` + +### Utility Functions +Available shell functions from `.init/functions.sh`: +- `batch_file_sequence ` - Rename files with sequence numbers +- `batch_image_webp` - Convert images to WebP format +- `batch_video_x264` - Convert videos to x264 codec +- `rs` - Rsync with sudo on remote (alias for complex rsync command) +- `ss` - Serve current directory on port 8000 +- `yt ` - Download YouTube video as MP3 + +## Projects Structure + +The `Projects/` directory contains development projects: +- `butter-sh/` - Butter shell projects +- `docker-compose/` - Docker compose configurations +- `pivoine.art/` - Jekyll-based art portfolio site +- `docs.pivoine.art/` - Documentation site +- `sexy.pivoine.art/` - Includes Rust package (`packages/buttplug/`) +- `node.js/` - Node.js applications (awesome, awesome-app, email-pour-vous, webshot) + +## Package Management + +### Node.js +- **Package manager**: pnpm (enabled via corepack) +- **Global packages**: Installed to `~/node_modules/` +- **PM2**: Configured via `ecosystem.config.js` for GitHub Copilot language server + +### Python +- **Installer**: pip +- **Dependencies**: Listed in `requirements.txt` (currently: pre-commit) + +### Ruby +- **Bundler**: Gemfile specifies Jekyll 4.3 and rubocop + +## Important Notes + +- This repository uses selective git tracking - most files are ignored by default +- Shell must source `.init/init.sh` for full environment setup (automatically done in `.zshrc`) +- Language runtimes are version-managed and installed via Ansible +- Docker requires user to be in `docker` group (managed by Ansible) +- The `.last_pwd` file tracks the last working directory for shell navigation diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..22c4eceb --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + + +gem 'jekyll', '~> 4.3' +gem 'rubocop' \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 00000000..1660e287 --- /dev/null +++ b/README.md @@ -0,0 +1,478 @@ +
+ +
+ _    _____    __    __ __ _   _____    ____ _ _____
+| |  / /   |  / /   / //_// | / /   |  / __ ( ) ___/
+| | / / /| | / /   / ,<  /  |/ / /| | / /_/ //\__ \
+| |/ / ___ |/ /___/ /| |/ /|  / ___ |/ _, _/ ___/ /
+|___/_/  |_/_____/_/ |_/_/ |_/_/  |_/_/ |_| /____/
+
+    __________  ____  ____________
+   / ____/ __ \/ __ \/ ____/ ____/
+  / /_  / / / / /_/ / / __/ __/
+ / __/ / /_/ / _, _/ /_/ / /___
+/_/    \____/_/ |_|\____/_____/
+
+ +# ⚡🔥 WHERE CODE MEETS CHAOS 🔥⚡ + +[![Debian](https://img.shields.io/badge/Debian-Trixie-A81D33?style=for-the-badge&logo=debian&logoColor=white)](https://www.debian.org/) +[![Powered by Metal](https://img.shields.io/badge/POWERED%20BY-METAL-FF0000?style=for-the-badge)](https://www.slayer.net/) +[![Built with Blood](https://img.shields.io/badge/BUILT%20WITH-BLOOD%20%26%20SWEAT-8B0000?style=for-the-badge)](/) +[![License: MIT](https://img.shields.io/badge/License-MIT-990000?style=for-the-badge)](LICENSE) + +**My Debian home directory - forged in the fires of chaos, tempered with configuration files,** +**and wielded with the fury of a thousand riffs.** + +*This is where dotfiles headbang and shell scripts scream.* + +
+ +--- + +## ⚡ THE ARSENAL ⚡ + +### 🎸 **WEAPONS OF MASS DEVELOPMENT** + +``` +┌─────────────────────────────────────────────────┐ +│ ⚔️ NODE.JS │ Managed by nvm │ +│ ⚔️ PYTHON │ Managed by pyenv │ +│ ⚔️ RUBY │ Managed by rbenv │ +│ ⚔️ RUST │ Managed by rustup │ +│ ⚔️ GO │ Managed by gvm │ +│ ⚔️ DOCKER │ Containerized destruction │ +│ ⚔️ POSTGRES │ Version 18 database engine │ +└─────────────────────────────────────────────────┘ +``` + +--- + +## 🔴 INITIALIZATION RITUAL 🔴 + +### **The `.init/` System - Your Shell's Dark Ceremony** + +The `.init/` directory is the beating heart of this environment. When your shell awakens, it performs a sacred ritual through `~/.init/init.sh`, summoning power from these ancient scripts: + +#### 🗡️ **THE SEVEN STAGES OF POWER** + +``` +┌──────────────────────────────────────────────────────────────┐ +│ 1. PATH.SH │ Forges the PATH to all binaries │ +│ 2. EXPORT.SH │ Exports environment variables │ +│ 3. ALIAS.SH │ Summons command shortcuts │ +│ 4. SOURCE.SH │ Sources external power (nvm, cargo, etc) │ +│ 5. FUNCTIONS.SH │ Unleashes custom shell functions │ +│ 6. EVAL.SH │ Evaluates version managers (rbenv, etc) │ +│ 7. START.SH │ Executes startup commands (ssh-add) │ +└──────────────────────────────────────────────────────────────┘ +``` + +#### 📜 **DETAILED BREAKDOWN OF EACH SCRIPT** + +##### **1️⃣ `path.sh` - The Path of Destruction** +Adds all binary directories to your `$PATH`: +- `~/bin` - Your personal executables +- `~/.local/bin` - Local user binaries +- `~/.rbenv/bin` - Ruby version manager +- `~/.pyenv/bin` - Python version manager +- `~/.cargo/bin` - Rust binaries +- `~/go/bin` - Go binaries +- `~/node_modules/.bin` - Node.js binaries +- `~/.init/bin` - Custom init scripts +- `~/Projects/kompose` - Kompose tooling + +##### **2️⃣ `export.sh` - Environmental Warfare** +```bash +export NVM_DIR="$HOME/.nvm" # Node Version Manager home +export REPOS_DIR="$HOME/repos" # Repository directory +export CHORE_CHORE="chore: chore" # Default commit message +``` + +##### **3️⃣ `alias.sh` - Command Line Sorcery** +```bash +ri # Reload init: source ~/.init/init.sh +g0 # Git stage all and check if clean +g1 # Git reset to single commit (nuclear option) +g2 # Get last commit message +rs # Rsync with sudo on remote +ss # Serve static files on port 8000 +yt # Download YouTube as MP3 +``` + +##### **4️⃣ `source.sh` - External Power Summoning** +Sources critical external scripts: +- **NVM** - Node Version Manager (`$NVM_DIR/nvm.sh`) +- **RVM** - Ruby Version Manager (commented out) +- **Cargo** - Rust environment (`~/.cargo/env`) +- **Bash completion** for NVM + +##### **5️⃣ `functions.sh` - The Grimoire of Bash** +Custom functions for deployment and media manipulation: + +**Git Warfare:** +- `_home_push` - Commit and push changes +- `_home_pull` - Stash, pull, and pop changes + +**Deployment Spells:** +- `_site_deploy_jekyll ` - Build & deploy Jekyll site +- `_site_deploy_nuxt ` - Build & deploy Nuxt site +- `_site_deploy_static ` - Deploy static files + +**Media Alchemy:** +- `batch_file_sequence ` - Rename files with numbers +- `batch_image_webp` - Convert all images to WebP +- `batch_video_x264` - Convert videos to x264 codec +- `_image_optimize ` - Full image optimization pipeline +- `_video_optimize ` - Optimize video with ffmpeg + +##### **6️⃣ `eval.sh` - Version Manager Invocation** +Initializes version managers through `eval`: +- **oh-my-posh** - Shell prompt theme engine +- **rbenv** - Ruby version manager +- **pyenv** - Python version manager + +##### **7️⃣ `start.sh` - The Final Awakening** +Executes startup commands: +- `ssh-add` - Adds SSH keys to the agent silently + +#### 🗂️ **Additional Directories** + +- **`.init/bin/`** - Custom executable scripts (e.g., `mime_mp4_gif.sh`) +- **`.init/hooks/`** - Reserved for shell hooks (currently empty) + +--- + +## 🩸 QUICK START RITUAL 🩸 + +### **Summoning the Environment** + +```bash +# 1. Clone this unholy repository +git init && git remote add origin git@github.com:valknarogg/home.git +git fetch && git reset --hard origin/main +git branch --set-upstream-to=origin/main main + +# 2. Install Ansible (if not already installed) +sudo apt install git ansible + +# 3. Configure git +git config --global init.defaultBranch main +git config --global --add safe.directory /home/$USER + +# 4. Unleash the Ansible playbook +sudo -u $USER ansible-playbook -K playbook.yml +``` + +### **Selective Provisioning** + +Run specific parts of the setup using tags: + +```bash +# Install only Node.js environment +ansible-playbook --tags node -K playbook.yml + +# Install Python + Ruby +ansible-playbook --tags python,ruby -K playbook.yml + +# Install everything +ansible-playbook -K playbook.yml +``` + +#### 🏷️ **Available Tags:** +`base` | `node` | `python` | `ruby` | `rust` | `zsh` | `postgres` | `docker` | `fonts` | `flatpak` | `github` | `oh-my-posh` + +--- + +## 🎯 ARTY - REPOSITORY ORCHESTRATION 🎯 + +### **What is Arty?** + +**Arty.sh** is a bash-based dependency and repository manager that orchestrates git subrepositories like a conductor of chaos. It's part of the [butter.sh](https://github.com/butter-sh/butter-sh.github.io) ecosystem - a suite of bash development tools. + +### **Installing Arty** + +Arty is already installed globally at `/usr/local/bin/arty`. If you need to install/update it: + +```bash +# Clone butter.sh ecosystem +git clone https://github.com/butter-sh/butter-sh.github.io.git ~/Projects/butter-sh + +# Install arty globally (requires sudo) +cd ~/Projects/butter-sh/projects/arty.sh +sudo ./arty.sh install +``` + +### **The `arty.yml` Configuration** + +The root `~/arty.yml` defines your entire repository ecosystem: + +```yaml +name: "Valknar's home" +version: "1.0.0" + +envs: + dev: # Development environment + prod: # Production environment + +references: + # Project repositories + - url: git@github.com:valknarogg/pivoine.art.git + into: Projects/pivoine.art + env: dev + + # Media repositories + - url: git@github.com:valknarogg/home-pictures.git + into: Bilder + env: dev + + # Version managers + - url: https://github.com/nvm-sh/nvm.git + into: .nvm + + # ... and many more + +scripts: + debug: echo "$ARTY_BIN_DIR" && echo "$ARTY_LIBS_DIR" +``` + +### **Using Arty** + +```bash +# Sync all dev environment repositories +arty sync --env dev + +# Sync production repositories only +arty sync --env prod + +# Install dependencies from arty.yml +arty install + +# Run custom scripts defined in arty.yml +arty debug + +# Show dependency tree +arty deps + +# Update a specific reference +arty update pivoine.art +``` + +### **What Arty Manages:** +- ✅ Project repositories (pivoine.art, sexy.pivoine.art, etc.) +- ✅ Media repositories (Pictures, Videos, Music) +- ✅ Docker compose configurations +- ✅ Version managers (nvm, rbenv, pyenv, gvm) +- ✅ Oh-My-Zsh and plugins +- ✅ Shell scripts and binaries + +### **Environment-Based Management** + +References can be tagged with `env: dev` or `env: prod` to control which repositories are synced in different environments. This allows you to: +- Keep heavy media files out of production servers +- Separate development projects from system utilities +- Maintain clean, minimal deployments + +--- + +## 🔥 COMMAND LINE BRUTALITY 🔥 + +### **Git Operations** + +```bash +g0 # Stage all changes and verify clean state +g1 # Nuclear reset to single commit +g2 # Show last commit message +git add -A && git commit -m "$(g2)" # Reuse last commit message +``` + +### **Media Processing** + +```bash +# Convert all images in directory to WebP +batch_image_webp + +# Rename files with sequence numbers +batch_file_sequence artwork webp + +# Optimize video +_video_optimize input.mov + +# Download YouTube video as MP3 +yt "https://youtube.com/watch?v=..." +``` + +### **Development Servers** + +```bash +# Serve current directory on port 8000 +ss + +# Run Jekyll site with livereload +cd ~/Projects/pivoine.art && bundle exec jekyll serve --livereload + +# Run Node.js dev server +cd ~/Projects/node.js/awesome && pnpm dev +``` + +### **Rsync Power** + +```bash +# Sync to remote with sudo +rs /local/path/ user@host:/remote/path/ +``` + +--- + +## 📁 PROJECT STRUCTURE 📁 + +``` +~/Projects/ +├── butter-sh/ # Butter.sh ecosystem (arty, judge, myst, etc.) +├── docker-compose/ # Docker orchestration configs +├── pivoine.art/ # Jekyll art portfolio (main site) +├── docs.pivoine.art/ # Documentation site +├── sexy.pivoine.art/ # Rust + web project (includes buttplug package) +└── node.js/ + ├── awesome/ # GitHub Awesome lists browser + ├── awesome-app/ # Awesome list application + ├── email-pour-vous/ # Email templating project + └── webshot/ # Website screenshot tool +``` + +--- + +## 🛠️ DOTFILE HIGHLIGHTS 🛠️ + +### **Shell Configuration** +- **`.zshrc`** - Oh-My-Zsh with Powerlevel10k theme +- **`.p10k.zsh`** - Powerlevel10k configuration +- **`.bashrc`** - Bash configuration (fallback) + +### **Version Files** +- **`.nvmrc`** - Node.js version +- **`.ruby-version`** - Ruby version +- **`.python-version`** - Python version + +### **Code Quality** +- **`.pre-commit-config.yaml`** - Pre-commit hooks (Python) +- **`.rubocop.yml`** - Ruby style enforcement +- **`eslint.config.mts`** - JavaScript/TypeScript linting +- **`.prettierrc`** - Code formatting rules +- **`biome.json`** - Fast linter/formatter + +### **Package Management** +- **`requirements.txt`** - Python packages (pip) +- **`Gemfile`** - Ruby gems (bundler) + +### **Git Configuration** +- **`.gitignore`** - INVERTED PATTERN (ignore all, allow specific files) +- **`.gitconfig`** - Git user configuration + +### **Orchestration** +- **`arty.yml`** - Repository and dependency management +- **`playbook.yml`** - Ansible system provisioning + +--- + +## ⚙️ GIT SELECTIVE TRACKING ⚙️ + +This repository uses an **inverted `.gitignore`** pattern: + +```gitignore +# Ignore everything +* + +# Allow specific files +!CLAUDE.md +!README.md +!.gitignore +!.init/** +!arty.yml +!playbook.yml +... +``` + +**Why?** To track only essential dotfiles and configurations while ignoring cache, logs, and user data. Your home directory becomes a git repository without the chaos. + +--- + +## 🎸 SHELL PLUGIN POWER 🎸 + +**Oh-My-Zsh Plugins Loaded:** +``` +git pm2 gh sudo ssh ruby rust python node github +rsync nvm rbenv pyenv docker docker-compose qrcode +zsh-autosuggestions zsh-syntax-highlighting +zsh-interactive-cd zsh-navigation-tools +``` + +--- + +## 🔗 USEFUL RESOURCES 🔗 + +### System & Shell +- [Ansible Documentation](https://docs.ansible.com/) +- [Oh-My-Zsh](https://ohmyz.sh/) +- [Powerlevel10k](https://github.com/romkatv/powerlevel10k) + +### Language Managers +- [nvm](https://github.com/nvm-sh/nvm) - Node Version Manager +- [rbenv](https://github.com/rbenv/rbenv) - Ruby Version Manager +- [pyenv](https://github.com/pyenv/pyenv) - Python Version Manager +- [gvm](https://github.com/moovweb/gvm) - Go Version Manager +- [rustup](https://rustup.rs/) - Rust Toolchain Manager + +### Orchestration +- [Arty.sh Documentation](https://github.com/butter-sh/butter-sh.github.io) +- [Butter.sh Ecosystem](https://butter.sh) + +--- + +## 🖤 LICENSE 🖤 + +MIT License - Do whatever the hell you want with it. + +--- + +
+ +
+═════════════════════════════════════════════════════════════════
+
+__________  ____  ______   _________
+  / ____/ __ \/ __ \/ ____/  /  _/ ___/
+ / /   / / / / / / / __/     / / \__ \
+/ /___/ /_/ / /_/ / /___   _/ / ___/ /
+\____/\____/_____/_____/  /___//____/
+
+  ______________  _______  ____  ____  ___    ______  __
+ /_  __/ ____/  |/  / __ \/ __ \/ __ \/   |  / __ \ \/ /
+  / / / __/ / /|_/ / /_/ / / / / /_/ / /| | / /_/ /\  /
+ / / / /___/ /  / / ____/ /_/ / _, _/ ___ |/ _, _/ / /
+/_/ /_____/_/  /_/_/    \____/_/ |_/_/  |_/_/ |_| /_/
+
+    __  __________________    __       _________
+   /  |/  / ____/_  __/   |  / /      /  _/ ___/
+  / /|_/ / __/   / / / /| | / /       / / \__ \
+ / /  / / /___  / / / ___ |/ /___   _/ / ___/ /
+/_/  /_/_____/ /_/ /_/  |_/_____/  /___//____/
+
+    ______________________  _   _____    __
+   / ____/_  __/ ____/ __ \/ | / /   |  / /
+  / __/   / / / __/ / /_/ /  |/ / /| | / /
+ / /___  / / / /___/ _, _/ /|  / ___ |/ /___
+/_____/ /_/ /_____/_/ |_/_/ |_/_/  |_/_____/
+
+═════════════════════════════════════════════════════════════════
+
+🔥⚡ FORGED BY VALKNAR ⚡🔥
+valknar@pivoine.art
+Powered by Debian | Fueled by Metal
+
+🤘 🤘 🤘
+
+ +**[⚔️ BACK TO THE TOP ⚔️](#)** + +
diff --git a/arty.yml b/arty.yml new file mode 100644 index 00000000..2de97762 --- /dev/null +++ b/arty.yml @@ -0,0 +1,65 @@ +name: "Valknar's home" +version: "1.0.0" +description: "Valknar's home repository" +author: "valknar@pivoine.art" +license: "MIT" + +envs: + dev: + prod: + + +references: +- url: git@github.com:butter-sh/butter-sh.github.io.git + into: Projects/butter-sh + env: dev +- url: git@github.com:valknarogg/home-pictures.git + into: Bilder + env: dev +- url: git@github.com:valknarogg/home-videos.git + into: Videos + ref: main + env: dev +- url: git@github.com:valknarogg/home-music.git + into: Musik + ref: main + env: dev +- url: git@github.com:valknarogg/docker-compose.git + into: Projects/docker-compose + env: + - dev + - prod +- url: git@github.com:valknarogg/pivoine.art.git + into: Projects/pivoine.art + ref: main + env: dev +- url: git@github.com:valknarxxx/sexy.pivoine.art.git + into: Projects/sexy.pivoine.art + env: dev +- url: git@github.com:valknarness/awesome.git + into: Projects/node.js/awesome + env: + - dev + - prod +- url: git@github.com:valknarness/awesome-app.git + into: Projects/node.js/awesome-app + env: dev +- url: https://github.com/nvm-sh/nvm.git + into: .nvm +- url: https://github.com/moovweb/gvm.git + into: .gvm +- url: https://github.com/rbenv/rbenv.git + into: .rbenv +- url: https://github.com/pyenv/pyenv.git + into: .pyenv +- url: https://github.com/ohmyzsh/ohmyzsh.git + into: .oh-my-zsh +- url: https://github.com/romkatv/powerlevel10k.git + into: .oh-my-zsh/custom/themes/powerlevel10k +- url: https://github.com/zsh-users/zsh-autosuggestions.git + into: .oh-my-zsh/custom/plugins/zsh-autosuggestions +- url: https://github.com/zsh-users/zsh-syntax-highlighting.git + into: .oh-my-zsh/custom/plugins/zsh-syntax-highlighting + +scripts: + debug: echo "$ARTY_BIN_DIR" && echo "$ARTY_LIBS_DIR" && echo "$ARTY_HOME" diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..24bfd99f --- /dev/null +++ b/biome.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "tab" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 00000000..850b233f --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,9 @@ +module.exports = { + apps: [ + { + name: "language-server", + script: + "./node_modules/@github/copilot-language-server/dist/language-server.js", + }, + ], +}; diff --git a/eslint.config.mts b/eslint.config.mts new file mode 100644 index 00000000..12480a5f --- /dev/null +++ b/eslint.config.mts @@ -0,0 +1,14 @@ +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import { defineConfig } from "eslint/config"; + +export default defineConfig([ + { + files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], + plugins: { js }, + extends: ["js/recommended"], + languageOptions: { globals: globals.browser }, + }, + tseslint.configs.recommended, +]); diff --git a/playbook.yml b/playbook.yml new file mode 100644 index 00000000..0c2191d0 --- /dev/null +++ b/playbook.yml @@ -0,0 +1,288 @@ +- hosts: localhost + connection: local + tasks: + - name: Install base packages + become: true + + ansible.builtin.apt: + pkg: + - make + - build-essential + - git + - curl + - wget + - rsync + - zsh + - imagemagick + - ffmpeg + - yt-dlp + - fzf + - icoutils + - postgresql-common + - unzip + tags: + - base + - python + - ruby + - rust + - zsh + - postgres + + - name: Prepare postgresql + ansible.builtin.shell: /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh + args: + executable: /bin/bash + tags: + - postgres + + - name: Install postgres package + become: true + ansible.builtin.apt: + pkg: + - postgresql-18 + update_cache: true + tags: + - postgres + + - name: Change root shell to zsh + become: true + ansible.builtin.user: + name: root + shell: /bin/zsh + tags: + - oh-my-posh + + - name: Give permissions to /root/bin + become: true + ansible.builtin.file: + path: /root/bin + state: directory + tags: + - oh-my-posh + + - name: Install oh-my-posh for root + become: true + ansible.builtin.shell: curl -s https://ohmyposh.dev/install.sh | bash -s -- -d /root/bin + args: + executable: /bin/bash + tags: + - oh-my-posh + + - name: Ensure root shell loads user bin + become: true + ansible.builtin.lineinfile: + path: /root/.zshrc + line: | + export PATH="$PATH:/root/bin" + if [ "$TERM_PROGRAM" != "Apple_Terminal" ]; then + eval "$(oh-my-posh init zsh)" + fi + create: yes + tags: + - oh-my-posh + + - name: Install node + ansible.builtin.shell: source ~/.init/init.sh && nvm install + args: + executable: /bin/bash + tags: + - node + + - name: Enable node corepack + ansible.builtin.shell: source ~/.init/init.sh && corepack enable + args: + executable: /bin/bash + tags: + - node + + - name: Install node packages + ansible.builtin.shell: source ~/.init/init.sh && cd ~ && pnpm install + args: + executable: /bin/bash + tags: + - node + + - name: Install python required packages + become: true + ansible.builtin.apt: + pkg: + - libssl-dev + - zlib1g-dev + - libbz2-dev + - libreadline-dev + - libsqlite3-dev + - llvm + - libncurses5-dev + tags: + - python + + - name: Install python + ansible.builtin.shell: source ~/.init/init.sh && pyenv install --skip-existing + args: + executable: /bin/bash + tags: + - python + + - name: Install python packages + ansible.builtin.shell: source ~/.init/init.sh && pip install -r ~/requirements.txt + args: + executable: /bin/bash + tags: + - python + + - name: Init python pre-commit + ansible.builtin.shell: source ~/.init/init.sh && cd ~ && pre-commit install + args: + executable: /bin/bash + tags: + - python + + - name: Install ruby required packages + become: true + ansible.builtin.apt: + pkg: + - libssl-dev + - libffi-dev + - libyaml-dev + - zlib1g-dev + tags: + - ruby + + - name: Install ruby + ansible.builtin.shell: source ~/.init/init.sh && rbenv install --skip-existing + args: + executable: /bin/bash + tags: + - ruby + + - name: Install ruby base packages + ansible.builtin.shell: source ~/.init/init.sh && gem install {{ item }} + args: + executable: /bin/bash + with_items: + - bundler + tags: + - ruby + + - name: Install ruby packages + ansible.builtin.shell: source ~/.init/init.sh && cd ~ && bundle install + args: + executable: /bin/bash + tags: + - ruby + + - name: Install rust required packages + become: true + ansible.builtin.apt: + pkg: + - libudev-dev + - libusb-1.0-0-dev + - libdbus-1-dev + - pkg-config + - cmake + tags: + - rust + + - name: Download Installer for rust + ansible.builtin.get_url: + url: https://sh.rustup.rs + dest: /tmp/sh.rustup.rs + mode: '0755' + force: 'yes' + tags: + - rust + + - name: Install rust + ansible.builtin.shell: /tmp/sh.rustup.rs -y + tags: + - rust + + - name: Change user shell to zsh + become: true + ansible.builtin.user: + name: '{{ ansible_user_id }}' + shell: /bin/zsh + tags: + - zsh + + - name: Update font cache + ansible.builtin.shell: fc-cache -f -v + tags: + - fonts + + - name: Install flatpak required packages + become: true + ansible.builtin.apt: + pkg: + - flatpak + - gnome-software-plugin-flatpak + - libgtk-3-dev + tags: + - flatpak + + - name: Add flathub repo + ansible.builtin.shell: flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + tags: + - flatpak + + - name: Install github required packages + become: true + ansible.builtin.apt: + pkg: + - gh + tags: + - github + + # - name: Add github copilot extension + # ansible.builtin.shell: gh extension install github/gh-copilot + # tags: + # - github + + - name: Install Docker required packages + become: true + ansible.builtin.apt: + name: + - apt-transport-https + - ca-certificates + - curl + - gnupg2 + - postgresql-client + tags: + - docker + - name: Add Docker repository + ansible.builtin.deb822_repository: + name: docker + uris: https://download.docker.com/linux/debian + types: deb + suites: trixie + architectures: amd64 + components: stable + signed_by: https://download.docker.com/linux/debian/gpg + tags: + - docker + - name: Install Docker Engine + become: true + ansible.builtin.apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + update_cache: true + tags: + - docker + + - name: Add user to docker group + become: true + ansible.builtin.user: + name: '{{ ansible_user_id }}' + groups: docker + tags: + - docker + + - name: Start Docker service + become: true + ansible.builtin.service: + name: docker + state: started + tags: + - docker diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..416634f5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pre-commit