自己動手設(shè)計代碼編輯器——(四)代碼智能提示(自動完成功能)

本來我的編輯器沒有自動完成功能的拄养,而且本來應(yīng)該繼續(xù)講代碼的載入與分析的离斩。
但剛好做了上一節(jié)的功能后,我臨時做出來了瘪匿,趁熱寫出來跛梗。

代碼自動完成,按自己的理解做的棋弥,不知道別人是怎么實現(xiàn)的核偿,先講自己的思路吧。
首先顽染,代碼自動完成漾岳,得記錄能自動完成的字符串(比如關(guān)鍵字、變量粉寞、類名等等)
這又要分:靜態(tài)載入和動態(tài)載入
所謂靜態(tài)載入尼荆,就是在程序啟動的時候載入的一些確定的字符串
比如:編輯器當前的配置是C#編譯器,那C#的關(guān)鍵字是確定的唧垦。這些是可以寫到配置文件里的捅儒,在程序啟動的時候就載入。
所謂動態(tài)載入振亮,就是在程序運行的時候巧还,分析代碼,在后才載入的字符串
比如:當前代碼的函數(shù)名双炕、變量等狞悲,這些是不能再之前確定的,只有當代碼分析完成后妇斤,才能確定摇锋。這部分字符串,在分析器里獲得站超。


好了荸恕,有了提示的字符串數(shù)組后,就可以實現(xiàn)功能了死相。
為了簡單融求,我這里只是在程序里直接定義了一些字符串數(shù)組
首先實現(xiàn)智能提示的核心類

public class IntelligentManager  
{  
        private CodeManager codeManager;  
          
        private string[] ss = new string[]  
        {  
            "int", "Integer",  
            "public", "private", "protected"  
        };  
          
        private List<string> result;  
          
        public List<string> Result  
        {  
            get  
            {  
                return result;  
            }  
        }  
          
        public IntelligentManager(CodeManager setCodeManager)  
        {  
            this.codeManager = setCodeManager;  
              
            this.result = new List<string>();  
              
            this.codeManager.TextChanged += TextChangedEvent;  
        }  
          
        public void MatchingString()  
        {  
            string inputString = codeManager.GetLastCut();  
              
            this.result.Clear();  
              
            if ( inputString.Length == 0 )  
            {  
                return;  
            }  
              
            inputString = inputString.ToLower(); // 代碼提示時,要不要區(qū)分大小寫就在這里搞定  
              
            foreach ( string s in ss )  
            {  
                if ( s.ToLower().StartsWith(inputString) && inputString.Length < s.Length )  
                {  
                    result.Add(s);  
                }  
            }  
        }  
          
        public void SelectMatching(int index)  
        {  
            if ( index < 0 || index >= result.Count )  
            {  
                return;  
            }  
              
            string str = result[index];  
            string lastString = codeManager.GetLastCut();  
              
            ReplaceStringCommand cmd = new ReplaceStringCommand(  
                codeManager,  
                codeManager.Text.Length - lastString.Length,  
                lastString.Length,  
                str);  
              
            codeManager.Execute(cmd);  
              
            result.Clear();  
        }  
          
        private void TextChangedEvent()  
        {  
            MatchingString();  
        }  
}

代碼不多算撮,也比較好理解生宛,稍微解釋下县昂。
MatchingString就是匹配CodeManager中,最后輸入的一個字符串塊
這里提一下陷舅,所謂字符串塊倒彰,就是被一些符號和空白符分開的東西,比如“abc,de+fg”這里就有三個塊莱睁,"abc","de","fg"待讳。他們被“," "+”這些符號分開了
因為我們不會為包含符號的字符串做匹配處理(比如str+abc,只用abc匹配仰剿,而不是str+abc)

selectMatching函數(shù)是表示選擇了匹配列表里的值
函數(shù)里面的ReplaceStringCommand是一個替換指定字符串的命令创淡,繼承IUndoCommand接口(不了解的,可以看上一節(jié))
TextChangedEvent是當CodeManager的文字發(fā)生改變的時候執(zhí)行了

特別說明南吮,我這里是用 codeManager.GetLastCut()來獲取最后輸入的一個塊琳彩。

在實際的項目中,應(yīng)該是取光標所在的塊部凑,至于怎么取汁针,就看自己的意思了,比較簡單砚尽。

CodeManager也要做一下對應(yīng)的改變
加入事件
public event CodeManagerEventHandler TextChanged;
另外在所有改變了文字內(nèi)容的地方,激活事件辉词。通知所有注冊了事件的其它類(這里只有IntelligentManager)

public void InsertCharacter(int index, char ch)  
{  
            text.Insert(index, ch);  
            TextChangedEvent();  
}  
  
private void TextChangedEvent()  
{  
            if ( TextChanged != null )  
            {  
                TextChanged.Invoke();  
            }  
} 

最后在Coder里定義即可
public IntelligentManager intelligentManager;
哦必孤,忘了說。為了顯示代碼提示的列表瑞躺,在上一節(jié)的基礎(chǔ)上敷搪,在窗體再拖一個label控件
在KeyDown事件的最后加入代碼

string[] ss = coder.intelligentManager.Result.ToArray();  
label2.Text = string.Empty;  
foreach ( string s in ss )  
{
  label2.Text += s;  
  label2.Text += '\n';  
}  

這樣就能顯示了。至于怎么選擇幢哨,看你了赡勘,可以按回車選中第一個,也可以按數(shù)字鍵捞镰,只需要調(diào)用函數(shù)SelectMatching闸与,傳入序號就可以了
當然,在真正的項目中岸售,還是得由IntelligentManager插件調(diào)用Renderer插件來自己繪制
好践樱,到這里代碼提示也完成了
當然,考慮效率問題凸丸,還有待優(yōu)化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拷邢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屎慢,更是在濱河造成了極大的恐慌瞭稼,老刑警劉巖忽洛,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異环肘,居然都是意外死亡欲虚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門廷臼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苍在,“玉大人,你說我怎么就攤上這事荠商〖盘瘢” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵莱没,是天一觀的道長初肉。 經(jīng)常有香客問我,道長饰躲,這世上最難降的妖魔是什么牙咏? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮嘹裂,結(jié)果婚禮上妄壶,老公的妹妹穿的比我還像新娘。我一直安慰自己寄狼,他們只是感情好丁寄,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泊愧,像睡著了一般伊磺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上删咱,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天屑埋,我揣著相機與錄音,去河邊找鬼痰滋。 笑死摘能,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的敲街。 我是一名探鬼主播徊哑,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼聪富!你這毒婦竟也來了莺丑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎梢莽,沒想到半個月后萧豆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡昏名,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年涮雷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轻局。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡洪鸭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仑扑,到底是詐尸還是另有隱情览爵,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布镇饮,位于F島的核電站蜓竹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏储藐。R本人自食惡果不足惜俱济,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钙勃。 院中可真熱鬧蛛碌,春花似錦、人聲如沸辖源。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽同木。三九已至,卻和暖如春跛十,著一層夾襖步出監(jiān)牢的瞬間彤路,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工芥映, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留洲尊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓奈偏,卻偏偏與公主長得像坞嘀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子惊来,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容