Alfred Workflowで勤怠記録を楽にする

# はじめに
みなさんAlfred使ってますか？

macユーザの作業効率化には必須といっても過言でないほどの威力を持ったツールですが、
その最大の魅力はショートカット機能を簡単に自作できるWorkflow機能にあります。

https://www.alfredapp.com/

今回は、自分の作業時間管理を題材にしながら、AlfredのWorkflow作成を中心に紹介をしていきたいと思います。

# リモートだと、作業時間が、掴みづらい
このコロナのご時世リモートワークも普及してきましたが、
在宅だとちょっとした離席が発生しやすかったり、通勤がない分始業と終業の境目があやふやになりがちだったりと時間管理が難しいなぁと感じる日々です。

となると、困るのが勤務時間報告。
おおよそ正確な時間は割り出せるけど、思い出すの手間だし、
出社していたときのように入退室記録から勤務時間自動で割り出して欲しい！

正直、勤務時間を管理するためのツールはあるんですけれど、休憩時間が記録できないことや、
ブラウザ開いてログインしてクリックというのがどうしても億劫だった私はなるべく最短でログを記録したいと考え始めます。

そうだ、Alfred使おう。

# Alfredとは？
多機能すぎてちゃんと説明するともう一本かけてしまうくらいなのですが、簡単にまとめると
「拡張性のめちゃくちゃ高いアプリランチャー」です。

https://www.alfredapp.com/

<div align="center">
<img width="500" alt="alfred_sample_screenshot" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/93880a2b-5a20-5e22-accd-13d8fbe6ed73.png">
</div>

一見、spotlightのような見た目をしていますが、spotlightが有する機能の他にも、
ブックマーク検索や、システム機能へのショートカット、snippetsの呼び出しなどなど、
日々のちょっとした手間を解消してくれるだけの機能が揃っています。

今回はその中でも、ショートカットなどから呼び出せるプログラマブルな機能を簡単に作成できるWorkflowを使って、作業時間の管理を実現しようと思います。

(本機能は有料版であるPowerpackに含まれています。
アプデを受けられる買い切り型で49ポンド(執筆時：約6846円)ですが、コスパを考えると格安なのでこの機会に是非！)

# 作っていく

- 勤務開始・終了時間、離席時間をさくっと記録できる
- 退勤後、当日分の作業時間レポートが確認できる
- alfredからさくっと呼び出せる

以上のことを踏まえながら、さくっと作っていきましょう。
導入に関しては公式か、他の記事を参照ください。
https://www.alfredapp.com/help/getting-started/

## Workflowを作る
まずは、AlfredのPreferenceからWorkflowsタブを開きます。
その後、左下の"＋"から"Blank Workflow"を選択し、Workflowを作成しましょう。

<div align="center">
<img width="1000" alt="alfred_imp_screenshot_00" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/54fe1db8-f5b9-13af-2dfe-15d970186a56.png">
</div>

Workflowの情報を記入するダイアログが出てきますので、ここもさくっと値を入れていきます。

<div align="center">
<img width="800" alt="alfred_imp_screenshot_01" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/f8d60173-5d68-8a34-4aee-7106e69d243f.png">
</div>

次に、Workflow Objectを配置していきます。
画面上右クリックし、3つのオブジェクトを配置し設定を行ってください。

**Inputs > Script Filter**

| 項目 | 値 |
|:-:|:-:|
| keyword | kintai |
| with space | ✔︎ Argument Optional |
| Placeholder title | Oneliner Kintai |
| Language | /bin/bash with input {query} |
| Script | `./node_modules/.bin/run-node src/index.js "{query}"` |
(src/index.jsについては後述)

**Actions > Run Script**

| 項目 | 値 |
|:-:|:-:|
| Language | /bin/bash with input {query} |
| running instances | Sequentially |
| Script | `./node_modules/.bin/run-node src/action.js "{query}"` |
(src/action.jsについては後述)

**Outputs > Large Type**

| 項目 | 値 |
|:-:|:-:|
| body | {query} |

設定が終わったら、Script Filter -> Run Script, Run Script -> Outputへコネクションをつなぎましょう。

<div align="center">
<img width="800" alt="alfred_imp_screenshot_01" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/eb0cf0e3-b99c-493c-947e-1f066b08a986.png">
</div>


### どういうこと？
ここで、少し立ち止まって何が作られたのかを見ていきましょう。

まず、**Script Filter**ですが、いきなりややこしいのでまずは画像を見てください。

Script Filterは、keywordに設定した値がAlfredに渡されるとScriptが実行され、その結果としてAlfredに表示するアイテムを返すことができます。
このアイテムにはargsという値を含めることができ、Alfredからアイテムが選択されたときにargsを次のWorkflow Objectに値を渡すことができます。

<div align="center">
<img width="800" alt="alfred_imp_screenshot_01" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/853a9796-c71b-c103-31de-2535ee3e18cb.png">
</div>

今回は、kintaiが呼ばれた時に、
argsとして「どのコマンド(shukkin, taikin, ...)を選んだか」を次のRun Scriptに渡していきます。
（細かい実装は後述します。）

***

次に、**RunScript**。
これは単にScriptに設定した処理が実行されます。
この処理で標準出力された結果は、次のWorkflow Objectに渡されます。

今回はここで、タイムスタンプを付したログをTSVへ出力し、勤務時間を記録します。

***

最後に**Large Type**です。
このObjectを使うとbodyに設定したテキストが画面上に大きく表示することができます。

今回はここに実行結果や、退勤後の作業時間レポートを表示させてみましょう。


<div align="center">
<img width="800" alt="alfred_imp_screenshot_02" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/83efd363-7572-65f6-92c2-7316c3945dd6.png">
</div>


## コードを書く

さて、実際に処理を行うスクリプトを書いていきましょう。
Workflowを作成すると、`~/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/`にフォルダが作成され関連ファイルが保存されます。
作成したWorkflowを右クリックして`Open in Finder`で直接開くことも可能です。

実際の処理を担当するスクリプトはこのフォルダの中に配置していきます。
今回はNode.jsで実装しましたが、フォルダ構造と実際のコードは次を参照してください
https://github.com/dh9489/alfred-oneliner-kintai

なお、Node.jsではWorkflowを楽に実装するためのライブラリが公開されていますので今回も利用しました。ありがたい。
https://github.com/sindresorhus/alfy

処理の流れを図にするとこんな感じ。
<div align="center">
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/13791428-2b26-b2c6-36e1-e82ae367603b.png">
</div>

（雑ですが複雑なコードではないので、ここでは詳しい説明を省きます。）

# 使ってみる
では実際に使ってみましょう。

`kintai shukkin`

<div align="center">
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/f4876041-0924-22f9-8208-8d1c3cf2e8e0.png"> <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/f5d7f37b-304c-8cca-a45b-1c83931957b4.png">
</div>

***

`kintai riseki`
<div align="center">
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/c5a0c01b-3dbe-363d-430d-8d3eaf72c141.png"> <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/662cddfa-3dfe-705d-3e53-60cd2b02af69.png">
</div>

***

`kintai chakuseki`
<div align="center">
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/e4286164-399d-d4b7-9153-d06aea3cc049.png"> <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/b4506b8c-43af-6124-b84b-74e7287bd8e2.png">
</div>

***

`kintai taikin`
<div align="center">
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/14bbbf7c-edbe-bb33-bd82-97008dd36522.png"> <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235673/bf94774e-6e7e-59de-f30b-78bd6cf24df1.png">
</div>

***

なお、tsvファイルを確認してみると、

```kintai_log.tsv
#time stamp     #command
1608357382951	shukkin
1608357436660	riseki
1608357447821	chakuseki
1608357480423	taikin
```

各コマンドを実行した時刻がTSVに記録されて、その情報をもとに作業時間が算出されていることがわかります。


# 最後に

今回は、AlfredのWorkflowに着目し、簡単なチュートリアルを交えながら紹介させていただきました。

今回紹介した以外にも様々なWorkflow Objectが用意されていますので、これを機にAlfredを使ってバリバリ作業を効率化していきましょう！
https://www.alfredapp.com/help/workflows/

また、既にAlfredユーザの方はおすすめのWorkflowがあればコメントでシェアしていただけると嬉しいです。

***

DeNA 公式 Twitter アカウント @DeNAxTech では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい！
Follow @DeNAxTech