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

かなり手抜きながら、LANGja_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だとうまくビルドできなかった。

 何か情報があれば寄せてください。みんな我慢しているのか、他にいい選択肢があって俺が知らないだけなのか、いつも不思議なんだよね。

 次に続く。


Categories : Tech