ショートカットで日付＋曜日入力 on Mac

:::note info
個人的に Evernote を使わなくなりましたが、ショートカットでの日付入力はメモアプリやNotionなどで活用しているのでタイトル変更して、内容も調整しました。 (2023/10/28)
:::

# 概要

元々これは、 Evernote のクライアントで以前できていた Command+Shift+D での日付+曜日の入力を Karabiner-Elements を使用してできるようにした、と言う記事でしたが、別に Evernote に限らずどんなアプリでも簡単に日付＋曜日入力ができるのでその方法を紹介します。この方法を応用すると任意のコマンド実行結果のショートカット入力も実現できそうです。

基本的に同等のことは https://www.head-t.com/2017/11/2017-11-08.html に紹介されている Automator を使う方法ででできるのですが、アプリ名のメニューに出てくる「サービス」が Evernote のアプリで使えない、という酷い作りでこの方法が使えず、微妙に使いづらくなっていました。

基本的な設計としては、シェルスクリプトを用意して、その中で (1) `date` コマンドで日付＋曜日の文字列を作り出し、`pbcopy`でクリップボードにコピー。(2) アップルスクリプトで「貼り付け」操作を起動する、と動作するようにして、そのシェルスクリプトを Karabiner-Elements の Complex Modification として実装する、という感じで実現します。

:::note info
Karabiner-Elements 13.7.0 あたりから、複数コマンド実行がうまく動かなくなりましたので、処理方法を改良しました。(2021/10/1)
:::

# 準備

Karabiner-Elements を使いますので、インストールしていない方は事前にしてください。
https://karabiner-elements.pqrs.org

自分の環境は MacOS 13.6。Karabiner-Elements は 14.12.0 です。

# アップルスクリプトのテスト

クリップボードにコピーした文字列はアップルスクリプトで「貼り付け」操作を起動して、テキストとして入力させます。アップルスクリプトが動くかどうか、以下のコマンドを入力して試してください。

```shell-session
$ osascript -e "tell application \"System Events\" to keystroke \"v\" using command down"
```

もし

```shell-session
36:68: execution error: System Eventsでエラーが起きました: osascriptにはキー操作の送信は許可されません。 (1002)
```

みたいな表示が出た場合、シェルスクリプトでのアップルスクリプト起動が許可されていませんので、設定の「セキュリティとプライバシー」から「プライバシー」の「アクセシビリティ」の項目にある「ターミナル」にチェックを入れておいてください。（ある時から、これをチェックしないと動かなくなりました。）


# シェルスクリプトの準備

シェルスクリプトを用意します。`date` コマンドで任意フォーマットで日付文字列を作って、`pbcopy` コマンドでそれをクリップボードに入れます。

フォーマットは自由に変えられます。今回は "2020年11月30日 月曜日" というフォーマットにしたいので、`date` コマンドに渡す引数は `"+%Y年%m月%d日 %A"` です。フォーマットについては `man strftime` をみてください。


クリップボードに日付の文字列を入れてしまうと、もちろんそれまでクリップボードに入ってた情報はなくなってしまうので、せめて文字列だけは保存し、あとで復元するようにします。最初に `pbpaste` の結果を変数に入れておいて、最後に `pbcopy` でクリップボードに戻します。

シェルスクリプトは `~/etc/copy_date.sh` として保存します（ファイル名・パスはもちろん任意）。

```shell:~/etc/copy_date.sh
#!/bin/bash
# Shell script for inserting date via Karabiner-Elements.
$TEMP=`pbpaste`
date "+%Y年%m月%d日 %A"|pbcopy
osascript -e "tell application \"System Events\" to keystroke \"v\" using command down"
echo $TEMP|pbcopy
```

# スクリプトのテスト

```
$ cd ~/etc
$ ./copy_date.sh
```
で日付がターミナルに出れば OK です。日付文字列が実行されてしまうので、以下のようにエラーが出るとは思います。。。

```
$ 2021年10月01日 金曜日
zsh: command not found: 2021年10月01日
```

# Karabiner-Elements の設定
`~/.config/karabiner/assets/complex_modifications` に以下のような JSON ファイルを作ります。やっていることは　`"shell_command"` 機能で上述のスクリプトを呼び出したあと、同じく `"shell_command"` でアップルスクリプトを起動し、ペーストを実行しています。

シェルスクリプトのパスは `/Users/wyetea/etc/copy_date.sh` になっているので、適宜変更してください。

```json:wyetea.json
{
  "title": "Wyetea's modifications",
  "rules": [
    {
      "description": "Command+Shift+D to insert the current date",
      "manipulators": [
	{
	  "type": "basic",
	  "from": {
	    "key_code": "d",
	    "modifiers": {
	      "mandatory": [ "command", "shift" ] 
	    }
	  },
	  "to": [
	    { "shell_command": "LANG=\"ja_JP.UTF-8\" /Users/wyetea/etc/copy_date.sh"}
	  ]
	}
      ]
    } 
  ]
}
```

保存すると、Karabiner-Elements の Complex modification の設定の "+Add rule" をクリックすると "Wyetea's modifications" が出てきますので有効にします。

最初実行すると、MacOS のアクセシビリティの変更を求められますので、制御を許可してください。

Command+Shift+D のキーバインドを変更した場合は、設定ファイルの "from" の部分を変更してください。Karabiner-Elements の設定ファイルの詳しい書き方は 
https://qiita.com/s-show/items/40ad22c4ee4a0465fad5
https://qiita.com/s-show/items/a1fd228b04801477729c
を参考にしてください。



## ハマったポイント

- `LANG` 変数の設定をシェルスクリプトの中で行ってもなぜかうまくいかない。`date` コマンドを Karabiner-Elements の設定ファイル内に直接書いてもだめ。これで２時間くらい溶かしました。
- 参考にしたサイトのアップルスクリプトの実行の部分のエスケープの仕方、間違ってますよね。。
- もっと簡単にできる方法あればよろしくお願いします。m(_ _)m

# 参考リンク一覧
- [「きょう」とテキストを打って「2017-11-08」の形式に変換する方法] (https://www.head-t.com/2017/11/2017-11-08.html)
- [Karabiner-Elementの設定例について](https://qiita.com/s-show/items/40ad22c4ee4a0465fad5) 
- [Karabiner-Elementsの設定項目をまとめました](https://qiita.com/s-show/items/a1fd228b04801477729c)