この記事はHamee Advent Calendar 2019の14日目の記事です。
はじめに
コマンドラインインターフェース(CLI)とアスキーアート(AA)は親和性が高く、sl
やcowsay
などその親和性を発揮したジョークコマンドが多数存在している
そこで、git-hookを利用してgit commit
したときにコミットメッセージをAAで装飾するジョークhookを作った
ぶち当たった壁
某掲示板を中心に発達したAAは主にWindowsのフォントで綺麗に表示されるようにできているため、別の環境でみようとした時に綺麗に見えない可能性がある。(というかフォントが変わると綺麗に見えなくなるのは当たり前だったが実際に見るまで酷さを知らなかった)
元々やろうとしてことはアスキーアートを大量に保存(もしくは外部から取得)しておき、コミットメッセージによってランダムなAAで装飾するものだったが、綺麗に表示されないAAが多かったため断念。
結局自分の環境で綺麗に表示され、できるだけ他のフォントでも崩れないようなAAをいくつか選んで装飾することにした。
装飾例
Roboto Mono Medium for Powerline
サイズ12での表示
短いコミットメッセージの場合
タイポを修正
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch test
# Changes to be committed:
# modified: test
長いコミットメッセージの場合
簡潔な説明が書けず長ったらしくなったコミットメッセージの場合
詳細なメッセージが残されている場合もある
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch test
# Changes to be committed:
# modified: test
マージコミットの場合
Merge branch 'test2' into test
# Conflicts:
# test2
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch test
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: test2
実装
#!/bin/sh
DOUNIDEMO(){
cat << EOS
*'\`\`・* 。
| \`*。
,。∩∧_,,∧ *
+ (´・ω・\`) *。+゚
\`*。 ヽ、 つ *゚*
\`・+。*・'゚⊃ +゚
☆ ∪~ 。*゚
\`・+。*・ ゚
EOS
}
DOG() {
cat << EOS
\
 ̄ヽ、 _ノ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
`'ー '´
○
O
__,.....--‐―― ― ― --..、
,/ l ヽ \
/ / ヽ`
l l !
ヽ / ● ● |
! ヽ l ヽノ/ と思うわんわんであった
,! \ │ _ ヽ
,! `´ (::)l
| `---、  ̄ l
! `ー 、.._./⌒iノ
! ヽ  ̄
EOS
}
N_TONE(){
cat << EOS
,-、 ,.-、
./::::\ /::::::ヽ
/:::::::::;ゝ--──-- 、._/:::::::::::|
/,.-‐''"´ \::::::::|
/ ヽ、::::|
/ ヽ|
l l
.| ● | んーと
l , , , ● l
\` 、 (_人__丿 、、、 /
\`ー 、__ /
/\`'''ー‐‐──‐‐‐┬'''""´
,-、 ,.-、
./::::\ /::::::ヽ
/:::::::::;ゝ--──-- 、._/:::::::::::|
/,.-‐''"´ \::::::::|
/ ヽ、::::|
/ ● ヽ|
l , , , ● l
.| (_人__丿 、、、 | $first_line
l l
\` 、 /
\`ー 、__ /
/\`'''ー‐‐──‐‐‐┬'''""´
EOS
}
max_len=0
first_line=''
is_merge=false
IFS=$'\n';
for line in `cat "$1"`
do
# コミットメッセージのうち最も長い行の長さを調べる
msg=$(echo $line | awk -F '[#]' '{print $1}');
if [ ${#msg} -gt $max_len ]; then
max_len=${#msg};
if [ -z "$first_line" ]; then
first_line=$msg;
fi
fi
# マージコミットかどうかを調べる
if [ "`echo $line | grep 'Merge'`" ]; then
is_merge=true;
fi
done
if [ $max_len -eq 0 ]; then
exit 0;
fi
# マージコミット用のAA
if $is_merge; then
echo "$( DOUNIDEMO )" >> $1;
exit 0;
fi
# コミットメッセージの横の長さによってAAを変える
case $max_len in
[1-9])
echo "$( N_TONE )" > $1;;
*)
echo "$( DOG )" >> $1;;
esac
git commit
でメッセージを確定させると末尾にAAが追加され、そのメッセージでcommit
する。
学べたこと
ざっくり簡潔に
- 文字列の長さを表示したい時は
${#hensumei}
と書く
-
while
でパイプを使うと別プロセスで実行され、ループ内部の変数の変化がループ外部で反映されない(ループ外部では値が変化していない) -
for
を使いパイプなしでファイルを一行ずつ読み込むことでそれを回避できる
- ヒアドキュメント内にカッコが片側だけある場合の出力
#!/bin/sh
echo $(cat << EOS
ヒアドキュメントの
例(
EOS
)
#$ sh test.sh
# test.sh: line 3: unexpected EOF while looking for matching `)'
# test.sh: line 9: syntax error: unexpected end of file
-
`" "`
で囲むかfunction
の戻り値から受け取ることでエラーを回避できる
#!/bin/sh
echo "`cat << EOS
ヒアドキュメントの
例(
EOS
`"
#$ sh test.sh
# ヒアドキュメントの
#
# 例(
#!/bin/sh
MY_FUNC(){
cat << EOS
ヒアドキュメントの
例(
EOS
}
echo "$( MY_FUNC )"
#$ sh test.sh
# ヒアドキュメントの
#
# 例(
おまけ
githubからコミットメッセージを見る
AAのバリエーションがもっと増やせるとよかったなあ と思うわんわんであった