いい加減 JapaneseIM (macOS Sierra 編)
このブログで過去にも度々触れてきてますが,またコイツの話.
cp: /System/Library/Input Methods/JapaneseIM.app/Contents/Resources/KeySetting_Default.plist: No such file or directory
げんなり.
気分転換に外の空気に触れようと,ちょっとふらりふらり彷徨っていたら.;
El Capitan では「/System/Library/Input Methods/JapaneseIM.app/Contents/Resources」でしたが。
Sierra では「/System/Library/Input Methods/JapaneseIM.app/Contents/PlugIns/JapaneseIM.appex/Contents/Resources」となっています。
は(呆.
命題:「スペースおよび記号は,常時半角で入力するよう,シェルスクリプト使って設定する.Sierra でもな!」の巻
以前やりました,こちらの Sierra 版ってやつ,か.
High Sierra のリリースがアナウンスされてるってのにね.
photo by "fancy crave on unsplash" fancy crave
今更な
以前より用意していたスクリプトを引っ張り出し,幸い,KeySetting_Default.plist
のパスを更新すれば,そのままで動いてくれたので一安心.
改訂.
#!/bin/bash -eu # # PlistBuddy のパスを獲っておく # # 期待される値: # pb=/usr/libexec/PlistBuddy pb=$(mdfind -onlyin /usr/libexec -name Plistbuddy) # # KeySetting_Default.plist のパスを獲る # # 期待される値: # plistis=/System/Library/Input Methods/JapaneseIM.app/Contents/PlugIns/JapaneseIM.appex/Contents/Resources/KeySetting_Default.plist echo "'locate' コマンドの準備 1/2; データベースの生成..." sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist & wait echo "...終了." echo "'locate' コマンドの準備 2/2; データベースを更新..." sudo /usr/libexec/locate.updatedb & wait echo "...終了." plistis=$(sudo locate "KeySetting_Default.plist") if [ -z "${plistis}" ]; then echo "'KeySetting_Default.plist' が見つかりませんでした.処理を中断しました." exit 1 fi function keyCheck { val=$("${pb}" -c "Print :keys:${1}:${2}:character" "${plistis}" 2>/dev/null || true) if [ "${val}" = "" ]; then sudo "${pb}" -c "Add :keys:${1}:${2}:character string ${3}" "${plistis}" else sudo "${pb}" -c "Set :keys:${1}:${2}:character ${3}" "${plistis}" fi } # plist のバックアップ [ ! -e ${HOME}/temp ] && mkdir ${HOME}/temp sudo cp -f "${plistis}" "${HOME}/temp/KeySetting_Default.plist~$(date '+%Y%m%d%H%M')" sudo "${pb}" -c "Set :keys:before_typing:\'' \'':character ' '" "${plistis}" # space sudo "${pb}" -c "Set :keys:*:\''|\'':character '|'" "${plistis}" # | vertical bar sudo "${pb}" -c "Set :keys:*:\''\!\'':character '\!'" "${plistis}" # ! exclamation sudo "${pb}" -c "Set :keys:*:\''"'\"'"\'':character '"'\"'"'" "${plistis}" # ” double quotation sudo "${pb}" -c "Set :keys:*:\''#\'':character '#'" "${plistis}" # # sharp sudo "${pb}" -c "Set :keys:*:\''$\'':character '$'" "${plistis}" # $ dollar sudo "${pb}" -c "Set :keys:*:\''%\'':character '%'" "${plistis}" # % percent sudo "${pb}" -c "Set :keys:*:\''&\'':character '&'" "${plistis}" # & ampersand sudo "${pb}" -c "Set :keys:*:\''\'\'':character '\''" "${plistis}" # ’ apostrophe(single quotation) sudo "${pb}" -c "Set :keys:*:\''(\'':character '('" "${plistis}" # () parentheses sudo "${pb}" -c "Set :keys:*:\'')\'':character ')'" "${plistis}" sudo "${pb}" -c "Set :keys:*:\''*\'':character '*'" "${plistis}" # * asterisk sudo "${pb}" -c "Set :keys:*:\''+\'':character '+'" "${plistis}" # + plus sudo "${pb}" -c "Set :keys:*:\''\:\'':character ':'" "${plistis}" # : colon sudo "${pb}" -c "Set :keys:*:\'';\'':character ';'" "${plistis}" # ; semicolon sudo "${pb}" -c "Set :keys:*:\''<\'':character '<'" "${plistis}" # <> angle bracket sudo "${pb}" -c "Set :keys:*:\''>\'':character '>'" "${plistis}" sudo "${pb}" -c "Set :keys:*:\''=\'':character '='" "${plistis}" # = equals sudo "${pb}" -c "Set :keys:*:\''?\'':character '?'" "${plistis}" # ? question sudo "${pb}" -c "Set :keys:*:\''@\'':character '@'" "${plistis}" # @ at sudo "${pb}" -c "Set :keys:*:\''^\'':character '^'" "${plistis}" # ^ caret sudo "${pb}" -c "Set :keys:*:\''_\'':character '_'" "${plistis}" # _ underscore sudo "${pb}" -c "Set :keys:*:\''\`\'':character '\`'" "${plistis}" # ‘ back quote keyCheck "before_typing" "\''/\''" "'/'" # / slash (solidus) keyCheck "typing" "\''/\''" "'/'" keyCheck "before_typing" "\''\\\\\''" "'\\\'" # \ backslash (reverse solidus) keyCheck "typing" "\''\\\\\''" "'\\\'" sudo killall -HUP JapaneseIM echo "*** おわり ***"
イメージとしてはこんなもん,程度に捉えてください.*1
そうそう,勿論 rootles モードが効いている状態では効きませんので.この意味が分からない方は,やらない方が良いでしょう.
あと,killall
してますが,再起動の方が確実.
今回は,ちょいと思うところあって,「一応,KeySetting_Default.plist
の内容はこんな感じになりますよ」と言うものを置いておきたいと思います.
今回の作業を通して知ったこと,分かったこと
これも以前より何となく気になっていたことがあって,せっかくの機会だと思い,その辺をハッキリしておこうと段階踏んで探る作業を行いました.
その備忘録.
Plist において,入力のキーを表すキャラクタは '
でクォートしているが,出力文字の方は要らない
これは見ての通り.
入力のキーを表す <key>
タグにて定義するキャラクタは,シングルクォーテーション,しかも実態参照 '
で行う.
しかし一方,それによって出力する文字列を定義する側の character
キーの <string>
タグの方では,その必要はない.
具体的には,こう.
上は “スペースバーを入力したら,全角スペースを出力する.” という例.;
<key>' '</key> <dict> <key>command</key> <string>direct_input</string> <key>character</key> <string> </string> </dict>
入力の スペースの方は,
' '
とする必要があるが,
出力の全角スペース
は,囲む必要はない.
そのキャラクタを囲むのは,実態参照 '
じゃなくても良い
直接,シングルクォーテーション '
使って囲んでも問題ないみたいです.
これはこちら Gist に置いておきましたスクリプトを走らせた後の内容を見て頂いても分かるでしょうか.
ここでも上述例を使って表すと,こう.;
<key>' '</key> <dict> <key>command</key> <string>direct_input</string> <key>character</key> <string> </string> </dict>
こんな “見れば分かる当たり前のこと” を,あえて確認したかったかと言うと,PlistBuddy
コマンドのエントリー “entry” に,どう書いてやるのが正解なのか,と言うのが気になったのが切っ掛け.
「今まで直接 '
使って囲んでいたけど,もしかして本当は '
の方が良かったり?」
OS 側がデフォルトとして提供するのが実態参照による書き方で,それがもし正解であるならば,その作法が従うべきだと思ったし,色々スッキリすると考えたのです.
そして結果,上述のとおり '
による縛りは特に無いようで,'
で記述しても問題ない様子.
更に,PlistBuddy
においてですと,"entry" で入力キーキャラクタ指定のクォートに実態参照 '
を使って書くと,上手く特定してくれない模様.
具体的に言うと,半角スペースを特定するのに,' '
とすると上手くヒットせず,' '
といった書き方をしてやると上手くいくっぽい.それは Set
だけでなく Plint
においても.
もしかしたら自分のやり方,間違っているのかもしれませんが.
$ "${pb}" -c "Print ':keys:before_typing:\' \''" "${plistis}" Print: Entry, ":keys:before_typing:' '", Does Not Exist $ "${pb}" -c "Print ':keys:before_typing:\\' \\''" "${plistis}" Print: Entry, ":keys:before_typing:' '", Does Not Exist $ sudo "${pb}" -c "Set :keys:before_typing:'' '':character ' '" "${plistis}" Password: Set: Entry, ":keys:before_typing:' ':character", Does Not Exist
これらのことから,とりあえず自分の中で,囲みで使うシングルクォーテーションは,OS 提供時デフォルト状態の plist にあるよう,実態参照ではなく,素直に '
を使う方で良い,としておくことに.
PlistBuddy
で Set
するとき “entry” も “value” も,そのキャラクタの記述は実態参照でなくても良い
みたいです.
上述のスクリプトを参照.
PlistBuddy
で value に <
や >
,そして &
と実際のキャラクタで定義してもキチンと処理は行い,設定もされる.そしてなおかつ,それら文字列は実態参照に変換したうえで書き込んでくれるっぽい.
心配しなくてよい.
PlistBuddy
の Set
で plist ファイルを更新すると,各要素の順序 (でいいのかな?) がぐちゃぐちゃになってくる
こちらの diff も合わせて参照して頂ければ伝わるかと思いますが.
これは「試しに.」と,まずはじめに “スペース” のみについて,PlistBuddy
で設定して出来るかどうかを確認してみた中で気になったこと.
pb=/usr/libexec/PlistBuddy plistis=/System/Library/Input Methods/JapaneseIM.app/Contents/PlugIns/JapaneseIM.appex/Contents/Resources/KeySetting_Default.plist sudo "${pb}" -c "Set :keys:before_typing:\'' \'':character ' '" "${plistis}"
とスペースの入力のケース,1 つだけサンプリングし,上のようにターミナルで直接入力し,実行.
実行後,確認のため対象の KeySetting_Default.plist
の中身を覗いてみたら,元の記述行にその内容がない.
揚句,更新前オリジナルの状態では,一番最初に記述されていた version
の要素が,一番下に来ているとかって.
ん? 何か書き込むタイミングなどで法則があったりするのかな,と思って見てみたものの,わからず.
正直気持ち悪いですが,上手く動作しているみたいなので良しとします.受け流す 笑
何か解決方法あるのでしょうか.
と言ったところで,plist に関する話は終わりです.
keysetting_default.plist
,mdfind
では探せない? そして locate
を知って,それ使った
今回のように,keysetting_default.plist
の場所移動によってスクリプトが機能しなくなるのは避けたいと考え,当該ファイルを探索する仕組みを取り入れようと考えました.
そんな中での話です.
ファイルの検索となれば,いつもの扱いにくい midfid
コマンド,となるわけですが,今回は薄っすら感じていたのですが,心配していた通り上手く引っ掛けてきてくれない様子.
mdfind
の振る舞いは,可視状態 invisible などの属性や,アクセス権等によって影響するものらしい話,聞いたこともあり,この keysetting_default.plist
もそれ絡みの話なのかな,と*2ぼんやり想像していたりします.
mdfind seems to ignore a lot of hidden files. ..略.. I haven’t found any way to search for files in some hidden directories like /private/etc/.
おそらくこれだって必要な “おまじない” をかけてやれば,きちんと拾ってくれるのでしょうが,正直,今かったるい笑.
仕方なく「find
かなぁ」と彷徨っていたら,こんなエントリに出会いました.;
» Mac/Linuxの「locate」コマンドで高速ファイル検索|「find」コマンドとの違いから「mdfind」の紹介まで - Qiita
これまでもしばしば目に入ってはきていたのですが,特に必然を感じなかったのと,何より敷居が高そうでスルーしてきたのですが,「mdfind
だるい」となった今,その距離感が劇的(笑に変化し,早速使ってみることに.
具体的な使い方等は,先のエントリにあるとおりで OK でした.*3
結果,さらっと見つけてくれて,願った通りしっかりとパスを引っ張って来てくれました.素晴らしい.
The locate command is very useful if you’re looking to track down every instance of a file, filetype, app, extension, things hidden deep in system folders, or just about anything else that Spotlight can’t manage.
locate
は,Spotlight が管理できないようなどんなファイルだって探すんだよ,って.
めでたしめでたし.
PlistBuddy
は,type
でも which
でもわからない.
これで気を良くし,「PlistBuddy
のパスも」と type
コマンド使ってみたら,結果を返してきません.which
もダメ.
/usr/libexecディレクトリは、初期設定ではパスが通っていないこともあり、 ..(略).. 「PlistBuddy」は、その/usr/libexecディレクトリに置かれているコマンドだ。
ということなだからなのでしょうか.
ずっと「OS 標準だから」という事で JapaneseIM の色々やり過ごしてきましたけど,今回の出来事を経ていい加減,自分の感情に正直になって拘るのやめようかなと本気で思ってきています.
あと,この作業で vim というツールを使ったことで色々助けられたのですけど,それについても触れられればと思ったのですが....また別の話とします.
はいおしまい.
*1:一応自分の環境では正しく動作して,設定も効いてくれてますけど.
*2:‘keysetting_default.plist’ のある場所は,'/System' 配下で,システム整合性保護 System Integrity Protection の対象ですし.
*3:ちょっと異なったのは,《データベース作成に時間がかかるので数分まつ.》って言っているけど,自分の場合はむしろ,その次の ‘sudo /usr/libexec/locate.updatedb’ の方が “数分” かかったりするくらい.