From b2413ef0de409e92a53eed54883a2c8d22584e47 Mon Sep 17 00:00:00 2001 From: vados-dev <192440777+vados-dev@users.noreply.github.com> Date: Wed, 1 Apr 2026 04:03:16 +0300 Subject: [PATCH] auto bbb --- .../bash-cli-spinners/.gitattributes | 2 + .../.github/workflows/ci.yml | 205 ++ .../.github/workflows/deploy-demo-site.yml | 45 + .../bash-cli-spinners/CLAUDE.md | 29 + .../bash-cli-spinners/LICENSE | 21 + .../bash-cli-spinners/Makefile | 79 + .../bash-cli-spinners/README.md | 144 ++ .../assets/demo-recording.cast | 934 ++++++++++ .../bash-cli-spinners/assets/demo.svg | 1 + .../bash-cli-spinners/demo.sh | 191 ++ .../bash-cli-spinners/spinner.sh | 364 ++++ .../bash-cli-spinners/spinners.json | 1651 +++++++++++++++++ .../bash-cli-spinners/test.sh | 225 +++ .../bash-cli-spinners/website/README.md | 69 + .../bash-cli-spinners/website/index.html | 412 ++++ .../bash-cli-spinners/website/spinners.json | 1 + 16 files changed, 4373 insertions(+) create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/.gitattributes create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/ci.yml create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/deploy-demo-site.yml create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/CLAUDE.md create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/LICENSE create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/Makefile create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/README.md create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/assets/demo-recording.cast create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/assets/demo.svg create mode 100755 bin/bash-progress-indicator/bash-cli-spinners/demo.sh create mode 100755 bin/bash-progress-indicator/bash-cli-spinners/spinner.sh create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/spinners.json create mode 100755 bin/bash-progress-indicator/bash-cli-spinners/test.sh create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/website/README.md create mode 100644 bin/bash-progress-indicator/bash-cli-spinners/website/index.html create mode 120000 bin/bash-progress-indicator/bash-cli-spinners/website/spinners.json diff --git a/bin/bash-progress-indicator/bash-cli-spinners/.gitattributes b/bin/bash-progress-indicator/bash-cli-spinners/.gitattributes new file mode 100644 index 0000000..e18ff48 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/.gitattributes @@ -0,0 +1,2 @@ +# Exclude HTML files under website/ from language stats +website/*.html linguist-detectable=false diff --git a/bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/ci.yml b/bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/ci.yml new file mode 100644 index 0000000..2e840f9 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/ci.yml @@ -0,0 +1,205 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + lint: + name: Lint Shell Scripts + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install shellcheck + run: | + sudo apt-get update + sudo apt-get install -y shellcheck + + - name: Run shellcheck on spinner.sh + run: shellcheck spinner.sh + + - name: Run shellcheck on test.sh + run: shellcheck test.sh + + - name: Run shellcheck on demo scripts + run: | + if [ -f demo.sh ]; then shellcheck demo.sh; fi + if [ -f demo_clean.sh ]; then shellcheck demo_clean.sh; fi + if [ -f comprehensive_demo.sh ]; then shellcheck comprehensive_demo.sh; fi + + test: + name: Run Tests + runs-on: ubuntu-latest + strategy: + matrix: + bash-version: ['4.4', '5.0', '5.1', '5.2'] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y jq bc + + - name: Install specific bash version + run: | + # Install bash from source for specific versions + if [ "${{ matrix.bash-version }}" != "$(bash --version | head -n1 | grep -o '[0-9]\+\.[0-9]\+')" ]; then + echo "Using system bash version: $(bash --version | head -n1)" + fi + + - name: Make scripts executable + run: | + chmod +x spinner.sh + chmod +x test.sh + + - name: Run test suite + run: ./test.sh + + - name: Test basic functionality + run: | + # Test list command + ./spinner.sh list + + # Test help command + ./spinner.sh help + + # Test invalid spinner + if ./spinner.sh show nonexistent 1 2>/dev/null; then + echo "ERROR: Invalid spinner should have failed" + exit 1 + fi + + echo "Basic functionality tests passed!" + + test-macos: + name: Test on macOS + runs-on: macos-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + brew install jq bc + + - name: Make scripts executable + run: | + chmod +x spinner.sh + chmod +x test.sh + + - name: Run test suite + run: ./test.sh + + performance: + name: Performance Tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y jq bc time + + - name: Make scripts executable + run: | + chmod +x spinner.sh + chmod +x test.sh + + - name: Performance benchmark + run: | + echo "=== Performance Benchmark ===" + + # Time the list command multiple times + echo "Testing list command performance..." + for i in {1..10}; do + /usr/bin/time -f "%e seconds" ./spinner.sh list >/dev/null + done + + # Test sourcing performance + echo "Testing sourcing performance..." + time (source ./spinner.sh && declare -f show_spinner >/dev/null) + + echo "Performance tests completed!" + + json-validation: + name: Validate JSON Data + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install jq + run: | + sudo apt-get update + sudo apt-get install -y jq + + - name: Validate spinners.json + run: | + echo "Validating spinners.json structure..." + + # Check if file is valid JSON + jq empty spinners.json + + # Check required fields exist + echo "Checking spinner data structure..." + + # Get all spinner names + spinners=$(jq -r 'keys[]' spinners.json) + + for spinner in $spinners; do + # Check each spinner has interval and frames + if ! jq -e ".\"$spinner\".interval" spinners.json >/dev/null; then + echo "ERROR: Spinner '$spinner' missing interval" + exit 1 + fi + + if ! jq -e ".\"$spinner\".frames" spinners.json >/dev/null; then + echo "ERROR: Spinner '$spinner' missing frames" + exit 1 + fi + + # Check frames is an array with at least one element + frame_count=$(jq ".\"$spinner\".frames | length" spinners.json) + if [ "$frame_count" -eq 0 ]; then + echo "ERROR: Spinner '$spinner' has no frames" + exit 1 + fi + done + + spinner_count=$(echo "$spinners" | wc -l) + echo "✅ Validated $spinner_count spinners successfully!" + + security: + name: Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install bandit (for general script security) + run: | + sudo apt-get update + sudo apt-get install -y shellcheck + + - name: Security scan with shellcheck + run: | + echo "Running security-focused shellcheck..." + shellcheck -S error spinner.sh + shellcheck -S error test.sh + + - name: Check for hardcoded secrets + run: | + echo "Checking for potential secrets..." + if grep -r -i "password\|secret\|key\|token" --include="*.sh" --include="*.json" .; then + echo "WARNING: Potential secrets found, please review" + else + echo "✅ No obvious secrets detected" + fi diff --git a/bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/deploy-demo-site.yml b/bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/deploy-demo-site.yml new file mode 100644 index 0000000..fd6b96b --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/.github/workflows/deploy-demo-site.yml @@ -0,0 +1,45 @@ +name: Deploy Demo Site to GitHub Pages + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Prepare website files + run: | + mkdir -p _site + cp website/index.html _site/ + cp spinners.json _site/ + cp website/README.md _site/ + + - name: Upload artifact + uses: actions/upload-pages-artifact@v4 + with: + path: '_site' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/bin/bash-progress-indicator/bash-cli-spinners/CLAUDE.md b/bin/bash-progress-indicator/bash-cli-spinners/CLAUDE.md new file mode 100644 index 0000000..b9a8536 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/CLAUDE.md @@ -0,0 +1,29 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a Bash/Zsh loading spinner library that provides multiple loading indicators for shell scripts. The project is currently in early development stage with only basic documentation files present. + +## Repository Structure + +The repository currently contains: +- `README.md` - Basic project description +- `LICENSE` - MIT license +- No source code files yet (spinner implementations to be added) + +## Development Notes + +- This is a shell script library focused on Bash/Zsh compatibility +- The library will offer five different loading spinner types +- No build system, test framework, or linting tools are currently configured +- Pure shell script implementation (no external dependencies expected) + +## Future Development + +When implementing spinners: +- Follow shell scripting best practices +- Ensure compatibility with both Bash and Zsh +- Consider terminal compatibility and cursor control sequences +- Implement clean start/stop mechanisms for each spinner type \ No newline at end of file diff --git a/bin/bash-progress-indicator/bash-cli-spinners/LICENSE b/bin/bash-progress-indicator/bash-cli-spinners/LICENSE new file mode 100644 index 0000000..0937c96 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Simon Egersand + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bin/bash-progress-indicator/bash-cli-spinners/Makefile b/bin/bash-progress-indicator/bash-cli-spinners/Makefile new file mode 100644 index 0000000..2e66ea4 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/Makefile @@ -0,0 +1,79 @@ +# Bash CLI Spinners Makefile + +.PHONY: serve demo help test lint clean install uninstall check +# Show available make targets (default) +help: + @echo "🌀 Bash CLI Spinners - Available targets:" + @echo "" + @echo " 🌐 serve - Start the spinner gallery web server" + @echo " 🎬 demo - Run the comprehensive spinner demo" + @echo " 🧪 test - Run the test suite" + @echo " 🔍 lint - Run shellcheck linting" + @echo " 📦 install - Install system-wide" + @echo " 🗑️ uninstall - Remove system installation" + @echo " 🧹 clean - Clean temporary files" + @echo " ✅ check - Run all checks (lint + test)" + @echo " ❓ help - Show this help message" + +# Start the spinner gallery web server +serve: + @echo "🌀 Starting Spinner Gallery Server..." + @echo "📂 Serving from: website/" + @echo "🔗 Creating symlink to spinners.json..." + @ln -sf ../spinners.json website/spinners.json + @echo "🌐 URL: http://localhost:8080" + @echo "📝 Press Ctrl+C to stop the server" + @echo "" + @cd website && python3 -m http.server 8080 + +# Run the comprehensive spinner demo +demo: + @echo "🎬 Running comprehensive spinner demo..." + @chmod +x demo.sh + @./demo.sh + +# Run the test suite +test: + @echo "🧪 Running test suite..." + @chmod +x test.sh + @./test.sh + +# Run linting with shellcheck +lint: + @echo "🔍 Running shellcheck..." + @if command -v shellcheck >/dev/null 2>&1; then \ + shellcheck spinner.sh test.sh demo.sh; \ + echo "✅ Linting passed!"; \ + else \ + echo "❌ shellcheck not found. Install with:"; \ + echo " macOS: brew install shellcheck"; \ + echo " Ubuntu: sudo apt install shellcheck"; \ + exit 1; \ + fi + +# Install system-wide +install: + @echo "📦 Installing bash-cli-spinners system-wide..." + @sudo cp spinner.sh /usr/local/bin/spinner + @sudo mkdir -p /usr/local/share/bash-cli-spinners + @sudo cp spinners.json /usr/local/share/bash-cli-spinners/ + @sudo sed -i.bak 's|SCRIPT_DIR.*|SPINNERS_JSON="/usr/local/share/bash-cli-spinners/spinners.json"|' /usr/local/bin/spinner + @echo "✅ Installed! You can now use 'spinner' command globally" + @echo "🧪 Test with: spinner list" + +# Uninstall system installation +uninstall: + @echo "🗑️ Removing system installation..." + @sudo rm -f /usr/local/bin/spinner + @sudo rm -rf /usr/local/share/bash-cli-spinners + @echo "✅ Uninstalled successfully" + +# Clean temporary files +clean: + @echo "🧹 Cleaning temporary files..." + @rm -f website/spinners.json + @echo "✅ Cleaned" + +# Run all checks before commit +check: lint test + @echo "✅ All checks passed! Ready to commit." diff --git a/bin/bash-progress-indicator/bash-cli-spinners/README.md b/bin/bash-progress-indicator/bash-cli-spinners/README.md new file mode 100644 index 0000000..8812a3a --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/README.md @@ -0,0 +1,144 @@ +# bash-cli-spinners [![CI](https://github.com/simeg/bash-cli-spinners/actions/workflows/ci.yml/badge.svg)](https://github.com/simeg/bash-cli-spinners/actions/workflows/ci.yml) +> +80 spinners for use in the terminal + +

+
+ +
+
+

+ +A bash/zsh cli spinner library **heavily inspired** by +[cli-spinners](https://github.com/sindresorhus/cli-spinners). + +**🌐 View Live Demo of all spinners 🌐** + +## Features + +- **+80 spinners** from the [`cli-spinners`](https://github.com/sindresorhus/cli-spinners) package +- **JSON-based** - Easy to extend and maintain +- **Color support** - 14 different colors available +- **Two modes** - Show for duration or run with command +- **Clean output** - Proper cursor management and cleanup +- **Web gallery** - Interactive browser interface to preview all spinners + +## Requirements + +- `bash` 4.0+ +- `jq` for JSON parsing +- `bc` for precise timing calculations + +Install requirements: +```bash +# macOS +brew install jq bc + +# Ubuntu/Debian +sudo apt install jq bc +``` + +## Quick Start + +```bash +# List all available spinners +./spinner.sh list + +# Show a spinner for 5 seconds +./spinner.sh show dots 5 "Loading data" blue + +# Run a command with a spinner +./spinner.sh run pong "Installing packages" bright_green sleep 10 +``` + +## Usage + +### Basic Usage +```bash +./spinner.sh show [message] [color] +./spinner.sh run [message] [color] +``` + +### Examples +```bash +# Simple 3-second dots spinner +./spinner.sh show dots 3 + +# Pong game with custom message and color +./spinner.sh show pong 5 "Playing pong!" bright_green + +# Weather spinner while downloading +./spinner.sh run weather "Downloading files" cyan curl -O https://example.com/file.zip + +# Material design spinner while compiling +./spinner.sh run material "Compiling project" bright_blue make build +``` + +## Available Colors + +### Basic Colors +![red](https://img.shields.io/badge/red-red?style=flat&color=CD5C5C) ![green](https://img.shields.io/badge/green-green?style=flat&color=228B22) ![yellow](https://img.shields.io/badge/yellow-yellow?style=flat&color=DAA520) ![blue](https://img.shields.io/badge/blue-blue?style=flat&color=4169E1) ![magenta](https://img.shields.io/badge/magenta-magenta?style=flat&color=DA70D6) ![cyan](https://img.shields.io/badge/cyan-cyan?style=flat&color=20B2AA) ![white](https://img.shields.io/badge/white-white?style=flat&color=F5F5F5) + +### Bright Colors +![bright_red](https://img.shields.io/badge/bright__red-bright_red?style=flat&color=FF6B6B) ![bright_green](https://img.shields.io/badge/bright__green-bright_green?style=flat&color=51CF66) ![bright_yellow](https://img.shields.io/badge/bright__yellow-bright_yellow?style=flat&color=FFD93D) ![bright_blue](https://img.shields.io/badge/bright__blue-bright_blue?style=flat&color=74C0FC) ![bright_magenta](https://img.shields.io/badge/bright__magenta-bright_magenta?style=flat&color=F783AC) ![bright_cyan](https://img.shields.io/badge/bright__cyan-bright_cyan?style=flat&color=66D9EF) ![bright_white](https://img.shields.io/badge/bright__white-bright_white?style=flat&color=FFFFFF) + +## Installation + +### For Use in Your Own Scripts + +To integrate this spinner library into your own bash/zsh scripts, you need both +core files: + +1. **Download the required files:** + ```bash + # Download spinner engine + curl -O https://raw.githubusercontent.com/simeg/bash-cli-spinners/main/spinner.sh + + # Download spinners database + curl -O https://raw.githubusercontent.com/simeg/bash-cli-spinners/main/spinners.json + ``` + +2. **Make spinner.sh executable:** + ```bash + chmod +x spinner.sh + ``` + +3. **Use in your scripts:** + ```bash + #!/usr/bin/env bash + set -euo pipefail + + # Bring spinner functions into *this* shell + source ./spinner.sh + + my_function() { + # your real logic here + sleep 10 + } + + # Run a finite task with a spinner + run_with_spinner "pong" "Installing" "cyan" my_function + + # Or pass a normal command directly (no function needed) + run_with_spinner "dots" "Building assets" "blue" npm run build + ``` + +## Architecture + +### JSON Structure + +Each spinner in `spinners.json` follows this format: +```json +{ + "spinner_name": { + "interval": 80, + "frames": ["frame1", "frame2", "frame3"] + } +} +``` + +- `interval`: Time between frames in milliseconds +- `frames`: Array of strings/characters to display + +## Related + +- [cli-spinners](https://github.com/sindresorhus/cli-spinners) diff --git a/bin/bash-progress-indicator/bash-cli-spinners/assets/demo-recording.cast b/bin/bash-progress-indicator/bash-cli-spinners/assets/demo-recording.cast new file mode 100644 index 0000000..f428510 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/assets/demo-recording.cast @@ -0,0 +1,934 @@ +{"version": 2, "width": 89, "height": 40, "timestamp": 1755927634, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}} +[0.026875, "o", "\u001b[?25l"] +[0.063221, "o", "\r\u001b[34m⠋\u001b[0m dots\u001b[K"] +[0.158156, "o", "\r\u001b[34m⠙\u001b[0m dots\u001b[K"] +[0.259349, "o", "\r\u001b[34m⠹\u001b[0m dots\u001b[K"] +[0.362642, "o", "\r\u001b[34m⠸\u001b[0m dots\u001b[K"] +[0.461336, "o", "\r\u001b[34m⠼\u001b[0m dots\u001b[K"] +[0.567807, "o", "\r\u001b[34m⠴\u001b[0m dots\u001b[K"] +[0.669379, "o", "\r\u001b[34m⠦\u001b[0m dots\u001b[K"] +[0.78825, "o", "\r\u001b[34m⠧\u001b[0m dots\u001b[K"] +[0.894001, "o", "\r\u001b[34m⠇\u001b[0m dots\u001b[K"] +[0.997854, "o", "\r\u001b[34m⠏\u001b[0m dots\u001b[K"] +[1.098322, "o", "\r\u001b[34m⠋\u001b[0m dots\u001b[K"] +[1.203212, "o", "\r\u001b[34m⠙\u001b[0m dots\u001b[K"] +[1.310179, "o", "\r\u001b[34m⠹\u001b[0m dots\u001b[K"] +[1.410961, "o", "\r\u001b[34m⠸\u001b[0m dots\u001b[K"] +[1.517013, "o", "\r\u001b[34m⠼\u001b[0m dots\u001b[K"] +[1.626392, "o", "\r\u001b[34m⠴\u001b[0m dots\u001b[K"] +[1.732613, "o", "\r\u001b[34m⠦\u001b[0m dots\u001b[K"] +[1.838137, "o", "\r\u001b[34m⠧\u001b[0m dots\u001b[K"] +[1.945696, "o", "\r\u001b[34m⠇\u001b[0m dots\u001b[K"] +[2.110806, "o", "\r\u001b[94m⣾\u001b[0m dots2\u001b[K"] +[2.214022, "o", "\r\u001b[94m⣽\u001b[0m dots2\u001b[K"] +[2.317327, "o", "\r\u001b[94m⣻\u001b[0m dots2\u001b[K"] +[2.413716, "o", "\r\u001b[94m⢿\u001b[0m dots2\u001b[K"] +[2.512389, "o", "\r\u001b[94m⡿\u001b[0m dots2\u001b[K"] +[2.620158, "o", "\r\u001b[94m⣟\u001b[0m dots2\u001b[K"] +[2.747817, "o", "\r\u001b[94m⣯\u001b[0m dots2\u001b[K"] +[2.865249, "o", "\r\u001b[94m⣷\u001b[0m dots2\u001b[K"] +[2.967197, "o", "\r\u001b[94m⣾\u001b[0m dots2\u001b[K"] +[3.069096, "o", "\r\u001b[94m⣽\u001b[0m dots2\u001b[K"] +[3.17816, "o", "\r\u001b[94m⣻\u001b[0m dots2\u001b[K"] +[3.277861, "o", "\r\u001b[94m⢿\u001b[0m dots2\u001b[K"] +[3.381993, "o", "\r\u001b[94m⡿\u001b[0m dots2\u001b[K"] +[3.483519, "o", "\r\u001b[94m⣟\u001b[0m dots2\u001b[K"] +[3.593463, "o", "\r\u001b[94m⣯\u001b[0m dots2\u001b[K"] +[3.709119, "o", "\r\u001b[94m⣷\u001b[0m dots2\u001b[K"] +[3.818182, "o", "\r\u001b[94m⣾\u001b[0m dots2\u001b[K"] +[3.912976, "o", "\r\u001b[94m⣽\u001b[0m dots2\u001b[K"] +[4.06311, "o", "\r\u001b[36m⠋\u001b[0m dots3\u001b[K"] +[4.167223, "o", "\r\u001b[36m⠙\u001b[0m dots3\u001b[K"] +[4.26682, "o", "\r\u001b[36m⠚\u001b[0m dots3\u001b[K"] +[4.370562, "o", "\r\u001b[36m⠞\u001b[0m dots3\u001b[K"] +[4.478998, "o", "\r\u001b[36m⠖\u001b[0m dots3\u001b[K"] +[4.590559, "o", "\r\u001b[36m⠦\u001b[0m dots3\u001b[K"] +[4.689885, "o", "\r\u001b[36m⠴\u001b[0m dots3\u001b[K"] +[4.809788, "o", "\r\u001b[36m⠲\u001b[0m dots3\u001b[K"] +[4.909416, "o", "\r\u001b[36m⠳\u001b[0m dots3\u001b[K"] +[5.014162, "o", "\r\u001b[36m⠓\u001b[0m dots3\u001b[K"] +[5.119089, "o", "\r\u001b[36m⠋\u001b[0m dots3\u001b[K"] +[5.238973, "o", "\r\u001b[36m⠙\u001b[0m dots3\u001b[K"] +[5.350206, "o", "\r\u001b[36m⠚\u001b[0m dots3\u001b[K"] +[5.454453, "o", "\r\u001b[36m⠞\u001b[0m dots3\u001b[K"] +[5.56225, "o", "\r\u001b[36m⠖\u001b[0m dots3\u001b[K"] +[5.668496, "o", "\r\u001b[36m⠦\u001b[0m dots3\u001b[K"] +[5.777226, "o", "\r\u001b[36m⠴\u001b[0m dots3\u001b[K"] +[5.875219, "o", "\r\u001b[36m⠲\u001b[0m dots3\u001b[K"] +[6.047425, "o", "\r\u001b[96m⠄\u001b[0m dots4\u001b[K"] +[6.145084, "o", "\r\u001b[96m⠆\u001b[0m dots4\u001b[K"] +[6.251546, "o", "\r\u001b[96m⠇\u001b[0m dots4\u001b[K"] +[6.3548, "o", "\r\u001b[96m⠋\u001b[0m dots4\u001b[K"] +[6.462375, "o", "\r\u001b[96m⠙\u001b[0m dots4\u001b[K"] +[6.587163, "o", "\r\u001b[96m⠸\u001b[0m dots4\u001b[K"] +[6.705532, "o", "\r\u001b[96m⠰\u001b[0m dots4\u001b[K"] +[6.817847, "o", "\r\u001b[96m⠠\u001b[0m dots4\u001b[K"] +[6.92178, "o", "\r\u001b[96m⠰\u001b[0m dots4\u001b[K"] +[7.027427, "o", "\r\u001b[96m⠸\u001b[0m dots4\u001b[K"] +[7.128924, "o", "\r\u001b[96m⠙\u001b[0m dots4\u001b[K"] +[7.229934, "o", "\r\u001b[96m⠋\u001b[0m dots4\u001b[K"] +[7.33121, "o", "\r\u001b[96m⠇\u001b[0m dots4\u001b[K"] +[7.437466, "o", "\r\u001b[96m⠆\u001b[0m dots4\u001b[K"] +[7.539063, "o", "\r\u001b[96m⠄\u001b[0m dots4\u001b[K"] +[7.647607, "o", "\r\u001b[96m⠆\u001b[0m dots4\u001b[K"] +[7.765168, "o", "\r\u001b[96m⠇\u001b[0m dots4\u001b[K"] +[7.872788, "o", "\r\u001b[96m⠋\u001b[0m dots4\u001b[K"] +[8.032272, "o", "\r\u001b[32m⠋\u001b[0m dots5\u001b[K"] +[8.141672, "o", "\r\u001b[32m⠙\u001b[0m dots5\u001b[K"] +[8.240283, "o", "\r\u001b[32m⠚\u001b[0m dots5\u001b[K"] +[8.338433, "o", "\r\u001b[32m⠒\u001b[0m dots5\u001b[K"] +[8.43926, "o", "\r\u001b[32m⠂\u001b[0m dots5\u001b[K"] +[8.544338, "o", "\r\u001b[32m⠂\u001b[0m dots5\u001b[K"] +[8.647289, "o", "\r\u001b[32m⠒\u001b[0m dots5\u001b[K"] +[8.754636, "o", "\r\u001b[32m⠲\u001b[0m dots5\u001b[K"] +[8.86018, "o", "\r\u001b[32m⠴\u001b[0m dots5\u001b[K"] +[8.958431, "o", "\r\u001b[32m⠦\u001b[0m dots5\u001b[K"] +[9.067674, "o", "\r\u001b[32m⠖\u001b[0m dots5\u001b[K"] +[9.17107, "o", "\r\u001b[32m⠒\u001b[0m dots5\u001b[K"] +[9.282898, "o", "\r\u001b[32m⠐\u001b[0m dots5\u001b[K"] +[9.386519, "o", "\r\u001b[32m⠐\u001b[0m dots5\u001b[K"] +[9.495223, "o", "\r\u001b[32m⠒\u001b[0m dots5\u001b[K"] +[9.600233, "o", "\r\u001b[32m⠓\u001b[0m dots5\u001b[K"] +[9.717232, "o", "\r\u001b[32m⠋\u001b[0m dots5\u001b[K"] +[9.823135, "o", "\r\u001b[32m⠋\u001b[0m dots5\u001b[K"] +[9.926992, "o", "\r\u001b[32m⠙\u001b[0m dots5\u001b[K"] +[10.104164, "o", "\r\u001b[92m⠁\u001b[0m dots6\u001b[K"] +[10.207995, "o", "\r\u001b[92m⠉\u001b[0m dots6\u001b[K"] +[10.312248, "o", "\r\u001b[92m⠙\u001b[0m dots6\u001b[K"] +[10.404262, "o", "\r\u001b[92m⠚\u001b[0m dots6\u001b[K"] +[10.507728, "o", "\r\u001b[92m⠒\u001b[0m dots6\u001b[K"] +[10.616193, "o", "\r\u001b[92m⠂\u001b[0m dots6\u001b[K"] +[10.730607, "o", "\r\u001b[92m⠂\u001b[0m dots6\u001b[K"] +[10.842017, "o", "\r\u001b[92m⠒\u001b[0m dots6\u001b[K"] +[10.94581, "o", "\r\u001b[92m⠲\u001b[0m dots6\u001b[K"] +[11.052429, "o", "\r\u001b[92m⠴\u001b[0m dots6\u001b[K"] +[11.150883, "o", "\r\u001b[92m⠤\u001b[0m dots6\u001b[K"] +[11.261252, "o", "\r\u001b[92m⠄\u001b[0m dots6\u001b[K"] +[11.362896, "o", "\r\u001b[92m⠄\u001b[0m dots6\u001b[K"] +[11.457693, "o", "\r\u001b[92m⠤\u001b[0m dots6\u001b[K"] +[11.569161, "o", "\r\u001b[92m⠴\u001b[0m dots6\u001b[K"] +[11.68757, "o", "\r\u001b[92m⠲\u001b[0m dots6\u001b[K"] +[11.78698, "o", "\r\u001b[92m⠒\u001b[0m dots6\u001b[K"] +[11.890387, "o", "\r\u001b[92m⠂\u001b[0m dots6\u001b[K"] +[12.029753, "o", "\r\u001b[33m⠈\u001b[0m dots7\u001b[K"] +[12.129186, "o", "\r\u001b[33m⠉\u001b[0m dots7\u001b[K"] +[12.229608, "o", "\r\u001b[33m⠋\u001b[0m dots7\u001b[K"] +[12.338206, "o", "\r\u001b[33m⠓\u001b[0m dots7\u001b[K"] +[12.436865, "o", "\r\u001b[33m⠒\u001b[0m dots7\u001b[K"] +[12.556684, "o", "\r\u001b[33m⠐\u001b[0m dots7\u001b[K"] +[12.660088, "o", "\r\u001b[33m⠐\u001b[0m dots7\u001b[K"] +[12.771414, "o", "\r\u001b[33m⠒\u001b[0m dots7\u001b[K"] +[12.875131, "o", "\r\u001b[33m⠖\u001b[0m dots7\u001b[K"] +[12.979201, "o", "\r\u001b[33m⠦\u001b[0m dots7\u001b[K"] +[13.090005, "o", "\r\u001b[33m⠤\u001b[0m dots7\u001b[K"] +[13.200243, "o", "\r\u001b[33m⠠\u001b[0m dots7\u001b[K"] +[13.29952, "o", "\r\u001b[33m⠠\u001b[0m dots7\u001b[K"] +[13.399936, "o", "\r\u001b[33m⠤\u001b[0m dots7\u001b[K"] +[13.505217, "o", "\r\u001b[33m⠦\u001b[0m dots7\u001b[K"] +[13.613293, "o", "\r\u001b[33m⠖\u001b[0m dots7\u001b[K"] +[13.719977, "o", "\r\u001b[33m⠒\u001b[0m dots7\u001b[K"] +[13.824617, "o", "\r\u001b[33m⠐\u001b[0m dots7\u001b[K"] +[13.922851, "o", "\r\u001b[33m⠐\u001b[0m dots7\u001b[K"] +[14.103116, "o", "\r\u001b[93m⠁\u001b[0m dots8\u001b[K"] +[14.208221, "o", "\r\u001b[93m⠁\u001b[0m dots8\u001b[K"] +[14.312504, "o", "\r\u001b[93m⠉\u001b[0m dots8\u001b[K"] +[14.416163, "o", "\r\u001b[93m⠙\u001b[0m dots8\u001b[K"] +[14.52005, "o", "\r\u001b[93m⠚\u001b[0m dots8\u001b[K"] +[14.63092, "o", "\r\u001b[93m⠒\u001b[0m dots8\u001b[K"] +[14.740457, "o", "\r\u001b[93m⠂\u001b[0m dots8\u001b[K"] +[14.849675, "o", "\r\u001b[93m⠂\u001b[0m dots8\u001b[K"] +[14.95153, "o", "\r\u001b[93m⠒\u001b[0m dots8\u001b[K"] +[15.068203, "o", "\r\u001b[93m⠲\u001b[0m dots8\u001b[K"] +[15.170059, "o", "\r\u001b[93m⠴\u001b[0m dots8\u001b[K"] +[15.273551, "o", "\r\u001b[93m⠤\u001b[0m dots8\u001b[K"] +[15.379631, "o", "\r\u001b[93m⠄\u001b[0m dots8\u001b[K"] +[15.489209, "o", "\r\u001b[93m⠄\u001b[0m dots8\u001b[K"] +[15.600008, "o", "\r\u001b[93m⠤\u001b[0m dots8\u001b[K"] +[15.704577, "o", "\r\u001b[93m⠠\u001b[0m dots8\u001b[K"] +[15.80754, "o", "\r\u001b[93m⠠\u001b[0m dots8\u001b[K"] +[15.908522, "o", "\r\u001b[93m⠤\u001b[0m dots8\u001b[K"] +[16.013651, "o", "\r\u001b[93m⠦\u001b[0m dots8\u001b[K"] +[16.113628, "o", "\r\u001b[93m⠖\u001b[0m dots8\u001b[K"] +[16.226014, "o", "\r\u001b[93m⠒\u001b[0m dots8\u001b[K"] +[16.329388, "o", "\r\u001b[93m⠐\u001b[0m dots8\u001b[K"] +[16.432346, "o", "\r\u001b[93m⠐\u001b[0m dots8\u001b[K"] +[16.534058, "o", "\r\u001b[93m⠒\u001b[0m dots8\u001b[K"] +[16.643146, "o", "\r\u001b[93m⠓\u001b[0m dots8\u001b[K"] +[16.751991, "o", "\r\u001b[93m⠋\u001b[0m dots8\u001b[K"] +[16.864164, "o", "\r\u001b[93m⠉\u001b[0m dots8\u001b[K"] +[17.02602, "o", "\r\u001b[31m⢹\u001b[0m dots9\u001b[K"] +[17.123368, "o", "\r\u001b[31m⢺\u001b[0m dots9\u001b[K"] +[17.236426, "o", "\r\u001b[31m⢼\u001b[0m dots9\u001b[K"] +[17.339706, "o", "\r\u001b[31m⣸\u001b[0m dots9\u001b[K"] +[17.452006, "o", "\r\u001b[31m⣇\u001b[0m dots9\u001b[K"] +[17.554428, "o", "\r\u001b[31m⡧\u001b[0m dots9\u001b[K"] +[17.661417, "o", "\r\u001b[31m⡗\u001b[0m dots9\u001b[K"] +[17.774373, "o", "\r\u001b[31m⡏\u001b[0m dots9\u001b[K"] +[17.877664, "o", "\r\u001b[31m⢹\u001b[0m dots9\u001b[K"] +[17.983514, "o", "\r\u001b[31m⢺\u001b[0m dots9\u001b[K"] +[18.090949, "o", "\r\u001b[31m⢼\u001b[0m dots9\u001b[K"] +[18.201471, "o", "\r\u001b[31m⣸\u001b[0m dots9\u001b[K"] +[18.315156, "o", "\r\u001b[31m⣇\u001b[0m dots9\u001b[K"] +[18.425201, "o", "\r\u001b[31m⡧\u001b[0m dots9\u001b[K"] +[18.527586, "o", "\r\u001b[31m⡗\u001b[0m dots9\u001b[K"] +[18.635353, "o", "\r\u001b[31m⡏\u001b[0m dots9\u001b[K"] +[18.732548, "o", "\r\u001b[31m⢹\u001b[0m dots9\u001b[K"] +[18.843962, "o", "\r\u001b[31m⢺\u001b[0m dots9\u001b[K"] +[19.021206, "o", "\r\u001b[91m⢄\u001b[0m dots10\u001b[K"] +[19.125551, "o", "\r\u001b[91m⢂\u001b[0m dots10\u001b[K"] +[19.226724, "o", "\r\u001b[91m⢁\u001b[0m dots10\u001b[K"] +[19.339397, "o", "\r\u001b[91m⡁\u001b[0m dots10\u001b[K"] +[19.438382, "o", "\r\u001b[91m⡈\u001b[0m dots10\u001b[K"] +[19.533645, "o", "\r\u001b[91m⡐\u001b[0m dots10\u001b[K"] +[19.638572, "o", "\r\u001b[91m⡠\u001b[0m dots10\u001b[K"] +[19.738196, "o", "\r\u001b[91m⢄\u001b[0m dots10\u001b[K"] +[19.841465, "o", "\r\u001b[91m⢂\u001b[0m dots10\u001b[K"] +[19.947804, "o", "\r\u001b[91m⢁\u001b[0m dots10\u001b[K"] +[20.050458, "o", "\r\u001b[91m⡁\u001b[0m dots10\u001b[K"] +[20.160703, "o", "\r\u001b[91m⡈\u001b[0m dots10\u001b[K"] +[20.269145, "o", "\r\u001b[91m⡐\u001b[0m dots10\u001b[K"] +[20.379772, "o", "\r\u001b[91m⡠\u001b[0m dots10\u001b[K"] +[20.491108, "o", "\r\u001b[91m⢄\u001b[0m dots10\u001b[K"] +[20.595742, "o", "\r\u001b[91m⢂\u001b[0m dots10\u001b[K"] +[20.724723, "o", "\r\u001b[91m⢁\u001b[0m dots10\u001b[K"] +[20.833766, "o", "\r\u001b[91m⡁\u001b[0m dots10\u001b[K"] +[20.943488, "o", "\r\u001b[91m⡈\u001b[0m dots10\u001b[K"] +[21.12275, "o", "\r\u001b[35m⠁\u001b[0m dots11\u001b[K"] +[21.248049, "o", "\r\u001b[35m⠂\u001b[0m dots11\u001b[K"] +[21.371875, "o", "\r\u001b[35m⠄\u001b[0m dots11\u001b[K"] +[21.497337, "o", "\r\u001b[35m⡀\u001b[0m dots11\u001b[K"] +[21.63192, "o", "\r\u001b[35m⢀\u001b[0m dots11\u001b[K"] +[21.749465, "o", "\r\u001b[35m⠠\u001b[0m dots11\u001b[K"] +[21.870201, "o", "\r\u001b[35m⠐\u001b[0m dots11\u001b[K"] +[22.00181, "o", "\r\u001b[35m⠈\u001b[0m dots11\u001b[K"] +[22.143282, "o", "\r\u001b[35m⠁\u001b[0m dots11\u001b[K"] +[22.266595, "o", "\r\u001b[35m⠂\u001b[0m dots11\u001b[K"] +[22.412846, "o", "\r\u001b[35m⠄\u001b[0m dots11\u001b[K"] +[22.531846, "o", "\r\u001b[35m⡀\u001b[0m dots11\u001b[K"] +[22.666661, "o", "\r\u001b[35m⢀\u001b[0m dots11\u001b[K"] +[22.784392, "o", "\r\u001b[35m⠠\u001b[0m dots11\u001b[K"] +[22.906548, "o", "\r\u001b[35m⠐\u001b[0m dots11\u001b[K"] +[23.084596, "o", "\r\u001b[95m⢀⠀\u001b[0m dots12\u001b[K"] +[23.191516, "o", "\r\u001b[95m⡀⠀\u001b[0m dots12\u001b[K"] +[23.301236, "o", "\r\u001b[95m⠄⠀\u001b[0m dots12\u001b[K"] +[23.402, "o", "\r\u001b[95m⢂⠀\u001b[0m dots12\u001b[K"] +[23.49998, "o", "\r\u001b[95m⡂⠀\u001b[0m dots12\u001b[K"] +[23.599917, "o", "\r\u001b[95m⠅⠀\u001b[0m dots12\u001b[K"] +[23.715003, "o", "\r\u001b[95m⢃⠀\u001b[0m dots12\u001b[K"] +[23.831211, "o", "\r\u001b[95m⡃⠀\u001b[0m dots12\u001b[K"] +[23.935734, "o", "\r\u001b[95m⠍⠀\u001b[0m dots12\u001b[K"] +[24.041802, "o", "\r\u001b[95m⢋⠀\u001b[0m dots12\u001b[K"] +[24.145727, "o", "\r\u001b[95m⡋⠀\u001b[0m dots12\u001b[K"] +[24.251049, "o", "\r\u001b[95m⠍⠁\u001b[0m dots12\u001b[K"] +[24.35656, "o", "\r\u001b[95m⢋⠁\u001b[0m dots12\u001b[K"] +[24.458031, "o", "\r\u001b[95m⡋⠁\u001b[0m dots12\u001b[K"] +[24.56907, "o", "\r\u001b[95m⠍⠉\u001b[0m dots12\u001b[K"] +[24.680434, "o", "\r\u001b[95m⠋⠉\u001b[0m dots12\u001b[K"] +[24.795536, "o", "\r\u001b[95m⠋⠉\u001b[0m dots12\u001b[K"] +[24.898581, "o", "\r\u001b[95m⠉⠙\u001b[0m dots12\u001b[K"] +[25.018674, "o", "\r\u001b[95m⠉⠙\u001b[0m dots12\u001b[K"] +[25.126248, "o", "\r\u001b[95m⠉⠩\u001b[0m dots12\u001b[K"] +[25.232879, "o", "\r\u001b[95m⠈⢙\u001b[0m dots12\u001b[K"] +[25.340126, "o", "\r\u001b[95m⠈⡙\u001b[0m dots12\u001b[K"] +[25.451211, "o", "\r\u001b[95m⢈⠩\u001b[0m dots12\u001b[K"] +[25.571182, "o", "\r\u001b[95m⡀⢙\u001b[0m dots12\u001b[K"] +[25.675034, "o", "\r\u001b[95m⠄⡙\u001b[0m dots12\u001b[K"] +[25.775248, "o", "\r\u001b[95m⢂⠩\u001b[0m dots12\u001b[K"] +[25.877506, "o", "\r\u001b[95m⡂⢘\u001b[0m dots12\u001b[K"] +[25.974985, "o", "\r\u001b[95m⠅⡘\u001b[0m dots12\u001b[K"] +[26.080449, "o", "\r\u001b[95m⢃⠨\u001b[0m dots12\u001b[K"] +[26.188416, "o", "\r\u001b[95m⡃⢐\u001b[0m dots12\u001b[K"] +[26.302455, "o", "\r\u001b[95m⠍⡐\u001b[0m dots12\u001b[K"] +[26.410038, "o", "\r\u001b[95m⢋⠠\u001b[0m dots12\u001b[K"] +[26.516381, "o", "\r\u001b[95m⡋⢀\u001b[0m dots12\u001b[K"] +[26.627947, "o", "\r\u001b[95m⠍⡁\u001b[0m dots12\u001b[K"] +[26.735264, "o", "\r\u001b[95m⢋⠁\u001b[0m dots12\u001b[K"] +[26.840505, "o", "\r\u001b[95m⡋⠁\u001b[0m dots12\u001b[K"] +[26.943341, "o", "\r\u001b[95m⠍⠉\u001b[0m dots12\u001b[K"] +[27.069093, "o", "\r\u001b[95m⠋⠉\u001b[0m dots12\u001b[K"] +[27.181082, "o", "\r\u001b[95m⠋⠉\u001b[0m dots12\u001b[K"] +[27.286769, "o", "\r\u001b[95m⠉⠙\u001b[0m dots12\u001b[K"] +[27.390786, "o", "\r\u001b[95m⠉⠙\u001b[0m dots12\u001b[K"] +[27.490075, "o", "\r\u001b[95m⠉⠩\u001b[0m dots12\u001b[K"] +[27.596073, "o", "\r\u001b[95m⠈⢙\u001b[0m dots12\u001b[K"] +[27.70381, "o", "\r\u001b[95m⠈⡙\u001b[0m dots12\u001b[K"] +[27.815048, "o", "\r\u001b[95m⠈⠩\u001b[0m dots12\u001b[K"] +[27.915761, "o", "\r\u001b[95m⠀⢙\u001b[0m dots12\u001b[K"] +[28.073967, "o", "\r\u001b[37m-\u001b[0m line\u001b[K"] +[28.247426, "o", "\r\u001b[37m\\\u001b[0m line\u001b[K"] +[28.405888, "o", "\r\u001b[37m|\u001b[0m line\u001b[K"] +[28.564617, "o", "\r\u001b[37m/\u001b[0m line\u001b[K"] +[28.716951, "o", "\r\u001b[37m-\u001b[0m line\u001b[K"] +[28.866895, "o", "\r\u001b[37m\\\u001b[0m line\u001b[K"] +[29.016902, "o", "\r\u001b[37m|\u001b[0m line\u001b[K"] +[29.167176, "o", "\r\u001b[37m/\u001b[0m line\u001b[K"] +[29.318533, "o", "\r\u001b[37m-\u001b[0m line\u001b[K"] +[29.473865, "o", "\r\u001b[37m\\\u001b[0m line\u001b[K"] +[29.634328, "o", "\r\u001b[37m|\u001b[0m line\u001b[K"] +[29.791075, "o", "\r\u001b[37m/\u001b[0m line\u001b[K"] +[29.946948, "o", "\r\u001b[37m-\u001b[0m line\u001b[K"] +[30.177291, "o", "\r\u001b[97m⠂\u001b[0m line2\u001b[K"] +[30.305936, "o", "\r\u001b[97m-\u001b[0m line2\u001b[K"] +[30.431217, "o", "\r\u001b[97m–\u001b[0m line2\u001b[K"] +[30.561001, "o", "\r\u001b[97m—\u001b[0m line2\u001b[K"] +[30.681796, "o", "\r\u001b[97m–\u001b[0m line2\u001b[K"] +[30.805413, "o", "\r\u001b[97m-\u001b[0m line2\u001b[K"] +[30.938587, "o", "\r\u001b[97m⠂\u001b[0m line2\u001b[K"] +[31.071451, "o", "\r\u001b[97m-\u001b[0m line2\u001b[K"] +[31.191281, "o", "\r\u001b[97m–\u001b[0m line2\u001b[K"] +[31.318383, "o", "\r\u001b[97m—\u001b[0m line2\u001b[K"] +[31.446375, "o", "\r\u001b[97m–\u001b[0m line2\u001b[K"] +[31.584207, "o", "\r\u001b[97m-\u001b[0m line2\u001b[K"] +[31.722659, "o", "\r\u001b[97m⠂\u001b[0m line2\u001b[K"] +[31.852126, "o", "\r\u001b[97m-\u001b[0m line2\u001b[K"] +[32.020763, "o", "\r\u001b[34m┤\u001b[0m pipe\u001b[K"] +[32.144649, "o", "\r\u001b[34m┘\u001b[0m pipe\u001b[K"] +[32.268161, "o", "\r\u001b[34m┴\u001b[0m pipe\u001b[K"] +[32.389548, "o", "\r\u001b[34m└\u001b[0m pipe\u001b[K"] +[32.509912, "o", "\r\u001b[34m├\u001b[0m pipe\u001b[K"] +[32.637953, "o", "\r\u001b[34m┌\u001b[0m pipe\u001b[K"] +[32.766576, "o", "\r\u001b[34m┬\u001b[0m pipe\u001b[K"] +[32.888074, "o", "\r\u001b[34m┐\u001b[0m pipe\u001b[K"] +[33.011122, "o", "\r\u001b[34m┤\u001b[0m pipe\u001b[K"] +[33.136128, "o", "\r\u001b[34m┘\u001b[0m pipe\u001b[K"] +[33.275719, "o", "\r\u001b[34m┴\u001b[0m pipe\u001b[K"] +[33.409919, "o", "\r\u001b[34m└\u001b[0m pipe\u001b[K"] +[33.533998, "o", "\r\u001b[34m├\u001b[0m pipe\u001b[K"] +[33.660849, "o", "\r\u001b[34m┌\u001b[0m pipe\u001b[K"] +[33.785247, "o", "\r\u001b[34m┬\u001b[0m pipe\u001b[K"] +[33.909907, "o", "\r\u001b[34m┐\u001b[0m pipe\u001b[K"] +[34.094469, "o", "\r\u001b[32m. \u001b[0m simpleDots\u001b[K"] +[34.53485, "o", "\r\u001b[32m.. \u001b[0m simpleDots\u001b[K"] +[34.954009, "o", "\r\u001b[32m...\u001b[0m simpleDots\u001b[K"] +[35.379109, "o", "\r\u001b[32m \u001b[0m simpleDots\u001b[K"] +[35.807607, "o", "\r\u001b[32m. \u001b[0m simpleDots\u001b[K"] +[36.242179, "o", "\r\u001b[32m.. \u001b[0m simpleDots\u001b[K"] +[36.666224, "o", "\r\u001b[32m...\u001b[0m simpleDots\u001b[K"] +[37.101297, "o", "\r\u001b[32m \u001b[0m simpleDots\u001b[K"] +[37.528737, "o", "\r\u001b[32m. \u001b[0m simpleDots\u001b[K"] +[37.947221, "o", "\r\u001b[32m.. \u001b[0m simpleDots\u001b[K"] +[38.371432, "o", "\r\u001b[32m...\u001b[0m simpleDots\u001b[K"] +[38.805148, "o", "\r\u001b[32m \u001b[0m simpleDots\u001b[K"] +[39.312058, "o", "\r\u001b[92m. \u001b[0m simpleDotsScrolling\u001b[K"] +[39.529471, "o", "\r\u001b[92m.. \u001b[0m simpleDotsScrolling\u001b[K"] +[39.753876, "o", "\r\u001b[92m...\u001b[0m simpleDotsScrolling\u001b[K"] +[39.982641, "o", "\r\u001b[92m ..\u001b[0m simpleDotsScrolling\u001b[K"] +[40.212932, "o", "\r\u001b[92m .\u001b[0m simpleDotsScrolling\u001b[K"] +[40.446968, "o", "\r\u001b[92m \u001b[0m simpleDotsScrolling\u001b[K"] +[40.689446, "o", "\r\u001b[92m. \u001b[0m simpleDotsScrolling\u001b[K"] +[40.904691, "o", "\r\u001b[92m.. \u001b[0m simpleDotsScrolling\u001b[K"] +[41.124624, "o", "\r\u001b[92m...\u001b[0m simpleDotsScrolling\u001b[K"] +[41.358636, "o", "\r\u001b[92m ..\u001b[0m simpleDotsScrolling\u001b[K"] +[41.586782, "o", "\r\u001b[92m .\u001b[0m simpleDotsScrolling\u001b[K"] +[41.81847, "o", "\r\u001b[92m \u001b[0m simpleDotsScrolling\u001b[K"] +[42.139513, "o", "\r\u001b[33m✶\u001b[0m star\u001b[K"] +[42.234987, "o", "\r\u001b[33m✸\u001b[0m star\u001b[K"] +[42.323472, "o", "\r\u001b[33m✹\u001b[0m star\u001b[K"] +[42.413941, "o", "\r\u001b[33m✺\u001b[0m star\u001b[K"] +[42.506663, "o", "\r\u001b[33m✹\u001b[0m star\u001b[K"] +[42.602899, "o", "\r\u001b[33m✷\u001b[0m star\u001b[K"] +[42.699898, "o", "\r\u001b[33m✶\u001b[0m star\u001b[K"] +[42.800491, "o", "\r\u001b[33m✸\u001b[0m star\u001b[K"] +[42.892793, "o", "\r\u001b[33m✹\u001b[0m star\u001b[K"] +[43.047041, "o", "\r\u001b[93m+\u001b[0m star2\u001b[K"] +[43.148001, "o", "\r\u001b[93mx\u001b[0m star2\u001b[K"] +[43.255523, "o", "\r\u001b[93m*\u001b[0m star2\u001b[K"] +[43.362062, "o", "\r\u001b[93m+\u001b[0m star2\u001b[K"] +[43.463572, "o", "\r\u001b[93mx\u001b[0m star2\u001b[K"] +[43.561524, "o", "\r\u001b[93m*\u001b[0m star2\u001b[K"] +[43.675306, "o", "\r\u001b[93m+\u001b[0m star2\u001b[K"] +[43.780039, "o", "\r\u001b[93mx\u001b[0m star2\u001b[K"] +[43.879677, "o", "\r\u001b[93m*\u001b[0m star2\u001b[K"] +[44.032328, "o", "\r\u001b[36m_\u001b[0m flip\u001b[K"] +[44.128644, "o", "\r\u001b[36m_\u001b[0m flip\u001b[K"] +[44.226131, "o", "\r\u001b[36m_\u001b[0m flip\u001b[K"] +[44.315929, "o", "\r\u001b[36m-\u001b[0m flip\u001b[K"] +[44.413427, "o", "\r\u001b[36m`\u001b[0m flip\u001b[K"] +[44.503292, "o", "\r\u001b[36m`\u001b[0m flip\u001b[K"] +[44.594492, "o", "\r\u001b[36m'\u001b[0m flip\u001b[K"] +[44.688664, "o", "\r\u001b[36m´\u001b[0m flip\u001b[K"] +[44.788022, "o", "\r\u001b[36m-\u001b[0m flip\u001b[K"] +[44.880451, "o", "\r\u001b[36m_\u001b[0m flip\u001b[K"] +[45.03555, "o", "\r\u001b[31m☱\u001b[0m hamburger\u001b[K"] +[45.159935, "o", "\r\u001b[31m☲\u001b[0m hamburger\u001b[K"] +[45.289343, "o", "\r\u001b[31m☴\u001b[0m hamburger\u001b[K"] +[45.416171, "o", "\r\u001b[31m☱\u001b[0m hamburger\u001b[K"] +[45.546319, "o", "\r\u001b[31m☲\u001b[0m hamburger\u001b[K"] +[45.672733, "o", "\r\u001b[31m☴\u001b[0m hamburger\u001b[K"] +[45.802553, "o", "\r\u001b[31m☱\u001b[0m hamburger\u001b[K"] +[45.92316, "o", "\r\u001b[31m☲\u001b[0m hamburger\u001b[K"] +[46.115894, "o", "\r\u001b[34m▁\u001b[0m growVertical\u001b[K"] +[46.261914, "o", "\r\u001b[34m▃\u001b[0m growVertical\u001b[K"] +[46.402949, "o", "\r\u001b[34m▄\u001b[0m growVertical\u001b[K"] +[46.551728, "o", "\r\u001b[34m▅\u001b[0m growVertical\u001b[K"] +[46.711108, "o", "\r\u001b[34m▆\u001b[0m growVertical\u001b[K"] +[46.859958, "o", "\r\u001b[34m▇\u001b[0m growVertical\u001b[K"] +[47.004278, "o", "\r\u001b[34m▆\u001b[0m growVertical\u001b[K"] +[47.145426, "o", "\r\u001b[34m▅\u001b[0m growVertical\u001b[K"] +[47.288755, "o", "\r\u001b[34m▄\u001b[0m growVertical\u001b[K"] +[47.429169, "o", "\r\u001b[34m▃\u001b[0m growVertical\u001b[K"] +[47.578386, "o", "\r\u001b[34m▁\u001b[0m growVertical\u001b[K"] +[47.729582, "o", "\r\u001b[34m▃\u001b[0m growVertical\u001b[K"] +[47.873911, "o", "\r\u001b[34m▄\u001b[0m growVertical\u001b[K"] +[48.022595, "o", "\r\u001b[34m▅\u001b[0m growVertical\u001b[K"] +[48.174179, "o", "\r\u001b[34m▆\u001b[0m growVertical\u001b[K"] +[48.331347, "o", "\r\u001b[34m▇\u001b[0m growVertical\u001b[K"] +[48.481228, "o", "\r\u001b[34m▆\u001b[0m growVertical\u001b[K"] +[48.63517, "o", "\r\u001b[34m▅\u001b[0m growVertical\u001b[K"] +[48.79531, "o", "\r\u001b[34m▄\u001b[0m growVertical\u001b[K"] +[48.942419, "o", "\r\u001b[34m▃\u001b[0m growVertical\u001b[K"] +[49.135422, "o", "\r\u001b[94m▏\u001b[0m growHorizontal\u001b[K"] +[49.277675, "o", "\r\u001b[94m▎\u001b[0m growHorizontal\u001b[K"] +[49.420104, "o", "\r\u001b[94m▍\u001b[0m growHorizontal\u001b[K"] +[49.571635, "o", "\r\u001b[94m▌\u001b[0m growHorizontal\u001b[K"] +[49.714029, "o", "\r\u001b[94m▋\u001b[0m growHorizontal\u001b[K"] +[49.859627, "o", "\r\u001b[94m▊\u001b[0m growHorizontal\u001b[K"] +[50.004666, "o", "\r\u001b[94m▉\u001b[0m growHorizontal\u001b[K"] +[50.147291, "o", "\r\u001b[94m▊\u001b[0m growHorizontal\u001b[K"] +[50.287595, "o", "\r\u001b[94m▋\u001b[0m growHorizontal\u001b[K"] +[50.420451, "o", "\r\u001b[94m▌\u001b[0m growHorizontal\u001b[K"] +[50.563676, "o", "\r\u001b[94m▍\u001b[0m growHorizontal\u001b[K"] +[50.708514, "o", "\r\u001b[94m▎\u001b[0m growHorizontal\u001b[K"] +[50.858197, "o", "\r\u001b[94m▏\u001b[0m growHorizontal\u001b[K"] +[51.061105, "o", "\r\u001b[35m \u001b[0m balloon\u001b[K"] +[51.233728, "o", "\r\u001b[35m.\u001b[0m balloon\u001b[K"] +[51.411927, "o", "\r\u001b[35mo\u001b[0m balloon\u001b[K"] +[51.574959, "o", "\r\u001b[35mO\u001b[0m balloon\u001b[K"] +[51.749099, "o", "\r\u001b[35m@\u001b[0m balloon\u001b[K"] +[51.912683, "o", "\r\u001b[35m*\u001b[0m balloon\u001b[K"] +[52.0877, "o", "\r\u001b[35m \u001b[0m balloon\u001b[K"] +[52.244201, "o", "\r\u001b[35m \u001b[0m balloon\u001b[K"] +[52.415884, "o", "\r\u001b[35m.\u001b[0m balloon\u001b[K"] +[52.580913, "o", "\r\u001b[35mo\u001b[0m balloon\u001b[K"] +[52.758322, "o", "\r\u001b[35mO\u001b[0m balloon\u001b[K"] +[52.920925, "o", "\r\u001b[35m@\u001b[0m balloon\u001b[K"] +[53.153049, "o", "\r\u001b[95m.\u001b[0m balloon2\u001b[K"] +[53.3145, "o", "\r\u001b[95mo\u001b[0m balloon2\u001b[K"] +[53.46075, "o", "\r\u001b[95mO\u001b[0m balloon2\u001b[K"] +[53.603789, "o", "\r\u001b[95m°\u001b[0m balloon2\u001b[K"] +[53.742777, "o", "\r\u001b[95mO\u001b[0m balloon2\u001b[K"] +[53.891033, "o", "\r\u001b[95mo\u001b[0m balloon2\u001b[K"] +[54.032724, "o", "\r\u001b[95m.\u001b[0m balloon2\u001b[K"] +[54.178918, "o", "\r\u001b[95m.\u001b[0m balloon2\u001b[K"] +[54.323103, "o", "\r\u001b[95mo\u001b[0m balloon2\u001b[K"] +[54.463134, "o", "\r\u001b[95mO\u001b[0m balloon2\u001b[K"] +[54.611476, "o", "\r\u001b[95m°\u001b[0m balloon2\u001b[K"] +[54.761577, "o", "\r\u001b[95mO\u001b[0m balloon2\u001b[K"] +[54.909482, "o", "\r\u001b[95mo\u001b[0m balloon2\u001b[K"] +[55.108075, "o", "\r\u001b[37m▓\u001b[0m noise\u001b[K"] +[55.228076, "o", "\r\u001b[37m▒\u001b[0m noise\u001b[K"] +[55.364418, "o", "\r\u001b[37m░\u001b[0m noise\u001b[K"] +[55.486669, "o", "\r\u001b[37m▓\u001b[0m noise\u001b[K"] +[55.610437, "o", "\r\u001b[37m▒\u001b[0m noise\u001b[K"] +[55.743791, "o", "\r\u001b[37m░\u001b[0m noise\u001b[K"] +[55.87372, "o", "\r\u001b[37m▓\u001b[0m noise\u001b[K"] +[56.052135, "o", "\r\u001b[32m⠁\u001b[0m bounce\u001b[K"] +[56.193857, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[56.338951, "o", "\r\u001b[32m⠄\u001b[0m bounce\u001b[K"] +[56.481923, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[56.62, "o", "\r\u001b[32m⠁\u001b[0m bounce\u001b[K"] +[56.758434, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[56.896872, "o", "\r\u001b[32m⠄\u001b[0m bounce\u001b[K"] +[57.037726, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[57.200428, "o", "\r\u001b[32m⠁\u001b[0m bounce\u001b[K"] +[57.354202, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[57.495633, "o", "\r\u001b[32m⠄\u001b[0m bounce\u001b[K"] +[57.632037, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[57.785454, "o", "\r\u001b[32m⠁\u001b[0m bounce\u001b[K"] +[57.931861, "o", "\r\u001b[32m⠂\u001b[0m bounce\u001b[K"] +[58.14434, "o", "\r\u001b[31m▖\u001b[0m boxBounce\u001b[K"] +[58.29111, "o", "\r\u001b[31m▘\u001b[0m boxBounce\u001b[K"] +[58.433318, "o", "\r\u001b[31m▝\u001b[0m boxBounce\u001b[K"] +[58.581573, "o", "\r\u001b[31m▗\u001b[0m boxBounce\u001b[K"] +[58.7309, "o", "\r\u001b[31m▖\u001b[0m boxBounce\u001b[K"] +[58.872858, "o", "\r\u001b[31m▘\u001b[0m boxBounce\u001b[K"] +[59.021947, "o", "\r\u001b[31m▝\u001b[0m boxBounce\u001b[K"] +[59.1787, "o", "\r\u001b[31m▗\u001b[0m boxBounce\u001b[K"] +[59.329643, "o", "\r\u001b[31m▖\u001b[0m boxBounce\u001b[K"] +[59.475183, "o", "\r\u001b[31m▘\u001b[0m boxBounce\u001b[K"] +[59.620163, "o", "\r\u001b[31m▝\u001b[0m boxBounce\u001b[K"] +[59.763336, "o", "\r\u001b[31m▗\u001b[0m boxBounce\u001b[K"] +[59.899407, "o", "\r\u001b[31m▖\u001b[0m boxBounce\u001b[K"] +[60.09992, "o", "\r\u001b[91m▌\u001b[0m boxBounce2\u001b[K"] +[60.23125, "o", "\r\u001b[91m▀\u001b[0m boxBounce2\u001b[K"] +[60.359693, "o", "\r\u001b[91m▐\u001b[0m boxBounce2\u001b[K"] +[60.483684, "o", "\r\u001b[91m▄\u001b[0m boxBounce2\u001b[K"] +[60.607021, "o", "\r\u001b[91m▌\u001b[0m boxBounce2\u001b[K"] +[60.734734, "o", "\r\u001b[91m▀\u001b[0m boxBounce2\u001b[K"] +[60.864756, "o", "\r\u001b[91m▐\u001b[0m boxBounce2\u001b[K"] +[60.984592, "o", "\r\u001b[91m▄\u001b[0m boxBounce2\u001b[K"] +[61.111801, "o", "\r\u001b[91m▌\u001b[0m boxBounce2\u001b[K"] +[61.248497, "o", "\r\u001b[91m▀\u001b[0m boxBounce2\u001b[K"] +[61.370763, "o", "\r\u001b[91m▐\u001b[0m boxBounce2\u001b[K"] +[61.496353, "o", "\r\u001b[91m▄\u001b[0m boxBounce2\u001b[K"] +[61.625051, "o", "\r\u001b[91m▌\u001b[0m boxBounce2\u001b[K"] +[61.756371, "o", "\r\u001b[91m▀\u001b[0m boxBounce2\u001b[K"] +[61.888035, "o", "\r\u001b[91m▐\u001b[0m boxBounce2\u001b[K"] +[62.080848, "o", "\r\u001b[33m◢\u001b[0m triangle\u001b[K"] +[62.15023, "o", "\r\u001b[33m◣\u001b[0m triangle\u001b[K"] +[62.220776, "o", "\r\u001b[33m◤\u001b[0m triangle\u001b[K"] +[62.29558, "o", "\r\u001b[33m◥\u001b[0m triangle\u001b[K"] +[62.373166, "o", "\r\u001b[33m◢\u001b[0m triangle\u001b[K"] +[62.449757, "o", "\r\u001b[33m◣\u001b[0m triangle\u001b[K"] +[62.519876, "o", "\r\u001b[33m◤\u001b[0m triangle\u001b[K"] +[62.589868, "o", "\r\u001b[33m◥\u001b[0m triangle\u001b[K"] +[62.665231, "o", "\r\u001b[33m◢\u001b[0m triangle\u001b[K"] +[62.738738, "o", "\r\u001b[33m◣\u001b[0m triangle\u001b[K"] +[62.811492, "o", "\r\u001b[33m◤\u001b[0m triangle\u001b[K"] +[62.881787, "o", "\r\u001b[33m◥\u001b[0m triangle\u001b[K"] +[62.950435, "o", "\r\u001b[33m◢\u001b[0m triangle\u001b[K"] +[63.081209, "o", "\r\u001b[36m◜\u001b[0m arc\u001b[K"] +[63.203464, "o", "\r\u001b[36m◠\u001b[0m arc\u001b[K"] +[63.328703, "o", "\r\u001b[36m◝\u001b[0m arc\u001b[K"] +[63.463653, "o", "\r\u001b[36m◞\u001b[0m arc\u001b[K"] +[63.586683, "o", "\r\u001b[36m◡\u001b[0m arc\u001b[K"] +[63.719117, "o", "\r\u001b[36m◟\u001b[0m arc\u001b[K"] +[63.84856, "o", "\r\u001b[36m◜\u001b[0m arc\u001b[K"] +[63.971257, "o", "\r\u001b[36m◠\u001b[0m arc\u001b[K"] +[64.106591, "o", "\r\u001b[36m◝\u001b[0m arc\u001b[K"] +[64.229482, "o", "\r\u001b[36m◞\u001b[0m arc\u001b[K"] +[64.346317, "o", "\r\u001b[36m◡\u001b[0m arc\u001b[K"] +[64.4727, "o", "\r\u001b[36m◟\u001b[0m arc\u001b[K"] +[64.604144, "o", "\r\u001b[36m◜\u001b[0m arc\u001b[K"] +[64.740776, "o", "\r\u001b[36m◠\u001b[0m arc\u001b[K"] +[64.874243, "o", "\r\u001b[36m◝\u001b[0m arc\u001b[K"] +[65.049744, "o", "\r\u001b[34m◡\u001b[0m circle\u001b[K"] +[65.188159, "o", "\r\u001b[34m⊙\u001b[0m circle\u001b[K"] +[65.33846, "o", "\r\u001b[34m◠\u001b[0m circle\u001b[K"] +[65.485196, "o", "\r\u001b[34m◡\u001b[0m circle\u001b[K"] +[65.635791, "o", "\r\u001b[34m⊙\u001b[0m circle\u001b[K"] +[65.783357, "o", "\r\u001b[34m◠\u001b[0m circle\u001b[K"] +[65.925346, "o", "\r\u001b[34m◡\u001b[0m circle\u001b[K"] +[66.064817, "o", "\r\u001b[34m⊙\u001b[0m circle\u001b[K"] +[66.203154, "o", "\r\u001b[34m◠\u001b[0m circle\u001b[K"] +[66.352912, "o", "\r\u001b[34m◡\u001b[0m circle\u001b[K"] +[66.503256, "o", "\r\u001b[34m⊙\u001b[0m circle\u001b[K"] +[66.664033, "o", "\r\u001b[34m◠\u001b[0m circle\u001b[K"] +[66.812745, "o", "\r\u001b[34m◡\u001b[0m circle\u001b[K"] +[67.018868, "o", "\r\u001b[35m◰\u001b[0m squareCorners\u001b[K"] +[67.222517, "o", "\r\u001b[35m◳\u001b[0m squareCorners\u001b[K"] +[67.422324, "o", "\r\u001b[35m◲\u001b[0m squareCorners\u001b[K"] +[67.624888, "o", "\r\u001b[35m◱\u001b[0m squareCorners\u001b[K"] +[67.823254, "o", "\r\u001b[35m◰\u001b[0m squareCorners\u001b[K"] +[68.026314, "o", "\r\u001b[35m◳\u001b[0m squareCorners\u001b[K"] +[68.233782, "o", "\r\u001b[35m◲\u001b[0m squareCorners\u001b[K"] +[68.438331, "o", "\r\u001b[35m◱\u001b[0m squareCorners\u001b[K"] +[68.645248, "o", "\r\u001b[35m◰\u001b[0m squareCorners\u001b[K"] +[68.84884, "o", "\r\u001b[35m◳\u001b[0m squareCorners\u001b[K"] +[69.05105, "o", "\r\u001b[35m◲\u001b[0m squareCorners\u001b[K"] +[69.253291, "o", "\r\u001b[35m◱\u001b[0m squareCorners\u001b[K"] +[69.455678, "o", "\r\u001b[35m◰\u001b[0m squareCorners\u001b[K"] +[69.66809, "o", "\r\u001b[35m◳\u001b[0m squareCorners\u001b[K"] +[69.873503, "o", "\r\u001b[35m◲\u001b[0m squareCorners\u001b[K"] +[70.15488, "o", "\r\u001b[32m◴\u001b[0m circleQuarters\u001b[K"] +[70.301801, "o", "\r\u001b[32m◷\u001b[0m circleQuarters\u001b[K"] +[70.454039, "o", "\r\u001b[32m◶\u001b[0m circleQuarters\u001b[K"] +[70.613958, "o", "\r\u001b[32m◵\u001b[0m circleQuarters\u001b[K"] +[70.758618, "o", "\r\u001b[32m◴\u001b[0m circleQuarters\u001b[K"] +[70.906158, "o", "\r\u001b[32m◷\u001b[0m circleQuarters\u001b[K"] +[71.052742, "o", "\r\u001b[32m◶\u001b[0m circleQuarters\u001b[K"] +[71.20911, "o", "\r\u001b[32m◵\u001b[0m circleQuarters\u001b[K"] +[71.370783, "o", "\r\u001b[32m◴\u001b[0m circleQuarters\u001b[K"] +[71.512024, "o", "\r\u001b[32m◷\u001b[0m circleQuarters\u001b[K"] +[71.666408, "o", "\r\u001b[32m◶\u001b[0m circleQuarters\u001b[K"] +[71.819365, "o", "\r\u001b[32m◵\u001b[0m circleQuarters\u001b[K"] +[72.000665, "o", "\r\u001b[31m◐\u001b[0m circleHalves\u001b[K"] +[72.067758, "o", "\r\u001b[31m◓\u001b[0m circleHalves\u001b[K"] +[72.13975, "o", "\r\u001b[31m◑\u001b[0m circleHalves\u001b[K"] +[72.212527, "o", "\r\u001b[31m◒\u001b[0m circleHalves\u001b[K"] +[72.281263, "o", "\r\u001b[31m◐\u001b[0m circleHalves\u001b[K"] +[72.357131, "o", "\r\u001b[31m◓\u001b[0m circleHalves\u001b[K"] +[72.430689, "o", "\r\u001b[31m◑\u001b[0m circleHalves\u001b[K"] +[72.495102, "o", "\r\u001b[31m◒\u001b[0m circleHalves\u001b[K"] +[72.562985, "o", "\r\u001b[31m◐\u001b[0m circleHalves\u001b[K"] +[72.629046, "o", "\r\u001b[31m◓\u001b[0m circleHalves\u001b[K"] +[72.695757, "o", "\r\u001b[31m◑\u001b[0m circleHalves\u001b[K"] +[72.764748, "o", "\r\u001b[31m◒\u001b[0m circleHalves\u001b[K"] +[72.843688, "o", "\r\u001b[31m◐\u001b[0m circleHalves\u001b[K"] +[72.91384, "o", "\r\u001b[31m◓\u001b[0m circleHalves\u001b[K"] +[73.036334, "o", "\r\u001b[37m╫\u001b[0m squish\u001b[K"] +[73.155587, "o", "\r\u001b[37m╪\u001b[0m squish\u001b[K"] +[73.282697, "o", "\r\u001b[37m╫\u001b[0m squish\u001b[K"] +[73.414127, "o", "\r\u001b[37m╪\u001b[0m squish\u001b[K"] +[73.547712, "o", "\r\u001b[37m╫\u001b[0m squish\u001b[K"] +[73.678349, "o", "\r\u001b[37m╪\u001b[0m squish\u001b[K"] +[73.810143, "o", "\r\u001b[37m╫\u001b[0m squish\u001b[K"] +[73.934313, "o", "\r\u001b[37m╪\u001b[0m squish\u001b[K"] +[74.138029, "o", "\r\u001b[34m⊶\u001b[0m toggle\u001b[K"] +[74.422229, "o", "\r\u001b[34m⊷\u001b[0m toggle\u001b[K"] +[74.705775, "o", "\r\u001b[34m⊶\u001b[0m toggle\u001b[K"] +[74.97769, "o", "\r\u001b[34m⊷\u001b[0m toggle\u001b[K"] +[75.251891, "o", "\r\u001b[34m⊶\u001b[0m toggle\u001b[K"] +[75.529358, "o", "\r\u001b[34m⊷\u001b[0m toggle\u001b[K"] +[75.814062, "o", "\r\u001b[34m⊶\u001b[0m toggle\u001b[K"] +[76.179612, "o", "\r\u001b[94m▫\u001b[0m toggle2\u001b[K"] +[76.281235, "o", "\r\u001b[94m▪\u001b[0m toggle2\u001b[K"] +[76.380612, "o", "\r\u001b[94m▫\u001b[0m toggle2\u001b[K"] +[76.487442, "o", "\r\u001b[94m▪\u001b[0m toggle2\u001b[K"] +[76.592264, "o", "\r\u001b[94m▫\u001b[0m toggle2\u001b[K"] +[76.697172, "o", "\r\u001b[94m▪\u001b[0m toggle2\u001b[K"] +[76.799151, "o", "\r\u001b[94m▫\u001b[0m toggle2\u001b[K"] +[76.9017, "o", "\r\u001b[94m▪\u001b[0m toggle2\u001b[K"] +[77.066344, "o", "\r\u001b[36m□\u001b[0m toggle3\u001b[K"] +[77.212374, "o", "\r\u001b[36m■\u001b[0m toggle3\u001b[K"] +[77.371478, "o", "\r\u001b[36m□\u001b[0m toggle3\u001b[K"] +[77.5166, "o", "\r\u001b[36m■\u001b[0m toggle3\u001b[K"] +[77.667443, "o", "\r\u001b[36m□\u001b[0m toggle3\u001b[K"] +[77.817376, "o", "\r\u001b[36m■\u001b[0m toggle3\u001b[K"] +[78.020554, "o", "\r\u001b[96m■\u001b[0m toggle4\u001b[K"] +[78.148648, "o", "\r\u001b[96m□\u001b[0m toggle4\u001b[K"] +[78.273899, "o", "\r\u001b[96m▪\u001b[0m toggle4\u001b[K"] +[78.39428, "o", "\r\u001b[96m▫\u001b[0m toggle4\u001b[K"] +[78.513195, "o", "\r\u001b[96m■\u001b[0m toggle4\u001b[K"] +[78.633827, "o", "\r\u001b[96m□\u001b[0m toggle4\u001b[K"] +[78.760151, "o", "\r\u001b[96m▪\u001b[0m toggle4\u001b[K"] +[78.882046, "o", "\r\u001b[96m▫\u001b[0m toggle4\u001b[K"] +[79.00719, "o", "\r\u001b[96m■\u001b[0m toggle4\u001b[K"] +[79.140113, "o", "\r\u001b[96m□\u001b[0m toggle4\u001b[K"] +[79.26875, "o", "\r\u001b[96m▪\u001b[0m toggle4\u001b[K"] +[79.393921, "o", "\r\u001b[96m▫\u001b[0m toggle4\u001b[K"] +[79.512912, "o", "\r\u001b[96m■\u001b[0m toggle4\u001b[K"] +[79.640911, "o", "\r\u001b[96m□\u001b[0m toggle4\u001b[K"] +[79.776414, "o", "\r\u001b[96m▪\u001b[0m toggle4\u001b[K"] +[79.901303, "o", "\r\u001b[96m▫\u001b[0m toggle4\u001b[K"] +[80.085415, "o", "\r\u001b[32m▮\u001b[0m toggle5\u001b[K"] +[80.218226, "o", "\r\u001b[32m▯\u001b[0m toggle5\u001b[K"] +[80.343418, "o", "\r\u001b[32m▮\u001b[0m toggle5\u001b[K"] +[80.476195, "o", "\r\u001b[32m▯\u001b[0m toggle5\u001b[K"] +[80.620809, "o", "\r\u001b[32m▮\u001b[0m toggle5\u001b[K"] +[80.750311, "o", "\r\u001b[32m▯\u001b[0m toggle5\u001b[K"] +[80.872506, "o", "\r\u001b[32m▮\u001b[0m toggle5\u001b[K"] +[81.068004, "o", "\r\u001b[92mဝ\u001b[0m toggle6\u001b[K"] +[81.386135, "o", "\r\u001b[92m၀\u001b[0m toggle6\u001b[K"] +[81.710203, "o", "\r\u001b[92mဝ\u001b[0m toggle6\u001b[K"] +[82.034287, "o", "\r\u001b[92m၀\u001b[0m toggle6\u001b[K"] +[82.363058, "o", "\r\u001b[92mဝ\u001b[0m toggle6\u001b[K"] +[82.684005, "o", "\r\u001b[92m၀\u001b[0m toggle6\u001b[K"] +[83.062166, "o", "\r\u001b[33m⦾\u001b[0m toggle7\u001b[K"] +[83.161741, "o", "\r\u001b[33m⦿\u001b[0m toggle7\u001b[K"] +[83.274442, "o", "\r\u001b[33m⦾\u001b[0m toggle7\u001b[K"] +[83.374654, "o", "\r\u001b[33m⦿\u001b[0m toggle7\u001b[K"] +[83.475625, "o", "\r\u001b[33m⦾\u001b[0m toggle7\u001b[K"] +[83.582185, "o", "\r\u001b[33m⦿\u001b[0m toggle7\u001b[K"] +[83.696235, "o", "\r\u001b[33m⦾\u001b[0m toggle7\u001b[K"] +[83.807551, "o", "\r\u001b[33m⦿\u001b[0m toggle7\u001b[K"] +[83.910326, "o", "\r\u001b[33m⦾\u001b[0m toggle7\u001b[K"] +[84.069991, "o", "\r\u001b[93m◍\u001b[0m toggle8\u001b[K"] +[84.187841, "o", "\r\u001b[93m◌\u001b[0m toggle8\u001b[K"] +[84.300849, "o", "\r\u001b[93m◍\u001b[0m toggle8\u001b[K"] +[84.41714, "o", "\r\u001b[93m◌\u001b[0m toggle8\u001b[K"] +[84.542752, "o", "\r\u001b[93m◍\u001b[0m toggle8\u001b[K"] +[84.655544, "o", "\r\u001b[93m◌\u001b[0m toggle8\u001b[K"] +[84.775617, "o", "\r\u001b[93m◍\u001b[0m toggle8\u001b[K"] +[84.896126, "o", "\r\u001b[93m◌\u001b[0m toggle8\u001b[K"] +[85.086438, "o", "\r\u001b[31m◉\u001b[0m toggle9\u001b[K"] +[85.215424, "o", "\r\u001b[31m◎\u001b[0m toggle9\u001b[K"] +[85.333032, "o", "\r\u001b[31m◉\u001b[0m toggle9\u001b[K"] +[85.46153, "o", "\r\u001b[31m◎\u001b[0m toggle9\u001b[K"] +[85.601754, "o", "\r\u001b[31m◉\u001b[0m toggle9\u001b[K"] +[85.726462, "o", "\r\u001b[31m◎\u001b[0m toggle9\u001b[K"] +[85.849248, "o", "\r\u001b[31m◉\u001b[0m toggle9\u001b[K"] +[86.025465, "o", "\r\u001b[91m㊂\u001b[0m toggle10\u001b[K"] +[86.14266, "o", "\r\u001b[91m㊀\u001b[0m toggle10\u001b[K"] +[86.268336, "o", "\r\u001b[91m㊁\u001b[0m toggle10\u001b[K"] +[86.395294, "o", "\r\u001b[91m㊂\u001b[0m toggle10\u001b[K"] +[86.521783, "o", "\r\u001b[91m㊀\u001b[0m toggle10\u001b[K"] +[86.641802, "o", "\r\u001b[91m㊁\u001b[0m toggle10\u001b[K"] +[86.763992, "o", "\r\u001b[91m㊂\u001b[0m toggle10\u001b[K"] +[86.893101, "o", "\r\u001b[91m㊀\u001b[0m toggle10\u001b[K"] +[87.079998, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[87.152387, "o", "\r\u001b[35m⧆\u001b[0m toggle11\u001b[K"] +[87.221237, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[87.298407, "o", "\r\u001b[35m⧆\u001b[0m toggle11\u001b[K"] +[87.370021, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[87.43916, "o", "\r\u001b[35m⧆\u001b[0m toggle11\u001b[K"] +[87.514366, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[87.586753, "o", "\r\u001b[35m⧆\u001b[0m toggle11\u001b[K"] +[87.655699, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[87.729872, "o", "\r\u001b[35m⧆\u001b[0m toggle11\u001b[K"] +[87.807482, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[87.880323, "o", "\r\u001b[35m⧆\u001b[0m toggle11\u001b[K"] +[87.953817, "o", "\r\u001b[35m⧇\u001b[0m toggle11\u001b[K"] +[88.094651, "o", "\r\u001b[95m☗\u001b[0m toggle12\u001b[K"] +[88.243667, "o", "\r\u001b[95m☖\u001b[0m toggle12\u001b[K"] +[88.383011, "o", "\r\u001b[95m☗\u001b[0m toggle12\u001b[K"] +[88.522083, "o", "\r\u001b[95m☖\u001b[0m toggle12\u001b[K"] +[88.677939, "o", "\r\u001b[95m☗\u001b[0m toggle12\u001b[K"] +[88.821931, "o", "\r\u001b[95m☖\u001b[0m toggle12\u001b[K"] +[89.029253, "o", "\r\u001b[37m=\u001b[0m toggle13\u001b[K"] +[89.130523, "o", "\r\u001b[37m*\u001b[0m toggle13\u001b[K"] +[89.243439, "o", "\r\u001b[37m-\u001b[0m toggle13\u001b[K"] +[89.345137, "o", "\r\u001b[37m=\u001b[0m toggle13\u001b[K"] +[89.448744, "o", "\r\u001b[37m*\u001b[0m toggle13\u001b[K"] +[89.563489, "o", "\r\u001b[37m-\u001b[0m toggle13\u001b[K"] +[89.666361, "o", "\r\u001b[37m=\u001b[0m toggle13\u001b[K"] +[89.788166, "o", "\r\u001b[37m*\u001b[0m toggle13\u001b[K"] +[89.896072, "o", "\r\u001b[37m-\u001b[0m toggle13\u001b[K"] +[90.064919, "o", "\r\u001b[34m←\u001b[0m arrow\u001b[K"] +[90.193583, "o", "\r\u001b[34m↖\u001b[0m arrow\u001b[K"] +[90.322226, "o", "\r\u001b[34m↑\u001b[0m arrow\u001b[K"] +[90.451985, "o", "\r\u001b[34m↗\u001b[0m arrow\u001b[K"] +[90.58216, "o", "\r\u001b[34m→\u001b[0m arrow\u001b[K"] +[90.711092, "o", "\r\u001b[34m↘\u001b[0m arrow\u001b[K"] +[90.833341, "o", "\r\u001b[34m↓\u001b[0m arrow\u001b[K"] +[90.956398, "o", "\r\u001b[34m↙\u001b[0m arrow\u001b[K"] +[91.081279, "o", "\r\u001b[34m←\u001b[0m arrow\u001b[K"] +[91.223941, "o", "\r\u001b[34m↖\u001b[0m arrow\u001b[K"] +[91.360444, "o", "\r\u001b[34m↑\u001b[0m arrow\u001b[K"] +[91.48488, "o", "\r\u001b[34m↗\u001b[0m arrow\u001b[K"] +[91.612259, "o", "\r\u001b[34m→\u001b[0m arrow\u001b[K"] +[91.73854, "o", "\r\u001b[34m↘\u001b[0m arrow\u001b[K"] +[91.861659, "o", "\r\u001b[34m↓\u001b[0m arrow\u001b[K"] +[92.057226, "o", "\r\u001b[94m⬆️ \u001b[0m arrow2\u001b[K"] +[92.158725, "o", "\r\u001b[94m↗️ \u001b[0m arrow2\u001b[K"] +[92.260312, "o", "\r\u001b[94m➡️ \u001b[0m arrow2\u001b[K"] +[92.366887, "o", "\r\u001b[94m↘️ \u001b[0m arrow2\u001b[K"] +[92.465139, "o", "\r\u001b[94m⬇️ \u001b[0m arrow2\u001b[K"] +[92.569996, "o", "\r\u001b[94m↙️ \u001b[0m arrow2\u001b[K"] +[92.67326, "o", "\r\u001b[94m⬅️ \u001b[0m arrow2\u001b[K"] +[92.770318, "o", "\r\u001b[94m↖️ \u001b[0m arrow2\u001b[K"] +[92.876963, "o", "\r\u001b[94m⬆️ \u001b[0m arrow2\u001b[K"] +[92.981768, "o", "\r\u001b[94m↗️ \u001b[0m arrow2\u001b[K"] +[93.091783, "o", "\r\u001b[94m➡️ \u001b[0m arrow2\u001b[K"] +[93.198024, "o", "\r\u001b[94m↘️ \u001b[0m arrow2\u001b[K"] +[93.314985, "o", "\r\u001b[94m⬇️ \u001b[0m arrow2\u001b[K"] +[93.430676, "o", "\r\u001b[94m↙️ \u001b[0m arrow2\u001b[K"] +[93.533894, "o", "\r\u001b[94m⬅️ \u001b[0m arrow2\u001b[K"] +[93.64379, "o", "\r\u001b[94m↖️ \u001b[0m arrow2\u001b[K"] +[93.7453, "o", "\r\u001b[94m⬆️ \u001b[0m arrow2\u001b[K"] +[93.851256, "o", "\r\u001b[94m↗️ \u001b[0m arrow2\u001b[K"] +[94.012015, "o", "\r\u001b[36m▹▹▹▹▹\u001b[0m arrow3\u001b[K"] +[94.152845, "o", "\r\u001b[36m▸▹▹▹▹\u001b[0m arrow3\u001b[K"] +[94.29602, "o", "\r\u001b[36m▹▸▹▹▹\u001b[0m arrow3\u001b[K"] +[94.437316, "o", "\r\u001b[36m▹▹▸▹▹\u001b[0m arrow3\u001b[K"] +[94.584782, "o", "\r\u001b[36m▹▹▹▸▹\u001b[0m arrow3\u001b[K"] +[94.720848, "o", "\r\u001b[36m▹▹▹▹▸\u001b[0m arrow3\u001b[K"] +[94.868312, "o", "\r\u001b[36m▹▹▹▹▹\u001b[0m arrow3\u001b[K"] +[95.013306, "o", "\r\u001b[36m▸▹▹▹▹\u001b[0m arrow3\u001b[K"] +[95.151535, "o", "\r\u001b[36m▹▸▹▹▹\u001b[0m arrow3\u001b[K"] +[95.287586, "o", "\r\u001b[36m▹▹▸▹▹\u001b[0m arrow3\u001b[K"] +[95.439261, "o", "\r\u001b[36m▹▹▹▸▹\u001b[0m arrow3\u001b[K"] +[95.580805, "o", "\r\u001b[36m▹▹▹▹▸\u001b[0m arrow3\u001b[K"] +[95.731681, "o", "\r\u001b[36m▹▹▹▹▹\u001b[0m arrow3\u001b[K"] +[95.871441, "o", "\r\u001b[36m▸▹▹▹▹\u001b[0m arrow3\u001b[K"] +[96.082641, "o", "\r\u001b[32m[ ]\u001b[0m bouncingBar\u001b[K"] +[96.184519, "o", "\r\u001b[32m[= ]\u001b[0m bouncingBar\u001b[K"] +[96.289306, "o", "\r\u001b[32m[== ]\u001b[0m bouncingBar\u001b[K"] +[96.396218, "o", "\r\u001b[32m[=== ]\u001b[0m bouncingBar\u001b[K"] +[96.509128, "o", "\r\u001b[32m[====]\u001b[0m bouncingBar\u001b[K"] +[96.619912, "o", "\r\u001b[32m[ ===]\u001b[0m bouncingBar\u001b[K"] +[96.724707, "o", "\r\u001b[32m[ ==]\u001b[0m bouncingBar\u001b[K"] +[96.825707, "o", "\r\u001b[32m[ =]\u001b[0m bouncingBar\u001b[K"] +[96.930114, "o", "\r\u001b[32m[ ]\u001b[0m bouncingBar\u001b[K"] +[97.029362, "o", "\r\u001b[32m[ =]\u001b[0m bouncingBar\u001b[K"] +[97.135305, "o", "\r\u001b[32m[ ==]\u001b[0m bouncingBar\u001b[K"] +[97.237956, "o", "\r\u001b[32m[ ===]\u001b[0m bouncingBar\u001b[K"] +[97.339797, "o", "\r\u001b[32m[====]\u001b[0m bouncingBar\u001b[K"] +[97.443837, "o", "\r\u001b[32m[=== ]\u001b[0m bouncingBar\u001b[K"] +[97.543729, "o", "\r\u001b[32m[== ]\u001b[0m bouncingBar\u001b[K"] +[97.647627, "o", "\r\u001b[32m[= ]\u001b[0m bouncingBar\u001b[K"] +[97.76964, "o", "\r\u001b[32m[ ]\u001b[0m bouncingBar\u001b[K"] +[97.864053, "o", "\r\u001b[32m[= ]\u001b[0m bouncingBar\u001b[K"] +[98.02498, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.125361, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.226083, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.325789, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.438225, "o", "\r\u001b[92m( ●)\u001b[0m bouncingBall\u001b[K"] +[98.538402, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.638762, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.747067, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.852949, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[98.958233, "o", "\r\u001b[92m(● )\u001b[0m bouncingBall\u001b[K"] +[99.064528, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.184332, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.293101, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.395279, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.495381, "o", "\r\u001b[92m( ●)\u001b[0m bouncingBall\u001b[K"] +[99.596444, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.701117, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.813779, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[99.918202, "o", "\r\u001b[92m( ● )\u001b[0m bouncingBall\u001b[K"] +[100.049956, "o", "\r\u001b[33m😄 \u001b[0m smiley\u001b[K"] +[100.265649, "o", "\r\u001b[33m😝 \u001b[0m smiley\u001b[K"] +[100.498167, "o", "\r\u001b[33m😄 \u001b[0m smiley\u001b[K"] +[100.725598, "o", "\r\u001b[33m😝 \u001b[0m smiley\u001b[K"] +[100.954882, "o", "\r\u001b[33m😄 \u001b[0m smiley\u001b[K"] +[101.178967, "o", "\r\u001b[33m😝 \u001b[0m smiley\u001b[K"] +[101.404362, "o", "\r\u001b[33m😄 \u001b[0m smiley\u001b[K"] +[101.629041, "o", "\r\u001b[33m😝 \u001b[0m smiley\u001b[K"] +[101.849718, "o", "\r\u001b[33m😄 \u001b[0m smiley\u001b[K"] +[102.136048, "o", "\r\u001b[93m🙈 \u001b[0m monkey\u001b[K"] +[102.458319, "o", "\r\u001b[93m🙈 \u001b[0m monkey\u001b[K"] +[102.800893, "o", "\r\u001b[93m🙉 \u001b[0m monkey\u001b[K"] +[103.127703, "o", "\r\u001b[93m🙊 \u001b[0m monkey\u001b[K"] +[103.453429, "o", "\r\u001b[93m🙈 \u001b[0m monkey\u001b[K"] +[103.787173, "o", "\r\u001b[93m🙈 \u001b[0m monkey\u001b[K"] +[104.111853, "o", "\r\u001b[93m🙉 \u001b[0m monkey\u001b[K"] +[104.437042, "o", "\r\u001b[93m🙊 \u001b[0m monkey\u001b[K"] +[104.772163, "o", "\r\u001b[93m🙈 \u001b[0m monkey\u001b[K"] +[105.107335, "o", "\r\u001b[93m🙈 \u001b[0m monkey\u001b[K"] +[105.437695, "o", "\r\u001b[93m🙉 \u001b[0m monkey\u001b[K"] +[105.770116, "o", "\r\u001b[93m🙊 \u001b[0m monkey\u001b[K"] +[106.170191, "o", "\r\u001b[95m💛 \u001b[0m hearts\u001b[K"] +[106.288912, "o", "\r\u001b[95m💙 \u001b[0m hearts\u001b[K"] +[106.411638, "o", "\r\u001b[95m💜 \u001b[0m hearts\u001b[K"] +[106.530797, "o", "\r\u001b[95m💚 \u001b[0m hearts\u001b[K"] +[106.662239, "o", "\r\u001b[95m❤️ \u001b[0m hearts\u001b[K"] +[106.790103, "o", "\r\u001b[95m💛 \u001b[0m hearts\u001b[K"] +[106.916515, "o", "\r\u001b[95m💙 \u001b[0m hearts\u001b[K"] +[107.044, "o", "\r\u001b[95m💜 \u001b[0m hearts\u001b[K"] +[107.172014, "o", "\r\u001b[95m💚 \u001b[0m hearts\u001b[K"] +[107.298041, "o", "\r\u001b[95m❤️ \u001b[0m hearts\u001b[K"] +[107.424945, "o", "\r\u001b[95m💛 \u001b[0m hearts\u001b[K"] +[107.551133, "o", "\r\u001b[95m💙 \u001b[0m hearts\u001b[K"] +[107.672755, "o", "\r\u001b[95m💜 \u001b[0m hearts\u001b[K"] +[107.804279, "o", "\r\u001b[95m💚 \u001b[0m hearts\u001b[K"] +[107.936151, "o", "\r\u001b[95m❤️ \u001b[0m hearts\u001b[K"] +[108.135908, "o", "\r\u001b[34m🕛 \u001b[0m clock\u001b[K"] +[108.261476, "o", "\r\u001b[34m🕐 \u001b[0m clock\u001b[K"] +[108.39034, "o", "\r\u001b[34m🕑 \u001b[0m clock\u001b[K"] +[108.517254, "o", "\r\u001b[34m🕒 \u001b[0m clock\u001b[K"] +[108.645904, "o", "\r\u001b[34m🕓 \u001b[0m clock\u001b[K"] +[108.765682, "o", "\r\u001b[34m🕔 \u001b[0m clock\u001b[K"] +[108.904028, "o", "\r\u001b[34m🕕 \u001b[0m clock\u001b[K"] +[109.035453, "o", "\r\u001b[34m🕖 \u001b[0m clock\u001b[K"] +[109.171363, "o", "\r\u001b[34m🕗 \u001b[0m clock\u001b[K"] +[109.291322, "o", "\r\u001b[34m🕘 \u001b[0m clock\u001b[K"] +[109.403969, "o", "\r\u001b[34m🕙 \u001b[0m clock\u001b[K"] +[109.524966, "o", "\r\u001b[34m🕚 \u001b[0m clock\u001b[K"] +[109.658898, "o", "\r\u001b[34m🕛 \u001b[0m clock\u001b[K"] +[109.799452, "o", "\r\u001b[34m🕐 \u001b[0m clock\u001b[K"] +[109.92246, "o", "\r\u001b[34m🕑 \u001b[0m clock\u001b[K"] +[110.111017, "o", "\r\u001b[94m🌍 \u001b[0m earth\u001b[K"] +[110.313318, "o", "\r\u001b[94m🌎 \u001b[0m earth\u001b[K"] +[110.531805, "o", "\r\u001b[94m🌏 \u001b[0m earth\u001b[K"] +[110.751826, "o", "\r\u001b[94m🌍 \u001b[0m earth\u001b[K"] +[110.977184, "o", "\r\u001b[94m🌎 \u001b[0m earth\u001b[K"] +[111.196495, "o", "\r\u001b[94m🌏 \u001b[0m earth\u001b[K"] +[111.407423, "o", "\r\u001b[94m🌍 \u001b[0m earth\u001b[K"] +[111.620595, "o", "\r\u001b[94m🌎 \u001b[0m earth\u001b[K"] +[111.822762, "o", "\r\u001b[94m🌏 \u001b[0m earth\u001b[K"] +[112.094959, "o", "\r\u001b[36m🌑 \u001b[0m moon\u001b[K"] +[112.201577, "o", "\r\u001b[36m🌒 \u001b[0m moon\u001b[K"] +[112.308966, "o", "\r\u001b[36m🌓 \u001b[0m moon\u001b[K"] +[112.413782, "o", "\r\u001b[36m🌔 \u001b[0m moon\u001b[K"] +[112.517158, "o", "\r\u001b[36m🌕 \u001b[0m moon\u001b[K"] +[112.620927, "o", "\r\u001b[36m🌖 \u001b[0m moon\u001b[K"] +[112.721816, "o", "\r\u001b[36m🌗 \u001b[0m moon\u001b[K"] +[112.827678, "o", "\r\u001b[36m🌘 \u001b[0m moon\u001b[K"] +[112.937805, "o", "\r\u001b[36m🌑 \u001b[0m moon\u001b[K"] +[113.044853, "o", "\r\u001b[36m🌒 \u001b[0m moon\u001b[K"] +[113.14788, "o", "\r\u001b[36m🌓 \u001b[0m moon\u001b[K"] +[113.247662, "o", "\r\u001b[36m🌔 \u001b[0m moon\u001b[K"] +[113.350706, "o", "\r\u001b[36m🌕 \u001b[0m moon\u001b[K"] +[113.463277, "o", "\r\u001b[36m🌖 \u001b[0m moon\u001b[K"] +[113.563575, "o", "\r\u001b[36m🌗 \u001b[0m moon\u001b[K"] +[113.666977, "o", "\r\u001b[36m🌘 \u001b[0m moon\u001b[K"] +[113.770458, "o", "\r\u001b[36m🌑 \u001b[0m moon\u001b[K"] +[113.864814, "o", "\r\u001b[36m🌒 \u001b[0m moon\u001b[K"] +[114.020415, "o", "\r\u001b[32m🚶 \u001b[0m runner\u001b[K"] +[114.195002, "o", "\r\u001b[32m🏃 \u001b[0m runner\u001b[K"] +[114.365734, "o", "\r\u001b[32m🚶 \u001b[0m runner\u001b[K"] +[114.527652, "o", "\r\u001b[32m🏃 \u001b[0m runner\u001b[K"] +[114.692592, "o", "\r\u001b[32m🚶 \u001b[0m runner\u001b[K"] +[114.859222, "o", "\r\u001b[32m🏃 \u001b[0m runner\u001b[K"] +[115.076288, "o", "\r\u001b[92m▐⠂ ▌\u001b[0m pong\u001b[K"] +[115.174445, "o", "\r\u001b[92m▐⠈ ▌\u001b[0m pong\u001b[K"] +[115.278669, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[115.394913, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[115.493415, "o", "\r\u001b[92m▐ ⡀ ▌\u001b[0m pong\u001b[K"] +[115.592173, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[115.691129, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[115.797193, "o", "\r\u001b[92m▐ ⠈ ▌\u001b[0m pong\u001b[K"] +[115.897054, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[115.998034, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[116.101098, "o", "\r\u001b[92m▐ ⡀ ▌\u001b[0m pong\u001b[K"] +[116.20948, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[116.310841, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[116.415407, "o", "\r\u001b[92m▐ ⠈ ▌\u001b[0m pong\u001b[K"] +[116.515614, "o", "\r\u001b[92m▐ ⠂▌\u001b[0m pong\u001b[K"] +[116.621713, "o", "\r\u001b[92m▐ ⠠▌\u001b[0m pong\u001b[K"] +[116.732025, "o", "\r\u001b[92m▐ ⡀▌\u001b[0m pong\u001b[K"] +[116.840002, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[116.946147, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[117.040564, "o", "\r\u001b[92m▐ ⠈ ▌\u001b[0m pong\u001b[K"] +[117.138448, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[117.240282, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[117.345561, "o", "\r\u001b[92m▐ ⡀ ▌\u001b[0m pong\u001b[K"] +[117.448395, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[117.549397, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[117.653628, "o", "\r\u001b[92m▐ ⠈ ▌\u001b[0m pong\u001b[K"] +[117.74977, "o", "\r\u001b[92m▐ ⠂ ▌\u001b[0m pong\u001b[K"] +[117.857762, "o", "\r\u001b[92m▐ ⠠ ▌\u001b[0m pong\u001b[K"] +[118.041938, "o", "\r\u001b[94m▐|\\____________▌\u001b[0m shark\u001b[K"] +[118.176875, "o", "\r\u001b[94m▐_|\\___________▌\u001b[0m shark\u001b[K"] +[118.327432, "o", "\r\u001b[94m▐__|\\__________▌\u001b[0m shark\u001b[K"] +[118.490683, "o", "\r\u001b[94m▐___|\\_________▌\u001b[0m shark\u001b[K"] +[118.63101, "o", "\r\u001b[94m▐____|\\________▌\u001b[0m shark\u001b[K"] +[118.774635, "o", "\r\u001b[94m▐_____|\\_______▌\u001b[0m shark\u001b[K"] +[118.92665, "o", "\r\u001b[94m▐______|\\______▌\u001b[0m shark\u001b[K"] +[119.078161, "o", "\r\u001b[94m▐_______|\\_____▌\u001b[0m shark\u001b[K"] +[119.233379, "o", "\r\u001b[94m▐________|\\____▌\u001b[0m shark\u001b[K"] +[119.38589, "o", "\r\u001b[94m▐_________|\\___▌\u001b[0m shark\u001b[K"] +[119.541579, "o", "\r\u001b[94m▐__________|\\__▌\u001b[0m shark\u001b[K"] +[119.705269, "o", "\r\u001b[94m▐___________|\\_▌\u001b[0m shark\u001b[K"] +[119.854453, "o", "\r\u001b[94m▐____________|\\▌\u001b[0m shark\u001b[K"] +[119.994665, "o", "\r\u001b[94m▐____________/|▌\u001b[0m shark\u001b[K"] +[120.152717, "o", "\r\u001b[94m▐___________/|_▌\u001b[0m shark\u001b[K"] +[120.294629, "o", "\r\u001b[94m▐__________/|__▌\u001b[0m shark\u001b[K"] +[120.448432, "o", "\r\u001b[94m▐_________/|___▌\u001b[0m shark\u001b[K"] +[120.592531, "o", "\r\u001b[94m▐________/|____▌\u001b[0m shark\u001b[K"] +[120.751157, "o", "\r\u001b[94m▐_______/|_____▌\u001b[0m shark\u001b[K"] +[120.892729, "o", "\r\u001b[94m▐______/|______▌\u001b[0m shark\u001b[K"] +[121.036375, "o", "\r\u001b[94m▐_____/|_______▌\u001b[0m shark\u001b[K"] +[121.185092, "o", "\r\u001b[94m▐____/|________▌\u001b[0m shark\u001b[K"] +[121.334119, "o", "\r\u001b[94m▐___/|_________▌\u001b[0m shark\u001b[K"] +[121.482184, "o", "\r\u001b[94m▐__/|__________▌\u001b[0m shark\u001b[K"] +[121.628531, "o", "\r\u001b[94m▐_/|___________▌\u001b[0m shark\u001b[K"] +[121.766532, "o", "\r\u001b[94m▐/|____________▌\u001b[0m shark\u001b[K"] +[121.910285, "o", "\r\u001b[94m▐|\\____________▌\u001b[0m shark\u001b[K"] +[122.104162, "o", "\r\u001b[31md\u001b[0m dqpb\u001b[K"] +[122.220151, "o", "\r\u001b[31mq\u001b[0m dqpb\u001b[K"] +[122.342465, "o", "\r\u001b[31mp\u001b[0m dqpb\u001b[K"] +[122.483415, "o", "\r\u001b[31mb\u001b[0m dqpb\u001b[K"] +[122.612366, "o", "\r\u001b[31md\u001b[0m dqpb\u001b[K"] +[122.741438, "o", "\r\u001b[31mq\u001b[0m dqpb\u001b[K"] +[122.868962, "o", "\r\u001b[31mp\u001b[0m dqpb\u001b[K"] +[123.004252, "o", "\r\u001b[31mb\u001b[0m dqpb\u001b[K"] +[123.144686, "o", "\r\u001b[31md\u001b[0m dqpb\u001b[K"] +[123.266593, "o", "\r\u001b[31mq\u001b[0m dqpb\u001b[K"] +[123.392774, "o", "\r\u001b[31mp\u001b[0m dqpb\u001b[K"] +[123.516344, "o", "\r\u001b[31mb\u001b[0m dqpb\u001b[K"] +[123.638991, "o", "\r\u001b[31md\u001b[0m dqpb\u001b[K"] +[123.775622, "o", "\r\u001b[31mq\u001b[0m dqpb\u001b[K"] +[123.904468, "o", "\r\u001b[31mp\u001b[0m dqpb\u001b[K"] +[124.082541, "o", "\r\u001b[93m☀️ \u001b[0m weather\u001b[K"] +[124.208916, "o", "\r\u001b[93m☀️ \u001b[0m weather\u001b[K"] +[124.335512, "o", "\r\u001b[93m☀️ \u001b[0m weather\u001b[K"] +[124.462779, "o", "\r\u001b[93m🌤 \u001b[0m weather\u001b[K"] +[124.594289, "o", "\r\u001b[93m⛅️ \u001b[0m weather\u001b[K"] +[124.722414, "o", "\r\u001b[93m🌥 \u001b[0m weather\u001b[K"] +[124.850377, "o", "\r\u001b[93m☁️ \u001b[0m weather\u001b[K"] +[124.971744, "o", "\r\u001b[93m🌧 \u001b[0m weather\u001b[K"] +[125.100185, "o", "\r\u001b[93m🌨 \u001b[0m weather\u001b[K"] +[125.247053, "o", "\r\u001b[93m🌧 \u001b[0m weather\u001b[K"] +[125.368576, "o", "\r\u001b[93m🌨 \u001b[0m weather\u001b[K"] +[125.492945, "o", "\r\u001b[93m🌧 \u001b[0m weather\u001b[K"] +[125.626639, "o", "\r\u001b[93m🌨 \u001b[0m weather\u001b[K"] +[125.76683, "o", "\r\u001b[93m🌨 \u001b[0m weather\u001b[K"] +[125.892688, "o", "\r\u001b[93m🌧 \u001b[0m weather\u001b[K"] +[126.023219, "o", "\r\u001b[93m🌨 \u001b[0m weather\u001b[K"] +[126.164665, "o", "\r\u001b[93m☁️ \u001b[0m weather\u001b[K"] +[126.299696, "o", "\r\u001b[93m🌥 \u001b[0m weather\u001b[K"] +[126.435324, "o", "\r\u001b[93m⛅️ \u001b[0m weather\u001b[K"] +[126.562046, "o", "\r\u001b[93m🌤 \u001b[0m weather\u001b[K"] +[126.68316, "o", "\r\u001b[93m☀️ \u001b[0m weather\u001b[K"] +[126.82162, "o", "\r\u001b[93m☀️ \u001b[0m weather\u001b[K"] +[127.043278, "o", "\r\u001b[92m🌲\u001b[0m christmas\u001b[K"] +[127.493646, "o", "\r\u001b[92m🎄\u001b[0m christmas\u001b[K"] +[127.923661, "o", "\r\u001b[92m🌲\u001b[0m christmas\u001b[K"] +[128.347174, "o", "\r\u001b[92m🎄\u001b[0m christmas\u001b[K"] +[128.784302, "o", "\r\u001b[92m🌲\u001b[0m christmas\u001b[K"] +[129.220629, "o", "\r\u001b[92m🎄\u001b[0m christmas\u001b[K"] +[129.650664, "o", "\r\u001b[92m🌲\u001b[0m christmas\u001b[K"] +[130.082744, "o", "\r\u001b[K\u001b[?25h\u001b[0m\u001b[?25h\u001b[0m"] diff --git a/bin/bash-progress-indicator/bash-cli-spinners/assets/demo.svg b/bin/bash-progress-indicator/bash-cli-spinners/assets/demo.svg new file mode 100644 index 0000000..43e5efc --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/assets/demo.svg @@ -0,0 +1 @@ +⠋dots⠙dots⠹dots⠸dots⠼dots⠴dots⠦dots⠧dots⠇dots⣾dots2⣽dots2⣻dots2⢿dots2⡿dots2⣟dots2⣯dots2⣷dots2⠋dots3⠙dots3⠚dots3⠞dots3⠖dots3⠦dots3⠴dots3⠲dots3⠄dots4⠆dots4⠇dots4⠋dots4⠙dots4⠸dots4⠰dots4⠋dots5⠙dots5⠒dots5⠂dots5⠐dots5⠒dots6⠂dots6⠲dots6⠴dots6⠤dots6⠄dots6⠒dots7⠐dots7⠖dots7⠦dots7⠤dots7⠠dots7⠁dots8⠉dots8⠒dots8⠂dots8⠤dots8⠄dots8⠠dots8⠐dots8⢹dots9⢺dots9⢼dots9⣸dots9⣇dots9⡧dots9⡗dots9⡏dots9⢄dots10⢂dots10⢁dots10⡁dots10⡈dots10⡐dots10⡠dots10⠁dots11⠂dots11⠄dots11⡀dots11⢀dots11⠠dots11⠐dots11⢋⠁dots12⡋⠁dots12⠍⠉dots12⠋⠉dots12⠉⠙dots12⠉⠩dots12⠈⢙dots12⠈⡙dots12-line\line|line/line⠂line2-line2–line2—line2┤pipe┘pipe┴pipe└pipe├pipe┌pipe┬pipe┐pipe.simpleDots..simpleDots...simpleDotssimpleDots.simpleDotsScrolling..simpleDotsScrolling...simpleDotsScrolling..simpleDotsScrolling.simpleDotsScrollingsimpleDotsScrolling✶star✸star✹star+star2xstar2*star2_flip-flip`flip☱hamburger☲hamburger☴hamburger▁growVertical▃growVertical▄growVertical▅growVertical▆growVertical▇growVertical▏growHorizontal▎growHorizontal▍growHorizontal▌growHorizontal▋growHorizontal▊growHorizontalballoon.balloonoballoonOballoon@balloon.balloon2oballoon2Oballoon2°balloon2▓noise▒noise░noise⠁bounce⠂bounce⠄bounce▖boxBounce▘boxBounce▝boxBounce▗boxBounce▌boxBounce2▀boxBounce2▐boxBounce2▄boxBounce2◢triangle◣triangle◤triangle◥triangle◜arc◠arc◝arc◞arc◡arc◟arc◡circle⊙circle◠circle◰squareCorners◳squareCorners◲squareCorners◱squareCorners◴circleQuarters◷circleQuarters◶circleQuarters◵circleQuarters◐circleHalves◓circleHalves◑circleHalves◒circleHalves╫squish╪squish⊶toggle⊷toggle▫toggle2▪toggle2□toggle3■toggle3■toggle4□toggle4▪toggle4▫toggle4▮toggle5▯toggle5ဝtoggle6၀toggle6⦾toggle7⦿toggle7◍toggle8◌toggle8◉toggle9◎toggle9㊂toggle10㊀toggle10㊁toggle10⧇toggle11⧆toggle11☗toggle12☖toggle12=toggle13*toggle13-toggle13←arrow↖arrow↑arrow↗arrow→arrow↘arrow↓arrow⬆️arrow2↗️arrow2➡️arrow2↘️arrow2⬇️arrow2↙️arrow2⬅️arrow2↖️arrow2▹▹▹▹▹arrow3▸▹▹▹▹arrow3▹▸▹▹▹arrow3▹▹▸▹▹arrow3▹▹▹▸▹arrow3▹▹▹▹▸arrow3[]bouncingBar[=]bouncingBar[==]bouncingBar[===]bouncingBar[====]bouncingBar[===]bouncingBar[==]bouncingBar[=]bouncingBar(●)bouncingBall(●)bouncingBall(●)bouncingBall(●)bouncingBall(●)bouncingBall😄smiley😝smiley🙈monkey🙉monkey🙊monkey💛hearts💙hearts💜hearts💚hearts❤️hearts🕛clock🕐clock🕑clock🌍earth🌎earth🌏earth🌑moon🌒moon🌓moon🌔moon🌕moon🌖moon🌗moon🌘moon🚶runner🏃runner▐⠠▌pong▐⠂▌pong▐⠠▌pong▐⠂▌pong▐|\____________▌sharkddqpbqdqpbpdqpbbdqpb☀️weather🌤weather⛅️weather🌥weather☁️weather🌧weather🌨weather🌲christmas🎄christmas⠏dots⠳dots3⠓dots3⠠dots4⠚dots5⠲dots5⠴dots5⠦dots5⠖dots5⠓dots5⠁dots6⠉dots6⠙dots6⠚dots6⠈dots7⠉dots7⠋dots7⠓dots7⠙dots8⠚dots8⠲dots8⠴dots8⠦dots8⠖dots8⠓dots8⠋dots8⠈dots11⢀⠀dots12⡀⠀dots12⠄⠀dots12⢂⠀dots12⡂⠀dots12⠅⠀dots12⢃⠀dots12⡃⠀dots12⠍⠀dots12⢋⠀dots12⡋⠀dots12⠍⠁dots12⢈⠩dots12⡀⢙dots12⠄⡙dots12⢂⠩dots12⡂⢘dots12⠅⡘dots12⢃⠨dots12⡃⢐dots12⠍⡐dots12⢋⠠dots12⡋⢀dots12⠍⡁dots12⠈⠩dots12⠀⢙dots12✺star✷star'flip´flip▉growHorizontal*balloon↙arrow(●)bouncingBall🕒clock🕓clock🕔clock🕕clock🕖clock🕗clock🕘clock🕙clock🕚clock▐⠂▌pong▐⠈▌pong▐⠂▌pong▐⡀▌pong▐⠠▌pong▐⠈▌pong▐⠂▌pong▐⡀▌pong▐⠠▌pong▐⠈▌pong▐⠂▌pong▐⠠▌pong▐⡀▌pong▐⠠▌pong▐⠈▌pong▐⠂▌pong▐⡀▌pong▐⠠▌pong▐⠈▌pong▐⠂▌pong▐_|\___________▌shark▐__|\__________▌shark▐___|\_________▌shark▐____|\________▌shark▐_____|\_______▌shark▐______|\______▌shark▐_______|\_____▌shark▐________|\____▌shark▐_________|\___▌shark▐__________|\__▌shark▐___________|\_▌shark▐____________|\▌shark▐____________/|▌shark▐___________/|_▌shark▐__________/|__▌shark▐_________/|___▌shark▐________/|____▌shark▐_______/|_____▌shark▐______/|______▌shark▐_____/|_______▌shark▐____/|________▌shark▐___/|_________▌shark▐__/|__________▌shark▐_/|___________▌shark▐/|____________▌shark \ No newline at end of file diff --git a/bin/bash-progress-indicator/bash-cli-spinners/demo.sh b/bin/bash-progress-indicator/bash-cli-spinners/demo.sh new file mode 100755 index 0000000..d46115e --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/demo.sh @@ -0,0 +1,191 @@ +#!/bin/bash + +# Comprehensive demo showing all specified spinners replacing each other in +# place + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# All requested spinners with colors (duration calculated dynamically) +spinners=( + # Dots family (Braille patterns) + "dots:blue" + "dots2:bright_blue" + "dots3:cyan" + "dots4:bright_cyan" + "dots5:green" + "dots6:bright_green" + "dots7:yellow" + "dots8:bright_yellow" + "dots9:red" + "dots10:bright_red" + "dots11:magenta" + "dots12:bright_magenta" + + # Lines and pipes + "line:white" + "line2:bright_white" + "pipe:blue" + + # Simple dots + "simpleDots:green" + "simpleDotsScrolling:bright_green" + + # Stars + "star:yellow" + "star2:bright_yellow" + + # Animations + "flip:cyan" + "hamburger:red" + + # Growing + "growVertical:blue" + "growHorizontal:bright_blue" + + # Balloons + "balloon:magenta" + "balloon2:bright_magenta" + + # Effects + "noise:white" + "bounce:green" + + # Box bouncing + "boxBounce:red" + "boxBounce2:bright_red" + + # Shapes + "triangle:yellow" + "arc:cyan" + "circle:blue" + "squareCorners:magenta" + "circleQuarters:green" + "circleHalves:red" + "squish:white" + + # Toggles + "toggle:blue" + "toggle2:bright_blue" + "toggle3:cyan" + "toggle4:bright_cyan" + "toggle5:green" + "toggle6:bright_green" + "toggle7:yellow" + "toggle8:bright_yellow" + "toggle9:red" + "toggle10:bright_red" + "toggle11:magenta" + "toggle12:bright_magenta" + "toggle13:white" + + # Arrows + "arrow:blue" + "arrow2:bright_blue" + "arrow3:cyan" + + # Bouncing + "bouncingBar:green" + "bouncingBall:bright_green" + + # Emoji animations + "smiley:yellow" + "monkey:bright_yellow" + "hearts:bright_magenta" + "clock:blue" + "earth:bright_blue" + "moon:cyan" + "runner:green" + + # Complex animations + "pong:bright_green" + "shark:bright_blue" + + # Others + "dqpb:red" + "weather:bright_yellow" + "christmas:bright_green" +) + +# Hide cursor at start +printf "\033[?25l" + +# Set trap to restore cursor on exit +trap 'printf "\033[?25h\033[0m"; exit' EXIT INT TERM + +# Track progress +current=0 + +for spinner_config in "${spinners[@]}"; do + current=$((current + 1)) + IFS=':' read -r name color <<< "$spinner_config" + + # Get frames array + frame_array=() + while IFS= read -r line; do + frame_array+=("$line") + done <<< "$(jq -r ".\"$name\".frames[]" "$SCRIPT_DIR/spinners.json" 2>/dev/null)" + frame_count=${#frame_array[@]} + + if [[ $frame_count -eq 0 ]]; then + continue + fi + + # Get interval and convert to sleep time + interval=$(jq -r ".\"$name\".interval" "$SCRIPT_DIR/spinners.json" 2>/dev/null) + sleep_time=$(echo "scale=3; $interval / 1000" | bc -l 2>/dev/null || echo "0.1") + + # Calculate dynamic duration based on frame count + # For spinners with few frames (1-4): show 3 complete cycles + # For spinners with medium frames (5-10): show 2 complete cycles + # For spinners with many frames (11+): show 1 complete cycle + if [[ $frame_count -le 4 ]]; then + cycles=3 + elif [[ $frame_count -le 10 ]]; then + cycles=2 + else + cycles=1 + fi + + # Calculate total duration: cycles * frames * interval_per_frame + duration=$(echo "scale=3; $cycles * $frame_count * $interval / 1000" | bc -l 2>/dev/null) + duration=${duration%.*} # Remove decimal part for integer seconds + duration=$((duration + 1)) # Add 1 second minimum + + # Set up colors + color_code="" + reset_code="" + case "$color" in + "red") color_code="\033[31m" ;; + "green") color_code="\033[32m" ;; + "yellow") color_code="\033[33m" ;; + "blue") color_code="\033[34m" ;; + "magenta") color_code="\033[35m" ;; + "cyan") color_code="\033[36m" ;; + "white") color_code="\033[37m" ;; + "bright_red") color_code="\033[91m" ;; + "bright_green") color_code="\033[92m" ;; + "bright_yellow") color_code="\033[93m" ;; + "bright_blue") color_code="\033[94m" ;; + "bright_magenta") color_code="\033[95m" ;; + "bright_cyan") color_code="\033[96m" ;; + "bright_white") color_code="\033[97m" ;; + esac + reset_code="\033[0m" + + # Run spinner animation for calculated duration + start_time=$(date +%s) + end_time=$((start_time + duration)) + frame_index=0 + + while [[ $(date +%s) -lt $end_time ]]; do + current_frame="${frame_array[$frame_index]}" + printf "\r${color_code}%s${reset_code} ${name}\033[K" "$current_frame" + + frame_index=$(( (frame_index + 1) % frame_count )) + sleep "$sleep_time" + done +done + +# Clear the line and restore cursor +printf "\r\033[K" +printf "\033[?25h\033[0m" diff --git a/bin/bash-progress-indicator/bash-cli-spinners/spinner.sh b/bin/bash-progress-indicator/bash-cli-spinners/spinner.sh new file mode 100755 index 0000000..bb4a2a6 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/spinner.sh @@ -0,0 +1,364 @@ +#!/bin/bash + +# JSON-based Bash Loading Spinner Engine +# Based on cli-spinners: https://github.com/sindresorhus/cli-spinners + +# shellcheck disable=SC2034 # Some variables may appear unused in specific conditions + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SPINNERS_JSON="$SCRIPT_DIR/spinners.json" + +# Performance optimization: Cache parsed data (requires bash 4.0+) +if [[ "${BASH_VERSION%%.*}" -ge 4 ]]; then + declare -A SPINNER_FRAMES_CACHE + declare -A SPINNER_INTERVAL_CACHE + CACHE_ENABLED=true +else + CACHE_ENABLED=false +fi +CACHE_LOADED=false + +# Check if jq is available for JSON parsing +if ! command -v jq >/dev/null 2>&1; then + echo "Error: jq is required for JSON parsing. Install with: brew install jq (macOS) or apt install jq (Ubuntu)" >&2 + exit 1 +fi + +# Check if spinners.json exists +if [[ ! -f "$SPINNERS_JSON" ]]; then + echo "Error: spinners.json not found at $SPINNERS_JSON" >&2 + exit 1 +fi + +# Load all spinner data into cache for performance +load_spinner_cache() { + if [[ "$CACHE_LOADED" == "true" ]]; then + return 0 + fi + + # Skip caching if not supported + if [[ "$CACHE_ENABLED" != "true" ]]; then + CACHE_LOADED=true + return 0 + fi + + local spinner_names + if ! spinner_names=$(jq -r 'keys[]' "$SPINNERS_JSON" 2>/dev/null); then + echo "Error: Failed to parse spinners.json" >&2 + return 1 + fi + + while IFS= read -r spinner_name; do + [[ -z "$spinner_name" ]] && continue + + # Cache frames (joined with newlines for storage) + local frames + frames=$(jq -r ".\"$spinner_name\".frames[]" "$SPINNERS_JSON" 2>/dev/null | tr '\n' '\0') + SPINNER_FRAMES_CACHE["$spinner_name"]="$frames" + + # Cache interval + local interval + interval=$(jq -r ".\"$spinner_name\".interval" "$SPINNERS_JSON" 2>/dev/null) + SPINNER_INTERVAL_CACHE["$spinner_name"]="$interval" + + done <<< "$spinner_names" + + CACHE_LOADED=true +} + +# List all available spinners +list_spinners() { + echo "Available spinners:" + jq -r 'keys[]' "$SPINNERS_JSON" | sort +} + +# Get spinner data (updated to work with cache) +get_spinner_data() { + local spinner_name="$1" + + if [[ "$CACHE_ENABLED" == "true" ]]; then + load_spinner_cache || return 1 + + if [[ -z "${SPINNER_FRAMES_CACHE[$spinner_name]:-}" ]]; then + echo "Error: Spinner '$spinner_name' not found" >&2 + return 1 + fi + + # Return cached data in JSON format for compatibility + local frames_json + frames_json=$(printf '%s' "${SPINNER_FRAMES_CACHE[$spinner_name]}" | tr '\0' '\n' | sed 's/.*/"&"/' | tr '\n' ',' | sed 's/,$//') + echo "{\"interval\":${SPINNER_INTERVAL_CACHE[$spinner_name]},\"frames\":[$frames_json]}" + else + # Fallback to direct JSON parsing + if ! jq -e ".\"$spinner_name\"" "$SPINNERS_JSON" >/dev/null 2>&1; then + echo "Error: Spinner '$spinner_name' not found" >&2 + return 1 + fi + jq -r ".\"$spinner_name\"" "$SPINNERS_JSON" + fi +} + +# Get spinner frames (optimized with cache) +get_frames() { + local spinner_name="$1" + + # Use cache if available + if [[ "$CACHE_ENABLED" == "true" ]]; then + load_spinner_cache || return 1 + + if [[ -z "${SPINNER_FRAMES_CACHE[$spinner_name]:-}" ]]; then + return 1 + fi + + printf '%s' "${SPINNER_FRAMES_CACHE[$spinner_name]}" | tr '\0' '\n' + else + # Fallback to direct JSON parsing + jq -r ".\"$spinner_name\".frames[]" "$SPINNERS_JSON" 2>/dev/null + fi +} + +# Get spinner interval (optimized with cache) +get_interval() { + local spinner_name="$1" + + # Use cache if available + if [[ "$CACHE_ENABLED" == "true" ]]; then + load_spinner_cache || return 1 + echo "${SPINNER_INTERVAL_CACHE[$spinner_name]:-}" + else + # Fallback to direct JSON parsing + jq -r ".\"$spinner_name\".interval" "$SPINNERS_JSON" 2>/dev/null + fi +} + +# Convert milliseconds to seconds for bash sleep +ms_to_seconds() { + local ms="$1" + echo "scale=3; $ms / 1000" | bc -l 2>/dev/null || echo "0.1" +} + +# Show spinner for a specified duration +show_spinner() { + local spinner_name="$1" + local duration="$2" + local message="${3:-Loading}" + local color="${4:-}" + local demo_mode="${5:-false}" + + # Validate inputs + if [[ -z "$spinner_name" ]]; then + echo "Usage: show_spinner [message] [color]" >&2 + return 1 + fi + + if [[ -z "$duration" ]] || ! [[ "$duration" =~ ^[0-9]+$ ]]; then + echo "Error: Duration must be a positive integer (seconds)" >&2 + return 1 + fi + + # Get spinner data + local frames interval sleep_time + if ! frames=$(get_frames "$spinner_name"); then + echo "Error: Failed to get frames for spinner '$spinner_name'" >&2 + return 1 + fi + + if ! interval=$(get_interval "$spinner_name"); then + echo "Error: Failed to get interval for spinner '$spinner_name'" >&2 + return 1 + fi + + # Convert interval to sleep time + sleep_time=$(ms_to_seconds "$interval") + + # Convert frames to array (compatible with older bash) + local frame_array=() + while IFS= read -r line; do + frame_array+=("$line") + done <<< "$frames" + local frame_count=${#frame_array[@]} + + if [[ $frame_count -eq 0 ]]; then + echo "Error: No frames found for spinner '$spinner_name'" >&2 + return 1 + fi + + # Set up colors if specified + local color_code="" reset_code="" + if [[ -n "$color" ]]; then + case "$color" in + "red") color_code="\033[31m" ;; + "green") color_code="\033[32m" ;; + "yellow") color_code="\033[33m" ;; + "blue") color_code="\033[34m" ;; + "magenta") color_code="\033[35m" ;; + "cyan") color_code="\033[36m" ;; + "white") color_code="\033[37m" ;; + "bright_red") color_code="\033[91m" ;; + "bright_green") color_code="\033[92m" ;; + "bright_yellow") color_code="\033[93m" ;; + "bright_blue") color_code="\033[94m" ;; + "bright_magenta") color_code="\033[95m" ;; + "bright_cyan") color_code="\033[96m" ;; + "bright_white") color_code="\033[97m" ;; + esac + reset_code="\033[0m" + fi + + # Hide cursor + printf "\033[?25l" + + # Set up trap to restore cursor on exit + trap 'printf "\033[?25h\033[0m"; exit' EXIT INT TERM + + # Run spinner animation + local start_time + start_time=$(date +%s) + local end_time=$((start_time + duration)) + local frame_index=0 + + while [[ $(date +%s) -lt $end_time ]]; do + local current_frame="${frame_array[$frame_index]}" + printf "\r${color_code}%s${reset_code} ${message}\033[K" "$current_frame" + + frame_index=$(( (frame_index + 1) % frame_count )) + sleep "$sleep_time" + done + + # Clear line and restore cursor + printf "\r\033[K" + printf "\033[?25h%s" "${reset_code}" +} + +# Run spinner while executing a command +run_with_spinner() { + local spinner_name="$1" + local message="${2:-Loading}" + local color="${3:-}" + shift 3 + local command=("$@") + + if [[ ${#command[@]} -eq 0 ]]; then + echo "Usage: run_with_spinner [message] [color] " >&2 + return 1 + fi + + # Get spinner data + local frames interval sleep_time + if ! frames=$(get_frames "$spinner_name"); then + echo "Error: Failed to get frames for spinner '$spinner_name'" >&2 + return 1 + fi + + if ! interval=$(get_interval "$spinner_name"); then + echo "Error: Failed to get interval for spinner '$spinner_name'" >&2 + return 1 + fi + + sleep_time=$(ms_to_seconds "$interval") + + # Convert frames to array (compatible with older bash) + local frame_array=() + while IFS= read -r line; do + frame_array+=("$line") + done <<< "$frames" + local frame_count=${#frame_array[@]} + + # Set up colors + local color_code="" reset_code="" + if [[ -n "$color" ]]; then + case "$color" in + "red") color_code="\033[31m" ;; + "green") color_code="\033[32m" ;; + "yellow") color_code="\033[33m" ;; + "blue") color_code="\033[34m" ;; + "magenta") color_code="\033[35m" ;; + "cyan") color_code="\033[36m" ;; + "white") color_code="\033[37m" ;; + "bright_red") color_code="\033[91m" ;; + "bright_green") color_code="\033[92m" ;; + "bright_yellow") color_code="\033[93m" ;; + "bright_blue") color_code="\033[94m" ;; + "bright_magenta") color_code="\033[95m" ;; + "bright_cyan") color_code="\033[96m" ;; + "bright_white") color_code="\033[97m" ;; + esac + reset_code="\033[0m" + fi + + # Start command in background + "${command[@]}" & + local cmd_pid=$! + + # Hide cursor + printf "\033[?25l" + + # Set up trap to restore cursor and cleanup + trap 'printf "\033[?25h\033[0m"; kill $cmd_pid 2>/dev/null; exit' EXIT INT TERM + + # Run spinner while command executes + local frame_index=0 + while kill -0 "$cmd_pid" 2>/dev/null; do + local current_frame="${frame_array[$frame_index]}" + printf "\r${color_code}%s${reset_code} ${message}\033[K" "$current_frame" + + frame_index=$(( (frame_index + 1) % frame_count )) + sleep "$sleep_time" + done + + # Wait for command to complete and get exit code + wait "$cmd_pid" + local exit_code=$? + + # Clear line and restore cursor + printf "\r\033[K" + printf "\033[?25h%s" "${reset_code}" + + return $exit_code +} + +# Main function for CLI usage +main() { + case "${1:-}" in + "list"|"ls") + list_spinners + ;; + "show") + shift + show_spinner "$@" + ;; + "run") + shift + run_with_spinner "$@" + ;; + "help"|"--help"|"-h"|"") + echo "JSON-based Bash Loading Spinner Engine" + echo "" + echo "Usage:" + echo " $0 list - List all available spinners" + echo " $0 show [message] [color] - Show spinner for duration (seconds)" + echo " $0 run [message] [color] - Run command with spinner" + echo "" + echo "Examples:" + echo " $0 list" + echo " $0 show dots 3 \"Loading data\" blue" + echo " $0 show pong 5 \"Playing game\" bright_green" + echo " $0 run shark \"Downloading\" cyan sleep 10" + echo "" + echo "Colors: red, green, yellow, blue, magenta, cyan, white" + echo " bright_red, bright_green, bright_yellow, bright_blue," + echo " bright_magenta, bright_cyan, bright_white" + ;; + *) + echo "Unknown command: $1" >&2 + echo "Use '$0 help' for usage information" >&2 + exit 1 + ;; + esac +} + +# Only run main if script is executed directly (not sourced) +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi diff --git a/bin/bash-progress-indicator/bash-cli-spinners/spinners.json b/bin/bash-progress-indicator/bash-cli-spinners/spinners.json new file mode 100644 index 0000000..25f7fc7 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/spinners.json @@ -0,0 +1,1651 @@ +{ + "dots": { + "interval": 80, + "frames": [ + "⠋", + "⠙", + "⠹", + "⠸", + "⠼", + "⠴", + "⠦", + "⠧", + "⠇", + "⠏" + ] + }, + "dots2": { + "interval": 80, + "frames": [ + "⣾", + "⣽", + "⣻", + "⢿", + "⡿", + "⣟", + "⣯", + "⣷" + ] + }, + "dots3": { + "interval": 80, + "frames": [ + "⠋", + "⠙", + "⠚", + "⠞", + "⠖", + "⠦", + "⠴", + "⠲", + "⠳", + "⠓" + ] + }, + "dots4": { + "interval": 80, + "frames": [ + "⠄", + "⠆", + "⠇", + "⠋", + "⠙", + "⠸", + "⠰", + "⠠", + "⠰", + "⠸", + "⠙", + "⠋", + "⠇", + "⠆" + ] + }, + "dots5": { + "interval": 80, + "frames": [ + "⠋", + "⠙", + "⠚", + "⠒", + "⠂", + "⠂", + "⠒", + "⠲", + "⠴", + "⠦", + "⠖", + "⠒", + "⠐", + "⠐", + "⠒", + "⠓", + "⠋" + ] + }, + "dots6": { + "interval": 80, + "frames": [ + "⠁", + "⠉", + "⠙", + "⠚", + "⠒", + "⠂", + "⠂", + "⠒", + "⠲", + "⠴", + "⠤", + "⠄", + "⠄", + "⠤", + "⠴", + "⠲", + "⠒", + "⠂", + "⠂", + "⠒", + "⠚", + "⠙", + "⠉", + "⠁" + ] + }, + "dots7": { + "interval": 80, + "frames": [ + "⠈", + "⠉", + "⠋", + "⠓", + "⠒", + "⠐", + "⠐", + "⠒", + "⠖", + "⠦", + "⠤", + "⠠", + "⠠", + "⠤", + "⠦", + "⠖", + "⠒", + "⠐", + "⠐", + "⠒", + "⠓", + "⠋", + "⠉", + "⠈" + ] + }, + "dots8": { + "interval": 80, + "frames": [ + "⠁", + "⠁", + "⠉", + "⠙", + "⠚", + "⠒", + "⠂", + "⠂", + "⠒", + "⠲", + "⠴", + "⠤", + "⠄", + "⠄", + "⠤", + "⠠", + "⠠", + "⠤", + "⠦", + "⠖", + "⠒", + "⠐", + "⠐", + "⠒", + "⠓", + "⠋", + "⠉", + "⠈", + "⠈" + ] + }, + "dots9": { + "interval": 80, + "frames": [ + "⢹", + "⢺", + "⢼", + "⣸", + "⣇", + "⡧", + "⡗", + "⡏" + ] + }, + "dots10": { + "interval": 80, + "frames": [ + "⢄", + "⢂", + "⢁", + "⡁", + "⡈", + "⡐", + "⡠" + ] + }, + "dots11": { + "interval": 100, + "frames": [ + "⠁", + "⠂", + "⠄", + "⡀", + "⢀", + "⠠", + "⠐", + "⠈" + ] + }, + "dots12": { + "interval": 80, + "frames": [ + "⢀⠀", + "⡀⠀", + "⠄⠀", + "⢂⠀", + "⡂⠀", + "⠅⠀", + "⢃⠀", + "⡃⠀", + "⠍⠀", + "⢋⠀", + "⡋⠀", + "⠍⠁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⢈⠩", + "⡀⢙", + "⠄⡙", + "⢂⠩", + "⡂⢘", + "⠅⡘", + "⢃⠨", + "⡃⢐", + "⠍⡐", + "⢋⠠", + "⡋⢀", + "⠍⡁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⠈⠩", + "⠀⢙", + "⠀⡙", + "⠀⠩", + "⠀⢘", + "⠀⡘", + "⠀⠨", + "⠀⢐", + "⠀⡐", + "⠀⠠", + "⠀⢀", + "⠀⡀" + ] + }, + "dots13": { + "interval": 80, + "frames": [ + "⣼", + "⣹", + "⢻", + "⠿", + "⡟", + "⣏", + "⣧", + "⣶" + ] + }, + "dots14": { + "interval": 80, + "frames": [ + "⠉⠉", + "⠈⠙", + "⠀⠹", + "⠀⢸", + "⠀⣰", + "⢀⣠", + "⣀⣀", + "⣄⡀", + "⣆⠀", + "⡇⠀", + "⠏⠀", + "⠋⠁" + ] + }, + "dots8Bit": { + "interval": 80, + "frames": [ + "⠀", + "⠁", + "⠂", + "⠃", + "⠄", + "⠅", + "⠆", + "⠇", + "⡀", + "⡁", + "⡂", + "⡃", + "⡄", + "⡅", + "⡆", + "⡇", + "⠈", + "⠉", + "⠊", + "⠋", + "⠌", + "⠍", + "⠎", + "⠏", + "⡈", + "⡉", + "⡊", + "⡋", + "⡌", + "⡍", + "⡎", + "⡏", + "⠐", + "⠑", + "⠒", + "⠓", + "⠔", + "⠕", + "⠖", + "⠗", + "⡐", + "⡑", + "⡒", + "⡓", + "⡔", + "⡕", + "⡖", + "⡗", + "⠘", + "⠙", + "⠚", + "⠛", + "⠜", + "⠝", + "⠞", + "⠟", + "⡘", + "⡙", + "⡚", + "⡛", + "⡜", + "⡝", + "⡞", + "⡟", + "⠠", + "⠡", + "⠢", + "⠣", + "⠤", + "⠥", + "⠦", + "⠧", + "⡠", + "⡡", + "⡢", + "⡣", + "⡤", + "⡥", + "⡦", + "⡧", + "⠨", + "⠩", + "⠪", + "⠫", + "⠬", + "⠭", + "⠮", + "⠯", + "⡨", + "⡩", + "⡪", + "⡫", + "⡬", + "⡭", + "⡮", + "⡯", + "⠰", + "⠱", + "⠲", + "⠳", + "⠴", + "⠵", + "⠶", + "⠷", + "⡰", + "⡱", + "⡲", + "⡳", + "⡴", + "⡵", + "⡶", + "⡷", + "⠸", + "⠹", + "⠺", + "⠻", + "⠼", + "⠽", + "⠾", + "⠿", + "⡸", + "⡹", + "⡺", + "⡻", + "⡼", + "⡽", + "⡾", + "⡿", + "⢀", + "⢁", + "⢂", + "⢃", + "⢄", + "⢅", + "⢆", + "⢇", + "⣀", + "⣁", + "⣂", + "⣃", + "⣄", + "⣅", + "⣆", + "⣇", + "⢈", + "⢉", + "⢊", + "⢋", + "⢌", + "⢍", + "⢎", + "⢏", + "⣈", + "⣉", + "⣊", + "⣋", + "⣌", + "⣍", + "⣎", + "⣏", + "⢐", + "⢑", + "⢒", + "⢓", + "⢔", + "⢕", + "⢖", + "⢗", + "⣐", + "⣑", + "⣒", + "⣓", + "⣔", + "⣕", + "⣖", + "⣗", + "⢘", + "⢙", + "⢚", + "⢛", + "⢜", + "⢝", + "⢞", + "⢟", + "⣘", + "⣙", + "⣚", + "⣛", + "⣜", + "⣝", + "⣞", + "⣟", + "⢠", + "⢡", + "⢢", + "⢣", + "⢤", + "⢥", + "⢦", + "⢧", + "⣠", + "⣡", + "⣢", + "⣣", + "⣤", + "⣥", + "⣦", + "⣧", + "⢨", + "⢩", + "⢪", + "⢫", + "⢬", + "⢭", + "⢮", + "⢯", + "⣨", + "⣩", + "⣪", + "⣫", + "⣬", + "⣭", + "⣮", + "⣯", + "⢰", + "⢱", + "⢲", + "⢳", + "⢴", + "⢵", + "⢶", + "⢷", + "⣰", + "⣱", + "⣲", + "⣳", + "⣴", + "⣵", + "⣶", + "⣷", + "⢸", + "⢹", + "⢺", + "⢻", + "⢼", + "⢽", + "⢾", + "⢿", + "⣸", + "⣹", + "⣺", + "⣻", + "⣼", + "⣽", + "⣾", + "⣿" + ] + }, + "dotsCircle": { + "interval": 80, + "frames": [ + "⢎ ", + "⠎⠁", + "⠊⠑", + "⠈⠱", + " ⡱", + "⢀⡰", + "⢄⡠", + "⢆⡀" + ] + }, + "sand": { + "interval": 80, + "frames": [ + "⠁", + "⠂", + "⠄", + "⡀", + "⡈", + "⡐", + "⡠", + "⣀", + "⣁", + "⣂", + "⣄", + "⣌", + "⣔", + "⣤", + "⣥", + "⣦", + "⣮", + "⣶", + "⣷", + "⣿", + "⡿", + "⠿", + "⢟", + "⠟", + "⡛", + "⠛", + "⠫", + "⢋", + "⠋", + "⠍", + "⡉", + "⠉", + "⠑", + "⠡", + "⢁" + ] + }, + "line": { + "interval": 130, + "frames": [ + "-", + "\\", + "|", + "/" + ] + }, + "line2": { + "interval": 100, + "frames": [ + "⠂", + "-", + "–", + "—", + "–", + "-" + ] + }, + "pipe": { + "interval": 100, + "frames": [ + "┤", + "┘", + "┴", + "└", + "├", + "┌", + "┬", + "┐" + ] + }, + "simpleDots": { + "interval": 400, + "frames": [ + ". ", + ".. ", + "...", + " " + ] + }, + "simpleDotsScrolling": { + "interval": 200, + "frames": [ + ". ", + ".. ", + "...", + " ..", + " .", + " " + ] + }, + "star": { + "interval": 70, + "frames": [ + "✶", + "✸", + "✹", + "✺", + "✹", + "✷" + ] + }, + "star2": { + "interval": 80, + "frames": [ + "+", + "x", + "*" + ] + }, + "flip": { + "interval": 70, + "frames": [ + "_", + "_", + "_", + "-", + "`", + "`", + "'", + "´", + "-", + "_", + "_", + "_" + ] + }, + "hamburger": { + "interval": 100, + "frames": [ + "☱", + "☲", + "☴" + ] + }, + "growVertical": { + "interval": 120, + "frames": [ + "▁", + "▃", + "▄", + "▅", + "▆", + "▇", + "▆", + "▅", + "▄", + "▃" + ] + }, + "growHorizontal": { + "interval": 120, + "frames": [ + "▏", + "▎", + "▍", + "▌", + "▋", + "▊", + "▉", + "▊", + "▋", + "▌", + "▍", + "▎" + ] + }, + "balloon": { + "interval": 140, + "frames": [ + " ", + ".", + "o", + "O", + "@", + "*", + " " + ] + }, + "balloon2": { + "interval": 120, + "frames": [ + ".", + "o", + "O", + "°", + "O", + "o", + "." + ] + }, + "noise": { + "interval": 100, + "frames": [ + "▓", + "▒", + "░" + ] + }, + "bounce": { + "interval": 120, + "frames": [ + "⠁", + "⠂", + "⠄", + "⠂" + ] + }, + "boxBounce": { + "interval": 120, + "frames": [ + "▖", + "▘", + "▝", + "▗" + ] + }, + "boxBounce2": { + "interval": 100, + "frames": [ + "▌", + "▀", + "▐", + "▄" + ] + }, + "triangle": { + "interval": 50, + "frames": [ + "◢", + "◣", + "◤", + "◥" + ] + }, + "binary": { + "interval": 80, + "frames": [ + "010010", + "001100", + "100101", + "111010", + "111101", + "010111", + "101011", + "111000", + "110011", + "110101" + ] + }, + "arc": { + "interval": 100, + "frames": [ + "◜", + "◠", + "◝", + "◞", + "◡", + "◟" + ] + }, + "circle": { + "interval": 120, + "frames": [ + "◡", + "⊙", + "◠" + ] + }, + "squareCorners": { + "interval": 180, + "frames": [ + "◰", + "◳", + "◲", + "◱" + ] + }, + "circleQuarters": { + "interval": 120, + "frames": [ + "◴", + "◷", + "◶", + "◵" + ] + }, + "circleHalves": { + "interval": 50, + "frames": [ + "◐", + "◓", + "◑", + "◒" + ] + }, + "squish": { + "interval": 100, + "frames": [ + "╫", + "╪" + ] + }, + "toggle": { + "interval": 250, + "frames": [ + "⊶", + "⊷" + ] + }, + "toggle2": { + "interval": 80, + "frames": [ + "▫", + "▪" + ] + }, + "toggle3": { + "interval": 120, + "frames": [ + "□", + "■" + ] + }, + "toggle4": { + "interval": 100, + "frames": [ + "■", + "□", + "▪", + "▫" + ] + }, + "toggle5": { + "interval": 100, + "frames": [ + "▮", + "▯" + ] + }, + "toggle6": { + "interval": 300, + "frames": [ + "ဝ", + "၀" + ] + }, + "toggle7": { + "interval": 80, + "frames": [ + "⦾", + "⦿" + ] + }, + "toggle8": { + "interval": 100, + "frames": [ + "◍", + "◌" + ] + }, + "toggle9": { + "interval": 100, + "frames": [ + "◉", + "◎" + ] + }, + "toggle10": { + "interval": 100, + "frames": [ + "㊂", + "㊀", + "㊁" + ] + }, + "toggle11": { + "interval": 50, + "frames": [ + "⧇", + "⧆" + ] + }, + "toggle12": { + "interval": 120, + "frames": [ + "☗", + "☖" + ] + }, + "toggle13": { + "interval": 80, + "frames": [ + "=", + "*", + "-" + ] + }, + "arrow": { + "interval": 100, + "frames": [ + "←", + "↖", + "↑", + "↗", + "→", + "↘", + "↓", + "↙" + ] + }, + "arrow2": { + "interval": 80, + "frames": [ + "⬆️ ", + "↗️ ", + "➡️ ", + "↘️ ", + "⬇️ ", + "↙️ ", + "⬅️ ", + "↖️ " + ] + }, + "arrow3": { + "interval": 120, + "frames": [ + "▹▹▹▹▹", + "▸▹▹▹▹", + "▹▸▹▹▹", + "▹▹▸▹▹", + "▹▹▹▸▹", + "▹▹▹▹▸" + ] + }, + "bouncingBar": { + "interval": 80, + "frames": [ + "[ ]", + "[= ]", + "[== ]", + "[=== ]", + "[====]", + "[ ===]", + "[ ==]", + "[ =]", + "[ ]", + "[ =]", + "[ ==]", + "[ ===]", + "[====]", + "[=== ]", + "[== ]", + "[= ]" + ] + }, + "bouncingBall": { + "interval": 80, + "frames": [ + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "( ●)", + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "(● )" + ] + }, + "smiley": { + "interval": 200, + "frames": [ + "😄 ", + "😝 " + ] + }, + "monkey": { + "interval": 300, + "frames": [ + "🙈 ", + "🙈 ", + "🙉 ", + "🙊 " + ] + }, + "hearts": { + "interval": 100, + "frames": [ + "💛 ", + "💙 ", + "💜 ", + "💚 ", + "❤️ " + ] + }, + "clock": { + "interval": 100, + "frames": [ + "🕛 ", + "🕐 ", + "🕑 ", + "🕒 ", + "🕓 ", + "🕔 ", + "🕕 ", + "🕖 ", + "🕗 ", + "🕘 ", + "🕙 ", + "🕚 " + ] + }, + "earth": { + "interval": 180, + "frames": [ + "🌍 ", + "🌎 ", + "🌏 " + ] + }, + "material": { + "interval": 17, + "frames": [ + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███████▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "██████████▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "█████████████▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁██████████████▁▁▁▁", + "▁▁▁██████████████▁▁▁", + "▁▁▁▁█████████████▁▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁▁▁████████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁▁█████████████▁▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁▁███████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁▁█████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁" + ] + }, + "moon": { + "interval": 80, + "frames": [ + "🌑 ", + "🌒 ", + "🌓 ", + "🌔 ", + "🌕 ", + "🌖 ", + "🌗 ", + "🌘 " + ] + }, + "runner": { + "interval": 140, + "frames": [ + "🚶 ", + "🏃 " + ] + }, + "pong": { + "interval": 80, + "frames": [ + "▐⠂ ▌", + "▐⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂▌", + "▐ ⠠▌", + "▐ ⡀▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐⠠ ▌" + ] + }, + "shark": { + "interval": 120, + "frames": [ + "▐|\\____________▌", + "▐_|\\___________▌", + "▐__|\\__________▌", + "▐___|\\_________▌", + "▐____|\\________▌", + "▐_____|\\_______▌", + "▐______|\\______▌", + "▐_______|\\_____▌", + "▐________|\\____▌", + "▐_________|\\___▌", + "▐__________|\\__▌", + "▐___________|\\_▌", + "▐____________|\\▌", + "▐____________/|▌", + "▐___________/|_▌", + "▐__________/|__▌", + "▐_________/|___▌", + "▐________/|____▌", + "▐_______/|_____▌", + "▐______/|______▌", + "▐_____/|_______▌", + "▐____/|________▌", + "▐___/|_________▌", + "▐__/|__________▌", + "▐_/|___________▌", + "▐/|____________▌" + ] + }, + "dqpb": { + "interval": 100, + "frames": [ + "d", + "q", + "p", + "b" + ] + }, + "weather": { + "interval": 100, + "frames": [ + "☀️ ", + "☀️ ", + "☀️ ", + "🌤 ", + "⛅️ ", + "🌥 ", + "☁️ ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "🌨 ", + "🌧 ", + "🌨 ", + "☁️ ", + "🌥 ", + "⛅️ ", + "🌤 ", + "☀️ ", + "☀️ " + ] + }, + "christmas": { + "interval": 400, + "frames": [ + "🌲", + "🎄" + ] + }, + "grenade": { + "interval": 80, + "frames": [ + "، ", + "′ ", + " ´ ", + " ‾ ", + " ⸌", + " ⸊", + " |", + " ⁎", + " ⁕", + " ෴ ", + " ⁓", + " ", + " ", + " " + ] + }, + "point": { + "interval": 125, + "frames": [ + "∙∙∙", + "●∙∙", + "∙●∙", + "∙∙●", + "∙∙∙" + ] + }, + "layer": { + "interval": 150, + "frames": [ + "-", + "=", + "≡" + ] + }, + "betaWave": { + "interval": 80, + "frames": [ + "ρββββββ", + "βρβββββ", + "ββρββββ", + "βββρβββ", + "ββββρββ", + "βββββρβ", + "ββββββρ" + ] + }, + "fingerDance": { + "interval": 160, + "frames": [ + "🤘 ", + "🤟 ", + "🖖 ", + "✋ ", + "🤚 ", + "👆 " + ] + }, + "fistBump": { + "interval": 80, + "frames": [ + "🤜    🤛 ", + "🤜    🤛 ", + "🤜    🤛 ", + " 🤜  🤛  ", + "  🤜🤛   ", + " 🤜✨🤛   ", + "🤜 ✨ 🤛  " + ] + }, + "soccerHeader": { + "interval": 80, + "frames": [ + " 🧑⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 " + ] + }, + "mindblown": { + "interval": 160, + "frames": [ + "😐 ", + "😐 ", + "😮 ", + "😮 ", + "😦 ", + "😦 ", + "😧 ", + "😧 ", + "🤯 ", + "💥 ", + "✨ ", + "  ", + "  ", + "  " + ] + }, + "speaker": { + "interval": 160, + "frames": [ + "🔈 ", + "🔉 ", + "🔊 ", + "🔉 " + ] + }, + "orangePulse": { + "interval": 100, + "frames": [ + "🔸 ", + "🔶 ", + "🟠 ", + "🟠 ", + "🔶 " + ] + }, + "bluePulse": { + "interval": 100, + "frames": [ + "🔹 ", + "🔷 ", + "🔵 ", + "🔵 ", + "🔷 " + ] + }, + "orangeBluePulse": { + "interval": 100, + "frames": [ + "🔸 ", + "🔶 ", + "🟠 ", + "🟠 ", + "🔶 ", + "🔹 ", + "🔷 ", + "🔵 ", + "🔵 ", + "🔷 " + ] + }, + "timeTravel": { + "interval": 100, + "frames": [ + "🕛 ", + "🕚 ", + "🕙 ", + "🕘 ", + "🕗 ", + "🕖 ", + "🕕 ", + "🕔 ", + "🕓 ", + "🕒 ", + "🕑 ", + "🕐 " + ] + }, + "aesthetic": { + "interval": 80, + "frames": [ + "▰▱▱▱▱▱▱", + "▰▰▱▱▱▱▱", + "▰▰▰▱▱▱▱", + "▰▰▰▰▱▱▱", + "▰▰▰▰▰▱▱", + "▰▰▰▰▰▰▱", + "▰▰▰▰▰▰▰", + "▰▱▱▱▱▱▱" + ] + }, + "dwarfFortress": { + "interval": 80, + "frames": [ + " ██████£££ ", + "☺██████£££ ", + "☺██████£££ ", + "☺▓█████£££ ", + "☺▓█████£££ ", + "☺▒█████£££ ", + "☺▒█████£££ ", + "☺░█████£££ ", + "☺░█████£££ ", + "☺ █████£££ ", + " ☺█████£££ ", + " ☺█████£££ ", + " ☺▓████£££ ", + " ☺▓████£££ ", + " ☺▒████£££ ", + " ☺▒████£££ ", + " ☺░████£££ ", + " ☺░████£££ ", + " ☺ ████£££ ", + " ☺████£££ ", + " ☺████£££ ", + " ☺▓███£££ ", + " ☺▓███£££ ", + " ☺▒███£££ ", + " ☺▒███£££ ", + " ☺░███£££ ", + " ☺░███£££ ", + " ☺ ███£££ ", + " ☺███£££ ", + " ☺███£££ ", + " ☺▓██£££ ", + " ☺▓██£££ ", + " ☺▒██£££ ", + " ☺▒██£££ ", + " ☺░██£££ ", + " ☺░██£££ ", + " ☺ ██£££ ", + " ☺██£££ ", + " ☺██£££ ", + " ☺▓█£££ ", + " ☺▓█£££ ", + " ☺▒█£££ ", + " ☺▒█£££ ", + " ☺░█£££ ", + " ☺░█£££ ", + " ☺ █£££ ", + " ☺█£££ ", + " ☺█£££ ", + " ☺▓£££ ", + " ☺▓£££ ", + " ☺▒£££ ", + " ☺▒£££ ", + " ☺░£££ ", + " ☺░£££ ", + " ☺ £££ ", + " ☺£££ ", + " ☺£££ ", + " ☺▓££ ", + " ☺▓££ ", + " ☺▒££ ", + " ☺▒££ ", + " ☺░££ ", + " ☺░££ ", + " ☺ ££ ", + " ☺££ ", + " ☺££ ", + " ☺▓£ ", + " ☺▓£ ", + " ☺▒£ ", + " ☺▒£ ", + " ☺░£ ", + " ☺░£ ", + " ☺ £ ", + " ☺£ ", + " ☺£ ", + " ☺▓ ", + " ☺▓ ", + " ☺▒ ", + " ☺▒ ", + " ☺░ ", + " ☺░ ", + " ☺ ", + " ☺ &", + " ☺ ☼&", + " ☺ ☼ &", + " ☺☼ &", + " ☺☼ & ", + " ‼ & ", + " ☺ & ", + " ‼ & ", + " ☺ & ", + " ‼ & ", + " ☺ & ", + "‼ & ", + " & ", + " & ", + " & ░ ", + " & ▒ ", + " & ▓ ", + " & £ ", + " & ░£ ", + " & ▒£ ", + " & ▓£ ", + " & ££ ", + " & ░££ ", + " & ▒££ ", + "& ▓££ ", + "& £££ ", + " ░£££ ", + " ▒£££ ", + " ▓£££ ", + " █£££ ", + " ░█£££ ", + " ▒█£££ ", + " ▓█£££ ", + " ██£££ ", + " ░██£££ ", + " ▒██£££ ", + " ▓██£££ ", + " ███£££ ", + " ░███£££ ", + " ▒███£££ ", + " ▓███£££ ", + " ████£££ ", + " ░████£££ ", + " ▒████£££ ", + " ▓████£££ ", + " █████£££ ", + " ░█████£££ ", + " ▒█████£££ ", + " ▓█████£££ ", + " ██████£££ ", + " ██████£££ " + ] + } +} diff --git a/bin/bash-progress-indicator/bash-cli-spinners/test.sh b/bin/bash-progress-indicator/bash-cli-spinners/test.sh new file mode 100755 index 0000000..f57c64b --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/test.sh @@ -0,0 +1,225 @@ +#!/bin/bash + +# Basic test suite for bash-cli-spinners +# Tests core functionality, dependencies, and data integrity + +# shellcheck disable=SC2034 # Disable unused variable warnings for color codes +# Note: Not using 'set -e' to allow tests to continue even if some fail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SPINNER_SCRIPT="$SCRIPT_DIR/spinner.sh" +SPINNERS_JSON="$SCRIPT_DIR/spinners.json" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Test counters +TESTS_RUN=0 +TESTS_PASSED=0 +TESTS_FAILED=0 + +# Test result tracking +test_pass() { + ((TESTS_RUN++)) + ((TESTS_PASSED++)) + echo -e "${GREEN}✓${NC} $1" +} + +test_fail() { + ((TESTS_RUN++)) + ((TESTS_FAILED++)) + echo -e "${RED}✗${NC} $1" + echo "🚨 TEST FAILURE DETAILS:" + echo " - Failed test: $1" + echo " - Script: $0" + echo " - Working directory: $(pwd)" + echo " - Files in current directory:" + ls -la || echo " Could not list files" + echo +} + +test_skip() { + echo -e "${YELLOW}⚠${NC} $1 (SKIPPED)" +} + +echo "🧪 Running bash-cli-spinners test suite..." +echo + +# Test 1: Check if required files exist +echo "📁 File Existence Tests" +if [[ -f "$SPINNER_SCRIPT" ]]; then + test_pass "spinner.sh exists" +else + test_fail "spinner.sh not found at $SPINNER_SCRIPT" +fi + +if [[ -f "$SPINNERS_JSON" ]]; then + test_pass "spinners.json exists" +else + test_fail "spinners.json not found at $SPINNERS_JSON" +fi + +# Test 2: Check if spinner.sh is executable +if [[ -x "$SPINNER_SCRIPT" ]]; then + test_pass "spinner.sh is executable" +else + test_fail "spinner.sh is not executable (run: chmod +x spinner.sh)" +fi + +echo + +# Test 3: Check dependencies +echo "🔧 Dependency Tests" +if command -v jq >/dev/null 2>&1; then + test_pass "jq is installed" +else + test_fail "jq is not installed (required for JSON parsing)" +fi + +if command -v bc >/dev/null 2>&1; then + test_pass "bc is installed" +else + test_fail "bc is not installed (required for timing calculations)" +fi + +echo + +# Test 4: JSON validity and structure +echo "📋 JSON Data Tests" +if command -v jq >/dev/null 2>&1 && [[ -f "$SPINNERS_JSON" ]]; then + if jq empty "$SPINNERS_JSON" >/dev/null 2>&1; then + test_pass "spinners.json is valid JSON" + + # Count spinners + spinner_count=$(jq 'keys | length' "$SPINNERS_JSON" 2>/dev/null || echo "0") + if [[ $spinner_count -gt 0 ]]; then + test_pass "spinners.json contains $spinner_count spinners" + else + test_fail "spinners.json contains no spinners" + fi + + # Test a few specific spinners exist + for spinner in "dots" "line" "pong"; do + if jq -e ".\"$spinner\"" "$SPINNERS_JSON" >/dev/null 2>&1; then + test_pass "Spinner '$spinner' exists in database" + else + test_fail "Spinner '$spinner' missing from database" + fi + done + + # Test spinner data structure + if jq -e '.dots.interval' "$SPINNERS_JSON" >/dev/null 2>&1 && \ + jq -e '.dots.frames[]' "$SPINNERS_JSON" >/dev/null 2>&1; then + test_pass "Spinner data has correct structure (interval + frames)" + else + test_fail "Spinner data structure is invalid" + fi + + else + test_fail "spinners.json is not valid JSON" + fi +else + test_skip "JSON validation (jq not available or file missing)" +fi + +echo + +# Test 5: Basic script functionality +echo "⚡ Functionality Tests" +if [[ -x "$SPINNER_SCRIPT" ]]; then + # Test help command + if "$SPINNER_SCRIPT" help >/dev/null 2>&1; then + test_pass "Help command works" + else + test_fail "Help command failed" + fi + + # Test list command + if "$SPINNER_SCRIPT" list >/dev/null 2>&1; then + test_pass "List command works" + else + test_fail "List command failed" + fi + + # Test invalid spinner handling + if ! "$SPINNER_SCRIPT" show nonexistent_spinner 1 >/dev/null 2>&1; then + test_pass "Invalid spinner name properly rejected" + else + test_fail "Invalid spinner name was accepted" + fi + + # Test sourcing (if dependencies available) + if command -v jq >/dev/null 2>&1 && command -v bc >/dev/null 2>&1; then + # shellcheck source=spinner.sh disable=SC1091 + if source "$SPINNER_SCRIPT" 2>/dev/null && \ + declare -f show_spinner >/dev/null 2>&1; then + test_pass "Script can be sourced and functions are available" + else + test_fail "Script sourcing failed or functions not available" + fi + else + test_skip "Function sourcing test (dependencies missing)" + fi + +else + test_skip "Functionality tests (spinner.sh not executable)" +fi + +echo + +# Test 6: Performance check (basic) +echo "🚀 Performance Tests" +if [[ -x "$SPINNER_SCRIPT" ]] && command -v jq >/dev/null 2>&1; then + # Time the list command + start_time=$(date +%s%N) + "$SPINNER_SCRIPT" list >/dev/null 2>&1 + end_time=$(date +%s%N) + duration=$(( (end_time - start_time) / 1000000 )) # Convert to milliseconds + + if [[ $duration -lt 1000 ]]; then # Less than 1 second + test_pass "List command completes quickly (${duration}ms)" + else + test_fail "List command is slow (${duration}ms)" + fi +else + test_skip "Performance tests (dependencies missing)" +fi + +echo + +# Test Summary +echo "📊 Test Summary" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "Tests run: $TESTS_RUN" +echo -e "Passed: ${GREEN}$TESTS_PASSED${NC}" +if [[ $TESTS_FAILED -gt 0 ]]; then + echo -e "Failed: ${RED}$TESTS_FAILED${NC}" +else + echo -e "Failed: $TESTS_FAILED" +fi + +echo + +if [[ $TESTS_FAILED -eq 0 ]]; then + echo -e "${GREEN}🎉 All tests passed!${NC}" + exit 0 +else + echo -e "${RED}❌ Some tests failed.${NC}" + echo "Please check the failed tests above and resolve any issues." + echo + echo "🔍 Environment Information:" + echo " - Working directory: $(pwd)" + echo " - Script location: $0" + echo " - Spinner script: $SPINNER_SCRIPT" + echo " - Spinners JSON: $SPINNERS_JSON" + echo " - Available files:" + ls -la 2>/dev/null || echo " Could not list files" + echo + echo "🔧 Dependencies Check:" + command -v jq >/dev/null && echo " - jq: $(which jq)" || echo " - jq: NOT FOUND" + command -v bc >/dev/null && echo " - bc: $(which bc)" || echo " - bc: NOT FOUND" + exit 1 +fi \ No newline at end of file diff --git a/bin/bash-progress-indicator/bash-cli-spinners/website/README.md b/bin/bash-progress-indicator/bash-cli-spinners/website/README.md new file mode 100644 index 0000000..e8354d8 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/website/README.md @@ -0,0 +1,69 @@ +# Spinner Gallery Website + +This website displays all available CLI spinners in an interactive grid +format, making it easy to browse and select spinners for your projects. + +## Features + +- **Interactive Grid**: All 88 spinners displayed simultaneously with live + animations at their authentic speeds +- **Dynamic Layout**: 4-column grid that adapts when searching/filtering +- **Search/Filter**: Real-time search to find specific spinners +- **Click to Copy**: Click any spinner to copy its name to clipboard +- **Theme Toggle**: Light/dark theme switcher with localStorage persistence +- **Responsive Design**: Works on desktop, tablet, and mobile devices +- **Live Animations**: Each spinner runs at its correct interval timing +- **Font Rendering Note**: Includes explanation why some spinners may appear + different than in terminal + +## Usage + +### Quick Start + +1. Use the Makefile target: + ```bash + make serve + ``` + +2. Open your browser to: `http://localhost:8080` + +### Manual Setup + +1. Start a local web server: + ```bash + cd website + python3 -m http.server 8080 + ``` + +2. Open your browser to: `http://localhost:8080` + +### Alternative Servers + +```bash +# Node.js (if you have npx) +npx serve . + +# PHP +php -S localhost:8000 + +# Python 2 +python -m SimpleHTTPServer 8080 +``` + +## File Structure + +- `index.html` - Main website file (self-contained with CSS/JS) +- `README.md` - This documentation +- `spinners.json` - Symlinked from parent directory (auto-created by `make + serve`) + +The website loads spinner data from a symlinked `spinners.json` file that +points to `../spinners.json`. + +## Browser Compatibility + +- Chrome/Edge 63+ +- Firefox 53+ +- Safari 13.1+ +- iOS Safari 13.4+ +- Any modern browser with JavaScript enabled diff --git a/bin/bash-progress-indicator/bash-cli-spinners/website/index.html b/bin/bash-progress-indicator/bash-cli-spinners/website/index.html new file mode 100644 index 0000000..c5e6ca2 --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/website/index.html @@ -0,0 +1,412 @@ + + + + + + Bash CLI Spinners Gallery + + + + + +
+

🌀 Bash CLI Spinners Gallery

+

Click any spinner to copy its name to clipboard

+

+ Note: Some spinners may appear different than in terminal due to font rendering +

+ +
+ +
+ +
+ Loading spinners... +
+
+ +
+
+ +
+ No spinners found matching your search. +
+ +
+ Copied to clipboard! +
+ + + + diff --git a/bin/bash-progress-indicator/bash-cli-spinners/website/spinners.json b/bin/bash-progress-indicator/bash-cli-spinners/website/spinners.json new file mode 120000 index 0000000..3588fff --- /dev/null +++ b/bin/bash-progress-indicator/bash-cli-spinners/website/spinners.json @@ -0,0 +1 @@ +../spinners.json \ No newline at end of file -- 2.52.0