在寫這篇文章的時(shí)候,我正在嘗試自己開(kāi)發(fā)一個(gè)我自己認(rèn)為能拿出去見(jiàn)人的IDE。當(dāng)然此時(shí)此刻我只開(kāi)展了一點(diǎn)點(diǎn)工作。所以這篇文章沒(méi)有什么最終的指導(dǎo)性,而是在記錄我開(kāi)發(fā)IDE的思考過(guò)程。當(dāng)然我覺(jué)得之前寫了那么多東西除了開(kāi)了源之后介紹了我的作品讓大家可以更好的理解并學(xué)習(xí)以外,其實(shí)也沒(méi)有什么大的效果(除了幾篇置頂?shù)慕坛涛覀€(gè)人覺(jué)得還是有點(diǎn)效果的……)。因此我嘗試做一下改變,把我的思考過(guò)程描述出來(lái)。一方面我自己可以從一個(gè)更高的高度來(lái)審視我自己,第二個(gè)就是如果你們想從我這里拿走什么,或者想教我什么,請(qǐng)自便哈。
其實(shí)以前并不是沒(méi)有開(kāi)發(fā)過(guò)IDE,只是那個(gè)IDE除了語(yǔ)法高亮以外什么都沒(méi)有,因此其實(shí)并沒(méi)有什么大的用處。個(gè)人認(rèn)為IDE要提供給你的功能有三點(diǎn):智能提示、集成調(diào)試、輔助部署。當(dāng)然在我眼中最厲害的IDE當(dāng)屬VisualStudio了,各種功能真是非常人性化,而且也跟我的觀點(diǎn)比較一致:我只是想開(kāi)發(fā)個(gè)編譯器然后開(kāi)發(fā)個(gè)makefile系統(tǒng)讓別人可以方便一點(diǎn)用我的編譯器而已,為什么我一定要用makefile來(lái)組織我的編譯器源代碼啊,一點(diǎn)都不方便(噗
是個(gè)程序員都是這么想的哈。
IDE還是好東西。前幾天我在vlpp.codeplex.com上面checkin了一份我開(kāi)發(fā)的語(yǔ)法高亮編輯器的雛形(下載后打開(kāi)Candidate\CodeBoxControl\CodeBoxControl.sln),完全用C#寫。我的Demo也是用的C#,外掛了一個(gè)可以分析C#的關(guān)鍵字、字符串和注釋的代碼著色器,在我的機(jī)器上(雖然我覺(jué)得比較強(qiáng)大,不過(guò)我的程序也是單核的,因此其實(shí)也只有2.7G的頻率)著色一個(gè)將近10萬(wàn)行的程序只需要半秒鐘。其實(shí)大家大可不必覺(jué)得C#很慢,其實(shí)是很快的,慢的是你的內(nèi)心。
當(dāng)然我也做了一點(diǎn)優(yōu)化,全文著色要半秒,不過(guò)其實(shí)你在編輯的時(shí)候是不需要總是全文著色的。所以我的著色器接口做了一點(diǎn)小限制:
1、你必須用狀態(tài)及實(shí)現(xiàn),而且狀態(tài)及的狀態(tài)只能用int類型來(lái)表達(dá)。
2、著色必須是上下文無(wú)關(guān)的。
對(duì)于2可能比較難理解。首先C#那個(gè)可以檢查出一個(gè)ID是不是一個(gè)類型然后變色其實(shí)根本不是著色器的任務(wù)(根據(jù)我的設(shè)計(jì),你可以在另一個(gè)地方臨時(shí)更改顏色,也能實(shí)現(xiàn))。其次對(duì)于一個(gè)給定的任意字符串前綴,其著色效果不能跟前綴之后的任何字符有關(guān)系。
因此我只需要記下每一行的末尾著色器當(dāng)時(shí)的狀態(tài),就可以從任意位置開(kāi)始到任意位置結(jié)束進(jìn)行部分著色了。因此這里就有很多的優(yōu)化空間。有了這些優(yōu)化之后,我用我的Demo編輯一個(gè)將近10萬(wàn)行的C#文件的時(shí)候,那個(gè)運(yùn)行在UI線程里面的著色算法絲毫沒(méi)有讓我覺(jué)得有延遲,只有在少數(shù)情況下(瞬間貼了好幾萬(wàn)行代碼,然后按ctrl+end跳到全文最后,我不得不對(duì)你貼進(jìn)去的東西立刻著色)才會(huì)讓你感覺(jué)到有小于半秒鐘的延遲。所以我覺(jué)得這個(gè)設(shè)計(jì)已經(jīng)可以達(dá)到我的要求了,因?yàn)槲易约簩懙拇a一般單個(gè)文件都沒(méi)有超過(guò)1萬(wàn)行,所以偶爾給我一個(gè)小于0.05秒的延遲其實(shí)也是無(wú)所謂的……
為什么可以進(jìn)行優(yōu)化呢。你可以想一下,如果我正在對(duì)某一行進(jìn)行編輯,而且這一行后面的代碼都已經(jīng)被著色過(guò)了,那么如果你的改動(dòng)都沒(méi)有讓行末尾的著色器狀態(tài)發(fā)生變化,那么這一行后面的所有字符都不需要更改他的著色,因此我就可以只對(duì)你當(dāng)前編輯的一行進(jìn)行著色(唯一修改的其實(shí)也就只有那種多行注釋,你一般也不會(huì)寫很多這種多行注釋的,都用的單行……)。一百來(lái)個(gè)字符的著色基本上可以忽略,因此無(wú)論你的文件有多大,其實(shí)著色速度是跟你平均每行的長(zhǎng)度有關(guān)系,只有在極少數(shù)情況下才會(huì)跟你的行數(shù)有關(guān)系。這個(gè)時(shí)候你可以看到著色器兩個(gè)限制的強(qiáng)大威力了吧。
那么,當(dāng)我們對(duì)一行代碼進(jìn)行斷點(diǎn)的時(shí)候,代碼顏色的修改是如何做的呢?為了這個(gè)東西去影響著色器那個(gè)強(qiáng)到可以忽略的效率實(shí)屬殺雞取卵,所以答案就是:外掛一個(gè)控制面板接口,讓你可以在顯示某一行的時(shí)候臨時(shí)修改那一行每個(gè)字符顏色。聽(tīng)起來(lái)好像很影響效率,不過(guò)我們要相信,一行代碼也就只有那么幾十到一百來(lái)個(gè)字符,一屏幕的代碼最多也就一兩千個(gè)字符。任何語(yǔ)言無(wú)論多慢,對(duì)一個(gè)一兩千那么長(zhǎng)的數(shù)組賦值,也是奇快無(wú)比的,何況是C#這么快的語(yǔ)言……
因此我們剩下的問(wèn)題就是如何實(shí)現(xiàn)一個(gè)可以修改文字顏色的普通文本框了哈。經(jīng)過(guò)我的3此研究,結(jié)論就是,不要用RichTextBox,你自己自繪從頭寫一個(gè)。第二個(gè)結(jié)論,凡是GUI最好都別用C++,無(wú)論GUI類庫(kù)多么好,一個(gè)沒(méi)有內(nèi)存管理器就足以讓你覺(jué)得很麻煩了,當(dāng)然對(duì)于編譯器本身我還是推薦C++的,因?yàn)榫幾g器雖然算法復(fù)雜,不過(guò)結(jié)構(gòu)簡(jiǎn)單,所有的內(nèi)存分配都是可以預(yù)測(cè)的,因此delete起來(lái)非常有信心。
最近一兩個(gè)星期都在糾結(jié)如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的上下文有關(guān)的智能提示功能(至少按個(gè)"."會(huì)有個(gè)列表什么的)。這個(gè)明天再寫了,今天只有一點(diǎn)點(diǎn)頭緒,還沒(méi)完全成型。


