CodeMirror自定義關鍵詞以及關鍵詞功能的源碼

背景

最近遇到一個需求是在 sql-hint提供的自動提示關鍵詞的基礎上,需要可以自定義關鍵詞。

解析

在上一篇文章我們知道,實現自動提示的功能,需要引入下面四個js文件

require("codemirror/lib/codemirror");
require("codemirror/mode/sql/sql");
require("codemirror/addon/hint/show-hint");
require("codemirror/addon/hint/sql-hint");

這裏面sql-hint是針對sql提示的js文件,我們找到它的位置並查看其源碼:

源碼裏最開始定義的變量:tablesdefaultTablekeywords。tables是可以直接在options配置的hintOptions屬性設置的,如果我們需要自動提示表名和表的字段:

options:{
    hintOptions:{
        tables:{
            xxx0_table_name:[],
            xxx1_table_name:['attribute_1','attribute_2']
        }
    }
}

而keywords自然和我們需要實現的自定義關鍵字有關係,搜索這個keywords,發現源碼有一個方法:

 function getKeywords(editor) {
    var mode = editor.doc.modeOption;
    if (mode === "sql") mode = "text/x-sql";
    return CodeMirror.resolveMode(mode).keywords;
  }

然後在registerHelper(這個是提供給外界定義提示模式配置的方法,我們也可以自己調用它)方法中,

CodeMirror.registerHelper("hint", "sql", function(editor, options) {
    ...
    keywords = getKeywords(editor);
    ...
}

得出結論

這樣就明顯了,關鍵詞是通過 CodeMirror.resolveMode(mode).keywords得到的。mode我自己設置的是’text/x-mariadb’, 我們打印一下CodeMirror.resolveMode(mode)這個對象看看:

let CodeMirror = require("codemirror/lib/codemirror");
console.log(CodeMirror.resolveMode("text/x-mariadb"));

打印的結果:

keywords 就是關鍵詞的配置,可以看到,它是使用對象格式的。

實現功能

現在我們在一個常量文件裏配置我們自己的關鍵詞數組:

  SQL_CUSTOM_KEYWORDS: ['xxxxxxxx'],

然後在使用編輯器的地方把它加入關鍵詞:

 constant.SQL_CUSTOM_KEYWORDS.forEach(words => {
      CodeMirror.resolveMode("text/x-mariadb").keywords[words] = true;
 });

附加知識

在stackoverflow有人在js-hint裏自定義關鍵字使用這樣的方式:

var orig = CodeMirror.hint.javascript;
CodeMirror.hint.javascript = function(cm) {
  var inner = orig(cm) || {from: cm.getCursor(), to: cm.getCursor(), list: []};
  inner.list.push("bozo");
  return inner;
};

我試着將CodeMirror.hint.javascript切換爲sql,自動提示列表確實出現了push的內容,不過並沒有和其他關鍵字一樣高亮,結合sql-hint源碼

CodeMirror.registerHelper("hint", "sql", function(editor, options) {
      ......
      addMatches(result, search, defaultTable, function(w) {
        return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");
    });
    addMatches(
        result,
        search,
        tables, function(w) {
          return objectOrClass(w, "CodeMirror-hint-table");
        }
    );
    if (!disableKeywords)
      addMatches(result, search, keywords, function(w) {
          return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");
      });
    return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
    
}

CodeMirror.hint.sql的內容看上去和registerHelper的回調方法是一件事情,只是由於直接往list裏push字符串,它並不能知道是keyword還是table/default-table,所以沒有高亮。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章