[Javascript] Monaco Editor 加入自訂的自動提示 auto hint , auto complete , intelligent sense

2021-10-25

上一篇文章,我們對 Monaco Editor 測試了一些功能 關於設定摺疊程式碼,註冊鍵盤事件,取得選取文字

今天我們來加入一個 令人雀躍的功能,就是加入智能提示的功能 intelligent sense

下面測試範例都皆是使用 Monaco Editor  撰寫 javascript 語言,假設你原本就有設計一些內建的 function

你希望客戶在寫的時候就有你的程式碼的 auto hint( intelligent sense ),就會需要用到這功能。

接下來我們就來看看要怎麼做到..



1. 比較麻煩的方法,這方法比較麻煩一點,但是對於 code snippet 就是很方便的,就是自動完成一段程式碼而並非提示而已

案例說明,我希望 使用者在寫 javascript code 的時候,輸入 DonmaUtil 會提示  GetUserInfo , GetBankInfo 這兩個 function

尚未修改前的提示:




進行修改


//


var editor = monaco.editor.create(document.getElementById('container'), {
   language: 'javascript',
   theme: 'vs-dark',
   tabCompletion: 'on',
   cursorSmoothCaretAnimation: true,
   formatOnPaste: true,
   mouseWheelZoom: true,
   autoClosingBrackets: "always",
   autoClosingOvertype: "always",
   autoClosingQuotes: "always",
   automaticLayout: "always"
 });

//所有自動提示的pool
 var suggestPool = [];


//填寫進入編輯器
 function fillRange(range) {
   for (var i = 0; i < suggestPool.length; i++) {
     suggestPool[i].range = range
   }
   return suggestPool;
 }

//載入提示庫,想要無腦改,改這function 就好了
 function fillDefaultPool() {


   suggestPool.push({
     label: 'DonmaUtil.GetUserInfo',
     kind: monaco.languages.CompletionItemKind.Function,
     insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
     insertText: 'DonmaUtil.GetUserInfo("userId");',
     detail: '取得用戶資訊'
   }, {
     label: 'DonmaUtil.GetBankInfo',
     kind: monaco.languages.CompletionItemKind.Function,
     insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
     insertText: 'DonmaUtil.GetBankInfo("bankId","bankKeyword");',
     detail: '取得銀行資訊'
   });

 }


 $('#btnAutoHint1').click(function() {

   //載入預設的提示建議
   fillDefaultPool();

   //註冊至編輯器,javscript  這語言
   monaco.languages.registerCompletionItemProvider('javascript', {
     provideCompletionItems: function(model, position) {
       var textUntilPosition = model.getValueInRange({
         startLineNumber: position.lineNumber,
         startColumn: 1,
         endLineNumber: position.lineNumber,
         endColumn: position.column
       });
       console.log(textUntilPosition);
       var match = textUntilPosition.replace(/[\*\[\]@@\$\(\)]/g, "").replace(/(\s+|\.)/g, " ");
       if (!match) {
         return {
           suggestions: []
         };
       }

       console.warn(textUntilPosition);
       var word = model.getWordUntilPosition(position);
       var range = {
         startLineNumber: position.lineNumber,
         endLineNumber: position.lineNumber,
         startColumn: word.startColumn,
         endColumn: word.endColumn
       };
       return {
         suggestions: fillRange(range)
       };
     }
   });

 });


//


Result:



2. 上面這方法 code 比較多,但是關於物件的部分呢

假設你定義了一個物件是 DonmaUser ,裡面有其 Id,Name,Age...,用第一種方法也可以,但是第二種方法更溫馨,但是缺點就是auto complete  程度不高不能自訂

但是對於定義已存在的 class 是很方便的。


修改後:




Code:

//


 $('#btnAutoHint2').click(function() {
		var additionalCode= `function DonmaUser(){
                                  this.Age=21;
                                  this.Id='';
                                  this.Name='';
                                  //$ref:DonmaUser
                                  this.Friend={};
                        	}`   ;
                            
     monaco.languages.typescript.javascriptDefaults.addExtraLib(additionalCode, '');

 });


//


Result :

reference :

https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.typescript.languageservicedefaults.html

https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html

https://microsoft.github.io/monaco-editor/api/enums/monaco.languages.completionitemkind.html


當麻許的超技八 2014 | Donma Hsu Design.