defaults command-line の実行方法の調査

# 概要
macOSの`defaults`コマンドは`write`でプリファレンスを変更するとき、各引数に入れるべき値をどのように見つければいいのかを調査した。つまりは設定変更の汎用的な調査方法自体を調査したってこと。

# 結論
`defaults write domain key 'value'`で値を変える。
`$HOME/Library/Preferences`にある`<application bundle identifier>.plist`から変更したい`domain`を推測して見つける。
`defaults read domain`で変更したい`key`を推測して見つける。
`value`については各`key`がどのように値の範囲や単位を定義しているのかはわからなかった。

# 調査履歴
## defaults write の引数
`UserDefaults`とはアプリに存在するユーザ毎に設定できるインターフェースである。UserDefaultsは `defaults` というコマンドラインユーティリティを使用してそのプリファレンスを設定することができる。ということは、[公式ドキュメント](https://developer.apple.com/documentation/foundation/nsuserdefaults?language=obj)を見て理解できたけど、`defaults`でプリファレンスを設定するにはどのような値を入れればよいのかがわからなかったので`man defaults`を見た。サブコマンドの説明に `write domain key 'value'` とある。つまりは`domain`と`key`と取りうる`value`がわからなければ設定することができない。

## 引数 domain
まずは`domain`から調べてみる。引き続き`man`の内容を見ると以下のように書いてある。

> User defaults belong to domains, which typically correspond to individual applications. 

つまり`domain`とはそれぞれのアプリケーションやシステムサービスが固有に持っているものらしい。[公式ドキュメント](https://developer.apple.com/documentation/foundation/nsuserdefaults?language=obj)の[参照リンク(For more details, see Preferences and Settings Programming Guide.)](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/AboutPreferenceDomains/AboutPreferenceDomains.html#//apple_ref/doc/uid/10000059i-CH2-SW6)(古いって注意出てるけど公式が参照してるから多分大丈夫)を見てみると、 Application Domain の節に以下のように書いてある。

> Because this domain is app-specific, the contents of the domain are tied to your app’s bundle identifier.

どうやら`domain`にはいろいろ種類があり、その中で Application Domain と呼ばれる`domain`は`application bundle identifier`に紐づくらしい。そのまま続きを読んでくと、この`domain` (Application Domain) のプリファレンスは`$HOME/Library/Preference`ディレクトリに`<bundle identifier>.plist`というファイル名で格納されているらしい。つまりアプリのUserDeafultsにおいて`defaults`コマンドの`domain`に入れる値は`application bundle identifier`であり、`application bundle identifier`は`$HOME/Library/Preference`配下にあるファイル名から推測可能ということだ。
まあここまでわかればどのアプリがどの`bundle identifier`を使用しているのかは名前から自分で推測したりして調べようかなと思う。

## 引数 key
次は`key`と`value`だ。これはアプリごとに調べなきゃならないということになりそうだ。先程`domain`に何を入れればいいのかわかったのでmanに書かれてた読み出し用のコマンド`defaults read`が使えそう。readした内容から自分が変えたい設定の英語とかを検索すれば`key`は見つかるかもしれない。

> read domain  Prints all of the user's defaults for domain to standard output.

ということで試しに `System Preferences > Keyboard > Keyboard > Key Repeat` をいじってみようと思う。
まずはこの設定がありそうなワードでgrepしてみる。

```
$ ls ~/Library/Preferences | grep system
com.apple.systempreferences.plist
com.apple.systemsound.plist
com.apple.systemuiserver.plist
$
```

お、引っかかった。`com.apple.systemprefernces`が怪しいので試しに`defaults read`して検索してみる。

```
$ defaults read com.apple.systempreferences | grep repeat
$
```

うーんないねえ。じゃあ今度はkeyboardで探してみる。

```
$ ls ~/Library/Preferences | grep keyboard
com.apple.keyboardservicesd.plist
com.apple.textInput.keyboardServices.textReplacement.plist
$ 
```

コレジャナイ感が漂うけど一応調べる。

```
$ defaults read com.apple.keyboardservicesd | grep repeat
$ 
$ defaults read com.apple.textInput.keyboardServices.textReplacement | grep repeat
$ 
```

うーんない。System Preferences.appはシステムよりだしちょっと特殊なのかもしれない。

再度、[About Preferences and Settings](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/AboutPreferenceDomains/AboutPreferenceDomains.html#//apple_ref/doc/uid/10000059i-CH2-SW6)を上から下まで読んでみると`domain`は Application Domain の他にも Argument Domain や Global Domain などがあるらしい。 Argument Domain はアプリ実行時の引数を対象としてるから今回探してるものとは違うのでスルーして、問題は Global Domain だ。こいつはすべてのアプリにまたがるプリファレンスの`domain`らしい。

たしかにまあ `Key Repeat` はアプリにまたがってるかもとか思いながらダメ元で Global Domain にかけてみる。先程のドキュメントの Viewing Preferences Using the Defaults Tool の節に従い Global Domain のプリファレンスを調べてみる。

```
$ defaults read NSGlobalDomain | grep repeat
$
```
なかったw しかしここで諦める私ではない。検索方法が間違っているのかもしれないという疑念をもとに、 [key, Key, repeat, Repeat] で今まで調べた場所を再度調べてみる。そして発見。

```
$ defaults read NSGlobalDomain | grep Key
    AKLastEmailListRequestDateKey = "2018-10-12 14:15:13 +0000";
    AppleKeyboardUIMode = 1;
    InitialKeyRepeat = 15;
    KeyRepeat = 1;
    NSAllowsBaseWritingDirectionKeyBindings = 0;
    NSNavPanelFileLastListModeForOpenModeKey = 3;
    NSNavPanelFileLastListModeForSaveModeKey = 1;
    NSNavPanelSidebarKeyForOpen =     (
    NSNavPanelSidebarKeyForSave =     (
    NSUserKeyEquivalents =     {
$
```

## 引数 value
じゃあ、`defaults write NSGlobalDomain KeyRepeat`まではわかった。じゃあこの今の`value`(`1`)は何を表しているのか。それがわからなければ変えるべき値はわからない。

`defaults`の`value`はどうすればわかるのか。一応、man曰く型は`defaults read-type domain key`でわかるらしい。

```
$ defaults read-type NSGlobalDomain KeyRepeat
Type is integer
$
```

おう、知ってたよ。取りうる範囲とかどういう単位なのかとかが知りたいんだよね。

[まあ調べればわかるんだけどこのコメントと同じ気持ちになる。](https://apple.stackexchange.com/questions/10467/how-to-increase-keyboard-key-repeat-rate-on-os-x/83923#comment339302_83923) どこで知ったのそれ？ってやつ
まあ調べれば信用できないけどわかるし、大抵boolとかで範囲とか単位はないから大丈夫なんだけど。



# 参考ソース
- [NSUserDefaults](https://developer.apple.com/documentation/foundation/nsuserdefaults?language=obj)
- [About Preferences and Settings](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/Introduction/Introduction.html#//apple_ref/doc/uid/10000059i)
- `man defaults`