保存する前のdiff(差分)をとる
前回までに、
-
-
- Dropboxのバージョン履歴とのdiff(dropbox_diff.sh)
- AppleScriptやリッチテキスト等のバイナリファイルとのdiff(convert_diff.sh)
-
と、diffを少しずつ拡張してきた。
今回さらに、
-
-
- 保存する前の書類とのdiff(document_diff.sh)
-
をとってみたい。
通常、diffするときはファイルに保存されているモノ同士を対象にするのだけど、ちょっと工夫すると、クリップボード(command-Cでコピーした内容)とのdiffをとれる。
$ pbpaste|diff file1.txt -
- pbpasteはクリップボードの内容を出力するOSX独自のコマンド。
- それをパイプで繋いで、diffの第2引数に指定している。
- diffコマンド末尾の - は、パイプで流れてきたテキストデータとみなされる。
- file1からクリップボードへの変化のdiff出力
- ちなみに、- を第1引数の位置に変更すると、差分の計算が逆になる。
- クリップボードからfile1への変化のdiff出力
$ pbpaste|diff - file1.txt
よって、GUIエディタでfile1.txt編集中に全体をコピーして、ターミナルで上記コマンドを入力すれば、
-
-
- 保存前の編集中の状態と、
- 保存済のファイル内容の、
-
diffがとれるのだ!
GUI操作を追加する
- いちいちすべてを選択して、コピーするのは面倒くさい。
- AppleScriptならcommand-A、command-Cの操作ができる。
- ところで、OSXにはosascriptコマンドが用意されている。
- osascriptは、指定されたAppleScriptを実行するコマンド。
- ならば、osascriptを利用して、AppleScriptでうまく包み込んであげれば、より使いやすいコマンドに仕上がるはず!
#!/bin/bash open "$1" sleep .5 osascript -e ' tell application "System Events" keystroke "a" using command down -- command-a keystroke "c" using command down -- command-c delay .5 end tell' pbpaste|diff -u "$1" - osascript -e ' tell application "System Events" keystroke tab using command down -- command-tab end tell'
convert_diff.shを利用する
- さらに、diffコマンドの部分を前回作ったconvert_diff.shに置き換えれば、バイナリファイルにも対応できるはず!
- しかし、前回作ったconvert_diff.shは、ちょっとやっつけコード的なところがあって、そのままではdiffコマンドの置き換えには耐えられない。
- できるだけ多くの状況でdiffコマンドの代わりに使えるように改良してみた。
#!/bin/bash convert() { case $1 in *.scpt ) echo -n "osadecompile" ;; *.rtf ) echo -n "textutil -convert txt -stdout" ;; *.jpg ) echo -n "exiftool" ;; * ) echo -n "cat";; esac } OPTION=("$@") PATH1=${OPTION[$(($# - 2))]} PATH2=${OPTION[$(($# - 1))]} unset OPTION[$(($# - 1))] unset OPTION[$(($# - 2))] # 一方がディレクトリだったら、他方のファイル名を補う if [ -d "$PATH1" ] && [ -f "$PATH2" ]; then PATH1="$PATH1/`basename "$PATH2"`" elif [ -f "$PATH1" ] && [ -d "$PATH2" ]; then PATH2="$PATH2/`basename "$PATH1"`" fi # 両方ともディレクトリだったら、変換せずにdiffを実行する if [ -d "$PATH1" ] && [ -d "$PATH2" ]; then echo "\`diff" "$@""|colordiff'" diff "$@"|(`which colordiff`||`which cat`) else echo "\`diff ${OPTION[@]} <(`convert "$PATH1"` \"$PATH1\") <(`convert "$PATH2"` \"$PATH2\")|colordiff'" diff "${OPTION[@]}" <(`convert "$PATH1"` "$PATH1") <(`convert "$PATH2"` "$PATH2")|(`which colordiff`||`which cat`) fi
- document_diff.shに組み込んでみた。
#!/bin/bash open "$1" sleep .5 osascript -e ' tell application "System Events" keystroke "a" using command down -- command-a keystroke "c" using command down -- command-c delay .5 end tell' pbpaste|~/convert_diff.sh -u "$1" - osascript -e ' tell application "System Events" keystroke tab using command down -- command-tab end tell'
Lion以降での問題
- 以上のシェルスクリプトは、Snow Leopard環境では何の問題もなく、うまく動いた。
- Lion以降であっても、オートセーブとバージョンに対応していないアプリケーションでは問題なく動く。
- しかし、LIon以降のオートセーブとバージョンに対応しているAppleScriptエディタやテキストエディットでは、
編集途中の差分がうまく表示されない...。
- オートセーブとバージョンに対応の環境では、編集ウィンドウへの入力と同時に、保存ファイルにも変更が加えられてしまうよう仕様のようだ。
- その結果、テキストファイルは編集した瞬間にファイルに保存されてしまう。
- たとえ、システム環境設定 >> 一般 >>「書類を閉じるときに変更内容を保持するかどうかを確認」をチェック入りにした状態でも、編集した瞬間にファイルに保存されているのだ。
- また、AppleScriptやリッチテキストも、編集中はファイルに何らかの変更が加えられる。
- そのため、osascriptコマンドやtextutilコマンドで変換しようとしても、エラーが発生してテキストに変換できなくなってしまった...。
Mountain Lion環境のAppleScriptエディタでdiff-docが使えないのは、ちょっと残念。