私が今所属しているwebエンジニアのためのアプレンティスシップ制度では、毎日の勉強成果を報告するために日誌を書くことが推奨されています。勉強の成果を公開することでモチベーションを維持する方法として期待できますし、企業へのアピールになり得るかもしれないという一石二鳥なアウトプットだとも言えます。アプレンティスシップ制度が気になった方は下記にリンク参照。
英国「アプレンティスシップ制度」に見る、オルタナティブな職業の入り口
マークダウン式で簡単に下記のようにして記載します。(人によってはもっと丁寧に書いていますが私はめんどくさがり屋なので、、、)書き終えたらリモートリポジトリにプッシュして、slackにURLを貼り付けるのが流れです。マークダウンって何?て思った方は下記参照。
【マークダウン記法とは?】マークダウンの書き方を網羅的に解説
## 本日の目標(TODO目標/できるようになりたいこと)
blog完成
## 学習時間(Hour)
3 hours
## 目標振り返り(TODO進捗/できるようになりたいこと振り返り)
- かなり軽い感じでblogを作成。
- rubocopのドキュメントとコードをざっくり拝見
## 詰まっていること(実現したいこと/現状/行ったこと/仮説)
open aiのapiを使うか、またモデルの選定。
## 学んだこと(新しい気付き、学び)
大きな学びはあまりなかった
## 感想(一日の感想、雑談)
コマンド作りがとても楽しい
## 明日の目標(TODO目標/できるようになりたいこと)
オブジェクト指向設計本を読む
しかしながら、めんどくさがりの私はなんとか最小の工数で済ませようと考えます。
そこで思いついたのは、面倒な作業を全部やってくれるコマンドを作れば良いじゃん〜ということでした。
そうなんです。コマンドは作ることが出来るんです!! はい、なので作ってしまいました!
diary.sh
#!/bin/bash -eu
# Specify the directory to create the daily logs in
diary_dir="${HOME}/Apprentice/diary"
# Create the directory if it doesn't exist
mkdir -p "${diary_dir}"
# Navigate to the diary directory
cd "${diary_dir}"
# Get today's date
today="$(date +%Y-%m-%d)"
year_month="$(date +%Y-%m)"
# Create a new diary file with today's date if it doesn't exist
if [ ! -f "${today}.md" ]; then
# Get the path of the template files
template_json="${diary_dir}/template.json"
template_md="${diary_dir}/template.md"
# Create a new diary file
mkdir -p "${diary_dir}/${year_month}"
cp "${template_md}" "${diary_dir}/${year_month}/${today}.md"
# Create a new JSON file with today's date
echo '{}' > "${diary_dir}/reports/${today}.json"
# Fill the new JSON file with data from the template
jq -s '.[0] * .[1]' "${template_json}" "${diary_dir}/reports/${today}.json" > tmp.$$.json && mv tmp.$$.json "${diary_dir}/reports/${today}.json"
fi
# Open the new diary file in Visual Studio Code
code "${diary_dir}/${year_month}/${today}.md"
push_diary.sh
#!/bin/bash -eu
# Specify the directory to create the daily logs in
diary_dir="${HOME}/Apprentice/diary/"
# Navigate to the diary directory
cd "${diary_dir}"
# Get today's date
today="$(date +%Y-%m-%d)"
year_month="$(date +%Y-%m)"
# Read the diary file
diary_file="${diary_dir}/${year_month}/${today}.md"
if [ ! -f "${diary_file}" ]; then
echo "Diary file not found: ${diary_file}"
exit 1
fi
# Read the content of each section
goal=$(sed -n '/^## 本日の目標/,/^##/p' "${diary_file}" | sed '1d;$d')
learning_hours=$(sed -n '/^## 学習時間/,/^##/p' "${diary_file}" | sed '1d;$d')
reflection=$(sed -n '/^## 目標振り返り/,/^##/p' "${diary_file}" | sed '1d;$d')
blocker=$(sed -n '/^## 詰まっていること/,/^##/p' "${diary_file}" | sed '1d;$d')
learning=$(sed -n '/^## 学んだこと/,/^##/p' "${diary_file}" | sed '1d;$d')
impression=$(sed -n '/^## 感想/,/^##/p' "${diary_file}" | sed '1d;$d')
tomorrow_goal=$(sed -n '/^## 明日の目標/,/^##/p' "${diary_file}" | sed '1d;$d')
# Create a JSON object with the content
json=$(cat <<EOF
{
"goal": "${goal}",
"learning_hours": "${learning_hours}",
"reflection": "${reflection}",
"blocker": "${blocker}",
"learning": "${learning}",
"impression": "${impression}",
"tomorrow_goal": "${tomorrow_goal}"
}
EOF
)
# Write the JSON object to the daily report file
report_file="${diary_dir}/reports/${today}.json"
echo "${json}" > "${report_file}"
# Add changes to the diary file
git add "${diary_file}" "${report_file}"
# Commit changes to the diary file
git commit -m "Update diary for ${today}"
# Push changes to remote repository
git push origin main
# Send a Slack notification for the daily report
python "${diary_dir}/slack_notification.py"
いやいや、いきなりこんなコードの塊見せられてもわからんわ!!と思った方、大丈夫です。
みっちり解説いたしましょう。
説明の前に、私が実現したかった要件について振り返ります。
- コマンドを打つと日誌用のファイルが作成される。(ex. 2023-04-21.md)
- 日誌用のファイルに内容を書いた後、一つのコマンドでGithubのリモートリポジトリにも内容が保存され、尚且つslackのチャンネルに内容が掲載される。
今回は、1番についてです。作成していく過程を示しながら説明していきます。
それでは、解説に入りましょう!Let’s get started!!
まず日誌用のファイルを作成するためにテンプレートを作ります。diaryフォルダの下に置いて下さい。 (Githubを触ったことがない人は下記リンクを参考にしながらリモートリポジトリでdiaryを作って下さい)
terminal
touch template.md
template.md
## 本日の目標(TODO目標/できるようになりたいこと)
## 学習時間(Hour)
## 目標振り返り(TODO進捗/できるようになりたいこと振り返り)
## 詰まっていること(実現したいこと/現状/行ったこと/仮説)
## 学んだこと(新しい気付き、学び)
## 感想(一日の感想、雑談)
## 明日の目標(TODO目標/できるようになりたいこと)
file tree
diary -- template.md
GitHub Docs 新しいリポジトリの作成
GitHub Docs リポジトリをクローンする
次に、日誌ファイルを作成するためのコマンド(実行ファイル)を作成します。コマンドは、簡潔に説明すると一つのファイルに書かれたコードを読み込むことで処理されます。binとは何?、なんでbinフォルダの下にファイルを作るのか気になった方は、Linuxについて勉強することを推奨します。
terminal
touch ~/bin/diary.sh
ファイルを作成したら、最初に見せたコードを書き込みます。
まず、シェルスクリプトを作るお作法としてファイル先頭に下記を書き込みます。今回のプログラムに影響はありませんが今後皆さんがさまざまなコマンドを作るときに、これを書かないと不便なことがあるかもしれないので。
diary.sh
#!/bin/bash -eu
次に、皆さんの作ったdiaryフォルダの場所の情報をdiary_dir変数に代入します。 下記は皆さんがホーム直下にdiaryフォルダを作成していることを想定していますが、例えばdiaryフォルダの位置が~/Apprentice/dairyの場合は、diary_dir=”${HOME}/Apprentice/diary”と変わります。
diary.sh
diary_dir="${HOME}/diary"
file tree
HOME - diary -template.md
- bin - diary.sh
下記でフォルダを作成します。オプションとして-pをつけることで、存在しないパスのフォルダも自動的に作成してくれます。例えば、mkdir -p ~/fruits/appleという構造のappleフォルダをfruitsフォルダがまだ存在していなくても自動的に指定した構造のフォルダとともに作成してくれます。
diary.sh
mkdir -p "${diary_dir}"
作成したフォルダに移動します。(diaryフォルダに移動)
cd "${diary_dir}"
そして、各変数に日誌を書いた日のデータを代入します。dateというコマンドに下記のフォーマットを与えると戻り値として2023-04-20、2023-04のように値が返ってきます。その値を文字列として変数に入れています。
today="$(date +%Y-%m-%d)"
year_month="$(date +%Y-%m)"
| format | explanation |
| %Y | 西暦4桁 |
| %y | 西暦下2桁 |
| %m | 月(01~12) |
| %d | 月(Jan~Dec) |
| %a | 月(Sun~Sut) |
| %d | 日(01~31) |
| %H | 時間(00~23) |
ここで、条件分岐を使用します。ここでは、当日のファイル(2023-04-20.md)がまだ作られていない場合はtrueを返し、if文に入っている処理を実行します。もうすでに作られている場合は、if文内の処理は飛ばされます。
オプションとして使用されている-fはそのファイルが存在しているかどうかを評価しています。もし-fがなければ、ファイルが存在しない、もしくは空のファイルであってもtrueを返してしまいif文内の処理が実行されてしまいます。
また、! は否定演算子と言って[]内で判定された結果を逆転させます。
if [ ! -f "${today}.md" ]; then
そして、ファイルがまだ作られていない場合は先ほど作成したtemplate.mdファイルがtemplate_mdの変数に代入されます。template_jsonは次回のpart2で説明しますのでここでは飛ばしてオッケーです。
template_json="${diary_dir}/template.json"
template_md="${diary_dir}/template.md"
ここでは、先ほど当日の情報を入れた変数year_month、todayを利用してフォルダとファイルが作成されます。cpコマンドはファイルの中身をコピーすることができる機能を持っており、template_mdに入れたテンプレートの情報を当日の日誌ファイルにコピーされることで自動生成されることを期待します。2023年4月20日に作成された場合は下記のツリー構造になります。
mkdir -p "${diary_dir}/${year_month}"
cp "${template_md}" "${diary_dir}/${year_month}/${today}.md"
HOME - bin - diary.sh
- diary - template.md
- 2023-04 - 2023-04-20.md
こちらのコードも次回のpart2に必要なコードです。今回は説明を省きます。
echo '{}' > "${diary_dir}/reports/${today}.json"
jq -s '.[0] * .[1]' "${template_json}" "${diary_dir}/reports/${today}.json" > tmp.$$.json && mv tmp.$$.json "${diary_dir}/reports/${today}.json"
fi
これで当日の日誌ファイルが作られていない場合の条件分岐は終了します。当日の日報ファイルが作成されるスクリプトを作ることができました。
私はvscodeを使用しており、作った瞬間にvscode上でファイルを編集できる状態にしたいために下記を追加しています。お使いのテキストエディタによってエディタが開かれるコードは違いますので適宜対応して下さい。(vscodeの場合はcode、エディタによってcodeから変更する必要がある)
code "${diary_dir}/${year_month}/${today}.md"
次にこの実行ファイルがコマンドとして使用できるように設定します。 ここでは皆さんが使っているシェルごとに対応する必要があります。
もし皆さんが使っているシェルが何かわからないときは下記のコマンドを打ってみて下さい。
echo $SHELL
>> /bin/zsh
自分の場合はzshを使っていることがわかります。人によってはbashなどのターミナルを使っている場合が多いです。
zshを使っている方は、.zshrcを、bashを使っている方は.bashrcに下記を記載して下さい。これはaliasと言ってターミナル上でdairyと打つと~/bin/diary.shを実行してくれるように省略することができます。もし違うコマンド名をご所望の方は、diaryにする必要はありません。(ex. make-dairy、mdなどでも可能)
alias diary='~/bin/diary.sh'
そして最後に、下記のコマンドを実行して下さい。これは、ファイルを実行する権限を与えるために必要です。
chmod +x ~/bin/diary.sh
以上で、作成した当日の日誌ファイル名のテンプレートが作られるコマンドが完成しました。 次回は、2番のリモートリポジトリへの保存とslack通知のためのコマンドについての解説になります。