[Rust] 初心者がコマンドラインツールを作成して反省するだけ

# [Rust] 初心者がコマンドラインツールを作成して反省するだけ

![キャプチャ](https://user-images.githubusercontent.com/43775946/60386182-e9eadd00-9acc-11e9-8ce7-ead3fc3c6ff3.PNG)

## 経緯
Rustを学習し始めて時間が少し経っているが実用的なものを全く作成していませんでした。
そこで何か作成できるものはないかと考えたところ、**サンバのリズム**のことを思い出し作成することになります。

<a href="https://github.com/various3211workd/dyktsr"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/various3211workd/dyktsr.png" width="460px"></a> 

## 環境
* Windows10 Pro
* rustup 1.18.3
* cargo 1.33.0-nightly
* 開発時間：1時間


## サンバのリズムの解析
サンバのリズムはココリコ遠藤さんが披露したネタの一つです。

基本的な文法は以下のようになっている

```
ホホホイ　ホホホイ　ホホホイ　ホイ
```

使用している文字は2種類しかありません。

これは現在主要なフォンノイマン型のコンピュータが`1`と`0`の2種類で構成されていることから、
コンピュータとの相性は抜群だということがわかります。

というわけで、入力する文字の種類を2種類にし、それをサンバのリズムの基本形（以下、基本形）に置き換える形でツールを作成していきます。

### 入力値のチェック
まずは入力文字数のチェックから

```rust:変更前
// check rhythmtext length
if 2 != rhythmtext.len() {
  panic!("I can't get on such rhythm (pointed out)");
}

let split_rhythm: Vec<char> = rhythmtext.chars().collect();
```

当初、上記の通りに書いていました。

ですが、入力される文字が日本語のようなUTF-8の形式だと対応ができなかったため先に分割しておいて配列の要素数を数える方法に変更します。

```rust:変更後
let split_rhythm: Vec<char> = rhythmtext.chars().collect();

// check rhythmtext length
if 2 != Vec::len(&split_rhythm) {
  panic!("I can't get on such rhythm (pointed out)");
}
```

### 基本形の作成
あとは分割した入力文字を基本形に当てはめることで文章は作成できる...
のだが、あまりきれいな書き方ができなかった

```rust:問題のコード1
// ホホホイ
let first_clause: String = 
  format!("{}{}{}{}", 
    split_rhythm[0],  // ホ
    split_rhythm[0],  // ホ
    split_rhythm[0],  // ホ
    split_rhythm[1]); // イ
```

`ホホホイ`を作成するにあたってそのまま配列のn番目の文字を入れる形になってしまった。
定数としてルールのようなものを宣言し、それにのっとて基本形を作成すればよかった...?

```rust:問題のコード2
// put samba rhythm
println!("{}{}   {}{}   {}{}",
  first_clause, charicon,
  first_clause, charicon, 
  last_clause, charicon);
```

出来上がった基本形と絵文字をつなげて標準出力に渡す形になってしまった。


動作確認をしてみる。

```powershell
PS>cargo run -- ホイ
    Finished dev [unoptimized + debuginfo] target(s) in 0.49s
     Running `target\debug\dyktsr.exe ホイ`
ホホホイ🙏   ホホホイ🙏   ホホホイホイ🙏
```

コードの品質はともかく、これで入力された文字をサンバのリズムに乗せることができたので追加の機能としていろいろ足していくことにした。

## 追加機能その１: 任意のアイコンの設定
ユーザが入力した文字を表示するようにしたいと思い、そのあたりの処理を作ることにしました。

コマンドライン引数周りでは`docopt`というcrateを使用しました。
オプションとして`i`と`文字列`を指定し、その文字列を出力するようにします。

```rust
// default char icon
let mut charicon = "🙏";
if args.get_bool("--item") {
  charicon = args.get_str("--item");
}
```

デフォルトでは`🙏`を出力するようにしており、itemフラグが`true`の場合に任意の文字列を入れるという形にしています。

C言語では入力値のチェックをしないような代入は危険な気がしますが、Rustではそのあたりを気にせずに使えるのでとても助かります。

実行してみると

```powershell
PS>cargo run -- ウキ -i 🐵
    Finished dev [unoptimized + debuginfo] target(s) in 0.70s
     Running `target\debug\dyktsr.exe ウキ -i 🐵`
ウウウキ🐵   ウウウキ🐵   ウウウキウキ🐵
```

となり、しっかりオプション`i`が効いていることがわかります。


## 追加機能その２: プエルトリコモード
**サンバのリズム**のネタにはプエルトリコが出てきますが、歌がこの節に入るとこれまでと基本形が変わってしまいます。

プエルトリコ状態は以下のような形になっています。

```:プエルトリコ
ホイホイ　ホホホホイ ホイホイホホイホホイ　ホイ
```

ノーマルモードですら綺麗にコードを書けなかったのにこんなに長くなるといよいよ恥ずかしいコードになってしまう...

こんなコードを書いてしまうとは、サンバのリズムの魔力は恐ろしいと思いました。

<details><summary>恐ろしい...</summary><div>

```rust
  let first_clause: String = 
    format!("{}{}{}{}", 
      split_rhythm[0], 
      split_rhythm[1],
      split_rhythm[0], 
      split_rhythm[1]);
  
  let second_clause: String = 
    format!("{}{}{}{}{}", 
      split_rhythm[0], 
      split_rhythm[0], 
      split_rhythm[0], 
      split_rhythm[0],
      split_rhythm[1]);

  let hoi_clause: String = 
    format!("{}{}", 
      split_rhythm[0], 
      split_rhythm[1]);

  let theard_clause: String = 
    format!("{}{}{}{}{}{}{}{}{}", 
      hoi_clause,
      hoi_clause,
      hoi_clause,
      split_rhythm[0], 
      split_rhythm[0], 
      split_rhythm[1],
      split_rhythm[0], 
      split_rhythm[0], 
      split_rhythm[1]);

  // put samba rhythm
  println!("{}{}   {}{}   {}{}   {}{}", 
    first_clause, charicon, 
    second_clause, charicon, 
    theard_clause, charicon, 
    hoi_clause, charicon);
```

</div></details>

## 感想
アルゴリズムや文字の処理周りの知識が足りないことがわかりました。
**ふと思いついたアプリを開発すると、自分に足りないものがはっきりわかって勉強になります。**


本ツールについては、ユーザが自由に基本形を設定出来たら面白くなりそうだと思いました。