commit 665ce577516546840268cf54a48569ed2aca315c Author: Sebastian Krüger Date: Wed Oct 29 00:06:12 2025 +0100 A new start 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