2013年6月23日日曜日

MavericksってHalf Moon Bayにあるんですね

Surfin in Mavericks
2010 Mavericks Competition from Wikipedia
今回の記事はMacは関係ありませんので、ごめんなさい。
今年のApple WWDCで新しいMacのOSの愛称としてMavericksが紹介されましたね。
Californiaと言っていましたがどこだろうと思って調べたらHalf Moon Bayにありました。

サーフィンの名所とのことでGoogleの画像検索でMavericksと入れると北斎の神奈川沖浪裏みたいな画像が大量に出てきます。

実は10年以上前にアメリカに住んでいたことがあるのですが、Half Moon Bayにも何度か行ったことがあり、懐かしくなりました。私が行った時は(多分Mavericksとは別の海岸ですが)、波も高くなくサーフィンの名所とは知りませんでした。何人かサーフィンをしている人はいましたけど。後、馬の散歩をさせている人もいましたね。
夏なのに海の水が、谷川の清流のようにすごく冷たかったことを覚えています。

Beach BoysのSurfin' U.S.A.ではもう少し南に下がったSanta Cruzが出てきますが、この辺り一体は太平洋の荒波を受けてサーフィンにいいのかもしれませんね。

2013年6月17日月曜日

MacBook Airのフタを閉じたら外付けディスクを自動アンマウント

MacBook Airを取り外して会議に出かけるときや自宅に持って帰る時、ディスプレイのフタを開けたら下の図のようなウォーニングが出ていることがあります。
理由は、MacBook Airのディスプレイを閉じて、その後USBケーブルを抜くのですが、外付けディスクをFinder上で取り出すという操作をしていないためです。
ファイルやディスクが壊れる原因にもなるのですが、急いでいると忘れてしまいます。

持ち運びする時は大概の場合、ディスプレイを閉じるのでスリープ状態になります。ということは、以前Synergyを使う際にインストールしたSleepWatcherが使えそうです。
スリープに入る際に外付けディスクをアンマウントすれば良さそうです。USBを再接続した時は、以前から自動でマウントされていますので、そのままで良さそうです。

現在のMacBook Airの設定では、~/.sleepというshスクリプトファイルにコマンドを書けば良いようにしています。
まず、ディスクがどのような名前でマウントされているか確認します。

$ mount

/dev/disk0s2 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
map -fstab on /Network/Servers (autofs, automounted, nobrowse)
/dev/disk1s3 on /Volumes/ExFAT (exfat, local, nodev, nosuid, noowners)
/dev/disk1s2 on /Volumes/Backup (hfs, local, nodev, nosuid, journaled)

1本のディスク(/dev/disk1)をパーティション分けして使っていたので、disuutilのunmountDiskコマンドを使うことにします。umountのmanを見ると、diskutilを使えて書いてありました。

~/.sleepに、以下のコマンドを追加して試したところ、うまくいきました。


/usr/sbin/diskutil unmountDisk /dev/disk1 2>&1 | logger


最後のloggerは、システムログにメッセージを出すためです。

2013年6月9日日曜日

bashのsequence expressionをfor文で使おうとしたら

bashにsequence expressionというものがあります。
例えば、{1..5}と書くと1 2 3 4 5に展開されます。
$ echo {1..5}
1 2 3 4 5
ファイル名の一部に連番がある場合にファイル名の生成に使ったり、for文の範囲指定に使えます。
例えば、
for i in {1..5}; do
  echo $i
done
と書くと、実行結果は
1
2
3
4
5
となります。ところが、範囲指定のどちらかに変数になっていると期待通りにはなりません。
N=5
for i in {1..$N}; do
  echo $i
done
では、結果は
{1..5}
となって、sequence expressionが表示されます。ブレース展開({}を用いた式の展開)は、bashの実行の最初期に行われ、その後変数展開が行われるためとのことです。
どうしても使いたい場合は、以下のように{1..5}となる部分をもう一度評価する必要があります。

N=5
for i in `eval echo {1..$N}`; do
  echo $i
done
の実行結果は
1
2
3
4
5
となります。最初に考えた{1..$N}より随分長くなってしまいます。これなら、以前のseqコマンドを使った書き方の

N=5
for i in `seq 1 $N`; do
  echo $i
done

が短いですね。
seqは外部コマンドで、eval, echoはbashの内部コマンドなので多少evalの方が軽いかもしれませんが、使う状況を考えるとseqのままで良さそうです。

2013年6月8日土曜日

icalBuddyをバージョンアップ [追記: 6/8 18:00]

icalBuddyというコマンドラインプログラムを使って、GeekTool, NerdToolで予定やTo Doを表示しています。
でも、Mountain Lionにしてから予定(カレンダーのデータ)が表示されなくなっていました。やっと重い腰を上げて解決することにしました。といっても結局バージョンアップしただけですが。
icalBuddyは、http://hasseg.org/icalBuddy/ で、Ali Rantakariさんが公開されています。
まず、動作しない原因ですが、icalBuddyがAddress book (連絡先)のデータにアクセスするときに拒否されてクラッシュしているためのようです。

2013-06-08 06:01:53.330 icalBuddy[99070:2623] Address book access is denied for executable at path: /usr/local/bin/icalBuddy
2013-06-08 06:01:53.331 icalBuddy[99070:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSConcreteMutableAttributedString initWithString:: nil value'

上記のエラーメッセージと共にスタックダンプも表示されます。想像ですが、アドレスブックにアクセスしようとして拒否され、そのデータが取れずにnilになってicalBuddyが終了というかクラッシュしたように見えます。
icalBuddyのウェブを見るとFAQにエラーメッセージを表示させないための解決方法が載っていました。
  1. icalBuddyにAddress bookのアクセス権を与える
  2. エラーメッセージを/dev/nullに送る
のどちらかを実行すればいいと書いてありますが、2番目はクラッシュを回避できないように思います。
気になったのは、カレンダーのデータを表示するのになぜAddress bookにアクセスする必要があるのかですが、特に記述はありませんでした。誕生日データを参照しようとしているのでしょうか。

1番目の解決策を試す前に、現在使っているバージョンが1.7.19と古いので最新版(1.8.8)にアップデートすることにしました。
今まではコンパイル済みのバイナリをインストールしていたのですが、ソースコードも欲しいと思い上記サイトのgitのアドレスから入手、コンパイルすることにしました。

念のためですが、以下の手順は普通にicalBuddyのサイトからコンパイル済みのバイナリ入りZIPファイルをダウンロードすることで全然かまわないです。

あらかじめ、Xcodeとcommand line toolをインストールしておく必要があります。
ビルド、インストールは以下のようにしました。

$ git clone http://hasseg.org/git-public/icalBuddy.git/
$ make 64BIT=1

単純なmakeだと32bit バイナリが生成されたので、気分的に64bitを指定してみました。
すると、今度はuniversal binaryになったので、上記makeのコマンドをコピペして、-arch i386を削って直接実行しました。複数行になっていますが、一行です。

$ clang  -O3 -Wall -std=c99 -force_cpusubtype_ALL -mmacosx-version-min=10.5 -arch x86_64 -framework Cocoa -framework CalendarStore -framework AppKit -framework AddressBook -o icalBuddy icalBuddy.m icalBuddy[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*.m ANSIEscapeHelper.m HG*.m IcalBuddy*.m *+HGAdditions.m

元のi386のままでも構わないのですが気分の問題でこうしてみました。
[* 次の文は、修正しました。クラッシュはなくなったのですが、system.logにaccecc deniedというメッセージは出ていました。6/18 18:0]
icalBuddyを実行してみるとエラーが出なくなっています。FAQの1番目のアクセス権を与えることも必要なさそうです。
その後インストールしようと思ったらMakefileの中にinstallターゲットがありません。
packageターゲットでZIPファイルを作り、そこから展開してインストールすることにしました。

$ mkdir deployment   # あらかじめ作っておく必要があるみたい
$ make package # 最後にエラーが出ますが関係なさそうなので気にしないことにします
$ cd deployment/1.8.8/
$ unzip icalBuddy-v1.8.8.zip
$ ./install.command    # /usr/local以外の場合はこのコマンドを修正する必要があります
=================================

This script will install icalBuddy and related files:

(icalBuddy installation found in:
 /usr/local
 -- using same path for updating:)

/usr/local/share/man/man1/icalBuddy.1
/usr/local/share/man/man1/icalBuddyLocalization.1
/usr/local/share/man/man1/icalBuddyConfig.1
/usr/local/bin/icalBuddy

We might need administrator privileges to install to
this location so please enter your password if prompted.

Input y to continue installing, c
to change the installation path or q to quit.
[y/c/q]: y
- Copying icalBuddy.1 to /usr/local/share/man/man1
Password:
  copied.
- Copying icalBuddyLocalization.1 to /usr/local/share/man/man1
  copied.
- Copying icalBuddyConfig.1 to /usr/local/share/man/man1
  copied.
- Copying icalBuddy to /usr/local/bin
  copied.

icalBuddy has successfully been installed.

以上で、icalBuddyがクラッシュしないようになりました。
ソースコード(何故連絡先にアクセスする必要があるのか)は、Cocoa, Objective-Cをよく知らないので見ていません。