ペーストボードにコピーが行われたときに、JavaScript で何かするというツールを書いた。

競合するソフトウェアがいくつかあると思うけど (dot-clipboard とか)、すぐできそうだし Swift で書かれたのはなさそうということで書いてみた。

ユースケースとしては

  • Slack のチャット画面を適当にコピーしたのを、自動でフォーマットしてペーストしやすくする
  • リッチテキストとしてコピーされるのがウザいので、プレーンテキストにしてしまう
  • 画像を自動でグリッチする

というのがあります。

つかいかた

起動するとアクセシビリティを有効にしろといわれるのでする

有効にしたらもう一度起動する。

コピーのイベントをキーイベントの Cmd+C を見ることで実現している (設定で変更可能)

あとフォーカスされているアプリとかウィンドウの名前を取得するためにアクセシビリティの機能を使っている

~/.copyhook.js を書く

function onCopied () {
	// console.log(pb.types());

	var bundleId = utils.focusedApplicationBundleId();
	console.log('onCopied: ' + bundleId);
	if (bundleId === "com.apple.Terminal") {
		// clear data without "public.utf8-plain-text"
		pb.copy(pb.string());
	}
}

こんな感じのを書く。これだと Terminal.app で Cmd+C を押した場合、プレーンテキストだけにして他のデータ型を削除するようになる。(Google Keep とかにペーストするとき意味不明な改行が入りまくったりするのを回避できる)

または、レポジトリにあるファイルをとりあえず使ってみるなら

git clone https://github.com/cho45/CopyHook.git
cd CopyHook
ln -s dotcopyhook.js ~/.copyhook.js
ln -s dotcopyhook ~/.copyhook

これだと Slack のアプリででコピーしたときいい感じにフォーマットするようになる。

JS をカスタマイズする

require() で ~/.copyhook 以下から外部ファイルを読みこんだりできるようになっている。

console.log() は OS X のシステムログに書きこむことができる。Console.app を起動すれば確認可能。

utils.focusedApplicationBundleId() でフォーカスされているアプリの bundle id を取得できたり、utils.focusedWindowName() でフォーカスされているウィンドウのタイトルを取得できたりする。これにより、処理を場合わけできる。

CopyHook の JS は直接ファイルの読み書きなどができるようになっていないが、utils.system() によって外部プログラムを呼びだせるようにしてある。

なお、書きかえた JS ファイルは次回コピー実行時に自動でリロードされる。

実装について

コピーイベント

ペーストボードに「コピーが行われた」という Notification (OS X でイベントコールバックしてくれる仕組み) はないので、別の方法でやる必要がある。

  • NSPasteboard の changeCount をポーリングする
    • 殆どのペーストボード監視アプリはこれでやっているはず
    • ポーリングなので常に余計にCPU負荷がかかる
  • Cmd+C 監視
    • 右クリックからコピーなどに対応できない
    • アクセシビリティ設定が必要

ポーリングで常に監視するのがとりあえず嫌だったので Cmd+C をデフォルトにしている。

設定でポーリングにも変更可能。

JavaScriptCore

JS の実行には JavaScriptCore.framework を使っている。OS X 10.9 から使えるようになった framework で、JS の実行環境とネイティブ実行環境をブリッジして使えるようにしてくれる。

JS で書けるようにしておくと、テキストフィルタするようなのを書く場合、とりあえず node で書いてテストして、それをそのまま CopyHook でも使うということができて便利。

  1. トップ
  2. tech
  3. CopyHook というペーストボードの中身をいじるツールを作った

伊勢参りしてきた。

熱田神宮

伊勢にいく前に名古屋の熱田神宮へ。熱田神宮の御神体は草薙剣 (天叢雲剣)とされていて、これはヤマタノオロチの尻尾から出てきたという、いわゆる三種の神器のひとつである。三種の神器は天孫降臨の際に天照大神がニニギに手渡したといわれるものなので、伊勢神宮内宮の御神体とされる、同じく三種の神器の一つである八咫の鏡と関係が深い。


結構敷地は広かった。また拝殿から本殿はかなり遠く、殆ど近づけない。さすがにかなり立派な神社だった。

外宮

名古屋から特急で一気に伊勢市へ。外宮から参拝するのが習わしということで、先に外宮から。



実は伊勢には京都に住んでいたころ日帰りで一度きており、外宮には参拝したことがあるが、それは遷宮前。

当然だけど遷宮して間もない (といっても既に3年目) ので社殿その他が綺麗だった。

正宮はとっくに遷宮が終わっているが、境内の他の神社などはまだ遷宮中のものもあって面白かった。以下は建築中で2つ並んでいる別宮風宮。

以下は土宮

また、外宮には「せんぐう館」というミュージアムができていて、これが思いのほか面白かった。特に、外宮の (内宮もだけど) 正宮は普通に参拝してもかなり遠くて屋根の一部しか見えないのだが、せんぐう館の中に実物大の模型として一部が作ってあって、とても良かった。

ほかに建築方法とか、宮大工の技みたいなのもあって良かった。大変おすすめ。

内宮

内宮は一泊後、早朝に参拝した (朝早くでないと人が多くなるから)。宿は神宮会館に泊まり、神宮会館は宿泊者向けに早朝参拝のガイドをしてくれるので、これに参加させてもらった。神宮会館は「伊勢神宮崇敬会」という財団法人が運営しており、なんとなくこわいかと思ったが全くそんなことはなかった…… ガイドの人は地元の人のようで、大変わかりやすい解説をしてくださった。結構ライトな説明でそれほど宗教色のある解説ではなかった。

前回の内宮と外宮の柱の一部が宇治橋の鳥居になるとか、御稲御倉 (稲の倉庫だが、主祭神が設定されており、御稲御倉神=宇迦之御魂神=稲荷神) が正宮のほぼ5分の1のサイズの唯一神明造りになっているとか、やっぱりその場で説明してもらえると楽しい。

荒祭宮ももちろん参拝した。

内宮は前回伊勢に来たときは人が多すぎて参拝しなかった (それほど参拝にこだわりがないので)。今回は早朝だったのでスムーズだった。5時から参拝できるみたい。

あと石段を登るとぱっと見、遷宮用の敷地がどこにあるのかよくわからないけど、石段ごともう一つ奥に敷地があるようだった。つまり前回見た石段は奥の石段だったわけだけど、奥には入れないのでそちらの敷地は見ることができない。

月讀宮

内宮の別宮。4つ社殿が並んでいて壮観。遷宮が終わっており全部ピカピカだった。メインの月讀宮が少し大きい。

月夜見宮

外宮の別宮。月讀宮と同じく月夜見尊が主祭神。

なんとなく神話上で殆ど出番のない月夜見尊が好きなので行ってみたかった。(出番がないので祭っている神社も非常に少ない)

まとめ

とりあえず当初行きたかったところは一通り行けてよかった。

神明造

神社建築だと神明造がやはりかっこいいと思っていて、パーツとしては特に千木 (斜めに飛びだしている棒の部分) と鰹木 (上にのっている丸太のようなもの) のところが好きである。

全体的なフォルムが直線的で古風かつ力強いところとか、教科書に乗っている「高床式倉庫」ほとんどそのまんまな感じも良い。

そういえば、普通の神社だと金物がだいたい銅製そのままなので、緑色になっているのだけれど、神宮周辺の神社は全て金メッキ(金箔を貼ったり、水銀を使ったり)になっており、豪華だった。