Full Code of unkontributors/super_unko for AI

oshiri a73b56dc01a6 cached
65 files
131.4 KB
58.2k tokens
1 requests
Download .txt
Repository: unkontributors/super_unko
Branch: oshiri
Commit: a73b56dc01a6
Files: 65
Total size: 131.4 KB

Directory structure:
gitextract_nf5gjjz4/

├── .github/
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── release.yml
│       └── unko.yml
├── .tar2package.yml
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── activate.sh
├── bin/
│   ├── bigunko.show
│   ├── super_unko
│   ├── unko.any
│   ├── unko.encode
│   ├── unko.fizzbuzz
│   ├── unko.grep
│   ├── unko.king
│   ├── unko.life
│   ├── unko.ls
│   ├── unko.ping
│   ├── unko.printpnm
│   ├── unko.puzzle
│   ├── unko.pyramid
│   ├── unko.question
│   ├── unko.say
│   ├── unko.shout
│   ├── unko.think
│   ├── unko.toilet
│   ├── unko.tower
│   ├── unko.tr
│   └── unko.yes
├── doc/
│   ├── ci-push.puml
│   ├── unko.puzzle.md
│   └── unko.toilet.md
├── docker/
│   ├── Dockerfile
│   └── install_bash.sh
├── docker-compose-ci.yml
├── docker-compose.yml
├── install.sh
├── lib/
│   └── super_unko/
│       ├── bigunko.txt
│       ├── unko.cow
│       ├── unko.csv
│       ├── unko.lib
│       ├── unko_command_not_found_hundle
│       └── unko_mb.cow
├── linter.sh
├── package.sh
├── pkg/
│   ├── super_unko.deb
│   └── super_unko.rpm
├── super_unko.plugin.zsh
├── test/
│   ├── functions.sh
│   ├── super_unko-test.bats
│   ├── unko.any-test.bats
│   ├── unko.encode-test.bats
│   ├── unko.fizzbuzz-test.bats
│   ├── unko.grep-test.bats
│   ├── unko.king-test.bats
│   ├── unko.printpnm-test.bats
│   ├── unko.pyramid-test.bats
│   ├── unko.toilet-test.bats
│   ├── unko.tower-test.bats
│   ├── unko.tr-test.bats
│   └── unko.yes-test.bats
├── test.sh
├── uninstall.sh
└── 💩.💩

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## Check list

* [ ] Were all tests passed of CI?
  * (Case: failing `test`) Please run tests and fix your code (see also: [Testing](https://github.com/unkontributors/super_unko/blob/oshiri/README.md#testing))
  * (Case: failing `format`) Please run `./linter.sh format-save` (see also: [CodeStyle and lint](https://github.com/unkontributors/super_unko/blob/oshiri/README.md#codestyle-and-lint))
  * (Case: failing `lint`) Please run linter and fix your code (see also: [CodeStyle and lint](https://github.com/unkontributors/super_unko/blob/oshiri/README.md#codestyle-and-lint))
* [ ] (Case: adding new command) Were tests added to cover new commands ?
* [ ] (Case: adding new command) Were descriptions for new commands added to README?



================================================
FILE: .github/workflows/release.yml
================================================
name: release

on:
  release:
    types: [published]

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Set output
        id: vars
        run: echo ::set-output name=tag::${GITHUB_REF:10}
      - name: Set tag to .tar2package.yml
        run: sed -i 's:\$VERSION:${{ steps.vars.outputs.tag }}:g' .tar2package.yml
      - run: Print .tar2package.yml
      - name: Generate packages
        run: ./package.sh
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files:
            - pkg/*.deb
            - pkg/*.rpm
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}



================================================
FILE: .github/workflows/unko.yml
================================================
name: test

on:
  push:
    branches:
      - oshiri
    paths-ignore:
      - 'LICENSE'
      - 'README.*'
      - 'doc/*'
      - 'img/*'
      - 'pkg/*'
  pull_request:
    paths-ignore:
      - 'LICENSE'
      - 'README.*'
      - 'doc/*'
      - 'img/*'
      - 'pkg/*'

env:
  APP_NAME: super_unko
  DOCKER_BUILDKIT: 1

jobs:
  skip:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Skip job"

  before:
    runs-on: ubuntu-latest
    if: "! contains(github.event.head_commit.message, '[skip ci]')"
    steps:
      - run: echo "no [skip ci]"

  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        version: [default, "3.2", "4.0", "4.1", "4.2", "4.3", "4.4", "5.0"]
    needs: before
    steps:
      - uses: actions/checkout@v2
      # FIXME: #95
      # - uses: satackey/action-docker-layer-caching@v0.0.8
      #   with:
      #     key: docker-image-cache-${{ matrix.version }}-{hash}
      #     restore-keys: |
      #       docker-image-cache-${{ matrix.version }}-
      - name: Test
        run: docker-compose -f docker-compose-ci.yml run ci_sh_${{ matrix.version }}

  format:
    runs-on: ubuntu-latest
    needs: before
    steps:
      - uses: actions/checkout@v2
      - name: Run format
        run: ./linter.sh format

  lint:
    runs-on: ubuntu-latest
    needs: before
    steps:
      - uses: actions/checkout@v2
      - name: Run lint
        run: ./linter.sh lint

  update-repository:
    runs-on: ubuntu-latest
    needs: [test, format, lint]
    if: github.ref == 'refs/heads/oshiri'
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

        # deb, rpmファイルの生成
      - name: Set latest tag version to output
        id: vars
        run: echo ::set-output name=tag::$(git tag -l '*.*.*' | sort -V | tail -n 1)
      - name: Set tag version to .tar2package.yml
        run: sed -i 's:\$VERSION:${{ steps.vars.outputs.tag }}:g' .tar2package.yml
      - name: Print .tar2package.yml
        run: cat .tar2package.yml
      - name: Generate packages
        run: ./package.sh
      - name: Git commit packages
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add pkg/*
          git commit -m ":arrow_up: [CI] update pkg/${{ env.APP_NAME }}.deb and pkg/${{ env.APP_NAME }}.rpm"

        # READMEに目次を埋め込む
      - name: Install gh-md-toc
        run: |
          wget https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc
          chmod +x gh-md-toc
      - name: Insert TOC
        run: |
          ./gh-md-toc --insert *.md doc/*.md
          rm *.md.orig.*
          rm *.md.toc.*
          rm doc/*.md.orig.*
          rm doc/*.md.toc.*
      - name: Git commit documents
        run: |
          git add *.md doc/*.md
          git commit -m ":memo: [CI] update TOC"

      - name: Git push
        uses: ad-m/github-push-action@v0.5.0
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: oshiri


================================================
FILE: .tar2package.yml
================================================
name : superunko
cmdname : superunko
summary : Super Unko
description : super_unko project is the one of the awesome, clean and sophisticated OSS project in the world. Let us create shit commands.
version : $VERSION
changelog : unko.tower power up
url : https://github.com/unkontributors/super_unko
author : Awesome Unkontributors
email : super@unko.com
libdir : /usr/lib


================================================
FILE: .travis.yml
================================================
language: bash

env:
  global:
    - PATH=${PATH}:${HOME}/kcov/bin

addons:
  apt:
    packages:
      - binutils-dev
      - libcurl4-openssl-dev
      - libdw-dev
      - libiberty-dev
      - bats

before_install:
    # kcov - coverage
  - wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz

install:
    # kcov
  - tar xzf master.tar.gz
  - cd kcov-master
  - mkdir build
  - cd build
  - cmake -DCMAKE_INSTALL_PREFIX=${HOME}/kcov ..
  - make
  - make install
  - cd ../..
  - rm -rf kcov-master
  - mkdir -p coverage

script:
  - |
    if [[ "$SH_VERSION" == default ]]; then
      # コンテナ経由で実行しようとすると失敗するのでしかたなく直接実行
      ./test.sh || true
    fi

after_success:
  # ダミーで送信
  - |
    if [[ "$SH_VERSION" == default ]]; then
      kcov --coveralls-id=$TRAVIS_JOB_ID test/coverage bin/unko.tower 3
    fi


================================================
FILE: LICENSE
================================================
💩 License

Copyright (c) 2017 greymd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this 💩 and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, 💩, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial 💩 of the Software.

THE SOFTWARE IS PROVIDED "💩", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
.PHONY: default
default: usage

.PHONY: usage
usage: ## Print help
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: setup
setup: ## Setup docker images
	docker-compose build
	docker-compose -f docker-compose-ci.yml build

.PHONY: check
check: test lint ## Run tests and linter

.PHONY: lint
lint: ## Run linter
	./linter.sh all

.PHONY: test
test: ## Run tests
	docker-compose -f docker-compose-ci.yml run --rm ci_sh_5.0

.PHONY: test-bash-version
test-bash-version: ## Run test all bash version
	docker-compose -f docker-compose-ci.yml up

.PHONY: clean
package: ## Build packages
	./package.sh

.PHONY: clean
clean: ## Clean packages
	$(RM) super_unko.tar.gz pkg/*.tmp


================================================
FILE: README.md
================================================
<h1 align="center">
  <img src="img/logo.png" width=50% />
</h1>

[![License](https://img.shields.io/badge/license-%F0%9F%92%A9-orange.svg)](./LICENSE)
[![Build Status](https://travis-ci.org/unkontributors/super_unko.svg?branch=oshiri)](https://travis-ci.org/unkontributors/super_unko)
[![Coverage Status](https://coveralls.io/repos/github/unkontributors/super_unko/badge.svg?branch=oshiri)](https://coveralls.io/github/unkontributors/super_unko?branch=oshiri)
![GitHub Actions Build Status](https://github.com/unkontributors/super_unko/workflows/test/badge.svg)

super_unko project is the one of the awesome, clean and sophisticated OSS project in the world.
Let's create poop commands!

super_unko プロジェクトは世界で最もクリーンで洗練されたOSSプロジェクトの一つです。
うんこなコマンドを作りましょう。

Table of Contents

<!--ts-->
* [Commands](README.md#commands)
* [Installation](README.md#installation)
   * [Linux](README.md#linux)
      * [With yum (RHEL compatible distros)](README.md#with-yum-rhel-compatible-distros)
      * [With apt (Debian base distros)](README.md#with-apt-debian-base-distros)
      * [With AUR (ArchLinux base distros)](README.md#with-aur-archlinux-base-distros)
   * [macOS](README.md#macos)
   * [Docker](README.md#docker)
   * [Zsh plugin manager](README.md#zsh-plugin-manager)
   * [Additional Installation](README.md#additional-installation)
* [Usage](README.md#usage)
* [Development](README.md#development)
   * [Codestyle and lint](README.md#codestyle-and-lint)
      * [Help](README.md#help)
      * [Code format](README.md#code-format)
      * [Code format and save](README.md#code-format-and-save)
      * [Code lint](README.md#code-lint)
      * [Code format and lint](README.md#code-format-and-lint)
   * [Testing](README.md#testing)
   * [CI workflow](README.md#ci-workflow)
* [Contribution](README.md#contribution)
* [LICENSE](README.md#license)
   * [Source Code](README.md#source-code)
   * [Logo](README.md#logo)
* [History](README.md#history)
* [For Unkontributors (開発者向け)](README.md#for-unkontributors-開発者向け)

<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
<!-- Added by: runner, at: Mon Apr 11 15:08:44 UTC 2022 -->

<!--te-->

Commands
========================

| Command       | Description |
|---------------|-------------|
| super_unko    | Controles sub unkommands |
| unko.tr       | Convert various expressions equals to poop into 💩 (poop). |
| unko.ls       | Shows various poop expression. |
| unko.yes      | Generate 💩 poop forever. |
| unko.tower    | Build your poop tower. |
| unko.pyramid  | Build your poop pyramid. |
| bigunko.show  | Big poop. |
| unko.printpnm | Generate 💩 PNM image file. |
| unko.puzzle   | Sliding block puzzle. |
| unko.toilet   | Display large 💩 characters. |
| unko.grep     | Print lines matching a 💩 pattern. |
| unko.say      | King 💩 says a message. |
| unko.shout    | King 💩 shouts a message. |
| unko.think    | King 💩 thinks something. |
| unko.life     | Play 💩's game of life. |
| unko.any      | Simple wrapper to 💩 substitution for unko.shout. |
| unko.king     | Build your king shift tower. |
| unko.fizzbuzz | No need to implement FizzBuzz. |
| unko.ping     | Ping the 💩 domain. |
| unko.encode   | Encode/Decode data and print to standard output. |
| unko.date     | TBD |
| unko.awk      | TBD |
| unko.xargs    | TBD |

Installation
========================

## Linux

### With `yum` (RHEL compatible distros)

```
$ sudo yum install https://git.io/superunko.linux.rpm
```

Uninstall (not `super_unko`)

```
$ sudo yum remove superunko
```


### With `apt` (Debian base distros)

```
$ wget https://git.io/superunko.linux.deb
$ sudo dpkg -i ./superunko.linux.deb
```

Uninstall (not `super_unko`)

```
$ sudo apt remove superunko
```

### With AUR (ArchLinux base distros)

You can install `super_unko` from https://aur.archlinux.org/packages/super_unko-git/ with your favorite aur helper.

e.g. with yay:

```
$ yay -S super_unko-git
```

Uninstall (not `super_unko`)

```
$ sudo pacman -R super_unko-git
```

## macOS

* With Homebrew

```
$ brew tap unkontributors/unko
$ brew install super_unko
```

Uninstall

```
$ brew remove super_unko
```


## Docker

* With docker

```bash
$ git clone https://github.com/unkontributors/super_unko.git
$ cd super_unko
$ docker-compose build
$ docker-compose run super_unko unko.shout こんにちは
$ docker run --rm -it unkontributors/super_unko unko.shout こんにちは
```

## Zsh plugin manager

Zsh plugin managers like [antigen](https://github.com/zsh-users/antigen), [zplug](https://github.com/zplug/zplug) can be adoptive.
Not only commands can be used but also [`command_not_found_handler`](https://github.com/zsh-users/zsh/blob/master/README#L249) is updated.
It is extremely helpful for developers.

* Example of antigen

```
antigen bundle "unkontributors/super_unko"
```

## Additional Installation

- [unko.puzzle](./doc/unko.puzzle.md)
- unko.shout - Need a [echo-sd](https://github.com/fumiyas/home-commands) command
- unko.say - Need a `cowsay` command (`$ apt install cowsay`)
- unko.think - Need a `cowthink` command (`$ apt install cowsay`)
- unko.toilet - Need a `toilet` command (`$ apt install toilet`)

Usage
========================

```
$ echo "うんこ" | unko.tr
💩

$ echo "うんち" | unko.tr
💩

$ ./unko.yes
💩
💩
💩
💩
💩
💩
💩
...
```

Development
========================

## Codestyle and lint

We are checking code with [shfmt](https://github.com/mvdan/sh) and [shellcheck](https://github.com/koalaman/shellcheck).
Please check your code by `linter.sh` if you want to add your origin unko commands.
We must provide clean unkos.
So, please run below and pass all checkings.

```bash
make setup

make lint
# or
./linter.sh
```

`linter.sh` checks your code or all code of this project.
**`linter.sh` depends on `docker` and `docker-compose` commands.**
And you **don't** need to install `shfmt` and `shellcheck`.

Usage examples of `linter.sh` are below.

### Help

```bash
./linter.sh help
```

### Code format

```bash
./linter.sh format
```

### Code format and save

```bash
./linter.sh format-save
```

### Code lint

```bash
./linter.sh lint
```

### Code format and lint

```bash
./linter.sh all
```

## Testing

We use the [bats](https://github.com/sstephenson/bats) testing framework.
`test.sh` calls the `bats`. But you **don't** need to install `bats`.
Test tasks use `docker` and the `docker` uses `bats` internally and runs tests.

Run below for testing.

```bash
make setup ## Need long times to build docker images.
make test
```

Run below for testing on multiple Bash versions.
Please do that and fix it if tests failed on CI.

```bash
make check
make test-bash-version
```

## CI workflow

CI workflow runs when you pushed.
Workflow diagram is below.

![CI push](./doc/ci-push.svg)

Contribution
========================
Welcome! Welcome!

LICENSE
==============

## Source Code
💩 LICENSE
 (Something like BSD license)

## Logo
Creative 💩 license
(Something like public domain)

History
==============

* [シェル芸勉強会中に爆誕したsuper_unkoリポジトリを巡る悲喜交々 - Togetter](https://togetter.com/li/1144376)
* [【まとめたくない】super_unkoリポジトリがスクスク成長【義務感】 - Togetter](https://togetter.com/li/1145304)

For Unkontributors (開発者向け)
========================

Please put your commands under `bin` directory.
Run `bash package.sh` on a host which `docker` installed to generate multiple installer packages under `pkg` directory.

Codebase is supposed to be scanned with code formatter and static analysis tools to ensure the quality of the code.
Please make sure prepared static checks are passed by running `./liner.sh all` before submitting your PR.
It would be appreciated if you could add tests to `./test.sh`.

Please make sure the default branch of this repository is `oshiri` (which means "bum") not `master`.

bin 以下になんか思いついたコマンドを放り投げてください。
docker が入った環境で `bash package.sh` すると pkg 以下に各種インストーラーが作成されます。

CIでコードフォーマットと静的解析にかけてコード品質を維持するようになりました。
PRするときは`./linter.sh all`で静的解析をパスすることを確認してください。

可能なら`./test.sh`にもテストコードを追加していただけると助かります。

なお、このリポジトリのデフォルトのブランチは`oshiri`であり`master`ではありません。


================================================
FILE: activate.sh
================================================
#!/bin/bash

if ! type super_unko > /dev/null 2>&1; then
  THIS_DIR=$(
    cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
  )
  export PATH="$PATH:$THIS_DIR/bin"
  # shellcheck source=/dev/null
  source "$THIS_DIR/lib/super_unko/unko_command_not_found_hundle"
fi


================================================
FILE: bin/bigunko.show
================================================
#!/bin/bash

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

echo -ne "$(base64 --decode < "${LIB_DIR}/bigunko.txt" | tr -d \\n)"


================================================
FILE: bin/super_unko
================================================
#!/bin/bash

set -eu

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

SCRIPT_NAME="$(basename "${BASH_SOURCE:-$0}")"
readonly SCRIPT_NAME

main() {
  if [[ $# -lt 1 ]]; then
    log "Must need sub command."
    usage >&2
    return 1
  fi

  local cmd="$1"
  shift

  case "$cmd" in
    help)
      usage
      return
      ;;
    *)
      local cmd_path
      local ret

      set +eu
      cmd_path="$(to_command_path "$cmd")"
      ret=$?
      if [[ "$ret" -eq 0 ]]; then
        "$cmd_path" "$@"
        return
      fi
      set -eu

      log "Illegal sub command. (cmd = $cmd)"
      usage >&2
      return 1
      ;;
  esac
}

usage() {
  cat << EOS
$SCRIPT_NAME is a master of unko.

About subcommands:
    $SCRIPT_NAME controles sub unkommands by own charisma.
    $SCRIPT_NAME can control them as unkommands if there are executables that
    called 'unko.*' or 'bigunko.*' in the same directory as $SCRIPT_NAME.

Available commands:
EOS
  local pad="    "
  echo "${pad}help"

  # bigunko.show系のを先に
  for cmd_fullpath in "$THIS_DIR/"bigunko*; do
    local cmd=${cmd_fullpath##*/}
    cmd=${cmd//unko./}
    echo "${pad}$cmd"
  done

  # unko.*系の
  for cmd_fullpath in "$THIS_DIR/"unko.*; do
    local cmd=${cmd_fullpath##*/*unko.}
    echo "${pad}$cmd"
  done
}

log() {
  echo -e "$SCRIPT_NAME: $*" 2>&1
}

## to_command_path はサブコマンド名からunkoコマンドのパスを得る
to_command_path() {
  local cmd="$1"

  for cmd_fullpath in "$THIS_DIR/bigunko".*; do
    local big_cmd=${cmd//big/bigunko.}
    local c=${cmd_fullpath##*/}
    if [[ "$c" == "$big_cmd" ]]; then
      echo "$cmd_fullpath"
      return
    fi
  done

  for cmd_fullpath in "$THIS_DIR/unko".*; do
    local c=${cmd_fullpath##*/unko.}
    if [[ "$c" == "$cmd" ]]; then
      echo "$cmd_fullpath"
      return
    fi
  done

  return 1
}

main ${1+"$@"}
exit $?


================================================
FILE: bin/unko.any
================================================
#!/bin/bash

set -eu

usage() {
  cat << EOF
Usage: $0 <UNKO> [PHRASE ...]
UNKO:   Alternative character of 💩.
PHRASE: Phrase for shout.
EOF
  exit 0
}

if [ $# -lt 1 ]; then
  usage
fi

UNKO="$1"
readonly UNKO

shift

UNKO_SHOUT="${0%/*}/unko.shout"
readonly UNKO_SHOUT

BASE_UNKO="$(exec "$UNKO_SHOUT" ${1+"$@"})"
readonly BASE_UNKO
echo -e "${BASE_UNKO//💩/$UNKO}"


================================================
FILE: bin/unko.encode
================================================
#!/bin/bash

if [[ "$LANG" = zh* ]] || [[ "$LANG" = en* ]]; then
  export TEXTDOMAINDIR="/usr/share/locale-langpack/${LANG%%.*}/LC_MESSAGES"
else
  export TEXTDOMAINDIR="/usr/share/locale-langpack/${LANG%%_*}/LC_MESSAGES"
fi
export TEXTDOMAIN=libc

UNKO_OCT="うんこウンコ💩👑"
usage() {
  echo "Usage: $0 [OPTION] [FILE]"
  echo "Unko encode or decode FILE, or standard input to standard output."
  echo "With no FILE, or when FILE is -, read standard input."
  echo "  -d : decode data"
  echo "  -h : display this help and exit"
}

encode() {
  od -b -v -An |
    sed -e "y/01234567/$UNKO_OCT/" |
    tr -d ' \n'
  echo
}

decode() {
  printf '%b' "$(
    sed "s/[^$UNKO_OCT]//g" |
      sed \
        -e "s/${UNKO_OCT:0:1}/0/g" \
        -e "s/${UNKO_OCT:1:1}/1/g" \
        -e "s/${UNKO_OCT:2:1}/2/g" \
        -e "s/${UNKO_OCT:3:1}/3/g" \
        -e "s/${UNKO_OCT:4:1}/4/g" \
        -e "s/${UNKO_OCT:5:1}/5/g" \
        -e "s/${UNKO_OCT:6:1}/6/g" \
        -e "s/${UNKO_OCT:7:1}/7/g" |
      tr -d '\n' |
      sed 's/.../\\&/g'
  )"
}

EXEC_COMMAND="encode"
FILE="-"

for arg in "$@"; do
  case "$arg" in
    "-h" | "--help")
      usage
      exit 0
      ;;
    "-d" | "--decode") EXEC_COMMAND="decode" ;;
    *) FILE="$arg" ;;
  esac
done

if [ "$FILE" = - ]; then
  "$EXEC_COMMAND"
else
  if [ -f "$FILE" ]; then
    "$EXEC_COMMAND" < "$FILE"
  elif [ -d "$FILE" ]; then
    printf '%s: %s: %s\n' "$0" "$FILE" $"Is a directory" >&2
    exit 1
  elif ! [ -e "$FILE" ]; then
    printf '%s: %s: %s\n' "$0" "$FILE" $"No such file or directory" >&2
    exit 1
  fi
fi

exit 0


================================================
FILE: bin/unko.fizzbuzz
================================================
#!/bin/bash

UNKO_FIZZ='💩'
UNKO_BUZZ='🍺'

king_unko() {
  unko.shout "$1"
}

usage() {
  cat << EOM
$0: $0 [unsigned_int]

$0: print fizzbuzz unkonized.

EOM
  exit 0
}

if [ $# -ne 1 ]; then
  usage
fi

is_integer() {
  IPT=$1
  if [[ "$IPT" =~ ^[0-9]+$ ]]; then
    return 0
  else
    return 1
  fi
}

if ! is_integer "$1"; then
  usage
fi

for ((NUM = 1; NUM <= $1; NUM++)); do
  if [ $((NUM % 3)) -eq 0 ] && [ $((NUM % 5)) -eq 0 ]; then
    king_unko "fizzbuzz"
  elif [ $((NUM % 5)) -eq 0 ]; then
    echo "$UNKO_BUZZ < buzz"
  elif [ $((NUM % 3)) -eq 0 ]; then
    echo "$UNKO_FIZZ < fizz"
  else
    echo "$NUM"
  fi
done


================================================
FILE: bin/unko.grep
================================================
#!/bin/bash

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

UNKO_REGEXP="$(awk -F , '1<NR{print $1}' "${LIB_DIR}/unko.csv" | tr '\n' '|' | sed -E 's/.$//')"
readonly UNKO_REGEXP

grep -E "$UNKO_REGEXP"


================================================
FILE: bin/unko.king
================================================
#!/bin/bash

set -eu

readonly THIS_CMD="${0##*/}"
readonly VERSION="v1.1.0"

# Unko parts
readonly TOP="${T:-👑}"
readonly UNKO="${U:-💩}"
readonly EYE="${E:-👁}"
readonly NOSE="${N:-👃}"
readonly MOUSE="${M:-👄}"
readonly LEFT_BRACKET="${L:-(}"
readonly RIGHT_BRACKET="${R:-)}"
readonly SPACE="${S:- }"

main() {
  local height=5

  if (($# < 1)); then
    print_king_unko "$height"
    return
  fi

  # 第1引数はヘルプ、バージョン、コマンド、段数のいずれか。
  #
  # サブコマンドの判定を2回行っている理由は、デフォルト値を使用してサブコマンド
  # を実行したいケースを処理するため。
  local opt="$1"
  shift
  case "$opt" in
    -h | --help)
      usage
      return
      ;;
    -v | --version)
      echo "$VERSION"
      return
      ;;
    shout)
      echo-sd "$@"
      print_king_unko "$height"
      return
      ;;
    *)
      height="$opt"

      if ! [[ "$height" =~ ^[[:digit:]]+$ ]]; then
        err "Invalid number '$height'"
        return 1
      fi

      # 数値を8進数として解釈しないようにするために
      # 0埋めの数値の先頭の0を削除
      height="$(sed -E "s/^0+//" <<< "$height")"

      if ((height < 5)); then
        err "Height must be not less than 5"
        err "See help ($THIS_CMD -h)"
        return 1
      fi
      ;;
  esac

  # 引数がなければkingを出力して終了
  if (($# < 1)); then
    print_king_unko "$height"
    return
  fi

  # サブコマンドとその引数として処理
  local sub_cmd="$1"
  shift
  case "$sub_cmd" in
    shout)
      echo-sd "$@"
      ;;
    *)
      err "Invalid sub command '$sub_cmd'"
      err "See help ($THIS_CMD -h)"
      return 1
      ;;
  esac
  print_king_unko "$height"
}

usage() {
  cat << EOS
$THIS_CMD prints a king unko.

Usage:
    $THIS_CMD -h | --help
    $THIS_CMD -v | --version
    $THIS_CMD [number] [shout] [sub options...]

Examples:
    $THIS_CMD
    $THIS_CMD 5
    $THIS_CMD shout おはようんこ
    $THIS_CMD 6 shout こんにちわーるど
    $THIS_CMD 7 shout --square こんばんわーるど
    echo さようんこなら | $THIS_CMD 8 shout -s

Options:
    -h --help                   Display this help and exit
    -v --version                Display this version and exit

Sub options:
    You can use options of 'echo-sd'.
    See 'echo-sd --help'.
EOS
}

## print_king_unko はキングウンコを任意の高さで出力する。
print_king_unko() {
  local height="$1"
  print_unko "$height" | set_parts
}

## print_unko は単純にうんこを任意の高さで出力する。
## トップには王冠がセットされる。
##
## うんこの高さ(h)とhに達するまでの変数iに対するうんこ(u)とパディング(p)算出の式は以下
##
## ウンコの数を求める関数 U
##   U(i)  = 2i - 1   (1 < i)
##   U'(i) = 0        (1 = i)
##
## パディングの数を求める関数 P
##   P(h,i)  = h - (i - 1)  (1 < i)
##   P'(h,i) = h + 1        (i = 1)
print_unko() {
  local height="$1"

  for ((i = 1; i <= height; i++)); do
    if ((i == 1)); then
      # i=1の時は王冠を出力
      local p=$((height + 1))
      local pad
      pad="$(repeat_str "$p" "$SPACE")"
      echo "${pad}${TOP}"
    else
      # うんこを出力
      local u=$((2 * i - 1))
      local p=$((height - (i - 1)))
      local unko
      local pad
      unko="$(repeat_str "$u" "$UNKO")"
      pad="$(repeat_str "$p" "$SPACE")"
      echo "${pad}${LEFT_BRACKET}${unko}${RIGHT_BRACKET}"
    fi
  done
}

## set_parts は目や口などのパーツをうんこにセットする。
set_parts() {
  # NOTE:
  #   sedの置換後の文字列に変数を使うとセパレータ文字が使えなくなるのでsedを使わ
  #   ない。
  awk \
    -v unko="$UNKO" \
    -v eye="$EYE" \
    -v nose="$NOSE" \
    -v mouse="$MOUSE" \
    'NR==3{
       r = unko unko unko unko unko
       s = unko eye unko eye unko
       gsub(r, s)
       print
     }
     NR==4{
       r = unko unko unko unko unko unko unko
       s = unko unko unko nose unko unko unko
       gsub(r, s)
       print
     }
     NR==5{
       r = unko unko unko unko unko unko unko unko unko
       s = unko unko unko unko mouse unko unko unko unko
       gsub(r, s)
       print
     }
     NR<3 || 5<NR { print }'
}

## repeat_str は任意の回数分、任意の文字を連続した1行のテキストを出力する。
repeat_str() {
  local n=$1
  local str=$2
  awk \
    -v n="$n" \
    -v str="$str" \
    'BEGIN{ for (i=0; i<n; i++) { printf "%s", str } }'
  echo
}

err() {
  echo -e "[ ERR ] $*" >&2
}

main ${1+"$@"}
exit $?


================================================
FILE: bin/unko.life
================================================
#!/usr/bin/env bash

set -u
CELL=()
NEXT_CELL=()
CURSOR_Y=0
CURSOR_X=0

## Use ANSI-C quoting because my text editor's layout is broken..
readonly DEFAULT_UNKO_LG_PLAYER=$'\xf0\x9f\x99\x87' # Person bowing
readonly DEFAULT_UNKO_LG_ALIVE=$'\xe2\xac\x9c'      # White tile. Toilet = $'\xf0\x9f\x9a\xbd'
readonly DEFAULT_UNKO_LG_DEAD=$'\xf0\x9f\x92\xa9'   # Unko
UNKO_LG_PLAYER=${UNKO_LG_PLAYER:-$DEFAULT_UNKO_LG_PLAYER}
UNKO_LG_ALIVE=${UNKO_LG_ALIVE:-$DEFAULT_UNKO_LG_ALIVE}
UNKO_LG_DEAD=${UNKO_LG_DEAD:-$DEFAULT_UNKO_LG_DEAD}

trap 'clear; cursor_visible' EXIT

usage() {
  cat <<- USAGE
Usage:
  unko.life [OPTIONS] [HEIGHT] [WIDTH]

OPTIONS:
  -h,--help    Display this help and exit

Environment Variables:
  * UNKO_LG_PLAYER ... Player icon
  * UNKO_LG_ALIVE  ... Alive cell
  * UNKO_LG_DEAD   ... Dead cell

Example:
  Play with below the command if your environment does not support any Emojis.
    $ UNKO_LG_ALIVE=_ UNKO_LG_DEAD="@" UNKO_LG_PLAYER="+" unko.life
USAGE
}

cursor_visible() {
  tput cnorm >&2
}

cursor_invisible() {
  tput civis >&2
}

cursor_topleft() {
  tput cup 0 0
}

initialize() {
  local _height="$1"
  shift
  local _width="$1"
  shift
  IFS=$'\n' read -r -a CELL -d '' <<< "$(yes 0 | head -n "$((_height * _width))")"
}

display() {
  local _height="$1"
  shift
  local _width="$1"
  shift
  local _msg="$1"
  shift
  local i=0
  cursor_topleft
  printf "\033[41m\033[4m\033[30m %s \033[0m: %s \\n" "Unko Generation" "$_msg"
  for s in "${CELL[@]}"; do
    ((i % _width == 0)) && echo
    if ((i == (CURSOR_Y * _width + CURSOR_X))); then
      printf "%s" "$UNKO_LG_PLAYER"
    else
      [[ "$s" == "0" ]] && printf "%s" "$UNKO_LG_ALIVE"
      [[ "$s" == "1" ]] && printf "%s" "$UNKO_LG_DEAD"
    fi
    ((i = i + 1))
  done
  echo
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "H" "Move Player Left"
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "J" "Move Player Down"
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "K" "Move Player Up"
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "L" "Move Player Right"
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "Space" "Generate Or Remove Unko"
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "S" "Start Unko Life Game!"
  printf "\033[30m\033[47m %s \033[0m: %s \\n" "Ctrl + C" "Quit Game"
}

get_cell_state() {
  local _height="$1"
  shift
  local _width="$1"
  shift
  local _y="$1"
  shift
  local _x="$1"
  shift
  ((_y < 0 || _y >= _height || _x < 0 || _x >= _width)) && {
    printf "%s\\n" 0
    return
  }
  printf "%s\\n" "$((CELL[_y * _width + _x]))"
}

get_next_cell_state() {
  local _index="$1"
  shift
  local _height="$1"
  shift
  local _width="$1"
  shift
  local _y=$((_index / _width))
  local _x=$((_index % _width))
  local alive_count=
  alive_count=$({
    get_cell_state "$_height" "$_width" "$((_y - 1))" "$((_x - 1))"
    get_cell_state "$_height" "$_width" "$((_y - 1))" "$((_x))"
    get_cell_state "$_height" "$_width" "$((_y - 1))" "$((_x + 1))"
    get_cell_state "$_height" "$_width" "$((_y))" "$((_x - 1))"
    get_cell_state "$_height" "$_width" "$((_y))" "$((_x + 1))"
    get_cell_state "$_height" "$_width" "$((_y + 1))" "$((_x - 1))"
    get_cell_state "$_height" "$_width" "$((_y + 1))" "$((_x))"
    get_cell_state "$_height" "$_width" "$((_y + 1))" "$((_x + 1))"
  } | paste -sd+ - | bc)
  if ((CELL[_index] == 0)); then
    ((alive_count == 3)) && {
      printf "%s\\n" 1
      return
    }
  elif ((CELL[_index] == 1)); then
    ((alive_count == 2 || alive_count == 3)) && {
      printf "%s\\n" 1
      return
    }
    ((alive_count <= 1)) && {
      printf "%s\\n" 0
      return
    }
    ((alive_count >= 4)) && {
      printf "%s\\n" 0
      return
    }
  fi
  printf "%s\\n" "$((CELL[_index]))"
  return
}

main() {
  local _height="${1:-10}"
  shift
  local _width="${1:-10}"
  shift
  if [[ $_height == '--help' ]] || [[ $_height == '-h' ]]; then
    trap '' EXIT
    usage
    return 0
  fi
  if ! [[ $_height =~ ^[0-9]*$ ]] || ! [[ $_width =~ ^[0-9]*$ ]] || ((_height <= 0)) || ((_width <= 0)); then
    trap '' EXIT
    usage
    return 1
  fi
  initialize "$_height" "$_width"
  clear
  cursor_invisible
  while true; do
    display "$_height" "$_width" "Initialize"
    read -rsn1 key
    case $key in
      h)
        ((CURSOR_X > 0)) && ((CURSOR_X--))
        ;;
      l)
        ((CURSOR_X < (_width - 1))) && ((CURSOR_X++))
        ;;
      k)
        ((CURSOR_Y > 0)) && ((CURSOR_Y--))
        ;;
      j)
        ((CURSOR_Y < (_height - 1))) && ((CURSOR_Y++))
        ;;
      s)
        # START GAME
        break
        ;;
      *)
        # Reverse cell state
        ((CELL[CURSOR_Y * _width + CURSOR_X] = 1 - CELL[CURSOR_Y * _width + CURSOR_X]))
        ;;
    esac
  done

  CURSOR_Y=-1
  CURSOR_X=-1
  local generation=0
  while true; do
    i=0
    display "$_height" "$_width" "     $generation     "
    for s in "${CELL[@]}"; do
      NEXT_CELL[i]="$(get_next_cell_state "$i" "$_height" "$_width")"
      ((i++))
    done
    CELL=("${NEXT_CELL[@]}")
    ((generation++))
  done
}

main ${1+"$@"}
exit $?


================================================
FILE: bin/unko.ls
================================================
#!/bin/bash
# Jot down any expression that means 💩.

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

awk -F , '1<NR{print $1}' "${LIB_DIR}/unko.csv"


================================================
FILE: bin/unko.ping
================================================
#!/usr/bin/env bash
# Ping the poop domain 💩.

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

TLDs=("com")

for tld in "${TLDs[@]}"; do
  while read -r unko; do
    LANG=C.UTF-8 ping -c 1 -s 1 -W 1 "${unko}.${tld}" 2> /dev/null 1>&2 && echo "Success ping to ${unko}.${tld}"
  done < <(cut -d "," -f 1 < "${LIB_DIR}/unko.csv" | sed "1d")
done
exit 0


================================================
FILE: bin/unko.printpnm
================================================
#!/bin/bash

SCRIPT_NAME="$(basename "${BASH_SOURCE:-$0}")"
readonly SCRIPT_NAME
readonly VERSION=v1.0.1

## main はメイン関数である。スクリプトの末尾で呼び出す。
##
## @param level    うんこの段数
## @param color_r  RGB値のR (0~255)
## @param color_g  RGB値のG (0~255)
## @param color_b  RGB値のB (0~255)
main() {
  local level=$1
  local color_r=$2
  local color_g=$3
  local color_b=$4

  local col
  local row
  local rgb
  col=$(max_stage_col "$level")
  row=$(max_stage_row "$level")
  rgb=$(max_value "$color_r" "$color_g" "$color_b")

  cat << EOS
P3
$col $row
$rgb
EOS
  cat << EOS | align_center 0 | sed -E "s/ /0/g;s/0/0 0 0 /g;s/[^ 0]/$color_r $color_g $color_b /g"
1
1
111
11111
$(stages "$level")
EOS
}

## max_stage_col は段のカラム幅を返す。
##
## @param n うんこの段数
## @return うんこの横幅
max_stage_col() {
  local n=$1
  echo $((11 + 8 * (n - 1) + 2))
}

## max_stage_col は段数を返す。
##
## @param n うんこの段数
## @return うんこの高さ
max_stage_row() {
  local n=$1
  echo $((4 + 4 * n))
}

## max_value は引数のうち最も大きな値を返す。
##
## @param  1
## @param  2
## @param  3
## @return 前述の3つの値のうち、もっとも数値として大きい値
max_value() {
  echo -e "$1\n$2\n$3" | sort -n | tail -n 1
}

## repeat は渡された引数の数分だけ1を出力して返す。
## 返す文字列は1行である。
##
## @param n 何文字繰り返すか
## @param c 出力する文字 (デフォルト: 1)
## @return n回繰り返した1
repeat() {
  local n=$1
  local c=${2:-1}
  seq "$n" | xargs -I@ echo -n "$c"
}

## stage はうんこの段を返す。
## 引数は段の横幅を指定する。
## 段、はうんこの横野箇所をさす。
## (    ) <- のこと
##
## @param i うんこの段の番号
## @param i番目のうんこ段
stage() {
  local i=$1
  local j=$((i + 2))
  cat << EOS
$(repeat "$i")
$(repeat "$j")
$(repeat "$j")
$(repeat "$i")
EOS
}

## stages は引数に指定した数だけうんこの段を返す。
## たとえば、2を指定したときは以下のようなイメージになる。
##  (   )
## (     )
##
## @param n うんこが何段か
## @param n回くりかえしたうんこの段
stages() {
  local n=$1
  seq "$n" | while read -r i; do
    stage $((11 + 8 * (i - 1)))
  done
}

## align_center は標準入力を指定の文字列で埋めて中央寄せする。
##
## @param pad 中央寄せのために詰める文字列
##            全角文字はNG
## @return 中央寄せされた文字列
align_center() {
  local pad="$1"

  # 最も大きい横幅を取得
  local max_width=0
  local lines=()
  while read -r line; do
    local w
    w=$(wc -c <<< "$line")

    if [ "$max_width" -lt "$w" ]; then
      max_width=$w
    fi
    lines+=("$line")
  done

  # うんこを1行ずつ出力
  for line in "${lines[@]}"; do
    local w
    w=$(wc -c <<< "$line")

    local left_width=$(((max_width - w) / 2))
    local right_width=$((max_width - left_width - w))
    echo "$(repeat "$left_width" "$pad")$line$(repeat "$right_width" "$pad")"
  done
}

## usage はこのスクリプトの使い方を標準出力する。
usage() {
  cat << EOS
$SCRIPT_NAME はうんこをPNM画像として出力するためのコマンドです。

Usage:

    $SCRIPT_NAME [flags] [unko_level]

Examples:

    # 通常の使用方法
    $SCRIPT_NAME 3 > unko3.pnm

    # RGB値を指定する例
    $SCRIPT_NAME 3 -r 255 -g 0 -b 0 > unko_rgb.pnm

    # PNG画像に変換する例(ImageMagickに依存)
    $SCRIPT_NAME 3 -r 255 -g 0 -b 0 | convert - -scale 100x100 /images/t.png

Flags:

    -h, --help          このヘルプを出力する
        --version       バージョン情報を出力する
    -r, --red int       RGB値のRを指定 (0~255) (default: 255)
    -g, --green int     RGB値のGを指定 (0~255) (default: 255)
    -b, --blue int      RGB値のBを指定 (0~255) (default: 255)
    -u, --unko-color    RGB値にうんこ色を指定する

EOS
}

## log はスクリプト名と合わせて、メッセージをエラー出力する。
log() {
  echo -e "$SCRIPT_NAME: $*" >&2
}

## is_empty は引数が空文字列であるかを判定する。
is_empty() {
  [[ -z "$1" ]]
}

## is_opt_key は引数がコマンドライン引数のオプションキーであるかを判定する。
is_opt_key() {
  [[ "$1" =~ ^-+ ]]
}

## validate_opt_value は引数がコマンドオプションの値であるかを判定する。
## 不正な値の場合はシェルを異常終了する。
validate_opt_value() {
  local value=$1
  if is_empty "$value" || is_opt_key "$value"; then
    log "requires an argument -- $value"
    exit 1
  fi
}

## set_opts はコマンドライン引数を解析して変数にセットする。
## セットする変数は下記の通り。
## - opt_red
## - opt_green
## - opt_blue
## - opt_unko_level
## これらの変数はトップレベルの変数として初期値を設定しておくこと。
set_opts() {
  local opt_use_unko_color=false
  while ((0 < $#)); do
    local opt=$1
    shift

    case "$opt" in
      '-h' | '--help')
        usage
        exit
        ;;
      '--version')
        echo $VERSION
        exit
        ;;
      '-r' | '--red')
        local color=$1
        shift
        validate_opt_value "$color"
        opt_red="$color"
        ;;
      '-g' | '--green')
        local color=$1
        shift
        validate_opt_value "$color"
        opt_green="$color"
        ;;
      '-b' | '--blue')
        local color=$1
        shift
        validate_opt_value "$color"
        opt_blue="$color"
        ;;
      '-u' | '--unko-color')
        opt_use_unko_color=true
        ;;
      -*)
        log "illegal option -- $1"
        exit 1
        ;;
      *)
        opt_unko_level=$opt
        ;;
    esac
  done

  if [ "$opt_use_unko_color" = true ]; then
    opt_red=217
    opt_green=112
    opt_blue=2
  fi
}

# テストフラグが付与されている時はmain関数を呼び出さない。
if [ ! "$RUN_TEST" = true ]; then
  # コマンドライン引数を取得
  opt_red=255
  opt_green=255
  opt_blue=255
  opt_unko_level=3
  set_opts ${1+"$@"}

  main "$opt_unko_level" "$opt_red" "$opt_green" "$opt_blue"
fi


================================================
FILE: bin/unko.puzzle
================================================
#!/usr/bin/env bash
set -eu
FRAME=30
TILES=${TILES:-3}
HEADER_HEIGHT=23 # Darwin
RANDOM_SLIDE=$((10 + TILES * TILES * TILES / 2))
PIXEL_ART_COLS=60 # BIGUNKO'
PIXEL_ART_ROWS=30 # BIGUNKO
DEBUG_UNKO=${DEBUG_UNKO:-false}
WINDOW_NAME="$(basename $0)"
BIGUNKO=""
WIDS=()

log_debug() {
  if [ "$DEBUG_UNKO" = "true" ]; then
    echo "[$$] $@" >&2
  fi
}

initialize() {
  platform=$(uname)
  # process stratum: this process -> shell(bash) -> terminal emulator ?
  pppid=$(ps -ef | awk "\$2==$PPID{print \$3}")
  case $platform in
    'Darwin')
      HEIGHT_OFFSET=-44
      WIDTH_OFFSET=0
      ;;
    'Linux')
      HEIGHT_OFFSET=-68
      WIDTH_OFFSET=-10
      ;;
    *)
      echo "error: $platform: unsupported platform" >&2
      exit 1
      ;;
  esac

  if [ $(ps -ef | awk "\$2==$pppid{print}" | grep [x]term | wc -l) -eq 0 ]; then
    echo 'error: require xterm' >&2
    exit 1
  fi

  which xdotool > /dev/null 2>&1 || {
    echo 'error: require xdotool' >&2
    exit 1
  }

  # expects current window is active
  root_cols=$(stty -a | grep columns | sed 's/.*columns \([^;]*\);.*/\1/')
  root_rows=$(stty -a | grep rows | sed 's/.*rows \([^;]*\);.*/\1/')
  root_wid=$(xdotool getactivewindow)
  root_wname=$(xdotool getwindowname $root_wid)
  root_wgeo=$(xdotool getwindowgeometry $root_wid | grep Geometry | awk '{print $2}')
  root_wpos=$(xdotool getwindowgeometry $root_wid | grep Position | awk '{print $2}')
  char_width=$((${root_wgeo%x*} / $root_cols))
  char_height=$((${root_wgeo#*x} / $root_rows))
  margin_width=$((${root_wgeo%x*} % $root_cols))
  margin_height=$((${root_wgeo#*x} % $root_rows))
  tile_window_width=$(($PIXEL_ART_COLS / $TILES * $char_width + $margin_width))
  tile_window_height=$(($PIXEL_ART_ROWS / $TILES * $char_height + $margin_height))
  tile_char_cols=$(($PIXEL_ART_COLS / $TILES))
  tile_char_rows=$(($PIXEL_ART_ROWS / $TILES))
  log_debug "window name: $WINDOW_NAME"
  log_debug "number of tiles on a side: $TILES"
  log_debug "root window columns: $root_cols"
  log_debug "root window rows: $root_rows"
  log_debug "root window id: $root_wid"
  log_debug "root window name: $root_wname"
  log_debug "root window geometry: $root_wgeo"
  log_debug "root window position: $root_wpos"
  log_debug "character width: $char_width"
  log_debug "character height: $char_height"
  log_debug "margin width: $margin_width"
  log_debug "margin height: $margin_height"
  log_debug "tile window width: $tile_window_width"
  log_debug "tile window height: $tile_window_height"
  log_debug "tile character columns: $tile_char_cols"
  log_debug "tile character rows: $tile_char_rows"
}

calculate_tile_position() {
  local tile_pos_x=$1 tile_pos_y=$2
  local wpos_x=$((${root_wpos%,*} + $tile_window_width * $tile_pos_x + $WIDTH_OFFSET))
  local wpos_y=$((${root_wpos#*,} + ($tile_window_height + $HEADER_HEIGHT) * $tile_pos_y + $HEIGHT_OFFSET))
  log_debug "calculate position: tile=${tile_pos_x},${tile_pos_y}; window=${wpos_x},${wpos_y}"
  echo "${wpos_x},${wpos_y}"
}

set_root_window() {
  local wpos=$(calculate_tile_position 1 0)
  local wpos_x=${wpos%,*} wpos_y=${wpos#*,}
  log_debug "set root window: wid=$root_wid; geometry=${tile_window_width}x${tile_window_height}; position=${wpos_x},${wpos_y}"
  xdotool set_window --name "$WINDOW_NAME" $root_wid
  xdotool windowsize $root_wid $tile_window_width $tile_window_height
  xdotool windowmove $root_wid $wpos_x $wpos_y
  clear
}

create_children() {
  local num_children=$(($TILES * $TILES - 2))
  log_debug "number of child windows: $num_children"
  for i in $(seq 2 $(($num_children + 1))); do
    local wpos=$(calculate_tile_position $(($i % $TILES)) $(($i / $TILES)))
    local wpos_x=${wpos%,*} wpos_y=${wpos#*,}
    log_debug "create child window: $i; geometry=${tile_char_cols}x${tile_char_rows}(chars); position=${wpos_x},${wpos_y}"
    xterm \
      -geometry "${tile_char_cols}x${tile_char_rows}+${wpos_x}+${wpos_y}" \
      -e "$0" &
  done
  sleep $(echo "scale=1; 0.3 + $TILES * $TILES / 10" | bc)
}

relocate() {
  local wids=($1)
  local i=1
  for wid in ${wids[@]}; do
    local wpos_x=$((${root_wpos%,*} + $tile_window_width * ($i % $TILES) + $WIDTH_OFFSET))
    local wpos_y=$((${root_wpos#*,} + ($tile_window_height + $HEADER_HEIGHT) * ($i / $TILES) + $HEIGHT_OFFSET))
    log_debug "relocate window: wid=$wid; position=${wpos_x},${wpos_y}"
    xdotool windowmove $wid $wpos_x $wpos_y
    let ++i
  done
}

trim_bigunko() {
  local tile_pos_x=$1 tile_pos_y=$2
  if [ "$BIGUNKO" == "" ]; then
    # cache bigunko to prevent broken pipe error
    BIGUNKO=$($(
      cd $(dirname $0)
      pwd
    )/bigunko.show | sed $'s/\(\033\[48;5;[0-9]*m\) /\\1 \\1 /g')
  fi

  echo "$BIGUNKO" |
    head -n $(($tile_char_rows * ($tile_pos_y + 1))) |
    tail -n $tile_char_rows |
    sed $'s/\(\033\[48;5;[0-9]*m\) /\\1 \\1 /g' |
    awk "
    {
      for (k = $tile_char_cols * $tile_pos_x + 1; k < $tile_char_cols * ($tile_pos_x + 1) + 1; k++) {
        printf \$k\" \";
      };
      printf \"\033[0m\";
      if (NR != $tile_char_rows) { print \"\" };
    }"
}

get_child_tty_names() {
  local child_wids="$1"
  for wid in $child_wids; do
    local pid=$(xdotool getwindowpid $wid)
    # get tty name of child process
    tty_name=$(ps -ef | grep "$WINDOW_NAME" | awk "\$3==$pid{print \$6}")
    log_debug "child process: wid=${wid}; pid=${pid}; tty=/dev/${tty_name}"
    echo $tty_name
  done
}

draw() {
  local child_wids="$1"
  local tty_names=($(get_child_tty_names "$child_wids"))
  local tile_pos_x=1 tile_pos_y=0
  log_debug "draw window: root; tile position=$tile_pos_x,$tile_pos_y"
  trim_bigunko $tile_pos_x $tile_pos_y
  for i in $(seq 0 $((${#tty_names[@]} - 1))); do
    tile_pos_x=$((($i + 2) % $TILES))
    tile_pos_y=$((($i + 2) / $TILES))
    log_debug "draw window: child $((i + 1)); tile position=$tile_pos_x,$tile_pos_y; tty=/dev/${tty_names[i]}"
    trim_bigunko $tile_pos_x $tile_pos_y >> /dev/${tty_names[i]}
  done
}

terminate_children() {
  local child_wids="$1"
  local i=0
  for wid in $child_wids; do
    # TODO: pid がない場合を考慮
    local pid=$(xdotool getwindowpid $wid)
    kill -INT $pid
    let ++i
  done
  return
}

slide_window() {
  local wid=$1
  local distance_x=$2
  local distance_y=$3
  local pos=$(xdotool getwindowgeometry $wid | grep Position | awk '{print $2}')
  local pos_x=${pos%,*}
  local pos_y=${pos#*,}
  log_debug "slide window: wid=$wid; pos=$pos_x,$pos_y; dis=$distance_x,$distance_y"
  for i in $(seq $FRAME); do
    xdotool windowmove $wid $(($pos_x + $distance_x / $FRAME * $i + $WIDTH_OFFSET)) $(($pos_y + $distance_y / $FRAME * $i + $HEIGHT_OFFSET))
  done
  xdotool windowmove $wid $(($pos_x + $distance_x + $WIDTH_OFFSET)) $(($pos_y + $distance_y + $HEIGHT_OFFSET))
}

shake_window() {
  local wid=$1
  local pos=$(xdotool getwindowgeometry $wid | grep Position | awk '{print $2}')
  local pos_x=${pos%,*}
  local pos_y=${pos#*,}
  for i in $(seq 5); do
    xdotool windowmove $wid $(($pos_x - 10 + $WIDTH_OFFSET)) $(($pos_y + $HEIGHT_OFFSET))
    xdotool windowmove $wid $(($pos_x + $WIDTH_OFFSET)) $(($pos_y + $HEIGHT_OFFSET))
    xdotool windowmove $wid $(($pos_x + 10 + $WIDTH_OFFSET)) $(($pos_y + $HEIGHT_OFFSET))
    xdotool windowmove $wid $(($pos_x + $WIDTH_OFFSET)) $(($pos_y + $HEIGHT_OFFSET))
  done
}

can_slide() {
  local null_index=$1
  local direction=$2
  case $direction in
    'up') if [ $null_index -lt $(($TILES * $TILES - $TILES)) ]; then return 0; fi ;;
    'down') if [ $null_index -ge $TILES ]; then return 0; fi ;;
    'left') if [ $(($null_index % $TILES)) -ne $(($TILES - 1)) ]; then return 0; fi ;;
    'right') if [ $(($null_index % $TILES)) -ne 0 ]; then return 0; fi ;;
  esac
  return 1
}

move_tile() {
  local direction=$1
  local anotation=$2
  local null_index=$(echo "${WIDS[@]}" | tr ' ' '\n' | nl -v0 | grep null | awk '{print $1}')
  local wid target_index distance_x distance_y
  # log_debug "current window ids: ${WIDS[@]}"

  if can_slide $null_index $direction; then
    case $direction in
      'up')
        target_index=$(($null_index + $TILES))
        distance_x=0
        distance_y=$((-$tile_window_height - $HEADER_HEIGHT))
        ;;
      'down')
        target_index=$(($null_index - $TILES))
        distance_x=0
        distance_y=$(($tile_window_height + $HEADER_HEIGHT))
        ;;
      'left')
        target_index=$(($null_index + 1))
        distance_x=-$tile_window_width
        distance_y=0
        ;;
      'right')
        target_index=$(($null_index - 1))
        distance_x=$tile_window_width
        distance_y=0
        ;;
    esac
    wid=${WIDS[$target_index]}
    # log_debug "slide window: direction=${direction}; target index=${target_index}; wid=${wid}"
    slide_window $wid $distance_x $distance_y
    WIDS[$null_index]=$wid
    WIDS[$target_index]='null'
  else
    if [ "$anotation" = 'true' ]; then
      case $direction in
        'up') target_index=$(($null_index - $TILES)) ;;
        'down') target_index=$(($null_index + $TILES)) ;;
        'left') target_index=$(($null_index - 1)) ;;
        'right') target_index=$(($null_index + 1)) ;;
      esac
      wid=${WIDS[$target_index]}
      shake_window $wid
    fi
  fi
}

randomize() {
  local direction
  local prev=-1
  local count=0
  while [ $count -le $RANDOM_SLIDE ]; do
    local rand=$((RANDOM % 4))
    case $rand in
      0)
        direction='up'
        if [ $prev -eq 1 ]; then continue; fi
        ;;
      1)
        direction='down'
        if [ $prev -eq 0 ]; then continue; fi
        ;;
      2)
        direction='left'
        if [ $prev -eq 3 ]; then continue; fi
        ;;
      3)
        direction='right'
        if [ $prev -eq 2 ]; then continue; fi
        ;;
    esac
    local null_index=$(echo "${WIDS[@]}" | tr ' ' '\n' | nl -v0 | grep null | awk '{print $1}')
    if can_slide $null_index $direction; then
      move_tile $direction 'false'
      prev=$rand
      # log_debug "randomize: count=$count; direction=$direction"
      let ++count
    fi
  done
}

solve() {
  local collect_hash=$(echo -n $1 | md5sum | cut -d' ' -f1)
  while IFS= read -r -n1 -s key; do
    if [ "$key" == $'\x1b' ]; then
      read -r -n2 -s rest
      key+="$rest"
    fi
    case "$key" in
      k | $'\x1b\x5b\x41')
        move_tile 'up' 'true'
        ;;
      j | $'\x1b\x5b\x42')
        move_tile 'down' 'true'
        ;;
      l | $'\x1b\x5b\x43')
        move_tile 'right' 'true'
        ;;
      h | $'\x1b\x5b\x44')
        move_tile 'left' 'true'
        ;;
    esac
    local wids_hash=$(echo -n "${WIDS[@]}" | md5sum | cut -d' ' -f1)
    if [ "$wids_hash" = "$collect_hash" ]; then break; fi
  done
}

clean_up() {
  # reset root window
  xdotool set_window --name "$root_wname" $root_wid
  xdotool windowsize $root_wid ${root_wgeo%x*} $((${root_wgeo#*x} + $WIDTH_OFFSET))
  xdotool windowmove $root_wid ${root_wpos%,*} $((${root_wpos#*,} + $HEIGHT_OFFSET))
  stty echo
  clear
  exit 0
}

processes=$(ps -ef | grep $WINDOW_NAME | grep -v grep)
if [ $(echo "$processes" | wc -l) -le 2 ]; then
  # parent window
  initialize
  set_root_window
  trap clean_up 2 # 2:SIGINT
  create_children
  xdotool windowactivate $root_wid
  xdotool windowfocus $root_wid
  wids=$(xdotool search --name "$WINDOW_NAME") # newline separated
  child_wids=$(echo "$wids" | grep -v $root_wid | tr '\n' ' ')
  relocate "$root_wid $child_wids"
  draw "$child_wids"
  WIDS=('null' $root_wid $child_wids)
  randomize
  xdotool windowactivate $root_wid
  xdotool windowfocus $root_wid
  solve "null $root_wid $child_wids"
  terminate_children "$child_wids"
  clean_up
else
  # child window
  cat
fi


================================================
FILE: bin/unko.pyramid
================================================
#!/usr/bin/env bash

# Sierpinski gasket is not unkoski gasket.
# Sierpinski is great mathematician.
# unkoski is peoples who love the unko.

SCRIPT_NAME="$(basename "${BASH_SOURCE:-$0}")"
readonly SCRIPT_NAME
readonly VERSION=v1.0.0

draw_pyramid() {
  local input="${1:-1}"
  if [[ "$input" =~ ^1 ]]; then
    return 0
  fi
  echo "${input//10/💩}" | cut -c 2- | tr 01 ' 💩'
  next_input=$(echo "0${input}0" | awk -F '' '{l=length($0);for(i=1;i<=l-2;i++){printf ($i+$(i+2))%2}}')
  draw_pyramid "$next_input"
}

rendering() {
  ## draw! 💩 turn!
  local pyramid_size="${1:-16}"
  draw_pyramid "$(printf "%0$((pyramid_size + 1))d%0${pyramid_size}d" 1)"
}

## unko.printpnmを参考に...
log() {
  echo -e "$SCRIPT_NAME: $*" >&2
}

usage() {
  cat << EOS

$SCRIPT_NAME is render unkoski gasket.
Sorry, could not beautiful rendering by some environment...

Usage:
    $SCRIPT_NAME [unko_size (default:16)]
Examples:
    $SCRIPT_NAME 16
Flags:
    -h, --help          show help
        --version       show version
EOS
  exit 0
}

main() {
  while ((0 < $#)); do
    local opt=$1
    shift

    case "$opt" in
      '-h' | '--help')
        usage
        exit
        ;;
      '--version')
        echo $VERSION
        exit
        ;;
      -*)
        log "illegal option '$opt'"
        exit 1
        ;;
      *)
        unko_size=$opt
        if ! [[ $unko_size =~ ^[1-9]+[[:digit:]]*$ ]]; then
          log "Invalid number '$unko_size'"
          return 1
        fi
        ;;
    esac
  done

  rendering "$unko_size"
  return 0
}

main ${1+"$@"}
exit $?


================================================
FILE: bin/unko.question
================================================
#!/bin/bash
TEXT=$*

eval unko.shout "${TEXT}"

while :; do
  read -rp "ok? (y/N/u): " ynu
  case "$ynu" in
    [yY]*)
      # y|Yの場合は正常終了
      exit 0
      ;;

    [uU]*)
      # u|Uの場合は再度聞く
      eval unko.shout "ブリブリブリ…" "もう一度聞いてやろう" "${TEXT}"
      continue
      ;;

    *)
      # デフォルト(N)で127で終了
      exit 127
      ;;
  esac
done


================================================
FILE: bin/unko.say
================================================
#!/bin/bash

# Get current directory
THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

COW_FILE="${LIB_DIR}/unko_mb.cow"
if ! (cowsay -f "${COW_FILE}" 'うんこ' | grep -qe 'うんこ' &&
  cowsay -f "${COW_FILE}" 'もりもり' | grep -qe '💩'); then
  COW_FILE="${LIB_DIR}/unko.cow"
fi

cowsay -f "${COW_FILE}" "$@"


================================================
FILE: bin/unko.shout
================================================
#!/bin/bash

echo-sd ${1+"$@"}
t="${T:-👑}"         # Top
u="${U:-💩}"         # Unko
le="${LE:-${E:-👁}}" # Left Eye
re="${RE:-${E:-👁}}" # Right Eye
n="${N:-👃}"         # Nose
m="${M:-👄}"         # Mouth
l="${L:-(}"         # Left side
r="${R:-)}"         # Right side
s="${S:- }"         # Space
cat << EOF
$s$s$s$s$s$s$t
$s$s$s$s$l$u$u$u$r
$s$s$s$l$u$le$u$re$u$r
$s$s$l$u$u$u$n$u$u$u$r
$s$l$u$u$u$u$m$u$u$u$u$r
EOF


================================================
FILE: bin/unko.think
================================================
#!/bin/bash

# Get current directory
THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

COW_FILE="${LIB_DIR}/unko_mb.cow"
if ! (cowsay -f "${COW_FILE}" 'うんこ' | grep -qe 'うんこ' &&
  cowsay -f "${COW_FILE}" 'もりもり' | grep -qe '💩'); then
  COW_FILE="${LIB_DIR}/unko.cow"
fi

cowthink -f "${COW_FILE}" "$@"


================================================
FILE: bin/unko.toilet
================================================
#!/bin/bash

usage() {
  cat << EOS >&2
Usage: unko.toilet [ -hv ] [ -w outputwidth ]
                   [ --crop ] [ --flip ] [ --flop ]
                   [ --180 ] [ --left ] [ --right ]
                   [ --border ] [ message ]

  -h, --help                  このヘルプを出力して終了します
  -w, --width <width, auto>   出力の幅です。autoを指定すると端末の幅になります
      --crop                  上下左右の無駄なスペースを削除します
      --flip                  水平方向に反転します
      --flop                  垂直方向に反転します
      --180                   180度回転します
      --left                  左へ90度回転します
      --right                 右へ90度回転します
      --border                枠線をつけます
EOS
  exit 1
}

not_found() {
  echo "[ERR] $* not found  [unko.toilet]" 1>&2
  exit 1
}

append_opt() {
  toilet_opt+=("$@")
}

version() {
  echo "unko.toilet version 💩.💩.💩 (20💩💩/💩💩/💩💩)"
  exit 0
}

unexpected() {
  echo "[ERR] Unexpected $1" 1>&2
  echo "" 1>&2
  usage
}

is_integer() {
  local num
  num=$1
  [[ "$num" =~ ^[0-9]+$ ]]
}

# unko.toilet 用のオプションをパースする
declare -a args
declare -a toilet_opt
while (($# > 0)); do
  opt=$1
  shift

  case "$opt" in
    -h | --help)
      # --help か -h が指定されていたらUsage出して終了
      usage
      ;;
    -v | --version)
      # --version か -v なら version情報を出力して終了
      version
      ;;
    -w | --width)
      num=$1
      shift

      if is_integer "$num"; then
        append_opt "--width" "$num"
      elif [ "$num" = auto ]; then
        append_opt "--termwidth"
      else
        unexpected "argument $opt $num <="
      fi
      ;;
    --left | --right | --flip | --flop | --180 | --border | --crop)
      append_opt "--filter" "${opt//--/}"
      ;;
    -*)
      # いずれのオプションともマッチしなかった
      unexpected "option $opt"
      ;;
    *)
      # 引数
      args+=("$opt")
      ;;
  esac
done

# 第一引数に与えた文字を変換、デフォルト文字はうんこ
text=("${args[@]:-うんこ}")

# stdinから入力されてるならそっちを使う
[ -p /dev/stdin ] && text=("$(cat -)")

# toilet がなかったらダメ
type toilet &> /dev/null || not_found "toilet command"

# フォントにbigmono9を使うので無かったらダメ
echo | toilet -f bigmono9 &> /dev/null || not_found "bigmono9 font"

# unko.toilet
toilet "${toilet_opt[@]}" -f bigmono9 "${text[@]}" |
  # 薄いところは消す
  sed 's/░\|▒/ /g' |
  # スペース以外を💩へ
  sed 's/[^ ]/💩/g' |
  # 幅調整
  sed 's/ /  /g'


================================================
FILE: bin/unko.tower
================================================
#!/usr/bin/env bash
set -u

readonly THIS_CMD="${0##*/}"
readonly DEFAULT_PADDING=" "
readonly DEFAULT_HEIGHT=3
readonly UNKO_TOP="人"

repeat_str() {
  local _num="$1"
  shift
  local _str="$1"
  shift
  awk \
    -v NUM="$_num" \
    -v STR="$_str" \
    'BEGIN{ for (i=0; i<NUM; i++) { printf "%s", STR } }'
  echo
}

print_unko() {
  local _level="${1:-3}"
  shift
  local _msg=("$@")
  local _msg_idx=0
  local _padding=" "
  local _left=
  local _result=
  local _mid1 _num1
  local _mid2 _num2
  ((_level = _level + 1))
  _left="$(repeat_str "$_level" "$_padding")"
  _result="${_left}${_padding}${UNKO_TOP}"
  for ((i = _level - 1; i > 0; i--)); do
    _left="$(repeat_str "$i" "$_padding")"
    _num1="$((_level - i + 1))"
    _mid1="$(print_array "${_msg[@]:$_msg_idx:$_num1}")"
    ((_msg_idx = _msg_idx + _num1))

    _num2="$((_level - i))"
    _mid2="$(print_array "${_msg[@]:$_msg_idx:$_num2}")"
    ((_msg_idx = _msg_idx + _num2))

    _result="${_result}"$'\n'"${_left}(${_mid1}${_mid2})"
  done
  printf "%s\\n" "${_result}"
}

unk_msg_error() {
  printf "%s\\n" "$THIS_CMD:error:${1-}"
}

unk_command_help() {
  cat << _EOS_
Usage:
  ${THIS_CMD} [OPTIONS] NUMBER

OPTIONS:
  --help         Display this help and exit
  -m <message>   Fill with the message
  -r             Read message from stdin
  -s <string>    Change default stuffed string
_EOS_
}

# Calculate sum of the number of character to be filled in the Unko.
char_sum() {
  local n="$1"
  echo "$((n * n + 2 * n))"
}

print_array() {
  for s in "$@"; do
    _pat='[ -~]' # cover all the ascii chars
    if [[ $s =~ $_pat ]]; then
      printf "%s " "$s" # padding
    else
      printf "%s" "$s"
    fi
  done
}

main() {
  local _msg=()
  local _opt_msg=0
  local _opt_stdin=0
  local _raw_msg=
  local _total_char=
  while (($# > 0)); do
    local _opt="$1"
    shift

    ## -ovalue → -o value (inspired by echo-sd)
    if [[ -n "${_opt}" ]] && [[ -z "${_opt##-[sm]?*}" ]]; then
      set -- "${_opt#??}" ${1+"$@"}
      _opt="${_opt%"${1}"}"
    fi

    case "$_opt" in
      --help)
        unk_command_help
        return 0
        ;;
      -m)
        _opt_msg=1
        _raw_msg="${1-}"
        shift
        ;;
      -s)
        _padding="${1-}"
        shift
        ;;
      -r)
        _opt_msg=1
        _opt_stdin=1
        ;;
      *)
        _num="$_opt"
        ;;
    esac
  done

  _padding=${_padding:-$DEFAULT_PADDING}
  _num=${_num:-$DEFAULT_HEIGHT}
  if ! [[ ${_num} =~ ^[[:digit:]]+$ ]]; then
    unk_msg_error "Invalid number '${_num}'"
    return 0
  fi
  _total_char="$(char_sum "${_num}")"
  if [[ ${_opt_msg} -eq 0 ]]; then
    IFS=$'\n' read -r -a _msg -d '' <<< "$(repeat_str "$_total_char" "$_padding" | grep -o .)"
  elif [[ ${_opt_msg} -eq 1 ]]; then
    if [[ ${_opt_stdin} -eq 1 ]]; then
      IFS=$'\n' read -r -a _msg -d '' <<< "$(cat | grep -o .)"
    else
      IFS=$'\n' read -r -a _msg -d '' <<< "$(printf "%s" "${_raw_msg}" | grep -o .)"
    fi
    _gap=$((_total_char - ${#_msg[@]}))
    if ((_gap > 0)); then
      IFS=$'\n' read -r -a _rest_msg -d '' <<< "$(repeat_str "$_gap" "$_padding" | grep -o .)"
      _msg=("${_msg[@]:-"$_padding"}" "${_rest_msg[@]}")
    fi
  fi
  print_unko "${_num}" "${_msg[@]:-}"
  return 0
}

main ${1+"$@"}
exit $?


================================================
FILE: bin/unko.tr
================================================
#!/bin/bash

# Get current directory
THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR

LIB_DIR="${THIS_DIR}/../lib/super_unko"
readonly LIB_DIR

sed -f <(awk -F , '1<NR{print $1}' "${LIB_DIR}/unko.csv" | sed 's|^|s/|;s|$|/💩/g|;')


================================================
FILE: bin/unko.yes
================================================
#!/bin/bash
yes '💩'


================================================
FILE: doc/ci-push.puml
================================================
@startuml

start

: git commit;
: git push;

partition "GitHub Actions" {
  fork
    : build docker image;
    partition "test" {
      fork
        : test bash default;
      fork again
        : test bash 3.2;
      fork again
        : test bash 4.0;
      fork again
        : test bash 4.1;
      fork again
        : test bash 4.2;
      fork again
        : test bash 4.3;
      fork again
        : test bash 4.4;
      fork again
        : test bash 5.0;
      end fork
    }
  fork again
    : format;
  fork again
    : lint;
  end fork
  if (is branch oshiri?) then (true)
    partition "update-repository" {
      : generate super_unko.deb;
      : generate super_unko.rpm;
      : generate markdown TOC;
      : git push ;
    }
  endif
}

end

@enduml


================================================
FILE: doc/unko.puzzle.md
================================================
# unko.puzzle

sliding block puzzle

Table of Contents

<!--ts-->
* [unko.puzzle](doc/unko.puzzle.md#unkopuzzle)
   * [Requirements](doc/unko.puzzle.md#requirements)
   * [Additional installation](doc/unko.puzzle.md#additional-installation)
      * [Linux](doc/unko.puzzle.md#linux)
         * [With yum (RHEL compatible distros)](doc/unko.puzzle.md#with-yum-rhel-compatible-distros)
         * [With apt (Debian base distros)](doc/unko.puzzle.md#with-apt-debian-base-distros)
      * [macOS](doc/unko.puzzle.md#macos)
         * [With Homebrew](doc/unko.puzzle.md#with-homebrew)
   * [Usage](doc/unko.puzzle.md#usage)
      * [Linux](doc/unko.puzzle.md#linux-1)
      * [macOS](doc/unko.puzzle.md#macos-1)
   * [for development](doc/unko.puzzle.md#for-development)

<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
<!-- Added by: runner, at: Mon Apr 11 15:08:44 UTC 2022 -->

<!--te-->

## Requirements

- X11
    - XQuartz (macOS)
- xterm

## Additional installation

### Linux

#### With `yum` (RHEL compatible distros)

* Enable epel repository

(skip)

* Install xdotool

```sh
$ sudo yum install xdotool
```

#### With `apt` (Debian base distros)

```sh
$ sudo apt install xdotool
```

### macOS

#### With Homebrew

```sh
$ brew cask install xquartz
$ brew install xdotool
```

## Usage

### Linux

1. Launch xterm.
1. Run `unko.puzzle` on xterm.
1. Enjoy!

### macOS

1. Launch xterm.
    ```sh
    $ PATH=$PATH:/opt/X11/bin xterm &
    ```
1. Run `unko.puzzle` on xterm.
    ```sh
    $ unko.puzzle
    ```
1. Enjoy!

---

```
Warning: XTEST extension unavailable on '(null)'.
Some functionality may be disabled; See 'man xdotool' for more info.
```

If you received such a message from xdotool, you may be able to resolve it by execute the following commands and restarting XQuartz:

```sh
$ defaults write org.x.X11 enable_test_extensions -boolean true
$ defaults write org.macosforge.xquartz.X11 enable_test_extensions -boolean true
```

See: https://stackoverflow.com/questions/1264210/does-mac-x11-have-the-xtest-extension

## for development

- tile map

```
+-+-+-+
|x|1|2|
+-+-+-+
|3|4|5|
+-+-+-+
|6|7|8|
+-+-+-+
```

- debug

```sh
$ DEBUG_UNKO=true TILES=2 unko.puzzle 2>>/tmp/unko.log
```


================================================
FILE: doc/unko.toilet.md
================================================
# unko.toilet

<font size=7>Text to UNKO Art!!!!</font>

Table of Contents

<!--ts-->
* [unko.toilet](doc/unko.toilet.md#unkotoilet)
   * [Requirements](doc/unko.toilet.md#requirements)
      * [Additional installation](doc/unko.toilet.md#additional-installation)
      * [apt](doc/unko.toilet.md#apt)
      * [brew/linuxbrew](doc/unko.toilet.md#brewlinuxbrew)
   * [Usage](doc/unko.toilet.md#usage)

<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
<!-- Added by: runner, at: Mon Apr 11 15:08:44 UTC 2022 -->

<!--te-->

## Requirements

- `toilet`
- `figlet`

### Additional installation

### apt

```sh
$ sudo apt install figlet toilet
```

### brew/linuxbrew

```sh
$ brew install figlet toilet
```

## Usage

```
unko.toilet [ -hv ] [ -w outputwidth ]
            [ --crop ] [ --flip ] [ --flop ]
            [ --180 ] [ --left ] [ --right ]
            [ --border ]
```


================================================
FILE: docker/Dockerfile
================================================
# vim: tw=0:
FROM ubuntu:20.04 AS base

RUN echo -e $'\n\
_人人人人人人人人人人人人人人人人人人人人人人_\n\
> super_unkoイメージを今からビルドするよ! <\n\
> これには少し時間がかかるよ!       <\n\
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄\n\
      👑\n\
    (💩💩💩)\n\
   (💩👁💩👁💩)\n\
  (💩💩💩👃💩💩💩)\n\
 (💩💩💩💩👄💩💩💩💩)'

ENV LANG ja_JP.UTF-8
RUN apt update -yqq \
    && apt install -y --no-install-recommends \
       language-pack-ja-base \
       toilet \
       figlet \
       bc \
       cowsay \
       curl \
       ca-certificates \
       locales \
    && locale-gen ja_JP.UTF-8 \
    && rm -rf /var/lib/apt/lists/*
COPY . /usr/local/src/super_unko
WORKDIR /usr/local/src/super_unko
RUN ./install.sh
RUN curl --retry 3 https://raw.githubusercontent.com/fumiyas/home-commands/master/echo-sd > /usr/local/bin/echo-sd
RUN chmod +x /usr/local/bin/echo-sd

RUN echo -e $'\n\
_人人人人人人人人人人人人人人人人人人人人人人人人_\n\
> super_unkoイメージのビルドが無事完了したよ! <\n\
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄\n\
      👑\n\
    (💩💩💩)\n\
   (💩👁💩👁💩)\n\
  (💩💩💩👃💩💩💩)\n\
 (💩💩💩💩👄💩💩💩💩)'

FROM base AS ci

ARG SH_VERSION=default

# Install bash-x.x
COPY ./docker/install_bash.sh /tmp/install_bash.sh
RUN apt update -yqq \
    && apt install -y --no-install-recommends build-essential bats byacc \
    && rm -rf /var/lib/apt/lists/* \
    && /tmp/install_bash.sh ${SH_VERSION} \
    && ./install.sh


================================================
FILE: docker/install_bash.sh
================================================
#!/bin/bash

set -eu

SCRIPT_NAME="$(basename "${BASH_SOURCE:-$0}")"
readonly SCRIPT_NAME

usage() {
  cat << EOS
$SCRIPT_NAME は指定のバージョンのBashを/bin/bashにインストールします。
インストール前のBashは同じディレクトリにbash.oldとしてバックアップされます。

Usage:
    $SCRIPT_NAME -h | --help
    $SCRIPT_NAME <version>      [default: default]

Available version:
    default
    3.2
    4.0
    4.1
    4.2
    4.3
    4.4
    5.0
EOS
}

case $1 in
  -h | --help)
    usage
    return
    ;;
esac

readonly TMPDIR=/tmp/bash
readonly SH_VERSION=${1:-default}

mkdir -p $TMPDIR

if [[ "$SH_VERSION" != "default" ]]; then
  (
    cd "$TMPDIR"
    curl -s --retry 3 "http://ftp.gnu.org/gnu/bash/bash-${SH_VERSION}.tar.gz" | tar xvz
    cd bash*
    ./configure
    make
    make install
    mv /bin/bash{,.old}
    cp -p ./bash /bin/bash
  )
fi

bash --version


================================================
FILE: docker-compose-ci.yml
================================================
version: '3.7'

x-build: &build
  context: .
  dockerfile: ./docker/Dockerfile
  target: ci

services:
  ci_sh_default: &default
    build:
      <<: *build
      args:
        SH_VERSION: default
    volumes:
      - "$PWD:/usr/local/src/super_unko"
    working_dir: /usr/local/src/super_unko
    entrypoint:
      - ./test.sh

  ci_sh_3.2:
    <<: *default
    build:
      <<: *build
      args:
        # Because bats supports 3.2.57 or more https://github.com/bats-core/bats-core
        SH_VERSION: 3.2.57

  ci_sh_4.0:
    <<: *default
    build:
      <<: *build
      args:
        SH_VERSION: 4.0

  ci_sh_4.1:
    <<: *default
    build:
      <<: *build
      args:
        SH_VERSION: 4.1

  ci_sh_4.2:
    <<: *default
    build:
      <<: *build
      args:
        SH_VERSION: 4.2

  ci_sh_4.3:
    <<: *default
    build:
      <<: *build
      args:
        SH_VERSION: 4.3

  ci_sh_4.4:
    <<: *default
    build:
      <<: *build
      args:
        SH_VERSION: 4.4

  ci_sh_5.0:
    <<: *default
    build:
      <<: *build
      args:
        SH_VERSION: 5.0


================================================
FILE: docker-compose.yml
================================================
version: '3.7'

services:
  super_unko:
    build:
      context: ./
      dockerfile: ./docker/Dockerfile
      target: base
    image: unkontributors/super_unko

  formatter:
    image: peterdavehello/shfmt
    container_name: formatter
    volumes:
      - "$PWD:/work"
    entrypoint:
      - "shfmt"
      - "-i"
      - "2"
      - "-ci"
      - "-sr"
      - "-d"

  linter:
    image: koalaman/shellcheck
    container_name: linter
    volumes:
      - "$PWD:/work"
    entrypoint:
      - "shellcheck"


================================================
FILE: install.sh
================================================
#!/bin/bash
set -ue

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR
readonly BINMODE=755
readonly LIBMODE=644
readonly PREFIX="${1:-/usr/local}"
readonly PREFIX_BIN="${PREFIX}/bin"
readonly PREFIX_LIB="${PREFIX}/lib/super_unko"

install -d "${PREFIX_BIN}"
install -m "${BINMODE}" "${THIS_DIR}"/bin/* "${PREFIX_BIN}"
install -d "${PREFIX_LIB}"
install -m "${LIBMODE}" "${THIS_DIR}"/lib/super_unko/* "${PREFIX_LIB}"


================================================
FILE: lib/super_unko/bigunko.txt
================================================
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1swbVxuClwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTsyNDht44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNb
NDg7NTs5NG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1swbVxuClwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFww
MzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFww
MzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBc
MDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7
OTRt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1
OzEwMG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBc
MDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7
NTht44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1
Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFww
MzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs5
NG3jgIBcMDMzWzQ4OzU7MjQ4beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1swbVxuClwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0
beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNb
NDg7NTs5NG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MTAw
beOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQ4
beOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTsxMDBt44CAXDAz
M1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7
MjQ4beOAgFwwMzNbNDg7NTsyNDht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1swbVxuClwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7MjUybeOAgFwwMzNbNDg7NTsy
NTJt44CAXDAzM1s0ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsxMDBt44CA
XDAzM1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsyNTJt44CAXDAzM1s0
ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MjU0beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzU4
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyMzJt44CAXDAzM1s0ODs1OzIzMm3jgIBcMDMzWzQ4OzU7MjUybeOAgFwwMzNbNDg7NTs5
NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsyNTRt44CAXDAz
M1s0ODs1OzIzMm3jgIBcMDMzWzQ4OzU7MjMybeOAgFwwMzNbNDg7NTsyNTRt44CAXDAzM1s0ODs1
OzI0OG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7OTRt
44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsyNTJt44CAXDAzM1s0ODs1OzIzMm3jgIBcMDMz
WzQ4OzU7MjMybeOAgFwwMzNbNDg7NTsyMzJt44CAXDAzM1s0ODs1OzI1NG3jgIBcMDMzWzQ4OzU7
OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsyNDht44CAXDAzM1s0ODs1OzI1NG3jgIBc
MDMzWzQ4OzU7MjMybeOAgFwwMzNbNDg7NTsyMzJt44CAXDAzM1s0ODs1OzI1NG3jgIBcMDMzWzQ4
OzU7MjUybeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1swbVxuClwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1Ozk0
beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7MjU0beOAgFwwMzNbNDg7NTsyMzJt44CAXDAz
M1s0ODs1OzIzMm3jgIBcMDMzWzQ4OzU7MjMybeOAgFwwMzNbNDg7NTsyNTRt44CAXDAzM1s0ODs1
OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsyNTRt44CA
XDAzM1s0ODs1OzIzMm3jgIBcMDMzWzQ4OzU7MjMybeOAgFwwMzNbNDg7NTsyNTRt44CAXDAzM1s0
ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTs1
OG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsyNTRt44CAXDAz
M1s0ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MjU0beOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1
Ozk0beOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MjU0beOA
gFwwMzNbNDg7NTsyNTRt44CAXDAzM1s0ODs1OzI1NG3jgIBcMDMzWzQ4OzU7MjU0beOAgFwwMzNb
NDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTs1
OG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTsxMDBt44CAXDAz
M1s0ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsxMDBt44CAXDAzM1s0ODs1
OzEwMG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBc
MDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsyNDht44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7
NTs5NG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsxMDBt
44CAXDAzM1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTsxMDBt44CAXDAz
M1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7
OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAz
M1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzU4
beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7OTRt
44CAXDAzM1s0ODs1OzEwMG3jgIBcMDMzWzQ4OzU7MTAwbeOAgFwwMzNbNDg7NTs5NG3jgIBcMDMz
WzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7MjUy
beOAgFwwMzNbNDg7NTsyNTJt44CAXDAzM1s0ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MjUybeOAgFww
MzNbNDg7NTsyNTJt44CAXDAzM1s0ODs1OzI1Mm3jgIBcMDMzWzQ4OzU7MjUybeOAgFwwMzNbNDg7
NTsyNTJt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7NTht44CA
XDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1
OzU4beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1swbVxuClwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1Ozk0beOAgFww
MzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5
NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMz
WzQ4OzU7OTRt44CAXDAzM1s0ODs1OzI1NG3jgIBcMDMzWzQ4OzU7MjU0beOAgFwwMzNbNDg7NTsy
NTRt44CAXDAzM1s0ODs1OzI1NG3jgIBcMDMzWzQ4OzU7MjUybeOAgFwwMzNbNDg7NTs1OG3jgIBc
MDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7
OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0
beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNb
NDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3j
gIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzI1NG3jgIBcMDMzWzQ4OzU7MjU0beOAgFwwMzNb
NDg7NTsyNDht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7OTRt
44CAXDAzM1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0
ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7
NTs5NG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBc
MDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7
NTht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7NTht44CAXDAz
M1s0ODs1Ozk0beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1Ozk0
beOAgFwwMzNbNDg7NTs5NG3jgIBcMDMzWzQ4OzU7OTRt44CAXDAzM1s0ODs1OzU4beOAgFwwMzNb
NDg7NTs1OG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0
ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTs1OG3jgIBcMDMz
WzQ4OzU7NTht44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7NTht
44CAXDAzM1s0ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7NTht44CAXDAzM1s0
ODs1OzU4beOAgFwwMzNbNDg7NTs1OG3jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbgpcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzBtXG4KXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1swbVxuClww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
MG1cbgpcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt
44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAz
M1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1
OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23j
gIBcMDMzWzBtXG4KXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4
OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQz
beOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFww
MzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7
NTsyNDNt44CAXDAzM1swbVxuClwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMz
WzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7
MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOA
gFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNb
NDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsy
NDNt44CAXDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CA
XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0
ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0
M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0ODs1OzI0M23jgIBc
MDMzWzQ4OzU7MjQzbeOAgFwwMzNbMG1cbg==


================================================
FILE: lib/super_unko/unko.cow
================================================
binmode STDOUT, ":utf8";
$the_cow =<<EOC;
\N{U+3000}\N{U+3000}\N{U+3000}\N{U+3000}\N{U+3000}\N{U+3000}\N{U+1F451}
\N{U+3000}\N{U+3000}\N{U+3000}\N{U+3000}\N{U+FF08}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+FF09}
\N{U+3000}\N{U+3000}\N{U+3000}\N{U+FF08}\N{U+1F4A9}\N{U+1F441}\N{U+1F4A9}\N{U+1F441}\N{U+1F4A9}\N{U+FF09}
\N{U+3000}\N{U+3000}\N{U+FF08}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F443}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+FF09}
\N{U+3000}\N{U+FF08}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F444}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+1F4A9}\N{U+FF09}

EOC


================================================
FILE: lib/super_unko/unko.csv
================================================
Name,Language
うんこ,Japanese
ウンコ,Japanese
うんち,Japanese
ウンチ,Japanese
下痢,Japanese
うんこっこ,Japanese
うんちっち,Japanese
うんこもりもり,Japanese
うんちもりもり,Japanese
poo,English
feces,English
shit,English
crap,English
caca,French
merde,French
Caga,Spanish
mierda,Spanish
Kacke,German
Scheiße,German
Feci,Italian
Merda,Italian
Merda,Portuguese
Cocô,Portuguese
Fezes,Portuguese
σκατά,Greek
Какашка,Russian
㞎㞎,Chinese
狗屁,Chinese
똥,Korian
ขี้,Thai
💩,Emoji


================================================
FILE: lib/super_unko/unko.lib
================================================
#!/usr/bin/env bash

FLAG_DEMO=0
if [ "$1" == "demo" ] ; then
  FLAG_DEMO=1
else
  if [ "$0" != "bash" ] ; then ### to use this library, use by `source` or `.`
cat <<EOU
usage: $0: king-unko substitution library.

How to use:

$ . path/to/unko.lib
$ unko.shout | sed -e "s/\$SOME_SYMBOL/ANOTHER_SYMBOL/"

EOU
  fi
fi

EYE=$(echo -e '\U1F441')
LIP=👄
NOSE=👃
CROWN=👑
UNKO=💩
LHSUNKO='('
RHSUNKO=')'
INDENT=' '

if [ $FLAG_DEMO -eq 1 ] ; then
	unko.shout デモだよ!! | tail -n +4 | sed -e "s/${LIP}/💋/" | \
		sed -e "s/${NOSE}/Δ/" | sed -e "s/${CROWN}/🌴/" | sed -e "s/${UNKO}/⭐/g" | \
		sed -e "s/$LHSUNKO///g" | sed -e "s/$RHSUNKO/\/g" | sed -e "s/$INDENT/三/g" |\
		sed -e "s/$EYE/ー/g"
fi

## vim: set ft=sh:


================================================
FILE: lib/super_unko/unko_command_not_found_hundle
================================================
#!/bin/bash
# コマンドがない場合に出力されるテキスト
function __command_not_found_unko() {
  local CMD=$1

  local TEXT=(
    "「${CMD}」なんてコマンドはないぜ… このキングうんこが言うんだ 間違いない"
    "違うな、間違っているぞ${USER}! 「${CMD}」なんてコマンドはない! このキングうんこにはわかる!"
    "「${CMD}」なんて存在しないコマンドを 打たれるたびに5セントもらってたら、今頃大金持ちだぜ!"
    "残念ながら「${CMD}」なんてコマンドはないようだな この私を呼び出す「unko.shout」はあるようなんだがな!"
  )

  local T="${TEXT[$((RANDOM % ${#TEXT[@]}))]}"
  eval unko.shout "$T" | sed "s/${CMD}/\x1b[32m&\x1b[0m/g;"
}

# コマンドが無い場合に実行される処理の定義
function __command_not_found() {
  case ${OSTYPE} in
    darwin*)
      __command_not_found_unko "$1"
      return 127
      ;;
    linux*)
      if [ -x /usr/lib/command-not-found ] || [ -x /usr/share/command-not-found/command-not-found ]; then
        if [ -x /usr/lib/command-not-found ]; then
          /usr/lib/command-not-found -- "$1"
          __command_not_found_unko "$1"
          return 127
        elif [ -x /usr/share/command-not-found/command-not-found ]; then
          /usr/share/command-not-found/command-not-found -- "$1"
          __command_not_found_unko "$1"
          return 127
        fi
      else
        __command_not_found_unko "$1"
        return 127
      fi
      ;;
  esac
}

# command_not_found_handle(zshの場合はcommand_not_found_handler)の定義
if [[ -n "$ZSH_EVAL_CONTEXT" ]]; then
  function command_not_found_handler() {
    trap '' 1 2 3 15
    __command_not_found "$1"
  }
else
  function command_not_found_handle() {
    __command_not_found "$1"
  }
fi


================================================
FILE: lib/super_unko/unko_mb.cow
================================================
$the_cow = <<EOC
      👑
    (💩💩💩)
   (💩👁💩👁💩)
  (💩💩💩👃💩💩💩)
 (💩💩💩💩👄💩💩💩💩)

EOC


================================================
FILE: linter.sh
================================================
#!/bin/bash

SCRIPT_NAME="$(basename "${BASH_SOURCE:-$0}")"
readonly SCRIPT_NAME

# Dockerコンテナ系の定数
readonly CONTAINER_DIR_PREFIX=/work

# 着色系ANSIエスケープシーケンス
readonly RED=$'\x1b[31m'
readonly GREEN=$'\x1b[32m'
readonly RESET=$'\x1b[m'

# デフォルトの静的解析対象
readonly DEFAULT_TARGET_FILES=(*.sh bin/*)

test_count=0
err_count=0

main() {
  # 引数なしのときはヘルプを出力して終了
  if [[ $# -lt 1 ]]; then
    usage >&2
    return 1
  fi

  while ((0 < $#)); do
    local opt=$1
    shift

    case "$opt" in
      help)
        usage
        return
        ;;
      setup)
        # フォーマットとlintに使うDockerイメージを取得
        docker-compose pull formatter linter
        ;;
      format)
        # コードフォーマットにかける
        overwrite=""
        cmd_format "$@"
        print_check_result
        return $?
        ;;
      format-save)
        # コードフォーマットにかけて上書き保存
        overwrite="-w"
        cmd_format "$@"
        print_check_result
        return $?
        ;;
      lint)
        # 静的解析
        cmd_lint "$@"
        print_check_result
        return $?
        ;;
      all)
        # コードフォーマット+静的解析
        cmd_format "$@"
        cmd_lint "$@"
        print_check_result
        return $?
        ;;
      *)
        usage >&2
        return 1
        ;;
    esac
  done
}

usage() {
  cat << EOS
$SCRIPT_NAME はプロジェクト内のシェルスクリプトのコードスタイルチェックをします。

Usage:
    $SCRIPT_NAME <command>

Available commands:
    help                      このヘルプを出力する。
    setup                     リントツールをセットアップする。
    format      [files...]    コードフォーマットにかける。
    format-save [files...]    コードフォーマットして上書き保存する。
    lint        [files...]    リントにかける。
    all                       プロジェクト全体をフォーマットとリントにかける。
EOS
}

## フォーマットにかけるサブコマンド。
cmd_format() {
  # 引数(ファイル)の指定があればそのファイルを解析する
  # なければデフォルト指定(プロジェクト全体)のファイルを解析する
  local files=("${DEFAULT_TARGET_FILES[@]}")
  if [[ 0 -lt $# ]]; then
    files=("$@")
  fi

  # テストするファイルの件数を加算
  test_count=$((test_count + ${#files[@]}))

  # コンテナ内のマウントディレクトリのフルパスに変更
  local fullpath_files=()
  for f in "${files[@]}"; do
    fullpath_files+=("$CONTAINER_DIR_PREFIX/$f")
  done

  run_shfmt "${fullpath_files[@]}"
}

## フォーマットにかける。
run_shfmt() {
  local files=("$@")
  local ret
  docker-compose run formatter $overwrite "${files[@]}"
  ret=$?
  if [[ "$ret" -ne 0 ]]; then
    err_count=$((err_count + 1))
  fi
}

## 静的解析にかけるサブコマンド。
cmd_lint() {
  # 引数(ファイル)の指定があればそのファイルを解析する
  # なければデフォルト指定(プロジェクト全体)のファイルを解析する
  local files=("${DEFAULT_TARGET_FILES[@]}")
  if [[ 0 -lt $# ]]; then
    files=("$@")
  fi

  # テストするファイルの件数を加算
  test_count=$((test_count + ${#files[@]}))

  # コンテナ内のマウントディレクトリのフルパスに変更
  local fullpath_files=()
  for f in "${files[@]}"; do
    # unko.puzzleはスキップする
    if [[ "$f" =~ ^.*unko.puzzle$ ]]; then
      continue
    fi
    fullpath_files+=("$CONTAINER_DIR_PREFIX/$f")
  done

  run_shellcheck "${fullpath_files[@]}"
}

## 静的解析にかける。
run_shellcheck() {
  local files=("$@")
  local ret
  docker-compose run linter "${files[@]}"
  ret=$?
  if [[ "$ret" -ne 0 ]]; then
    err_count=$((err_count + 1))
  fi
}

## テストの結果を出力する。
print_check_result() {
  echo "--------------------------------------------------------------------------------"
  if [[ "$err_count" -lt 1 ]]; then
    echo -e "[ ${GREEN}PASS${RESET} ] ($test_count/$test_count) all lint were passed."
    return
  else
    echo -e "[ ${RED}FAIL${RESET} ] lint were failed."
    return 1
  fi
}

main ${1+"$@"}
exit $?


================================================
FILE: package.sh
================================================
#!/bin/bash
set -ue
THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR
{
  cd "${THIS_DIR}"
  tar zcvf super_unko.tar.gz bin lib .tar2package.yml
  docker run -i greymd/tar2rpm:1.0.1 < super_unko.tar.gz > pkg/super_unko.rpm.tmp
  mv pkg/super_unko.rpm{.tmp,}
  docker run -i greymd/tar2deb:1.0.1 < super_unko.tar.gz > pkg/super_unko.deb.tmp
  mv pkg/super_unko.deb{.tmp,}
  rm super_unko.tar.gz
}


================================================
FILE: super_unko.plugin.zsh
================================================
source "`dirname $0`/activate.sh"


================================================
FILE: test/functions.sh
================================================
#!/bin/bash

coverage() {
  # kcovのインストールされている環境でのみ実行
  if type kcov 2> /dev/null; then
    local options=(--bash-dont-parse-binary-dir)
    kcov "${options[@]}" coverage "$@" || true
  fi
}


================================================
FILE: test/super_unko-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="$(pwd)/../bin/super_unko"

@test "コマンドを指定しない場合はヘルプを出力して、異常終了する" {
  run "$TARGET_COMMAND"
  [ "$status" -ne 0 ]
  coverage "$TARGET_COMMAND"
}

@test "ヘルプを明示的に出力するときは正常終了する" {
  run "$TARGET_COMMAND" help
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND" help
}

@test "unko.lsを呼び出す" {
  run "$TARGET_COMMAND" ls
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = うんこ ]
  coverage "$TARGET_COMMAND" ls
}

@test "unko.anyを呼び出す" {
  run "$TARGET_COMMAND" any
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND" any
}

@test "unko.trを呼び出す" {
  run "$TARGET_COMMAND" tr <<< うんこ
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = 💩 ]
  coverage "$TARGET_COMMAND" tr <<< うんこ
}

@test "unko.towerを呼び出す" {
  run "$TARGET_COMMAND" tower
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (   )" ]
  [ "${lines[2]}" = "  (     )" ]
  [ "${lines[3]}" = " (       )" ]
  coverage "$TARGET_COMMAND" tower
}

@test "unko.tower 2を呼び出す" {
  run "$TARGET_COMMAND" tower 2
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "    人" ]
  [ "${lines[1]}" = "  (   )" ]
  [ "${lines[2]}" = " (     )" ]
  coverage "$TARGET_COMMAND" tower 2
}

@test "bigunko.showを呼び出す" {
  run "$TARGET_COMMAND" bigshow
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND" bigshow
}

#@test "unko.pingを呼び出す" {
#  run "$TARGET_COMMAND" ping
#  [ "$status" -eq 0 ]
#  coverage "$TARGET_COMMAND" ping
#}

@test "存在しないコマンドのときは異常終了する" {
  run "$TARGET_COMMAND" unchi
  [ "$status" -ne 0 ]
  coverage "$TARGET_COMMAND" unchi
}


================================================
FILE: test/unko.any-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.any"
readonly BASH_REQUIRE_VERSION=4.0

#==============================================================================
# NOTE:
#   echo-sdはBash4.0以下では動かないため、Bash4.1以上のみテストする
#==============================================================================

bash_version=$(bash --version | grep -Eo "[0-9]+\.[0-9]+" | head -n 1)
if [ $(echo "$BASH_REQUIRE_VERSION < $bash_version" | bc) -eq 0 ]; then
  echo "  Bash${BASH_REQUIRE_VERSION}以下はスキップ"
  exit 0
fi

@test '引数がない場合はヘルプを出力する' {
  run "$TARGET_COMMAND"
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND"
}

@test '引数が1つのときは💩の置換のみ' {
  run "$TARGET_COMMAND" あ
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "_人人人人人人_" ]
  [ "${lines[1]}" = "> 突然の死 <" ]
  [ "${lines[2]}" = " ̄Y^Y^Y^Y^Y^Y^ ̄" ]
  [ "${lines[3]}" = "      👑" ]
  [ "${lines[4]}" = "    (あああ)" ]
  [ "${lines[5]}" = "   (あ👁あ👁あ)" ]
  [ "${lines[6]}" = "  (あああ👃あああ)" ]
  [ "${lines[7]}" = " (ああああ👄ああああ)" ]
  coverage "$TARGET_COMMAND" あ
}

@test '引数が2つのときは💩の置換と文言変更' {
  run "$TARGET_COMMAND" あ い
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "_人人人_" ]
  [ "${lines[1]}" = "> い <" ]
  [ "${lines[2]}" = " ̄Y^Y^Y^ ̄" ]
  [ "${lines[3]}" = "      👑" ]
  [ "${lines[4]}" = "    (あああ)" ]
  [ "${lines[5]}" = "   (あ👁あ👁あ)" ]
  [ "${lines[6]}" = "  (あああ👃あああ)" ]
  [ "${lines[7]}" = " (ああああ👄ああああ)" ]
  coverage "$TARGET_COMMAND" あ い
}

@test '引数に /' {
  run "$TARGET_COMMAND" /
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "_人人人人人人_" ]
  [ "${lines[1]}" = "> 突然の死 <" ]
  [ "${lines[2]}" = " ̄Y^Y^Y^Y^Y^Y^ ̄" ]
  [ "${lines[3]}" = "      👑" ]
  [ "${lines[4]}" = "    (///)" ]
  [ "${lines[5]}" = "   (/👁/👁/)" ]
  [ "${lines[6]}" = "  (///👃///)" ]
  [ "${lines[7]}" = " (////👄////)" ]
  coverage "$TARGET_COMMAND" あ い
}

@test '引数にエスケープ文字' {
  run "$TARGET_COMMAND" '\\'
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = '_人人人人人人_' ]
  [ "${lines[1]}" = '> 突然の死 <' ]
  [ "${lines[2]}" = ' ̄Y^Y^Y^Y^Y^Y^ ̄' ]
  [ "${lines[3]}" = '      👑' ]
  [ "${lines[4]}" = '    (\\\)' ]
  [ "${lines[5]}" = '   (\👁\👁\)' ]
  [ "${lines[6]}" = '  (\\\👃\\\)' ]
  [ "${lines[7]}" = ' (\\\\👄\\\\)' ]
  coverage "$TARGET_COMMAND" '\\'
}

@test 'ASCIIコード表33~127まででの置換 (エスケープ文字は除外)' {
  grep -o . <<< '!"#$%&'"'"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~' | while read -r ch; do
    run "$TARGET_COMMAND" "$ch"
    [ "$status" -eq 0 ]
    [ "${lines[0]}" = "_人人人人人人_" ]
    [ "${lines[1]}" = "> 突然の死 <" ]
    [ "${lines[2]}" = " ̄Y^Y^Y^Y^Y^Y^ ̄" ]
    [ "${lines[3]}" = "      👑" ]
    [ "${lines[4]}" = "    ($ch$ch$ch)" ]
    [ "${lines[5]}" = "   ($ch👁$ch👁$ch)" ]
    [ "${lines[6]}" = "  ($ch$ch$ch👃$ch$ch$ch)" ]
    [ "${lines[7]}" = " ($ch$ch$ch$ch👄$ch$ch$ch$ch)" ]
    coverage "$TARGET_COMMAND" "$ch"
  done
}


================================================
FILE: test/unko.encode-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.encode"

@test "-h でヘルプを出力する" {
  run "$TARGET_COMMAND" -h
  echo "$output"
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ ^Usage:.* ]]
  coverage "$TARGET_COMMAND" -h
}

@test "--help でヘルプを出力する" {
  run "$TARGET_COMMAND" --help
  echo "$output"
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ ^Usage:.* ]]
  coverage "$TARGET_COMMAND" --help
}

@test '引数なしのときは標準入力をエンコード' {
  run "$TARGET_COMMAND" <<< うんこ
  echo "$output"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "ウンウこうんこう💩ウンウこうこここウウンウこうんここウうんこ" ]
  coverage "$TARGET_COMMAND" <<< うんこ
}

@test '-d で標準入力をデコード {
  run "$TARGET_COMMAND" -d <<< ウンウこうんこう💩ウンウこうこここウウンウこうんここウうんこ
  echo "$output"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "うんこ" ]
  coverage "$TARGET_COMMAND" -d <<< ウンウこうんこう💩ウンウこうこここウウンウこうんここウうんこ
}

@test '--decode で標準入力をデコード {
  run "$TARGET_COMMAND" --decode <<< ウンウこうんこう💩ウンウこうこここウウンウこうんここウうんこ
  echo "$output"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "うんこ" ]
  coverage "$TARGET_COMMAND" --decode <<< ウンウこうんこう💩ウンウこうこここウウンウこうんここウうんこ
}

@test 'ファイルが存在しない場合エラー' {
  export LANG=ja_JP.UTF-8
  run "$TARGET_COMMAND" うんこ
  echo "$output"
  [ "$status" -eq 1 ]
  [[ "${lines[0]}" =~ .*そのようなファイルやディレクトリはありません ]]
  coverage LANG=ja_JP.UTF-8 "$TARGET_COMMAND" うんこ
}

@test 'ディレクトリの場合エラー' {
  export LANG=ja_JP.UTF-8
  run "$TARGET_COMMAND" .
  echo "$output"
  [ "$status" -eq 1 ]
  [[ "${lines[0]}" =~ .*ディレクトリです ]]
  coverage LANG=ja_JP.UTF-8 "$TARGET_COMMAND" .
}

@test 'ファイルが存在しない場合エラー(英語版)' {
  export LANG=en_US.UTF-8
  run "$TARGET_COMMAND" うんこ
  echo "$output"
  [ "$status" -eq 1 ]
  [[ "${lines[0]}" =~ .*"No such file or directory" ]]
  coverage LANG=en_US.UTF-8 "$TARGET_COMMAND" うんこ
}

@test 'ディレクトリの場合エラー(英語版)' {
  export LANG=en_US.UTF-8
  run "$TARGET_COMMAND" .
  echo "$output"
  [ "$status" -eq 1 ]
  [[ "${lines[0]}" =~ .*"Is a directory" ]]
  coverage LANG=en_US.UTF-8 "$TARGET_COMMAND" .
}


================================================
FILE: test/unko.fizzbuzz-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="$(pwd)/../bin/unko.fizzbuzz"
readonly BASH_REQUIRE_VERSION=4.0

#==============================================================================
# NOTE:
#   echo-sdはBash4.0以下では動かないため、Bash4.1以上のみテストする
#==============================================================================

bash_version=$(bash --version | grep -Eo "[0-9]+\.[0-9]+" | head -n 1)
if [ $(echo "$BASH_REQUIRE_VERSION < $bash_version" | bc) -eq 0 ]; then
  echo "  Bash${BASH_REQUIRE_VERSION}以下はスキップ"
  exit 0
fi

@test "引数がない時はヘルプを出力する" {
  run "$TARGET_COMMAND"
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ .*unko.fizzbuzz:* ]]
  coverage "$TARGET_COMMAND"
}

@test "引数が正の整数でない時はヘルプを出力する" {
  for i in -1 1.1 a whoami '$(whoami)' あ 漢字 "" - "*" / "?" '_[$(whoami >&2)]'; do
    run "$TARGET_COMMAND" "$i"
    [ "$status" -eq 0 ]
    [[ "${lines[0]}" =~ .*unko.fizzbuzz:* ]]
    coverage "$TARGET_COMMAND" "$i"
  done
}

@test "引数が0のときは何も出力しない" {
  run "$TARGET_COMMAND" 0
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" == "" ]]
  coverage "$TARGET_COMMAND" 0
}

@test "引数が3のときは3まで出力する" {
  run "$TARGET_COMMAND" 3
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" == 1 ]]
  [[ "${lines[1]}" == 2 ]]
  [[ "${lines[2]}" =~ .*fizz$ ]]
  [[ "${lines[3]}" == "" ]]
  coverage "$TARGET_COMMAND" 3
}

@test "引数が16のときは16まで出力する" {
  run "$TARGET_COMMAND" 16
  [ "$status" -eq 0 ]
  [[ "${lines[1]}" == 2 ]]
  [[ "${lines[2]}" =~ .*fizz$ ]]
  [[ "${lines[3]}" == 4 ]]
  [[ "${lines[4]}" =~ .*buzz$ ]]
  [[ "${lines[5]}" =~ .*fizz$ ]]
  [[ "${lines[14]}" =~ .*人人.* ]]
  [[ "${lines[15]}" =~ .*fizzbuzz.* ]]
  coverage "$TARGET_COMMAND" 16
}


================================================
FILE: test/unko.grep-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.grep"

@test "unko.grepはうんことマッチする" {
  run "$TARGET_COMMAND" <<< "$(echo -e 'うんこ\nあ')"
  [ "$status" -eq 0 ]
  [ "$output" = うんこ ]
  coverage "$TARGET_COMMAND" <<< "$(echo -e 'うんこ\nあ')"
}

@test "unko.grepはうんこ(2行)とマッチする" {
  run "$TARGET_COMMAND" <<< "$(echo -e 'うんこ\nうんち')"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = うんこ ]
  [ "${lines[1]}" = うんち ]
  coverage "$TARGET_COMMAND" <<< "$(echo -e 'うんこ\nうんち')"
}

@test "unko.grepは💩とマッチする" {
  run "$TARGET_COMMAND" <<< "💩"
  [ "$status" -eq 0 ]
  [ "$output" = 💩 ]
  coverage "$TARGET_COMMAND" <<< "💩"
}


================================================
FILE: test/unko.king-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="$(pwd)/../bin/unko.king"
readonly BASH_REQUIRE_VERSION=4.0

@test "-h でヘルプを出力する" {
  run "$TARGET_COMMAND" -h
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ ^unko.king.* ]]
  coverage "$TARGET_COMMAND" -h
}

@test "--help でヘルプを出力する" {
  run "$TARGET_COMMAND" --help
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ ^unko.king.* ]]
  coverage "$TARGET_COMMAND" --help
}

@test "-v でバージョンを出力する" {
  run "$TARGET_COMMAND" -v
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ ^v ]]
  coverage "$TARGET_COMMAND" -v
}

@test "--version でバージョンを出力する" {
  run "$TARGET_COMMAND" --version
  [ "$status" -eq 0 ]
  [[ "${lines[0]}" =~ ^v ]]
  coverage "$TARGET_COMMAND" --version
}

@test "引数未指定の時はデフォルト5になる" {
  run "$TARGET_COMMAND"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "      👑" ]
  [ "${lines[1]}" = "    (💩💩💩)" ]
  [ "${lines[2]}" = "   (💩👁💩👁💩)" ]
  [ "${lines[3]}" = "  (💩💩💩👃💩💩💩)" ]
  [ "${lines[4]}" = " (💩💩💩💩👄💩💩💩💩)" ]
  coverage "$TARGET_COMMAND"
}

@test "引数 5" {
  run "$TARGET_COMMAND" 5
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "      👑" ]
  [ "${lines[1]}" = "    (💩💩💩)" ]
  [ "${lines[2]}" = "   (💩👁💩👁💩)" ]
  [ "${lines[3]}" = "  (💩💩💩👃💩💩💩)" ]
  [ "${lines[4]}" = " (💩💩💩💩👄💩💩💩💩)" ]
  coverage "$TARGET_COMMAND" 5
}

@test "0埋めの数値 (8進数のテスト)" {
  for i in '05' '07' '08' '09' '010'; do
    run "$TARGET_COMMAND" "$i"
    [ "$status" -eq 0 ]
    coverage "$TARGET_COMMAND" "$i"
  done
}

@test "引数 5 未満はNG" {
  for i in -1 0 1 2 3 4; do
    run "$TARGET_COMMAND" $i
    [ "$status" -ne 0 ]
    coverage "$TARGET_COMMAND" $i
  done
}

@test "引数 6" {
  run "$TARGET_COMMAND" 6
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "       👑" ]
  [ "${lines[1]}" = "     (💩💩💩)" ]
  [ "${lines[2]}" = "    (💩👁💩👁💩)" ]
  [ "${lines[3]}" = "   (💩💩💩👃💩💩💩)" ]
  [ "${lines[4]}" = "  (💩💩💩💩👄💩💩💩💩)" ]
  [ "${lines[5]}" = " (💩💩💩💩💩💩💩💩💩💩💩)" ]
  coverage "$TARGET_COMMAND" 6
}

@test "オプション以外の第1引数は数値のみ受け付ける" {
  for i in a whoami '$(whoami)' あ 漢字 "" - "*" / "?" '_[$(whoami >&2)]'; do
    run "$TARGET_COMMAND" "$i"
    [ "$status" -ne 0 ]
    [[ "$output" =~ ^.*ERR.*Invalid.*number.*$ ]]
    coverage "$TARGET_COMMAND" "$i"
  done
}

@test "第1引数に段数、第2引数が不正なケース" {
  for i in a whoami '$(whoami)' あ 漢字 "" - "*" / "?" '_[$(whoami >&2)]'; do
    run "$TARGET_COMMAND" 8 "$i"
    [ "$status" -ne 0 ]
    [[ "$output" =~ ^.*ERR.*Invalid.*sub.*command.*$ ]]
    coverage "$TARGET_COMMAND" 8 "$i"
  done
}

#==============================================================================
# NOTE:
#   以降のテストではecho-sdを使用する。
#   echo-sdはBash4.0以下では動かないため、Bash4.1以上のみテストする。
#==============================================================================

bash_version=$(bash --version | grep -Eo "[0-9]+\.[0-9]+" | head -n 1)
if [ $(echo "$BASH_REQUIRE_VERSION < $bash_version" | bc) -eq 0 ]; then
  echo "  Bash${BASH_REQUIRE_VERSION}以下はスキップ"
  exit 0
fi

@test "第1引数にはshoutを受け付ける。デフォルトの段数は5" {
  run "$TARGET_COMMAND" shout こんにちは
  [ "$status" -eq 0 ]
  [[ "${lines[1]}" =~ ^.*こんにちは.*$ ]]
  [ "${lines[3]}" = "      👑" ]
  [ "${lines[4]}" = "    (💩💩💩)" ]
  [ "${lines[5]}" = "   (💩👁💩👁💩)" ]
  [ "${lines[6]}" = "  (💩💩💩👃💩💩💩)" ]
  [ "${lines[7]}" = " (💩💩💩💩👄💩💩💩💩)" ]
  coverage "$TARGET_COMMAND" shout こんにちは
}

@test "第1引数に段数、第2引数にshout" {
  run "$TARGET_COMMAND" 8 shout こんばんは
  [ "$status" -eq 0 ]
  [[ "${lines[1]}" =~ ^.*こんばんは.*$ ]]
  coverage "$TARGET_COMMAND" 8 shout こんばんは
}

@test "shoutの第3引数以降はオプション" {
  run bash -c "echo うんこ | $TARGET_COMMAND 7 shout -s"
  [ "$status" -eq 0 ]
  [[ "${lines[1]}" =~ ^.*うんこ.*$ ]]
  coverage bash -c "echo うんこ | $TARGET_COMMAND 7 shout -s"
}


================================================
FILE: test/unko.printpnm-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="$(pwd)/../bin/unko.printpnm"

setup() {
  export RUN_TEST=true
  load "$TARGET_COMMAND"
}

@test "unko.printpnmのmax_stage_col関数は引数1のとき13を返す" {
  run max_stage_col 1
  [ "$status" -eq 0 ]
  [ "$output" -eq 13 ]
  coverage max_stage_col 1
}

@test "unko.printpnmのmax_stage_row関数は引数1のとき8を返す" {
  run max_stage_row 1
  [ "$status" -eq 0 ]
  [ "$output" -eq 8 ]
  coverage max_stage_row 1
}

@test "unko.printpnmのmax_value関数は引数の中からもっとも大きな値を返す" {
  run max_value 1 2 3
  [ "$status" -eq 0 ]
  [ "$output" -eq 3 ]
  coverage max_value 1 2 3
}

@test "unko.printpnmのmax_value関数は引数の中からもっとも大きな値を返す。並び順は関係ない" {
  run max_value 3 2 1
  [ "$status" -eq 0 ]
  [ "$output" -eq 3 ]
  coverage max_value 3 2 1
}

@test "unko.printpnmのmax_value関数は引数の中からもっとも大きな値を返す。2桁の整数に対しても" {
  run max_value 10 12 3
  [ "$status" -eq 0 ]
  [ "$output" -eq 12 ]
  coverage max_value 10 12 3
}

@test "unko.printpnmのrepeat関数は引数の数だけ1を連続して返す" {
  run repeat 3
  [ "$status" -eq 0 ]
  [ "$output" = 111 ]
  coverage repeat 3
}

@test "unko.printpnmのrepeat関数は引数の数だけ引数を連続して返す" {
  run repeat 3 0
  [ "$status" -eq 0 ]
  [ "$output" = 000 ]
  coverage repeat 3 0
}

@test "unko.printpnmのalign_center関数は文字列を指定の文字で中央揃えして返す (奇数)" {
  run align_center 0 <<< "$(echo -e '1\n111')"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "010" ]
  [ "${lines[1]}" = "111" ]
  coverage align_center 0 <<< "$(echo -e '1\n111')"
}

@test "unko.printpnmのalign_center関数は文字列を指定の文字で中央揃えして返す (偶数)" {
  run align_center 0 <<< "$(echo -e '1\n1111')"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "0100" ]
  [ "${lines[1]}" = "1111" ]
  coverage align_center 0 <<< "$(echo -e '1\n1111')"
}



================================================
FILE: test/unko.pyramid-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.pyramid"

@test 'unko.pyramidは引数なしのときは16段' {
  run "$TARGET_COMMAND"
  [ "$status" -eq 0 ]
  [ "${lines[0]}"  = "               💩               " ]
  [ "${lines[1]}"  = "              💩💩              " ]
  [ "${lines[2]}"  = "             💩  💩             " ]
  [ "${lines[3]}"  = "            💩💩💩💩            " ]
  [ "${lines[4]}"  = "           💩      💩           " ]
  [ "${lines[5]}"  = "          💩💩    💩💩          " ]
  [ "${lines[6]}"  = "         💩  💩  💩  💩         " ]
  [ "${lines[7]}"  = "        💩💩💩💩💩💩💩💩        " ]
  [ "${lines[8]}"  = "       💩              💩       " ]
  [ "${lines[9]}"  = "      💩💩            💩💩      " ]
  [ "${lines[10]}" = "     💩  💩          💩  💩     " ]
  [ "${lines[11]}" = "    💩💩💩💩        💩💩💩💩    " ]
  [ "${lines[12]}" = "   💩      💩      💩      💩   " ]
  [ "${lines[13]}" = "  💩💩    💩💩    💩💩    💩💩  " ]
  [ "${lines[14]}" = " 💩  💩  💩  💩  💩  💩  💩  💩 " ]
  [ "${lines[15]}" = "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩" ]
  coverage "$TARGET_COMMAND"
}

@test 'unko.pyramidの美しさはブラウザのコードレビューでも確認できる' {
  run bash -c "$TARGET_COMMAND 8|tr 💩 🎄|sed '1s/🎄/👑/';yes 💩|head -2|xargs printf '% 11s\n'"
  [ "${lines[0]}"  = "       👑       " ]
  [ "${lines[1]}"  = "      🎄🎄      " ]
  [ "${lines[2]}"  = "     🎄  🎄     " ]
  [ "${lines[3]}"  = "    🎄🎄🎄🎄    " ]
  [ "${lines[4]}"  = "   🎄      🎄   " ]
  [ "${lines[5]}"  = "  🎄🎄    🎄🎄  " ]
  [ "${lines[6]}"  = " 🎄  🎄  🎄  🎄 " ]
  [ "${lines[7]}"  = "🎄🎄🎄🎄🎄🎄🎄🎄" ]
  [ "${lines[8]}"  = "       💩" ]
  [ "${lines[9]}"  = "       💩" ]

}

@test 'unko.pyramidの引数1' {
  run "$TARGET_COMMAND" 1
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "💩" ]
}

@test "オプション以外の第1引数は数値のみ受け付ける" {
  for i in 0 16.5 a $ '_[$(whoami >&2)]' whoami '$(whoami)' あ 漢字 "*" / "?"; do
    run "$TARGET_COMMAND" "$i"
    [ "$status" -ne 0 ]
    [ "$output" = "unko.pyramid: Invalid number '${i}'" ]
  done
}

@test "第1引数に段数、第2引数が不正なケース" {
  for i in 0 16.5 a $ '_[$(whoami >&2)]' whoami '$(whoami)' あ 漢字 "*" / "?"; do
    run "$TARGET_COMMAND" 16 "$i"
    [ "$status" -ne 0 ]
    [ "$output" = "unko.pyramid: Invalid number '${i}'" ]
  done
}

@test "-から始まる不正なオプションはエラー" {
  for i in - -a --; do
    run "$TARGET_COMMAND" "$i"
    [ "$status" -ne 0 ]
    [ "$output" = "unko.pyramid: illegal option '${i}'" ]
  done
}



================================================
FILE: test/unko.toilet-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.toilet"

@test "普通に実行" {
  run "$TARGET_COMMAND"
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND"
}

@test "おかしなオプション--お菓子" {
  run "$TARGET_COMMAND" --お菓子
  [ "$status" -ne 0 ]
  coverage "$TARGET_COMMAND" --お菓子
}

readonly HANAGE_BASE64="ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAg
ICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPCfkqkgICAg8J+SqSAg
8J+SqSAgICAKICDwn5KpICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgIPCfkqkgIPCf
kqkgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICDwn5KpICDwn5KpICDwn5KpICAgIAogICAg
8J+SqSAg8J+SqSAgICAgIPCfkqnwn5Kp8J+SqSAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqfCfkqkg
IPCfkqnwn5KpICAgICAgICAgICAgICDwn5KpICAgICAgICAgIPCfkqnwn5Kp8J+SqSAgICAgIAog
ICAg8J+SqSAgICDwn5Kp8J+SqfCfkqnwn5KpICAgICAgICAgICAgICAgIPCfkqkgICAgICAgIPCf
kqnwn5KpICAgICAgICAgICAg8J+SqSAg8J+SqfCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgCiAg
8J+SqSAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAg8J+SqSAgICAgIPCfkqkgICAgICAg
ICAgICAgIPCfkqkgICAgICAgICAgICDwn5KpICAgICAgICAgIAogIPCfkqkgICAgICAgICAgICDw
n5KpICAgICAgICAgICAgICDwn5KpICAgICAgICDwn5KpICAgICAgICAgICAgICDwn5KpICAgICAg
ICAgICAg8J+SqSAgICAgICAgICAKICDwn5KpICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAg
8J+SqSAgICAgICAg8J+SqSAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgIPCfkqkgICAgICAg
ICAgCiAg8J+SqSAgICAgIPCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgICDwn5KpICAgIPCfkqnw
n5Kp8J+SqfCfkqkgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICDwn5KpICAgICAgICAgIAog
IPCfkqkgIPCfkqnwn5KpICAgICAg8J+SqfCfkqkgICAgICAgICAgICAgIPCfkqkgICAgICDwn5Kp
8J+SqSAgICAgICAgICAgICAg8J+SqfCfkqkgICAgICDwn5KpICAgICAgICAgICAgCiAg8J+SqfCf
kqkgIPCfkqkgICAgICDwn5KpICDwn5KpICAgICAgICAgICAg8J+SqSAgICAgIPCfkqkgIPCfkqkg
ICAgICAgICAgICDwn5KpICAgICAgICDwn5KpICAgICAgICAgICAgCiAgICDwn5KpICAgIPCfkqnw
n5Kp8J+SqSAgICAgICAgICAgICAgICAgICAg8J+SqfCfkqnwn5KpICAgICAgICAgICAgICAgICAg
ICAgICAgICDwn5KpICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK"

@test "stdinから" {
  run bash -c "echo はなげ| $TARGET_COMMAND | base64"
  [ "$status" -eq 0 ]
  [ "$output" = "$HANAGE_BASE64" ]
  coverage "$TARGET_COMMAND" <<< はなげ
}

# @test "引数に" {
#   run bash -c "$TARGET_COMMAND はなげ | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "$HANAGE_BASE64" ]
#   coverage "$TARGET_COMMAND" はなげ
# }

# @test "flip" {
#   run bash -c "$TARGET_COMMAND --flip | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPCfkqnwn5KpICAgICAg
# ICAgIAogICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgICAgICDwn5Kp
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICDwn5Kp8J+SqfCf
# kqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAg
# ICAg8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgCiAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICDwn5Kp
# 8J+SqSAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPCf
# kqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgIPCfkqkg
# ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAg
# ICAgICDwn5Kp8J+SqfCfkqkgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAKICAg
# ICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgIPCfkqkgICAg
# ICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAKICAgICAgICDwn5KpICAgICAgICAgIPCf
# kqkgICAgICAgICAgICDwn5KpICAgICAg8J+SqSAgICAgIPCfkqkgICAgICAgICAgICAgICAg8J+S
# qSAgICAgICAgICAgICAgCiAgICAgICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgICAg
# ICAgICDwn5KpICAgIPCfkqkgICAgICDwn5KpICAgICAgICAgICAgICAgICAg8J+SqSAgICAgICAg
# ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPCfkqnwn5KpICAgICAg
# ICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgIAogICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgIAo=" ]
#   coverage "$TARGET_COMMAND" --flip
# }
#
# @test "flop" {
#   run bash -c "$TARGET_COMMAND --flop | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAg
# ICDwn5KpICAgICAgICAgIPCfkqnwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAKICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgIPCfkqkgICAgICDwn5KpICAg
# IPCfkqkgICAgICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgCiAgICAg
# ICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICDwn5KpICAgICAg8J+SqSAgICAgIPCfkqkgICAg
# ICAgICAgICDwn5KpICAgICAgICAgIPCfkqkgICAgICAgIAogICAgICAgICAgICAgIPCfkqkgICAg
# ICAgICAgICAgICAgICDwn5KpICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAg
# ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICDwn5Kp8J+S
# qfCfkqkgICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgICAgCiAgICAg
# ICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAg
# ICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# IAogICAg8J+SqfCfkqkgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgCiAgICAgICAg8J+SqfCfkqnw
# n5Kp8J+SqSAgICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgICAgICAg
# 8J+SqfCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAg
# ICAgICAKICAgICAgICAgIPCfkqnwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgIPCfkqkgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgIAo=" ]
#   coverage "$TARGET_COMMAND" --flop
# }
#
# @test "180" {
#   run bash -c "$TARGET_COMMAND --180 | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICDwn5Kp8J+SqSAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAg8J+SqSAgICAg
# ICAgICAKICAgICAgICAgIPCfkqnwn5Kp8J+SqfCfkqnwn5KpICAgICAgICAgICAgICAgIPCfkqkg
# ICAg8J+SqSAgICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgCiAgICAg
# ICAg8J+SqSAgICAgICAgICDwn5KpICAgICAgICAgICAg8J+SqSAgICAgIPCfkqkgICAgICDwn5Kp
# ICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg
# 8J+SqSAgICAgICAgICAgICAgICAgIPCfkqkgICAg8J+SqSAgICAgICAgICAgICAgICAgIPCfkqkg
# ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAg
# ICAg8J+SqfCfkqnwn5KpICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgCiAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAg
# ICAgICAg8J+SqSAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAg
# IAogICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+SqSAgICAg
# ICAgICAgICAgICAgICAg8J+SqSAgICAgICAg8J+SqfCfkqkgICAgCiAgICAgICAgICDwn5Kp8J+S
# qfCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAg
# ICAgICAg8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg8J+SqSAg
# ICAgICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgIPCfkqnwn5KpICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPCf
# kqkgICAgICAgIAo=" ]
#   coverage "$TARGET_COMMAND" --180
# }
#
# @test "right" {
#   run bash -c "$TARGET_COMMAND --right | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwn5Kp8J+SqSAgICAg
# ICAgICAgICAgICAKICAgICAgICAgICAg8J+SqfCfkqkgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAg8J+SqfCfkqkgICAg8J+SqfCfkqnwn5Kp8J+SqQogICAgICAgICAgICAgICAg8J+SqfCfkqnw
# n5Kp8J+SqfCfkqnwn5KpICAgICAgICAgICAgICAgIPCfkqnwn5KpICAgIPCfkqnwn5KpICAgIAog
# ICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCf
# kqkgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg8J+SqfCfkqkgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg8J+SqfCf
# kqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+S
# qfCfkqnwn5Kp8J+SqfCfkqkgICAgICAgIAogICAgICAgICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+S
# qfCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg
# IPCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# CiAgICAgICAgICAgICAgICAgICAg8J+SqfCfkqkgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIPCfkqnwn5Kp8J+SqfCfkqnwn5Kp
# 8J+SqSAgICAgICAgICAgICAgICDwn5Kp8J+SqSAgICAgICAgCiAgICAgICAgICAgICAgICDwn5Kp
# 8J+SqSAgICAgICAgICAgICAgICAgICAgICAgIPCfkqnwn5KpICAgICAgICAgICAgCiAgICAgICAg
# ICAgICAgICDwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqSAgICAg
# ICAgICAgIAogICAgICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAg
# ICAg8J+SqfCfkqkgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo=" ]
#   coverage "$TARGET_COMMAND" --right
# }
#
# @test "left" {
#   run bash -c "$TARGET_COMMAND --left | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgIAogICAgICAgICAgICDwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAg8J+SqfCfkqnw
# n5Kp8J+SqSAgICAgICAgICAgICAgICAKICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqSAgICAg
# ICAgICAgICAgICAgICAg8J+SqfCfkqkgICAgICAgICAgICAgICAgCiAgICAgICAgICAgIPCfkqnw
# n5KpICAgICAgICAgICAgICAgICAgICAgICAg8J+SqfCfkqkgICAgICAgICAgICAgICAgCiAgICAg
# ICAg8J+SqfCfkqkgICAgICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5KpICAgICAg
# ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICDwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICDwn5Kp8J+SqfCfkqnwn5KpICAgICAgICAgICAgCiAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAg8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqkgICAgICAg
# ICAgICAKICAgICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+S
# qfCfkqkgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAKICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwn5Kp8J+SqSAgICAgICAg
# ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp
# 8J+SqSAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIPCfkqnwn5KpICAgIPCfkqnwn5Kp
# ICAgICAgICAgICAgICAgIPCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAK
# 8J+SqfCfkqnwn5Kp8J+SqSAgICDwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAgICAgICAgICDw
# n5Kp8J+SqSAgICAgICAgICAgIAogICAgICAgICAgICAgICAg8J+SqfCfkqkgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo=" ]
#   coverage "$TARGET_COMMAND" --left
# }
#
# @test "border" {
#   run bash -c "$TARGET_COMMAND --border | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnw
# n5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCf
# kqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+S
# qfCfkqkK8J+SqSAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+SqQrwn5KpICAgICAgICAg
# IPCfkqnwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgIPCfkqkK8J+SqSAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAg
# ICAgICDwn5KpCvCfkqkgICAgICAgIPCfkqnwn5Kp8J+SqfCfkqkgICAgICAgICAgICAgICAgICAg
# ICAg8J+SqSAgICAgICAgICAgICAgICAgICAgICAgIPCfkqnwn5Kp8J+SqfCfkqnwn5KpICAgICAg
# ICAgIPCfkqkK8J+SqSAgICDwn5Kp8J+SqSAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgICAg
# 8J+SqSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICDwn5KpCvCf
# kqkgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+SqQrwn5KpICAgICAgICAgICAgICAg
# IPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgIPCfkqkK8J+SqSAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAg
# ICAgIPCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICAg
# ICAgICDwn5KpCvCfkqkgICAgICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAg
# IPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgICAgIPCfkqkK8J+S
# qSAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgICAgICDwn5KpICAgICAg8J+SqSAgICAgIPCf
# kqkgICAgICAgICAgICDwn5KpICAgICAgICAgIPCfkqkgICAgICAgIPCfkqkK8J+SqSAgICAgICAg
# ICAgIPCfkqkgICAgICAgICAgICAgICAgICDwn5KpICAgICAg8J+SqSAgICDwn5KpICAgICAgICAg
# ICAgICAgIPCfkqnwn5Kp8J+SqfCfkqnwn5KpICAgICAgICAgIPCfkqkK8J+SqSAgICAgICAgICDw
# n5KpICAgICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICDwn5Kp8J+SqSAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAg8J+SqQrwn5KpICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAg8J+SqQrwn5KpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+SqQrwn5KpICAgICAgICAg
# ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
# ICAgICAgICAgICAgICAgICAg8J+SqQrwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCf
# kqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+S
# qfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp
# 8J+SqfCfkqnwn5Kp8J+SqfCfkqnwn5Kp8J+SqQo=" ]
#   coverage "$TARGET_COMMAND" --border
# }

readonly WIDTH_20="ICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgCiAgICAgICAgICDwn5Kp8J+SqSAgICAgICAg
ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICDwn5Kp8J+SqfCfkqnw
n5KpICAgICAgICAgICAgCiAgICDwn5Kp8J+SqSAgICAgICAg8J+SqSAgICAgICAgICAKICAgICAg
ICAgICAgICAgIPCfkqkgICAgICAgICAgCiAgICAgICAgICAgICAgICDwn5KpICAgICAgICAgIAog
ICAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAKICAgICAgICAgICAgICDwn5KpICAgICAgICAg
ICAgCiAgICAgICAgICAgICAg8J+SqSAgICAgICAgICAgIAogICAgICAgICAgICDwn5KpICAgICAg
ICAgICAgICAKICAgICAgICAgIPCfkqkgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg
ICAgICAgICAgICAgIAogICAgICAgIPCfkqkgICAgICAgICAgICAgICAgICAKICAgICAgICAgIPCf
kqkgICAgICAgICAgICAgICAgCiAgICAgICAgICDwn5KpICAgICAgICAgICAgICAgIAogICAgICAg
IPCfkqkgICAgICAgICAgICAgICAgICAKICAgICAgICDwn5KpICAgICAgICAgICAgICAgICAgCiAg
ICAgIPCfkqnwn5Kp8J+SqSAgICAgICAgICAgICAgICAKICAgICAg8J+SqSAgICDwn5KpICAgICAg
ICAgICAgICAKICAgIPCfkqkgICAgICDwn5KpICAgICAg8J+SqSAgICAgIAogICAg8J+SqSAgICAg
IPCfkqkgICAg8J+SqSAgICAgICAgCiAg8J+SqSAgICAgICAgICDwn5Kp8J+SqSAgICAgICAgICAK
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg
CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg
IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgIPCfkqkgICAgICAgICAgICAgICAg
ICAgIAogICAgICAgIPCfkqnwn5Kp8J+SqfCfkqnwn5KpICAgICAgICAgIAogICAgICAgICAgICAg
IPCfkqkgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg
ICAgICAgICAgICAgICAgICAgCiAgICDwn5KpICAgICAgICAgICAgICAgICAgICAgIAogICAg8J+S
qSAgICAgICAgICAgICAgICAgICAgICAKICAgICAg8J+SqSAgICAgICAgICDwn5KpICAgICAgICAK
ICAgICAgICDwn5Kp8J+SqfCfkqnwn5Kp8J+SqSAgICAgICAgICAKICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo="

# @test "-w 20" {
#   run bash -c "$TARGET_COMMAND -w 20 | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "$WIDTH_20" ]
#   coverage "$TARGET_COMMAND" -w 20
# }
#
# @test "--width 20" {
#   run bash -c "$TARGET_COMMAND --width 20 | base64"
#   [ "$status" -eq 0 ]
#   [ "$output" = "$WIDTH_20" ]
#   coverage "$TARGET_COMMAND" --width 20
# }

@test "--help" {
  run bash -c "$TARGET_COMMAND --help"
  [ "$status" -ne 0 ]
  coverage "$TARGET_COMMAND" --help
}

@test "-h" {
  run bash -c "$TARGET_COMMAND -h"
  [ "$status" -ne 0 ]
  coverage "$TARGET_COMMAND" -h
}

@test "-h == --help" {
  run bash -c "$TARGET_COMMAND -h 2>&1"
  [ "$status" -ne 0 ]
  [ "$output" = "$($TARGET_COMMAND --help 2>&1)" ]
}

@test "ヘルプメッセージは正しいかな?" {
  run bash -c "$TARGET_COMMAND --help 2>&1 | base64"
  [ "$status" -eq 0 ]
  [ "$output" = "VXNhZ2U6IHVua28udG9pbGV0IFsgLWh2IF0gWyAtdyBvdXRwdXR3aWR0aCBdCiAgICAgICAgICAg
ICAgICAgICBbIC0tY3JvcCBdIFsgLS1mbGlwIF0gWyAtLWZsb3AgXQogICAgICAgICAgICAgICAg
ICAgWyAtLTE4MCBdIFsgLS1sZWZ0IF0gWyAtLXJpZ2h0IF0KICAgICAgICAgICAgICAgICAgIFsg
LS1ib3JkZXIgXSBbIG1lc3NhZ2UgXQoKICAtaCwgLS1oZWxwICAgICAgICAgICAgICAgICAg44GT
44Gu44OY44Or44OX44KS5Ye65Yqb44GX44Gm57WC5LqG44GX44G+44GZCiAgLXcsIC0td2lkdGgg
PHdpZHRoLCBhdXRvPiAgIOWHuuWKm+OBruW5heOBp+OBmeOAgmF1dG/jgpLmjIflrprjgZnjgovj
gajnq6/mnKvjga7luYXjgavjgarjgorjgb7jgZkKICAgICAgLS1jcm9wICAgICAgICAgICAgICAg
ICAg5LiK5LiL5bem5Y+z44Gu54Sh6aeE44Gq44K544Oa44O844K544KS5YmK6Zmk44GX44G+44GZ
CiAgICAgIC0tZmxpcCAgICAgICAgICAgICAgICAgIOawtOW5s+aWueWQkeOBq+WPjei7ouOBl+OB
vuOBmQogICAgICAtLWZsb3AgICAgICAgICAgICAgICAgICDlnoLnm7TmlrnlkJHjgavlj43ou6Lj
gZfjgb7jgZkKICAgICAgLS0xODAgICAgICAgICAgICAgICAgICAgMTgw5bqm5Zue6Lui44GX44G+
44GZCiAgICAgIC0tbGVmdCAgICAgICAgICAgICAgICAgIOW3puOBuDkw5bqm5Zue6Lui44GX44G+
44GZCiAgICAgIC0tcmlnaHQgICAgICAgICAgICAgICAgIOWPs+OBuDkw5bqm5Zue6Lui44GX44G+
44GZCiAgICAgIC0tYm9yZGVyICAgICAgICAgICAgICAgIOaeoOe3muOCkuOBpOOBkeOBvuOBmQo=" ]
}

@test "--version" {
  run "$TARGET_COMMAND" --version
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND" --version
}

@test "-v" {
  run "$TARGET_COMMAND" -v
  [ "$status" -eq 0 ]
  coverage "$TARGET_COMMAND" -v
}

@test "--version == -v" {
  run "$TARGET_COMMAND" -v
  [ "$status" -eq 0 ]
  [ "$output" = "$($TARGET_COMMAND --version)" ]
}

@test "バージョン情報は正しいかな?" {
  run bash -c "$TARGET_COMMAND --version | base64"
  [ "$status" -eq 0 ]
  [ "$output" = "dW5rby50b2lsZXQgdmVyc2lvbiDwn5KpLvCfkqku8J+SqSAoMjDwn5Kp8J+SqS/wn5Kp8J+SqS/w
n5Kp8J+SqSkK" ]
}

@test "全テスト終わり💩" {
  [ "💩" = "💩" ]
}


================================================
FILE: test/unko.tower-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.tower"

@test 'unko.towerは引数なしのときは3段' {
  run "$TARGET_COMMAND"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (   )" ]
  [ "${lines[2]}" = "  (     )" ]
  [ "${lines[3]}" = " (       )" ]
  coverage "$TARGET_COMMAND"
}

@test 'unko.towerで引数2' {
  run "$TARGET_COMMAND" 2
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "    人" ]
  [ "${lines[1]}" = "  (   )" ]
  [ "${lines[2]}" = " (     )" ]
  coverage "$TARGET_COMMAND" 2
}

@test 'unko.towerで引数4' {
  run "$TARGET_COMMAND" 4
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "      人" ]
  [ "${lines[1]}" = "    (   )" ]
  [ "${lines[2]}" = "   (     )" ]
  [ "${lines[3]}" = "  (       )" ]
  [ "${lines[4]}" = " (         )" ]
  coverage "$TARGET_COMMAND" 4
}

@test 'unko.towerでメッセージを埋め込む' {
  run "$TARGET_COMMAND" -s あい
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (あいあ)" ]
  [ "${lines[2]}" = "  (いあいあい)" ]
  [ "${lines[3]}" = " (あいあいあいあ)" ]
  coverage "$TARGET_COMMAND" -s あい
}

@test 'unko.towerで先頭から文字数分だけメッセージを埋め込む' {
  run "$TARGET_COMMAND" -m あい
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (あい )" ]
  [ "${lines[2]}" = "  (     )" ]
  [ "${lines[3]}" = " (       )" ]
  coverage "$TARGET_COMMAND" -m あい
}

@test 'unko.towerで半角文字は全角文字1つ分で置換される' {
  run "$TARGET_COMMAND" -m ab
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (a b  )" ]
  [ "${lines[2]}" = "  (     )" ]
  [ "${lines[3]}" = " (       )" ]
  coverage "$TARGET_COMMAND" -m ab
}

@test 'unko.tower -mで置換文字に/が含まれていても置換できる' {
  run "$TARGET_COMMAND" -m /
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (/   )" ]
  [ "${lines[2]}" = "  (     )" ]
  [ "${lines[3]}" = " (       )" ]
  coverage "$TARGET_COMMAND" -m /
}

@test 'unko.tower -sで置換文字に/が含まれていても置換できる' {
  run "$TARGET_COMMAND" -s /
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "     人" ]
  [ "${lines[1]}" = "   (/ / / )" ]
  [ "${lines[2]}" = "  (/ / / / / )" ]
  [ "${lines[3]}" = " (/ / / / / / / )" ]
  coverage "$TARGET_COMMAND" -s /
}

@test 'unko.tower -sで置換文字に\\が含まれていても置換できる' {
  run "$TARGET_COMMAND" -s '\\'
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = '     人' ]
  [ "${lines[1]}" = '   (\ \ \ )' ]
  [ "${lines[2]}" = '  (\ \ \ \ \ )' ]
  [ "${lines[3]}" = ' (\ \ \ \ \ \ \ )' ]
  coverage "$TARGET_COMMAND" -s '\\'
}

@test 'unko.tower -sASCIIコード表33~127までの全ての文字は半角文字として扱う (\\は除外)' {
  grep -o . <<< '!"#$%&'"'"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~' | while read -r ch; do
    run "$TARGET_COMMAND" -s "$ch"
    [ "$status" -eq 0 ]
    [ "${lines[0]}" = "     人" ]
    [ "${lines[1]}" = "   ($ch $ch $ch )" ]
    [ "${lines[2]}" = "  ($ch $ch $ch $ch $ch )" ]
    [ "${lines[3]}" = " ($ch $ch $ch $ch $ch $ch $ch )" ]
    coverage "$TARGET_COMMAND" -s "$ch"
  done
}



================================================
FILE: test/unko.tr-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

readonly TARGET_COMMAND="../bin/unko.tr"

@test "unko.trでうんこは💩になる" {
  run "$TARGET_COMMAND" <<< うんこ
  [ "$status" -eq 0 ]
  [ "$output" = 💩 ]
  coverage "$TARGET_COMMAND" <<< うんこ
}

@test "unko.trでうんちは💩になる" {
  run "$TARGET_COMMAND" <<< うんち
  [ "$status" -eq 0 ]
  [ "$output" = 💩 ]
  coverage "$TARGET_COMMAND" <<< うんち
}

@test "unko.trで下痢は💩になる" {
  run "$TARGET_COMMAND" <<< 下痢
  [ "$status" -eq 0 ]
  [ "$output" = 💩 ]
  coverage "$TARGET_COMMAND" <<< 下痢
}

@test "unko.trで💩は💩になる" {
  run "$TARGET_COMMAND" <<< 💩
  [ "$status" -eq 0 ]
  [ "$output" = 💩 ]
  coverage "$TARGET_COMMAND" <<< 💩
}


================================================
FILE: test/unko.yes-test.bats
================================================
#!/usr/bin/env bats
source functions.sh

#==============================================================================
# NOTE:
#   yesをcoverageに渡しつつ、無限の出力を停止できないためcoverageを取得しない
#==============================================================================

readonly TARGET_COMMAND="../bin/unko.yes"

@test "unko.yesの1つ目の文字列は💩である" {
  run bash -c "$TARGET_COMMAND | head -n 1"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "💩" ]
}

@test "unko.yesの2つ目の文字列は💩である" {
  run bash -c "$TARGET_COMMAND | head -n 2"
  [ "$status" -eq 0 ]
  [ "${lines[0]}" = "💩" ]
  [ "${lines[1]}" = "💩" ]
}



================================================
FILE: test.sh
================================================
#!/bin/bash

SCRIPT_NAME="$(basename "${BASH_SOURCE:-$0}")"
readonly SCRIPT_NAME

readonly RED=$'\x1b[31m'
readonly BLUE=$'\x1b[34m'
readonly RESET=$'\x1b[m'

cd test || exit 1

main() {
  # 引数未指定の場合は全てのテストを実行する
  local error_count=0
  local ret
  if [[ $# -lt 1 ]]; then
    for test_script in *-test.bats; do
      echo -e "${BLUE}${test_script}${RESET}"
      ./"$test_script"
      ret=$?
      if [[ "$ret" -ne 0 ]]; then
        error_count=$((error_count + 1))
      fi
      echo
    done
    return "$error_count"
  fi

  local cmd="$1"

  # ヘルプの出力
  if [[ "$cmd" == help ]]; then
    usage
    return
  fi

  # マッチするコマンドのみ実行
  for test_script in *-test.bats; do
    if [[ "$cmd"-test.bats == "$test_script" ]]; then
      echo -e "${BLUE}${test_script}${RESET}"
      ./"$test_script"
      ret=$?
      return "$ret"
    fi
  done

  usage >&2
  return 1
}

usage() {
  cat << EOS
$SCRIPT_NAME はtestディレクトリ配下のテストスクリプトを実行する。

Usage:
    $SCRIPT_NAME              全てのテストを実行する
    $SCRIPT_NAME <command>    コマンド、あるいはテストスクリプトを実行する

Available commands:
    help             このヘルプを出力する
    <test_script>    test/*-test.batsの任意の1つのスクリプト

Available test scripts:
EOS
  for test_script in *-test.bats; do
    echo "${test_script//-test.bats/}"
  done
}

print_bash_version() {
  echo "------------------------------------------------------------------------------"
  bash --version
  echo "------------------------------------------------------------------------------"
}

type bats >&/dev/null
ret=$?
if [[ "$ret" -ne 0 ]]; then
  echo -e "[ ${RED}ERR${RESET} ] bats was not found. See a section of Testing on README."
  exit 1
fi

print_bash_version
main ${1+"$@"}
ret=$?
print_bash_version

exit $ret


================================================
FILE: uninstall.sh
================================================
#!/bin/bash
set -ue

THIS_DIR=$(
  cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd
)
readonly THIS_DIR
readonly PREFIX="${1:-/usr/local}"
readonly PREFIX_BIN="${PREFIX}/bin"
readonly PREFIX_LIB="${PREFIX}/lib/super_unko"

for cmd in "${THIS_DIR}"/bin/*; do
  rm -f "$PREFIX_BIN/$(basename "$cmd")"
done
rm -rf "$PREFIX_LIB"


================================================
FILE: 💩.💩
================================================
💩
Download .txt
gitextract_nf5gjjz4/

├── .github/
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── release.yml
│       └── unko.yml
├── .tar2package.yml
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── activate.sh
├── bin/
│   ├── bigunko.show
│   ├── super_unko
│   ├── unko.any
│   ├── unko.encode
│   ├── unko.fizzbuzz
│   ├── unko.grep
│   ├── unko.king
│   ├── unko.life
│   ├── unko.ls
│   ├── unko.ping
│   ├── unko.printpnm
│   ├── unko.puzzle
│   ├── unko.pyramid
│   ├── unko.question
│   ├── unko.say
│   ├── unko.shout
│   ├── unko.think
│   ├── unko.toilet
│   ├── unko.tower
│   ├── unko.tr
│   └── unko.yes
├── doc/
│   ├── ci-push.puml
│   ├── unko.puzzle.md
│   └── unko.toilet.md
├── docker/
│   ├── Dockerfile
│   └── install_bash.sh
├── docker-compose-ci.yml
├── docker-compose.yml
├── install.sh
├── lib/
│   └── super_unko/
│       ├── bigunko.txt
│       ├── unko.cow
│       ├── unko.csv
│       ├── unko.lib
│       ├── unko_command_not_found_hundle
│       └── unko_mb.cow
├── linter.sh
├── package.sh
├── pkg/
│   ├── super_unko.deb
│   └── super_unko.rpm
├── super_unko.plugin.zsh
├── test/
│   ├── functions.sh
│   ├── super_unko-test.bats
│   ├── unko.any-test.bats
│   ├── unko.encode-test.bats
│   ├── unko.fizzbuzz-test.bats
│   ├── unko.grep-test.bats
│   ├── unko.king-test.bats
│   ├── unko.printpnm-test.bats
│   ├── unko.pyramid-test.bats
│   ├── unko.toilet-test.bats
│   ├── unko.tower-test.bats
│   ├── unko.tr-test.bats
│   └── unko.yes-test.bats
├── test.sh
├── uninstall.sh
└── 💩.💩
Condensed preview — 65 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (157K chars).
[
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 739,
    "preview": "## Check list\n\n* [ ] Were all tests passed of CI?\n  * (Case: failing `test`) Please run tests and fix your code (see als"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 713,
    "preview": "name: release\n\non:\n  release:\n    types: [published]\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    steps:\n      - use"
  },
  {
    "path": ".github/workflows/unko.yml",
    "chars": 3039,
    "preview": "name: test\n\non:\n  push:\n    branches:\n      - oshiri\n    paths-ignore:\n      - 'LICENSE'\n      - 'README.*'\n      - 'doc"
  },
  {
    "path": ".tar2package.yml",
    "chars": 372,
    "preview": "name : superunko\ncmdname : superunko\nsummary : Super Unko\ndescription : super_unko project is the one of the awesome, cl"
  },
  {
    "path": ".travis.yml",
    "chars": 822,
    "preview": "language: bash\n\nenv:\n  global:\n    - PATH=${PATH}:${HOME}/kcov/bin\n\naddons:\n  apt:\n    packages:\n      - binutils-dev\n  "
  },
  {
    "path": "LICENSE",
    "chars": 1046,
    "preview": "💩 License\n\nCopyright (c) 2017 greymd\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
  },
  {
    "path": "Makefile",
    "chars": 770,
    "preview": ".PHONY: default\ndefault: usage\n\n.PHONY: usage\nusage: ## Print help\n\t@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) "
  },
  {
    "path": "README.md",
    "chars": 8003,
    "preview": "<h1 align=\"center\">\n  <img src=\"img/logo.png\" width=50% />\n</h1>\n\n[![License](https://img.shields.io/badge/license-%F0%9"
  },
  {
    "path": "activate.sh",
    "chars": 260,
    "preview": "#!/bin/bash\n\nif ! type super_unko > /dev/null 2>&1; then\n  THIS_DIR=$(\n    cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n "
  },
  {
    "path": "bin/bigunko.show",
    "chars": 219,
    "preview": "#!/bin/bash\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n\nLIB_DIR=\"${THIS_DIR}/../lib/"
  },
  {
    "path": "bin/super_unko",
    "chars": 1853,
    "preview": "#!/bin/bash\n\nset -eu\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n\nSCRIPT_NAME=\"$(base"
  },
  {
    "path": "bin/unko.any",
    "chars": 367,
    "preview": "#!/bin/bash\n\nset -eu\n\nusage() {\n  cat << EOF\nUsage: $0 <UNKO> [PHRASE ...]\nUNKO:   Alternative character of 💩.\nPHRASE: P"
  },
  {
    "path": "bin/unko.encode",
    "chars": 1575,
    "preview": "#!/bin/bash\n\nif [[ \"$LANG\" = zh* ]] || [[ \"$LANG\" = en* ]]; then\n  export TEXTDOMAINDIR=\"/usr/share/locale-langpack/${LA"
  },
  {
    "path": "bin/unko.fizzbuzz",
    "chars": 630,
    "preview": "#!/bin/bash\n\nUNKO_FIZZ='💩'\nUNKO_BUZZ='🍺'\n\nking_unko() {\n  unko.shout \"$1\"\n}\n\nusage() {\n  cat << EOM\n$0: $0 [unsigned_int"
  },
  {
    "path": "bin/unko.grep",
    "chars": 292,
    "preview": "#!/bin/bash\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n\nLIB_DIR=\"${THIS_DIR}/../lib/"
  },
  {
    "path": "bin/unko.king",
    "chars": 3888,
    "preview": "#!/bin/bash\n\nset -eu\n\nreadonly THIS_CMD=\"${0##*/}\"\nreadonly VERSION=\"v1.1.0\"\n\n# Unko parts\nreadonly TOP=\"${T:-👑}\"\nreadon"
  },
  {
    "path": "bin/unko.life",
    "chars": 5061,
    "preview": "#!/usr/bin/env bash\n\nset -u\nCELL=()\nNEXT_CELL=()\nCURSOR_Y=0\nCURSOR_X=0\n\n## Use ANSI-C quoting because my text editor's l"
  },
  {
    "path": "bin/unko.ls",
    "chars": 238,
    "preview": "#!/bin/bash\n# Jot down any expression that means 💩.\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonl"
  },
  {
    "path": "bin/unko.ping",
    "chars": 439,
    "preview": "#!/usr/bin/env bash\n# Ping the poop domain 💩.\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS"
  },
  {
    "path": "bin/unko.printpnm",
    "chars": 4883,
    "preview": "#!/bin/bash\n\nSCRIPT_NAME=\"$(basename \"${BASH_SOURCE:-$0}\")\"\nreadonly SCRIPT_NAME\nreadonly VERSION=v1.0.1\n\n## main はメイン関数"
  },
  {
    "path": "bin/unko.puzzle",
    "chars": 11602,
    "preview": "#!/usr/bin/env bash\nset -eu\nFRAME=30\nTILES=${TILES:-3}\nHEADER_HEIGHT=23 # Darwin\nRANDOM_SLIDE=$((10 + TILES * TILES * TI"
  },
  {
    "path": "bin/unko.pyramid",
    "chars": 1552,
    "preview": "#!/usr/bin/env bash\n\n# Sierpinski gasket is not unkoski gasket.\n# Sierpinski is great mathematician.\n# unkoski is people"
  },
  {
    "path": "bin/unko.question",
    "chars": 340,
    "preview": "#!/bin/bash\nTEXT=$*\n\neval unko.shout \"${TEXT}\"\n\nwhile :; do\n  read -rp \"ok? (y/N/u): \" ynu\n  case \"$ynu\" in\n    [yY]*)\n "
  },
  {
    "path": "bin/unko.say",
    "chars": 385,
    "preview": "#!/bin/bash\n\n# Get current directory\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n\nLIB_"
  },
  {
    "path": "bin/unko.shout",
    "chars": 415,
    "preview": "#!/bin/bash\n\necho-sd ${1+\"$@\"}\nt=\"${T:-👑}\"         # Top\nu=\"${U:-💩}\"         # Unko\nle=\"${LE:-${E:-👁}}\" # Left Eye\nre=\"$"
  },
  {
    "path": "bin/unko.think",
    "chars": 387,
    "preview": "#!/bin/bash\n\n# Get current directory\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n\nLIB_"
  },
  {
    "path": "bin/unko.toilet",
    "chars": 2216,
    "preview": "#!/bin/bash\n\nusage() {\n  cat << EOS >&2\nUsage: unko.toilet [ -hv ] [ -w outputwidth ]\n                   [ --crop ] [ --"
  },
  {
    "path": "bin/unko.tower",
    "chars": 3274,
    "preview": "#!/usr/bin/env bash\nset -u\n\nreadonly THIS_CMD=\"${0##*/}\"\nreadonly DEFAULT_PADDING=\" \"\nreadonly DEFAULT_HEIGHT=3\nreadonly"
  },
  {
    "path": "bin/unko.tr",
    "chars": 259,
    "preview": "#!/bin/bash\n\n# Get current directory\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n\nLIB_"
  },
  {
    "path": "bin/unko.yes",
    "chars": 20,
    "preview": "#!/bin/bash\nyes '💩'\n"
  },
  {
    "path": "doc/ci-push.puml",
    "chars": 767,
    "preview": "@startuml\n\nstart\n\n: git commit;\n: git push;\n\npartition \"GitHub Actions\" {\n  fork\n    : build docker image;\n    partition"
  },
  {
    "path": "doc/unko.puzzle.md",
    "chars": 2228,
    "preview": "# unko.puzzle\n\nsliding block puzzle\n\nTable of Contents\n\n<!--ts-->\n* [unko.puzzle](doc/unko.puzzle.md#unkopuzzle)\n   * [R"
  },
  {
    "path": "doc/unko.toilet.md",
    "chars": 895,
    "preview": "# unko.toilet\n\n<font size=7>Text to UNKO Art!!!!</font>\n\nTable of Contents\n\n<!--ts-->\n* [unko.toilet](doc/unko.toilet.md"
  },
  {
    "path": "docker/Dockerfile",
    "chars": 1320,
    "preview": "# vim: tw=0:\nFROM ubuntu:20.04 AS base\n\nRUN echo -e $'\\n\\\n_人人人人人人人人人人人人人人人人人人人人人人_\\n\\\n> super_unkoイメージを今からビルドするよ! <\\n\\\n>"
  },
  {
    "path": "docker/install_bash.sh",
    "chars": 810,
    "preview": "#!/bin/bash\n\nset -eu\n\nSCRIPT_NAME=\"$(basename \"${BASH_SOURCE:-$0}\")\"\nreadonly SCRIPT_NAME\n\nusage() {\n  cat << EOS\n$SCRIP"
  },
  {
    "path": "docker-compose-ci.yml",
    "chars": 1082,
    "preview": "version: '3.7'\n\nx-build: &build\n  context: .\n  dockerfile: ./docker/Dockerfile\n  target: ci\n\nservices:\n  ci_sh_default: "
  },
  {
    "path": "docker-compose.yml",
    "chars": 511,
    "preview": "version: '3.7'\n\nservices:\n  super_unko:\n    build:\n      context: ./\n      dockerfile: ./docker/Dockerfile\n      target:"
  },
  {
    "path": "install.sh",
    "chars": 445,
    "preview": "#!/bin/bash\nset -ue\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\nreadonly BINMODE=755\n"
  },
  {
    "path": "lib/super_unko/bigunko.txt",
    "chars": 20827,
    "preview": "XDAzM1s0ODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzNbNDg7NTsyNDNt44CAXDAzM1s0\nODs1OzI0M23jgIBcMDMzWzQ4OzU7MjQzbeOAgFwwMzN"
  },
  {
    "path": "lib/super_unko/unko.cow",
    "chars": 567,
    "preview": "binmode STDOUT, \":utf8\";\n$the_cow =<<EOC;\n\\N{U+3000}\\N{U+3000}\\N{U+3000}\\N{U+3000}\\N{U+3000}\\N{U+3000}\\N{U+1F451}\n\\N{U+3"
  },
  {
    "path": "lib/super_unko/unko.csv",
    "chars": 428,
    "preview": "Name,Language\nうんこ,Japanese\nウンコ,Japanese\nうんち,Japanese\nウンチ,Japanese\n下痢,Japanese\nうんこっこ,Japanese\nうんちっち,Japanese\nうんこもりもり,Japa"
  },
  {
    "path": "lib/super_unko/unko.lib",
    "chars": 700,
    "preview": "#!/usr/bin/env bash\n\nFLAG_DEMO=0\nif [ \"$1\" == \"demo\" ] ; then\n  FLAG_DEMO=1\nelse\n  if [ \"$0\" != \"bash\" ] ; then ### to u"
  },
  {
    "path": "lib/super_unko/unko_command_not_found_hundle",
    "chars": 1458,
    "preview": "#!/bin/bash\n# コマンドがない場合に出力されるテキスト\nfunction __command_not_found_unko() {\n  local CMD=$1\n\n  local TEXT=(\n    \"「${CMD}」なんてコ"
  },
  {
    "path": "lib/super_unko/unko_mb.cow",
    "chars": 76,
    "preview": "$the_cow = <<EOC\n      👑\n    (💩💩💩)\n   (💩👁💩👁💩)\n  (💩💩💩👃💩💩💩)\n (💩💩💩💩👄💩💩💩💩)\n\nEOC\n"
  },
  {
    "path": "linter.sh",
    "chars": 3385,
    "preview": "#!/bin/bash\n\nSCRIPT_NAME=\"$(basename \"${BASH_SOURCE:-$0}\")\"\nreadonly SCRIPT_NAME\n\n# Dockerコンテナ系の定数\nreadonly CONTAINER_DI"
  },
  {
    "path": "package.sh",
    "chars": 424,
    "preview": "#!/bin/bash\nset -ue\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\n{\n  cd \"${THIS_DIR}\"\n "
  },
  {
    "path": "super_unko.plugin.zsh",
    "chars": 34,
    "preview": "source \"`dirname $0`/activate.sh\"\n"
  },
  {
    "path": "test/functions.sh",
    "chars": 191,
    "preview": "#!/bin/bash\n\ncoverage() {\n  # kcovのインストールされている環境でのみ実行\n  if type kcov 2> /dev/null; then\n    local options=(--bash-dont-p"
  },
  {
    "path": "test/super_unko-test.bats",
    "chars": 1545,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"$(pwd)/../bin/super_unko\"\n\n@test \"コマンドを指定しない場合はヘルプを出力し"
  },
  {
    "path": "test/unko.any-test.bats",
    "chars": 2798,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.any\"\nreadonly BASH_REQUIRE_VERSION=4.0\n\n#="
  },
  {
    "path": "test/unko.encode-test.bats",
    "chars": 1942,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.encode\"\n\n@test \"-h でヘルプを出力する\" {\n  run \"$TA"
  },
  {
    "path": "test/unko.fizzbuzz-test.bats",
    "chars": 1649,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"$(pwd)/../bin/unko.fizzbuzz\"\nreadonly BASH_REQUIRE_VER"
  },
  {
    "path": "test/unko.grep-test.bats",
    "chars": 628,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.grep\"\n\n@test \"unko.grepはうんことマッチする\" {\n  run"
  },
  {
    "path": "test/unko.king-test.bats",
    "chars": 3599,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"$(pwd)/../bin/unko.king\"\nreadonly BASH_REQUIRE_VERSION"
  },
  {
    "path": "test/unko.printpnm-test.bats",
    "chars": 1683,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"$(pwd)/../bin/unko.printpnm\"\n\nsetup() {\n  export RUN_T"
  },
  {
    "path": "test/unko.pyramid-test.bats",
    "chars": 2317,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.pyramid\"\n\n@test 'unko.pyramidは引数なしのときは16段'"
  },
  {
    "path": "test/unko.toilet-test.bats",
    "chars": 20370,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.toilet\"\n\n@test \"普通に実行\" {\n  run \"$TARGET_CO"
  },
  {
    "path": "test/unko.tower-test.bats",
    "chars": 2929,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.tower\"\n\n@test 'unko.towerは引数なしのときは3段' {\n  "
  },
  {
    "path": "test/unko.tr-test.bats",
    "chars": 637,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\nreadonly TARGET_COMMAND=\"../bin/unko.tr\"\n\n@test \"unko.trでうんこは💩になる\" {\n  run \"$TA"
  },
  {
    "path": "test/unko.yes-test.bats",
    "chars": 584,
    "preview": "#!/usr/bin/env bats\nsource functions.sh\n\n#=============================================================================="
  },
  {
    "path": "test.sh",
    "chars": 1705,
    "preview": "#!/bin/bash\n\nSCRIPT_NAME=\"$(basename \"${BASH_SOURCE:-$0}\")\"\nreadonly SCRIPT_NAME\n\nreadonly RED=$'\\x1b[31m'\nreadonly BLUE"
  },
  {
    "path": "uninstall.sh",
    "chars": 320,
    "preview": "#!/bin/bash\nset -ue\n\nTHIS_DIR=$(\n  cd \"$(dirname \"${BASH_SOURCE:-$0}\")\" && pwd\n)\nreadonly THIS_DIR\nreadonly PREFIX=\"${1:"
  },
  {
    "path": "💩.💩",
    "chars": 2,
    "preview": "💩\n"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the unkontributors/super_unko GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 65 files (131.4 KB), approximately 58.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!