前作”EmOcean“のすばらしいできばえに感動して久しいが、新作”Kailash“が去年出ていたことに今ごろ気づいて入手。
これもいい…。テーマに沿ってエキゾチックな音色やエフェクトも織り込みつつ、エッジの効いたスリリングな変拍子リフパートと耽美的なシンフォニックパートのコントラストが相変わらずすてき。
表向きはヴォーカリストのソロアルバムだけど、一人コーラス連発でうっとうしいとか、いろんな声色使いまくるのが気持ち悪いとかいうことがない。キーボードもギターものびのびやってるし、いい意味で余計な力が抜けていて心地よい。
アマゾンにリンクを張ったものの今は高い中古しかないっぽいので、安い(2,000円以下)出品があるときに買うか、HMVでも探してみて。
朝、昨日残したハンバーガーを食べて出たらなんか獣臭い。すかさずチャイラテを飲んでごまかした。
昼はみんなでそば屋へ。揚げ物も肉も食べたくないので山菜そばにしたが、ここの山菜そばはいつも食べてから後悔する。水煮の山菜が、あくがないのはいいが香りもなくて、何よりすっぱいんだよ。もう食わね。
まあ、夜おいしいもの食べるからいいんだ!
ひさしぶりに挑戦。平均で30cpm, 5wpmくらい上がってきた。

You reached 343 points, so you achieved position 9597 on the ranking list
You type 436 characters per minute
You have 82 correct words and
you have 1 wrong words
手ぬぐいを掛けない方が若干速いのが悔しい。でも、家のKinesisは埃が入るとすぐチャタリングを起こし出すんだよ。そろそろ新モデルでも出して背中を押してくれないかなあ。
流行っているキーボード早打ちテストをやってみた。リラックスした姿勢だと成績が芳しくないので、前傾姿勢で頑張ったら400字/分はコンスタントに行ける。370くらいだとミスのプレッシャーもなく楽に打てるんだが、スコアを取りに行くならリスクを負って攻めなければならない。
で、20回くらい頑張った今日のベストはこれ。

You reached 308 points, so you achieved position 10402 on the ranking list
You type 416 characters per minute
You have 75 correct words and
you have 1 wrong words
タイピングテストはみんなそうだけど、ミスは時間と点数のダブルで痛い。もっと練習して基礎体力を高め、泰然自若の境地を得なくては。
ちなみに、打つのはKinesisの方が断然楽だけど、速度自体はMacBookのキーボードでも大して変わらなかった。記号はアポストロフィ以外皆無で、シフト系の操作もほとんどないからね。
寝坊。パールセンター入り口のはな福で昼を食う。レタスチャーハンと醤油ラーメンのセットにしたけど、平凡でつまらなかった。隣のマックで今日発売のグラコロを買って行こうかと思ったけど、飯との取り合わせがジャンクすぎるので自重。

さて、ついに温かい料理が運ばれてきました。穴子とフォアグラのキャベツ包み。一目見て、ボリュームがすごい。きれいに二皿で出してきてくれるのでコソコソ取り分ける必要もなく、仲良く同じ料理を味わえます。アラカルトだけどコースみたい。
これにナイフを入れ、とろみのついたソースを絡めて口に運ぶわけです。うわ、穴子とフォアグラの境目がわからない!うまい!こう芳醇なうまみのパンチが内側から放たれたのでは、頬がだらしなく緩んでしまうのもしかたない。ソースも絶品。この菜っ葉はなんだろう。強すぎない個性が、とてもいいアクセントでした。
ここらで赤ワインも選ぼう。赤もよく悩みました。ソムリエに選択肢を挙げてもらった中から、最高のヴィンテージワインをチョイス。98 Clos Vougeot Daniel Rion。ああ、こんなおいしいワインをいただいてしまっていいのでしょうか。いいんです!
ブドウの味わい、タンニン、スパイシーさ、甘酸っぱさ、ワイルドさ、なめらかさ。調和とかそういうレベルではなくて、すべてがそれぞれに主張しながら、お互いに負けていないんだよね。この堂々たるヴィンテージには味蕾から脳天まですっかりやられました。何年に一回かでも、こんなワインを飲めたら幸せ者だ。

そして、料理も絶頂を迎えます。白子のガレット パイ包み レンズ豆のソース。いやあ、言葉もない。なんというすばらしい造形。パイとかタルトは底のところがあまり気に入らないことが多いんだけど、このガレットは文句なし。
サクサクのパイ生地の中には、とろっとした新鮮な白子がたっぷり。香ばしいガレットを添えて、レンズ豆のソースで召し上がれ。本当に感動した。
前菜二品だけで心底満足してしまったが、まだメインが二品。ゆっくりワインを楽しみましょう…。(つづく)
夜はミーティングを途中で抜けてコート・ドールへ。白金高輪から、タクシーで10分ほどの三田ハウスは落ち着いた佇まいだった。
ちょっとドキドキしながらドアを開け、フロントで名前を告げる。ここまではけっこう緊張していて、万が一カードが使えなくなったらと思って現金で十万も財布に入れてきたほど。到着もぎりぎりになってしまったので、納得の行くオーダーができるか心配にもなっていた。
しばらくして通されたテーブルは、電話で予約したときに最後のひとつと言われたラッキーな席。ここは言わずもがなの高級なお店だけど、もてなしが丁重かつやわらかくて、とてもリラックスした気分になった。
まずはシャンパンをいただいて姫君と乾杯。半月遅れの誕生祝いだ。そしてじっくりメニューを吟味する。残念なことにオマール海老と鴨がもう切れてしまったということで凹んだが、豊富に残るオプションから悩みに悩み抜いて料理を選ぶ。
注文のときに、何皿くらい食べられるものか聴いたら、男女二人なら前菜二、三皿にメイン二皿程度で十分だと言う。本当かなと思いながら、五皿頼んだ。
次にワインを選ぶ。これも相当に悩んだ。ソムリエがえらかった。一押しの白についての説明がとても魅力的な一方で、姫の思い入れのチョイスについても、その良さをいろんな言葉で表現してくれる。当然大いに迷うわけだけど、これは楽しい時間だよ。最終的に選んだのは姫のファーストチョイス、00 Pouilly-Fumé Grand Millésime。本当にすばらしかった。辛うじて、これを味わう舌を持っている喜びに浸ったけれども、今振り返って、それを雄弁な言葉で表現する舌の方は持ち合わせていないのだった。おこがましい、ともいう。白がこんなにうまいと思ったのは初めて!とだけ言っておこう。心の中に、味の記憶を大切にしまっておくことにします。

まず運ばれてきたお皿は、赤ピーマンのムース トマトソース添え。これは全員に振る舞われる名物なわけですが、これがね、笑っちゃうくらいおいしいんです。スプーンですくって口に入れたら、もうそのまま固まってしまいたい。赤ピーマンのほのかな甘みと、トマトの酸味が口の中で絶妙のストライプを成します。
ひんやりと冷たいので、脳天をしゃきっとさせつつ、舌の根っこの味覚をゆっくりと起こしていくような、そんなすばらしいアペタイザー。

次は野菜のエチュベ。これも冷たい、酸味の利いた一品。この野菜は酢で蒸してあるはずなのだけど、どうしてこんなに歯ごたえがいいのだろう。蒸し具合が技なのだね。白ワインも進みます。
最近の不摂生で口の中が若干荒れ気味だったので、突き刺す酸味に叱られているようでした。そう、おいしいものは体調を万全に整えていただきに参らなければなりません。
さあ、味覚は起きた。何でもござれ!

今夜は素敵な店に行くので昼は軽く流したいところだが、かといってあまりにひどいものを腹に抱えてしまっては後から来る料理に失礼とも言える。
そんなときはカレーがちょうどいい。煮込み料理なので消化がよく、スパイシーなので内臓の働きも活発になるはずだ。というわけで、カレー研究所にやって来た。いろんな種類のカレーがあるが、まだ試していないものがいいと思ってインドネシアカレー。オプションでスパイス二倍、辛さ二倍。牛肉と茄子がたっぷりでなかなか。そんなに辛くないので辛めにしてちょうどよかった。
エンコーディング/ロカール判定をまともにしてみた。[2007-11-06改訂]
Index: NSStringITerm.m
===================================================================
RCS file: /cvsroot/iterm/iTerm/NSStringITerm.m,v
retrieving revision 1.8
diff -u -r1.8 NSStringITerm.m
--- NSStringITerm.m 13 Nov 2006 08:01:04 -0000 1.8
+++ NSStringITerm.m 6 Nov 2007 09:24:28 -0000
@@ -294,9 +294,92 @@
return [NSString stringWithFormat:@"%d", num];
}
++ (BOOL)isCJKEncoding:(NSStringEncoding)encoding
+{
+ static NSMutableDictionary *isEncodingCJK = nil; // cache for encoding to isCJK mapping
+ static NSStringEncoding previousEncoding = 1; // ASCII
+ static BOOL isCJK = NO;
+ NSNumber *key, *val;
+ const char *lang;
+
+ if (encoding == previousEncoding) {
+ //NSLog(@"encoding[0x%08lx] is %s, again", encoding, isCJK ? "CJK" : "not CJK");
+ return isCJK;
+ }
+
+ previousEncoding = encoding;
+
+ key = [NSNumber numberWithUnsignedInt:encoding];
+
+ if (isEncodingCJK == nil) {
+ isEncodingCJK = [[NSMutableDictionary alloc] init];
+ }
+ else {
+ val = [isEncodingCJK objectForKey:key];
+
+ if (val != nil) {
+ isCJK = [val boolValue];
+ //NSLog(@"encoding[0x%08lx] is %s, IIRC", encoding, isCJK ? "CJK" : "not CJK");
+ return isCJK;
+ }
+ }
+
+ switch (encoding) {
+ // Simplified Chinese
+ case 0x80000019: // Mac
+ case 0x80000421: // Windows
+ case 0x80000631: // GBK
+ case 0x80000632: // GB 18030
+ case 0x80000930: // EUC
+ // Traditional Chinese
+ case 0x80000002: // Mac
+ case 0x80000423: // Windows
+ case 0x80000931: // EUC
+ case 0x80000A03: // Big5
+ case 0x80000A06: // Big5 HKSCS
+ // Japanese
+ case 0x00000003: // EUC
+ case 0x00000008: // Windows
+ case 0x00000015: // ISO-2022-JP
+ case 0x80000001: // Mac
+ case 0x80000628: // Shift JIS X0213
+ case 0x80000A01: // Shift JIS
+ // Korean
+ case 0x80000003: // Mac
+ case 0x80000422: // Windows
+ case 0x80000840: // ISO-2022-KR
+ case 0x80000940: // EUC
+ isCJK = YES;
+ //NSLog(@"0x%08lx is known to be %s", encoding, isCJK ? "CJK" : "not CJK");
+ break;
+
+ case 0x00000004: // UTF-8
+ isCJK = ((lang = getenv("LC_ALL")) != NULL ||
+ (lang = getenv("LC_CTYPE")) != NULL ||
+ (lang = getenv("LANG")) != NULL) &&
+ strlen(lang) >= 3 &&
+ (!strncmp(lang, "ja_", 3) ||
+ !strncmp(lang, "kr_", 3) ||
+ !strncmp(lang, "zh_", 3));
+ //NSLog(@"locale[%s] looks %s", lang, isCJK ? "CJK" : "not CJK");
+ break;
+
+ default:
+ isCJK = NO;
+ //NSLog(@"encoding[0x%08lx] is not known to be CJK", encoding);
+ break;
+ }
+
+ // Store in cache
+ val = [NSNumber numberWithBool:isCJK];
+ [isEncodingCJK setObject:val forKey:key];
+
+ return isCJK;
+}
+
+ (BOOL)isDoubleWidthCharacter:(unichar)unicode encoding:(NSStringEncoding) e
{
- if (unicode <= 0xa0 || (unicode>0x452 && unicode <0x200f))
+ if (unicode <= 0xa0 || (unicode>0x452 && unicode <0x1100))
return NO;
/*
unicode character width check
@@ -325,11 +408,7 @@
/* Ambiguous ones */
- if ((e)==0x80000019||(e)==0x80000421||(e)==0x80000631||(e)==0x80000632||(e)==0x80000930 || //GB
- (e)==0x80000002||(e)==0x80000423||(e)==0x80000931||(e)==0x80000a03||(e)==0x80000a06 || //BIG5
- (e)==0x80000001||(e)==0x8||(e)==0x15 || //JP
- (e)==0x80000628||(e)==0x80000a01 || //SJIS
- (e)==0x80000422||(e)==0x80000003||(e)==0x80000840||(e)==0x80000940) //KR
+ if ([self isCJKEncoding:e])
{
if ((unicode >=0xfe00 && unicode <=0xfe0f) ||
(unicode >=0x2776 && unicode <=0x277f) ||
これならsubmit可能か。ただ、描画部分でASCII/non-ASCIIフォントの選択を誤るのでまだ不完全。また時間が取れたら見ます。
あと、下線が倍幅に対応していない。
Index: PTYTextView.m
===================================================================
RCS file: /cvsroot/iterm/iTerm/PTYTextView.m,v
retrieving revision 1.307
diff -u -r1.307 PTYTextView.m
--- PTYTextView.m 17 Jun 2007 01:56:31 -0000 1.307
+++ PTYTextView.m 6 Nov 2007 02:07:04 -0000
@@ -963,7 +963,7 @@
//draw underline
if (theLine[j].fg_color & UNDER_MASK && theLine[j].ch) {
[[self colorForCode:(fgcode & 0x1ff)] set];
- NSRectFill(NSMakeRect(curX,curY-2,charWidth,1));
+ NSRectFill(NSMakeRect(curX,curY-2,double_width?charWidth*2:charWidth,1));
}
}
}
ほかにも、あんまり致命的ではないが特定のケースでカーソル移動によって文字の右半分が欠けたりする。まあ、ソースがあるからいつか捕まえて直せるだろう。Terminal.appもソースを公開してほしいね。
LeopardのTerminal.appをしばらく使っているうちに、こいつは使えない代物だと分かった。
まず、「○」とか「△」とかの記号を倍幅文字と認識してくれない。これは再描画しても直らないのでTigerのTerminal.appよりひどい。もしかすると、日本語フォントの記号グリフに沿った文字幅情報を含むエンコーディング定義を追加することできれいに対処できるのかもしれないが、その方法は未調査。ていうか、こんなのデベロッパープレビュー段階で気づかなかったんだろうか。Appleには日本人ハッカーはいないの?
二番目に、CommandキーをMetaキーとして使えないのが不便。TigerではAPE+Cmd2Optでなんとかなったが、今のところLeopardには対応していない。ていうかCmd2Optの配布物ってWeb Archive等を漁らないと手に入らなかった気がする。なんにせよ、Emacs使いにとってMetaキーが左下のちっこいOptionキーひとつというのは致命的だ。小指をつって死ねと言うに等しい。小指が休職したら、Ctrl+[で亀のようなもたもた人生を遅れというのか。
あと、ANSIカラーを調整できないので目に優しくない。頼みの綱はTerminalColorsだが、作者のサイトを見るとLeopardのTerminal.appに対応するのは当分先になりそうだ。
どうにかしようにもソースがない。じゃあソースがあるものをいじろう、ということでiTermに手を入れました。まず、第一の記号問題を解決するパッチがこれ。
Index: NSStringITerm.m
===================================================================
RCS file: /cvsroot/iterm/iTerm/NSStringITerm.m,v
retrieving revision 1.8
diff -u -r1.8 NSStringITerm.m
--- NSStringITerm.m 13 Nov 2006 08:01:04 -0000 1.8
+++ NSStringITerm.m 5 Nov 2007 14:04:20 -0000
@@ -286,6 +286,8 @@
0xfffd,
};
+static int isJapaneseEnvironment = -1;
+
@implementation NSString (iTerm)
@@ -296,8 +298,22 @@
+ (BOOL)isDoubleWidthCharacter:(unichar)unicode encoding:(NSStringEncoding) e
{
- if (unicode <= 0xa0 || (unicode>0x452 && unicode <0x200f))
- return NO;
+ if (unicode <= 0xa0 || (unicode>0x452 && unicode <0x200f))
+ return NO;
+
+ if (isJapaneseEnvironment < 0) {
+ const char ja_JP[] = "ja_JP.";
+ const char *lang = getenv("LANG");
+
+ if (lang != NULL && strlen(lang) > sizeof(ja_JP) - 1 && !strncmp(lang, ja_JP, sizeof(ja_JP) - 1))
+ isJapaneseEnvironment = YES;
+ else
+ isJapaneseEnvironment = NO;
+ }
+
+ if (isJapaneseEnvironment && unicode >= 0x2000)
+ return YES;
+
/*
unicode character width check
see. http://www.unicode.org
かなり手抜きながら、LANGがja_JPっぽいときはU+2000以上の文字は倍幅とみなすものだ。
次に第二のCommandキーをMetaキーにするパッチがこれ。
Index: iTermApplication.m
===================================================================
RCS file: /cvsroot/iterm/iTerm/iTermApplication.m,v
retrieving revision 1.10
diff -u -r1.10 iTermApplication.m
--- iTermApplication.m 7 Nov 2006 08:03:08 -0000 1.10
+++ iTermApplication.m 5 Nov 2007 13:51:06 -0000
@@ -43,6 +43,10 @@
id aWindow;
PseudoTerminal *currentTerminal;
PTYSession *currentSession;
+ unsigned int modflag;
+ unichar unicode;
+ NSString *keystr;
+ NSEvent *newEvent;
if([anEvent type] == NSKeyDown)
@@ -57,16 +61,42 @@
currentSession = [currentTerminal currentSession];
if([currentSession hasKeyMappingForEvent: anEvent highPriority: YES])
+ {
[currentSession keyDown: anEvent];
- else
- [super sendEvent: anEvent];
- }
- else
- [super sendEvent: anEvent];
+ return;
+ }
+
+ modflag = [anEvent modifierFlags];
+
+ if ((modflag & NSCommandKeyMask)) {
+ keystr = [anEvent characters];
+ unicode = [keystr length] > 0 ? [keystr characterAtIndex : 0] : 0;
+ switch (unicode)
+ {
+ case 0x20: // Switch Input Source
+ case NSCarriageReturnCharacter: // Enter Full Screen
+ break;
+
+ default:
+ newEvent = [NSEvent keyEventWithType: [anEvent type]
+ location: [anEvent locationInWindow]
+ modifierFlags: ((modflag - NSCommandKeyMask) | NSAlternateKeyMask)
+ timestamp: [anEvent timestamp]
+ windowNumber: [anEvent windowNumber]
+ context: [anEvent context]
+ characters: keystr
+ charactersIgnoringModifiers: [anEvent charactersIgnoringModifiers]
+ isARepeat: [anEvent isARepeat]
+ keyCode: [anEvent keyCode]];
+ [currentSession keyDown: newEvent];
+ return;
+ }
+ }
+ }
}
- else
- [super sendEvent: anEvent];
+
+ [super sendEvent: anEvent];
}
@end
これは、一部の組合せを除き、CommandキーをOptionキーと同一視させる修正。もちろん、Keyboard Profileの「Option Key as」でOptionキーをMetaキーにしないと無意味だ。ふつうは日本語を直接入力したいだろうから、そこの設定は「Meta」ではなく「+Esc」にするだろう。
なお、第三の色問題はiTermには存在しない。Display Profileでいじれるから。
iTermのサイトからCVSでソースを取ってきて上のパッチを当て、好みに応じていじってビルドしてください。特にどのCommandキーショートカットを生かすかの部分は人それぞれのはず。ビルド方法は、iTerm.xcodeprojを開いてビルドボタンを押すだけ。Xcodeは最新版(Tigerなら2.5, Leopardなら3.0)にしておいた方がいい。Tiger 10.4.10 + Xcode 2.4だとうまくビルドできなかった。
何か情報があれば寄せてください。みんな我慢しているのか、他にいい選択肢があって俺が知らないだけなのか、いつも不思議なんだよね。
次に続く。