プロンプトに活動限界時間を表示する

私は18:00になると稼働できなくなるうえ、ひきざんがにがてなので残り時間で表示しようと思います。

リアルタイムなタイマーでもないので現在時刻を表示する系の亜種です。
時間計算大変だったよー備忘録。

# 完成品

![image.png](https://qiita-image-store.s3.amazonaws.com/0/62354/18624fb4-d09b-db74-c7ad-1587a9c5e7b9.png)

```bash:eva.fish
function eva
    set now   (date +%s)
    set limit (date -d '18:00' +%s)
    set remaining (expr $limit - $now)

    set sec (expr $remaining \% 60)
    set min (expr \( $remaining \% 3600 \) / 60)
    set hrs (expr $remaining / 3600)

    printf "%d:%02d:%02d" $hrs $min $sec
end
```

プロンプト表示は単純に関数をechoすればいいです。

```bash:fish_right_prompt.fish
function fish_right_prompt
    if [ $status -eq 0 ]
        set_color magenta
        echo "(ﾟーﾟ*)  "
    else
        set_color blue
        echo "(＝ω＝.) "
    end
    if not set -q __fish_prompt_regalias
        # グローバルにしないと毎回変わるよ
        set -g __fish_prompt_regalias (regalias)
    end
    echo (eva |golor)" "
    set_color cyan
    echo "$__fish_prompt_regalias"
    #set_color yellow
    #echo -n $USER
    #set_color normal
    #echo -n '@'
    #set_color red
    #hostname
end
```

編集面倒なので今使っているものを貼り付けましたが、
`echo (eva)`でOK


関数名がevaなのは

>![image](https://edit-anything.com/edius/wp-content/uploads/eva_blur.jpg)
[エヴァンゲリオン風カウントダウン – edius…?](https://edit-anything.com/edius/technique_19_eva_countdown.html)

定時以降働きたくないということで
動きが止まるイメージ+コロン区切りのカウントダウン表示=エヴァ
でした。

S2機関もないです。


# つまづき

## 今日の18時求められない問題

検索では
`date -d '10 day'`
など単語でフォーマットを指定するものばかりが引っかかったので、類推から`date`の柔軟さに賭けて
`date -d '18:00'`
で取れた。これで「今日の」が前提になるのは助かる。

## 時刻の引き算

ShellScriptの日付操作の貧弱さに泣いた…

[シェルスクリプトで時間計算を一人前にこなす - Qiita](https://qiita.com/richmikan@github/items/14e32d099bd9bcc7f8e8)

>シェルスクリプトが敬遠される理由の一つ。それは時間の計算機能が弱いところだ。

[風邪ひいた, シェルスクリプトで時間差を求める - Days of Speed(2013-01-07)](http://www.nofuture.tv/diary/20130107.html)

これで`+%s`でUNIX時間に変換できて、単純な引き算で差秒が導き出せることがわかった。

```bash
    set now   (date +%s)
    set limit (date -d '18:00' +%s)
    set remaining (expr $limit - $now)
```

## 秒数のH:i:s化

差分の秒はUNIX時間とは関係ないので、これをUNIX時間として変換すると1970年にタイムスリップしてしまう。

でも時間は時間なので簡単に変換してくれると思いきや、自作せねばならぬもよう…

いくつかあったが、これを採用した。

[bashの計算式で、秒数をHH:MM:SSフォーマットに変換する - Qiita](https://qiita.com/catfist/items/890a3502e2cb9b191d91)

>```bash
i=6789
((sec=i%60, min=(i%3600)/60, hrs=i/3600))
timestamp=$(printf "%d:%02d:%02d" $hrs $min $sec)
echo $timestamp
```

```bash
    set sec (expr $remaining \% 60)
    set min (expr \( $remaining \% 3600 \) / 60)
    set hrs (expr $remaining / 3600)

    printf "%d:%02d:%02d" $hrs $min $sec
```

## エスケープ問題

`expr`の式が通らなくて躓いた。

### fish？

すでにコードで見られるように、`%`をエスケープしなければならない。

### `expr`

更に、`()`もエスケープせねばならず、さらにさらに前後にスペースをつけなければならない。

exprは普段使わないので、つまづきまくった。

## `expr`代替探し問題

`expr`の使い方を探す中で

[シェルで変数のインクリメントに expr を使うと100倍遅い件 - Qiita](https://qiita.com/d_nishiyama85/items/a117d59a663cfcdea5e4)

を見つけて、では`((...))`をつかうか…としたらfishはPOSIX互換ではないので使えなし。

[Bash $((算術式)) のすべて - A 基本編 - Qiita](https://qiita.com/akinomyoga/items/9761031c551d43307374)

代替を探すも見つからなく…

[fishからbashのletを呼び出してちょっと計算する - Qiita](https://qiita.com/ryotako/items/b17757574ac38aee385a)

>fishでは，計算は基本的に`math`コマンドにやってもらうことになっています．

[math:bcを召喚して強力数値計算！exprなんていらない](http://fish.rubikitch.com/math/)

[コマンドライン上で計算する方法まとめ【UNIX】【Windows】 | バシャログ。](http://bashalog.c-brains.jp/17/07/06-160000.php)

>最近はやりの fish には、 `math` というコマンドが用意されています。
`math` を使うと、 `expr` よりも高度な計算ができます。

私がしたいのは高度な計算ではなく単純な四則演算の低度な計算なわけで。

その場合、主に速度面で`math`を採用するメリットを記事単位で探し出せなかったので`expr`のままとしました。
この回り道もなかなか時間を使った。