The Old Blog Archive (Traditional Chinese), 2004-2009

Archive for June, 2006

輸入法開發實驗:地理資訊輸入法(一)

(註:其實這應該要畫很多圖來說明的,在此先略)

ilya先前和我討論到:有沒有可能拿OpenVanilla來做地理資訊的輸入工具?他的需求,簡單說來,有以下兩類:

  • 輸入中文地名,出一地的英文地名或古地名
  • 輸入中文地名,出一地的經緯度或其他座標資料

在和ilya以及中研院OpenGIS Lab的張欽隆討論後,我們決定將這個輸入法的開發,變成一種公開的實驗。

這篇文章便是這一系列實驗的第一篇。我的初步構想是:藉這個機會,來實現OpenVanilla最初設計的其中一個理想──簡化輸入法的開發過程,讓開發者能專心於輸入法的邏輯和演算法,而不需煩心於各種作業系統平台的實作細節。

同時,我也希望藉由這個實驗,來說明OpenVanilla晚近加入的一個新設計──所謂的「詞彙管理架構」,以及為什麼詞彙管理架構能夠填補現有輸入法設計的不足。

最後,也希望藉由這個實驗,來走一遍一個 open source project 的開發流程,包括了建立程式碼的版本管理倉庫、選擇版本授權等等雖然屬於「周邊」(peripheral)、但對於計劃延續不可或缺的部份。

問題分析

地理資訊的輸入是一件麻煩的事。由於與一個地名相關的資訊種類繁多,如果能以「地名」為中心,也就是拿地名來當key,便能輸入各種資料,對於地理相關工作應該是很有幫助的。Ilya的需求是由此出發的。

同時,地名也是一種有歷史性(historicity)的東西。地名不只是現時、此刻的存在,也代表了歷史的累積。打當今地名而能出古地名的需求,也是由此而衍生出來的。

輸入法所可能提供的協助

輸入法在軟體工程上是一種奇特的存在。雖然輸入法最早是輸入亞洲語文所不可或缺的工具(sine qua non)[1],但是本質上輸入法是一種變換(transform):輸入一串組字鍵碼,得出組字結果。嚴格說來輸入法其實就是一種索引鍵─鍵值(key-value)的查找關係。

而,因為輸入法在現代桌面環境上,可以與任何需要文字輸入的GUI元件共同工作,於是很奇異的,輸入法變成一種增加軟體功能的方法。也就是說,藉由擴充輸入法的功能,我們等於同時也擴充了應用程式的功能(簡繁轉換及標點符號轉換均為其例)。因此,輸入法可以被當成一種「非侵入式的外掛」(non-intrusive plug-in)。

然而,由於主流的輸入法架構,僅僅作到一次性的key-value查找(例如:以倉頡組字碼找中文字),因此就算我們打出了「台北」兩字,我們依然只能把這兩個字剪貼到另一套資料庫程式,藉以檢索與「台北」兩字相關的地理資訊。

OpenVanilla早期設計了所謂的「輸出過濾器」(output filter)的架構,是可以針對「以詞為輸出單元的輸入法」(例如酷音,每一次輸入都是一個詞)做輸出處理。例如,我們可以設計一個「打『台北』出Taipei」filter。然而過濾器的缺點是:在UI邏輯上,filter是一種單向的、多對一的(one-direction, many-to-one)轉換。對於地理資訊來說,我們需要一個反饋的過程,亦即,當打完「台北」之後,我們可能要讓用戶再一次選擇與「台北」相關的地理資訊。

這種類似「二次選字」的事情,用filter是無法做到的。

OpenVanilla的詞彙管理架構

OpenVanilla於2006年初提出了「詞彙管理架構」。事實上一套「詞彙管理架構」是由兩個元件組成的:置如輸入法之前的「鍵碼前置處理器」(Key Preprocessor)跟「詞彙補捉器」(Phrase Catcher)。詞彙補捉器其實是一個filter,只是不停地把使用者輸入的文字給收集進來。

這樣的好處是,讓非以詞彙為輸出單位的輸入法(例如倉頡,一次只輸出一個字),也能夠收集詞彙。而,透過置於輸入法之前的「鍵碼前置處理器」,我們可以在還沒進到輸入法之前,就先對使用者的按鍵做處理:例如,把從「詞彙補捉器」收集來的詞,丟進資料庫裡,或是拿來查找。

也就是說,透過 key preprocessor ,我們可以做到一個「超輸入法」(meta-input method),讓使用者可以用任何一種輸入法打完「台北」兩個字,然後再拿「台北」兩字做一些事。

由於 key processor + phrase catcher 這樣的架構可以做到「再一次的查找與轉換」,我們的地理資訊輸入需求,似乎可以再利用(reuse)這個 pattern 來達成我們的需求。

實作的方法

通常,在原型階段,我們會先用一些 dirty hack 以及 top-down approach ,很快地把程式的功能原型寫出來,來證明概念可行。在此之後,我們再改走 bottom-up approach ,細細烹煮(cook)每個所需的元件,最後再放到一起大火快炒,勾芡上桌。

由於設計樣式已經有了,這個設計也被證明可行,我們要做的是依照需求,重寫一套依地名查找地理資料的輸入法。

在此之前,我們得先把一些材料準備好。

材料:地理資訊的 XML 資料表

我們收到的是一份長相如下的 XML 資料表:

<place id='1'>
    <zh_name>漁人</zh_name>
    <en_name>Yuren</en_name>
    <lon>121˚ 32' 40"</lon>
    <lat>22˚ 1' 5"</lat>
</place>

以上是該 XML 資料表的簡化版,我們先列出中文地名、英文地名與經緯度四項資料。

生的XML資料並不是那麼好利用。OpenVanilla推薦使用SQLite3。因此我們得先把XML煮成SQLite3能用的資料。

最懶的方法:XML::Simple

煮 XML 文件的方法很多,最懶又最快的方法,當然是使用 Perl 的 XML::Simple 模組了。

#!/usr/bin/perl -w
use strict;
use XML::Simple;
my $filename=shift or die "Must specify a filename";
my $data=XMLin($filename);

嗯,好像這樣就煮完了,似乎沒什麼挑戰性。當然,如果你只裝 XML::Simple ,在 OS X 上可能會發生一些問題(XML::Simple 預設的 XML parser 是 XML::SAX::PurePerl ,在 UTF-8 判斷上似乎有點 suck),因此建議再安裝 XML::SAX::Expat ,就會順心如意多了:

sudo cpan install XML::SAX::Expat
sudo cpan install XML::Simple

然後是怎麼轉換到 SQLite3 的問題。比較笨的作法是用 Perl 的 DBI 模組,然後實際開啟一個 SQLite3 資料庫,把轉換好的 $data 依欄位一個一個寫進去。

但是,這樣做,就實在太不懶惰了。SQLite3 的好處是,我們完全可以把資料生成另一堆生的 SQL 指令,然後讓 SQLite3 來吃。因為對 SQLite3 來說,一個資料庫就是一個檔案,所以萬一不高興,反正砍掉重練就是了。

所以,我們把煮成了 Perl hash 的資料一個個倒出來:

my $places=$data->{'place'};

for my $x (sort(keys(%$places))) {
    my $d = $places->{$x};

    print "INSERT INTO geoinfo (zh_name, en_name, lon, lat) VALUES (",
        sqlquote($d->{zh_name}), ", ",
        sqlquote($d->{en_name}), ", ",
        sqlquote($d->{lon}), ", ",
        sqlquote($d->{lat}), ");\\n";
}

也就是說呢,我們把資料 dump 成一條又一條的 SQL INSERT 指令。

那個 sqlquote 是一個小的函數,幫忙我們把字串加上 SQL 的 quote:

sub sqlquote {
    my $x=shift;
    $x =~ s/\\'/\\'\\'/g;
    return "'$x'";
}

然後,我們在倒資料前,先加上建立資料庫 schema 和 index 的指令:

print "CREATE TABLE geoinfo (zh_name, en_name, lon, lat);\\n";
print "CREATE INDEX idx_zh_name ON geoinfo (zh_name);\\n";
print "BEGIN;\\n";

並在最後加上

print "COMMIT;\\n";

之所以要用 SQL transaction 來做插入,是因為 SQLite 在 non-transaction insert 的表現慢得嚇死人。用了 BEGIN…COMMIT 之後大體上會瞬間完成所有 insert 的動作。

好了,這樣差不多了,只要再做點水管工(plumbing),我們就可以把 XML 檔案轉成 SQLite3 的 DB 了:

./gendb.pl source.xml | sqlite3 geoinfo.db

從這裡開始……

我們還沒談到去哪找地方放這些程式的問題,因此目前還不會有可以下載的地方。有了資料庫,我們就可以開始想想怎麼設計輸入法了。希望我很快就有時間來寫下一篇。

註解

  1. T. C. Chiang, D. Liu, K. M. Liu, W. Z. Yang, P. T. Tan, M. J. Hsieh, T. H. Chang, W. L. Hsu, “OpenVanilla – A Non-Intrusive Plug-In Framework of Text Services”. 2005. (Abstract).

It’s there…. OpenVanilla 0.7.2發布

這應該是 OpenVanilla 誕生到現在,在包裝上最花時間的一次。It’s finally here!

詳細的發布說明、取得方式及安裝說明──這一版請大家至少一定要讀一下「Ok,我到底該安裝哪套variant?」一節──請參考OpenVanilla 0.7.2的版本發布說明

對了,這一次 0.7.2 正式版的推出,有一個要特別感謝的人:davidyu。因為他的耐心與鍥而不捨──或許也因為他的PowerBook特別搞怪(?)──我們終於得以克服0.7.2-beta以來一直很難再現(reproduce)的一個嚴重bug。雖然這一半是OS X的問題,但至少以這次的修正來說,以後應該不會再發生「需要靠砍神秘的 .plist 才能修復 OV」的奇怪情事了。再次謝謝他的熱心幫忙。

OpenVanilla 0.7.2正式版小規模發布(再更新)

Update: 正式發布工作已經完成,取得及安裝方式,請參考OV wiki上的0.7.2版本發布說明

Update: 若您是行列輸入法的使用者,又在 2006/6/21 至 2006/6/25 之間曾安裝過 0.7.2 正式版,請參考這個說明,並至這裡下載修正檔案,就可以解決Caps Lock的問題了。

我們開始針對 OpenVanilla 0.7.2 for OS X 版本做小型的發布。0.7.2 正式版與 beta 版相比,新增及改進的項目主要有幾個:

  • 修正 0.7.2 beta 一直以來的幾個大問題:Num lock key 造成 OV 失靈、長期開機後會完全失效、需要靠刪除某個神奇的 .plist 檔才能修復再起不能的 OV 等難解的麻煩。
  • 增加一個解除安裝程式,可以把舊版或會造成衝突的版本清除掉。
  • 先前所有 patch 都整合了進來,包括針對詞彙管理工具等模組的修正。
  • 簡易/速成輸入法配合 Windows 習慣,改為九個選字鍵。

進一步的說明,請參考OpenVanilla Wiki

OV募款活動更新:WWDC 2006門票取得

今年 OpenVanilla 募款活動的第一項目標──參加今年的 WWDC──已經正式啟動。我們也已經取得了 WWDC 的門票(電子門票,票是直接進到了 ADC member 的 “account asset” 項目中)。lukhnos 將準備辦美國簽證,然後 OV 今年的募款活動頁也將改版,之後將做為發布捐款收入及開支項目,以及常態性的捐款活動所用。

要做的事情總是很多,會一步一步做好的。

謝謝大家!

Talk: OpenVanilla與簡體中文使用者

在星期六(2006-06-16)的北京BeiMac聚會利用了十分鐘的時間,用lightening talk的方式,簡單介紹了一下OpenVanilla。當天的投影片可以在這裡下載

That’s What I Am…

boē lián-tńg

Boē lián-tńg, or, “not fluent” in Taiwanese Holo, often written as “不輪轉”, is what I often say to admit my embarrassment of never being able to master that language (…”yet”).

Picture courtesy of Pektiong, the person behind OV’s POJ input method.

推薦一位朋友(與 OV 募款活動再 update)

OV 的好朋友 hlb 日前在自己的 blog 上貼了一篇找工作的文章,之後據稱來洽談的信件如雪片般飛來(之所以稱雪片般,是因為他其實只想找一份工作,卻來了十一份offer,因此募工作的達成率是 1100%,用大陸的說法,叫做海量)。

後來他寫了一篇感想,同樣放在他的 blog 上。雖然 hlb 老是自謙自己是小喀,我倒覺得他是過份 under-sell 自己了。好比,以 résumé 來說,這一次我覺得如果他要寫自己是「OpenVanilla 2006募款活動的 campaign consultant」,絕對當之無愧。

我們剛開始 OV 募款活動的時候,網頁是我弄的一個很簡陋的版本。hlb 稟持其處女座性格,實在看不下去,然後也同樣稟持其處女座性格,馬上動手改將起來,而有了現在的樣子。總工時:兩小時。成果?A site speaks louder than words。

雖然我想 hlb 目前可能沒興趣,但是我直覺,他會是 NGO 的搶手人材。這樣的 campaign consultant,去哪打著燈籠找啊!

所以,如果你要找的是 web designer,或者是 web standard 相關的工作,甚或是 consultant,我可以在此掛保證:He’s the man.

以上。(因為我同樣看不下去他的 under-sell 作風,所以一定要來幫他做點促銷活動。什麼?促銷只是為了把東西賣掉?君不見國際品牌如 Apple, Coke, Pepsi, Budweiser 者,每年的 marketing 預算仍是砸得不手軟嗎?)

PS. 雖然我看不下去,但是我不是處女座的。何以證明?我沒有立刻跳下海改將起來…… m(_ _)m

OV 募款活動 update: 我們昨日收到一筆暱名捐款,這是一位同樣長期關心中文 open source 軟體發展的朋友。我們在此謝謝他的關心,也在此轉達他對於 Windows IME, OV-Win32 與 Chewing Windows 版本發展的期待。截至本 blog 發布為止,我們已經募得了 NTD 105,588 (USD 3,300) 元的經費。WWDC 2006 的門票費用將在近日內支出購得。捐款贊助人的名單也將時時更新於 http://donate.openvanilla.org 上頭。再次謝謝大家對 OV 的支持與幫助!

募款活動目標達成! (2006-06-08 20:35 UTC+8)

已募得 NT$84,319 (USD 2,635)
目標達成──And Beyond!

 

今天下午三點半,我離開辦公室開會,我快要不知道該怎麼形容今天的感覺,怎麼說呢…… 我很想趕快發佈這項消息,終於到了剛剛才有機會坐下來,把這幾個小時以來收到的信,一一整理,然後……:

OpenVanilla 2006年的募款活動,目標達成!

而且,大家所捐助的款項總額,已經遠超過本次募款的目標。As promised, 我們會將超出部份,做為 OV 長久性的募款基金,供作下次我們有成員要參加技術活動,或是我們要舉辦技術活動的經費來源。

同時,lukhnos的舊金山行與zonble的北京行,將順利啟動。

在此趕快簡短發布這項消息。募款網頁已經更新。之後還有很多要寫的東西,想說的話,想表達的感謝,想寫的信。

在還來不及說這一些之前,僅讓我在此代表OpenVanilla Team,向所有支持我們、幫助我們的朋友,說聲:謝謝!

募款活動update (2006-06-08 20:30 UTC+8)

這八個小時以來,我們又陸續收到了Jinghua Zhong, Li-chun Lin, Liu Li Chang, Huan-Yi Tseng, Mike Chen, LiFeng Tu, cynosure, Geoffery Wang, ChuanHung Lin, jwbai, Naili Chang, Hsien-Jan Cheng, Li-Cheng Yeh, Po King Chan, Kwan Man Ho, marouflash, Chia-Cheng Yeh, Acer Hwang, Chieh-Chen Wu, Jedi, Zero等朋友的捐款支持。謝謝!

OV募款進度update (2006-06-08 12:00 UTC+8)

謝謝各位朋友的支持,目前 OV 募款進度已經完成 80% 。自 2006-06-08 台北時間凌晨四點到現在,我們又陸續收到了這幾位朋友的贊助款:Rong-En Fan, Li-Lun Wang, Chungyang Chen, Wen Ming Lin, leeys, johnnykao, jserv, Paul Yang (他的贊助款項是在寫這篇update時進來的,總款項會於稍後更新到募款活動主頁上)。

同時,我們也收到一位同樣是台灣open source界重要人物的(又)一筆大筆捐款──NTD 30k。

不過,因為 30k 這筆錢數額真的太大了,我們決定將這筆錢還給他。畢竟一直以來這位朋友對 OV 已經多所支持!

另外,新收到的使用者見證:

為什麼用 OV?因為開發者我認識,有什麼功能要求或軟體問題,直接找開發者即可,大不了還可以自己修!──jserv,OV-Win32使用者

以及,

承蒙 OV 開發者們的照顧,讓我的林檎成為我享受寫作的工具──momizi

再次謝謝大家!

Next »