漢字仮名交じり文の読み仮名抽出(メモ編)

ちょっと思いついたので、メモです。

  1. Mac標準搭載のmecab
  2. CFStringTokenizer
    • 分かち書きされた各形態素をローマ字表記へ変換する
      • 品詞情報を用いて表記と読みが違うもの(『は』『へ』等)は読み用表記(『わ』『え』)にする
    • CFStringTransformでひらがな化

これで、何もインストールせずに読みかな抽出ができるかも?


ん〜
Mac標準搭載のmecabで、featureを見ると品詞情報しかない。。。
dicrcをいじれば読みをとれるのだろうか・・・
それとも、そもそもデータ入ってないのだろうか・・・
よくわかりません

Cocoa右クリックメニュー

今回のお遊び実験

目的

  • NSViewを継承しているクラスで、右クリックした時にポップアップメニューを表示する。
  • NSMenuを少しいじくる

NSViewを継承しているクラスってたくさんあります。
というか、GUIに設置にするものはほとんど(といか全部?)がそうでしょう。
今回はあえてNSButtonでやってみたいと思います。
誰もそんなことしたいと思わないだろうと?
お遊びだからいいのです。


実は実装は簡単です。

+ (NSMenu *)defaultMenu;

をオーバライドすれば、完了です。
その他にも、

- (NSMenu*)menuForEvent:(NSEvent*)event;

をオーバーライドする方法があります。
後者はクリック情報を内部処理で使いたい場合に使います。
例えば、指定した範囲ないでのみポップアップメニューを表示するとか。


今回は、前者を使います。

ではでは、サンプルコードです。

@interface PJPopUpMenuButton : NSButton
@end

@implementation PJPopUpMenuButton
+ (NSMenu*)defaultMenu {
	NSMenu * menu = [[[NSMenu alloc] initWithTitle:@"PJPopUpMenu"] autorelease];
	[menu addItemWithTitle:@"menu1" action:nil keyEquivalent:@""];
	return menu;
}
@end

なんとも簡単ですね。

NSMenuをいじってみる

次はNSMenuをいじってこんなことをしてみます。

これは、NSMenuItemのsetView:メソッドを使えば実現できます。
ソース

+ (NSMenu*)defaultMenu {
	NSMenu * menu = [[[NSMenu alloc] initWithTitle:@"PJPopUpMenu"] autorelease];
	[menu addItemWithTitle:@"menu1"
					action:nil
			 keyEquivalent:@""];
	
	//
	// メニュー内にNSButtonを入れてみる
	//
	NSMenuItem *buttonItem = [[[NSMenuItem alloc] initWithTitle:@"buttonItem" action:nil keyEquivalent:@""] autorelease];
	NSButton *button = [[[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)] autorelease];
	{
	[button setTitle:@"buttonItem"];
	[button setBezelStyle:NSTexturedSquareBezelStyle];
	}
	[buttonItem setView:button];
	[menu addItem:buttonItem];
	
	
	//
	// メニュー内にNSSliderを入れてみる
	//
	NSMenuItem *sliderItem = [[[NSMenuItem alloc] initWithTitle:@"sliderItem" action:nil keyEquivalent:@""] autorelease];
	NSSlider *slider = [[[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)] autorelease];
	{
		[slider setMinValue:0.0f];
		[slider setMaxValue:100.0f];
		[slider setFloatValue:50.0f];
	}
	[sliderItem setView:slider];
	[menu addItem:sliderItem];
	return menu;
}

とまぁ、結構遊べるものです。
NSMenuに関しては別記事にて、もう少し色々してみたい思います。

メニューの表示位置を変えてみる

では、最後に、ポップアップメニューの表示位置を変えてみます。
まずポップアップメニューが表示されるフローについて簡単に説明します。
右クリックが検知された際の動作は

  1. - (void)rightMouseDown:(NSEvent*)theEvent
  2. - (NSMenu*)menuForEvent:(NSEvent*)theEvent
  3. + (NSMenu*)defaultMenu

右クリックが検知されると1が呼び出されます。

1のデフォルト動作は、
 2を呼び出し、その返り値がnilでなければ、
 クリックされた場所にメニューを表示する
2のデフォルト動作は、3を呼び出す
3のデフォルト動作はnilを返す

という様になっています。
(2のデフォルト動作がもしかしたら違うかもしれませんが、ここではこれで差し支えないので、こうしておきます。中途半端ですみません)
つまり、表示位置をコントロールするには、1までさかのぼる必要があります。


また、表示される位置についてです。
絵にするとこんな感じになっています。

座標系が左下基準というのに、注意する必要があります。

そして、クリックされた場所の情報は、
rightMouseDown:の引数であるNSEventに含まれています。
こいつをいじくってやれば、表示位置を変更できるわけです。NSEventについては割愛します。

というわけで、コードはこんな感じになります。

- (void)rightMouseDown:(NSEvent *)theEvent {
//
// クリック位置をずらす
//
        NSPoint displayPoint = NSMakePoint([theEvent locationInWindow].x-100, [theEvent locationInWindow].y+100);
//
// 新しいNSEventを作る
// これをもとにポップアップメニューを表示させる
//
	NSEvent * newEvent = [NSEvent mouseEventWithType:[theEvent type]
		location:displayPoint
		modifierFlags:[theEvent modifierFlags]	
		timestamp:[theEvent timestamp]
		windowNumber:[theEvent windowNumber]
		context:[theEvent context]
		eventNumber:[theEvent eventNumber] 
		clickCount:[theEvent clickCount]
		pressure:[theEvent pressure]];
//
// 新しく作ったNSEventを使ってポップアップメニューを表示
// デフォルトでは、theEventを使っているのでしょう
//
	[NSMenu popUpContextMenu:[[self class] defaultMenu] withEvent:newEvent forView:self];
}


さぁ、どんな使い道があるのか・・・
僕にはさっぱりです。

CocoBot2を振り返る。そして、ご意見頂戴!

簡単にではありますが、CocoBot2を振り返ってみる。

特徴/機能

  • 開発開始当初に設計した機能がまだ何個も手つかず。故に永遠のアルファ
  • 簡易IRCクライアント
    • 陳腐なボット機能
  • Twitterハッシュタグ検索クライアント
  • 上記クライアントのコメントをニコニコ風に表示する
  • 上記クライアントのコメント読み上げ(要読み上げソフトウェア)
    • 読み上げ時のテキスト置き換え機能(w->わら)
    • 作成した読み上げ設定のスイッチング機能
  • バグまみれ

だいたいこんな感じでしょうか


利用者の方はどう思っているのでしょうか。
フィードバックをきちんと吸い上げられる機構がないので、確かめようがないのですが。
どうしたらいいですかね?
アプリケーションの使用者がいるのかどうか怪しいという懸念もあります(苦笑)
なのに、なぜ開発を続けているのか。
単に自分の思い描くものが出来上がっていくのが嬉しいから
それだけです。


ところで、そんなことはどうでもいいのです。
今後について、質問してみようと思います。
もし、この記事を目に通してくださった方がいたら、ぜひともご意見を。

今後についての質問

  1. 他の読み上げアプリケーションへの対応について
    • ゆっくろいど』というアプリケーションを見つけました。対応してみようと思うのですが、どうでしょうか?
    • 読み上げソフトは組み込みにしてほしいですか?(声が多く集まれば、そうするかもしれません。)
  2. 他のサービスへの対応
    • ニコ生やStickam等、対応して欲しい他のサービスはありますか?
  3. 欲しい機能
    • 何か実装して欲しい機能はありますか?

よろしくお願いします。

NSStringをローマ字表記に変換してみる

CFStringTokenizerはトークン分割に非常に役立つAPIです。
分割される様子を見る限り、結構きちんと形態素解析できていると思います。
(もしかしたら、mecab使っているのかな?まぁ、その辺はよくわからないですが、とりあえずおいておきましょう。)

今回そんなCoreFoundationのCFStringTokenizerで、遊んでみます。

目標

  • 文字列をトークン分割する(わかちがきする)
  • トークン分割された文字列をローマ字表記に変更する
すもももももももものうち
すもも も もも も もも の うち
sumomo mo momo mo momo no uchi

って感じの2項目です。
取得できるローマ字表記は、読み用のものではないので、その点はご留意を。
(助詞の『は』や『へ』は、きちんとトークン分割されますが、『ha』『he』と出力されます)
この点に関しては、もうちょっと調べたいと思います。

ソース

/*
 *	トークン解析に必要なもの
 */
NSString * testString;
CFLocaleRef locale; // ロケール:tokenizer生成に使用
CFRange range; // 解析用範囲:tokenizer生成に使用  : のちに検知されたトークンの範囲用として使用
{//トークン解析に必要なもの:初期化
	testString = @"すもももももももものうち";
	range = CFRangeMake(0, [testString length]);
	locale = CFLocaleCopyCurrent();// !!!: 要CFRelease
}

/*
 *	トークン解析してくれる子
 */
CFStringTokenizerRef tokenizer; // トークン解析してくれるよ !!!: 要CFRelease
tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, (CFStringRef)testString, range, kCFStringTokenizerUnitWordBoundary, locale);

CFStringTokenizerTokenType tokenType; // 見つかったトークンの状態
// 最初に見つかったトークンの状態で初期化
tokenType = CFStringTokenizerGoToTokenAtIndex(tokenizer, 0);

/*
 * トークン毎ループ
 */
while (tokenType != kCFStringTokenizerTokenNone) {
	//
	// range を解析用範囲から見つかったトークンの範囲へと使用方法を変更
	//
	range = CFStringTokenizerGetCurrentTokenRange(tokenizer);
	
	CFTypeRef latin; // トークンのローマ字表記 !!!: 要CFRelease
	latin = CFStringTokenizerCopyCurrentTokenAttribute(tokenizer, kCFStringTokenizerAttributeLatinTranscription);
	
	NSLog( @"token:%@ => latin:%@",[testString substringWithRange:NSMakeRange(range.location, range.length)], latin);
	
	CFRelease(latin);
	
	tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer);
}

CFRelease(locale);
CFRelease(tokenizer);

AqKanji2Koeの辞書って?

AquestさんがAqKanji2Koeというライブラリを提供してします。
これは漢字仮名交じり文からAquesTalk/AquesTalk2で利用できる記号列を生成してくれるライブラリです。


ところで、漢字の読みかな辞書とかどうしているのかな?
と思い、ちょっと探ってみた。


正体は MeCab + NAIST Japanese Dictionary でした。


ん〜・・・
音声記号付加処理をどうにか自分できれば、あるいは・・・
とか、思いながら現在AqKanji2Koeに変わるものを製作開始


完成した際に配布とかしたら、Aquestさんに怒られるかな?

NSStringとswitch 2

switchっぽいものでNSStringを扱うパート2
非常に気持ち悪いですがね

void PJSwitch(NSString * cmpdString, void (^block)(NSString*)) {
	block(cmpdString);
}
void PJCase(NSString*constantString,NSString* cmpdString,void (^block)()) {
	if ([cmpdString isEqualToString:constantString]) block();
}
NSString *fooString = ...;
PJSwitch(fooString, ^(NSString *arg1) {
// fooString   は   swith(<ここの部分>)
	__block BOOL stop = NO;
	while (1) {
		PJCase( @"hoge", arg1, ^() {
			NSLog(@"matched hoge");
			stop = YES;
		});  if (stop) {  break;  }
		PJCase(@"fuga", arg1, ^() {
			NSLog(@"matched fuga");
                        stop = YES;
		});  if (stop) {  break;  }

		break;
	}
});

NSTableViewいろいろなセルを表示2

前回の記事と内容はほとんど変わりませんが、
また、遊んでみます。

今回の目的

  • NSTableViewにいろんなセルを表示
  • 他の列に対して動的に変わるセルを表示
    • 今回はNSPopUpButtonの選択状態に応じて変わるようにしてみます
  • 実用性は考えない


ソースです。
http://dl.dropbox.com/u/28881228/MultipleCellTableView2.zip