背景
最近遇到一個需求是在 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文件,我們找到它的位置並查看其源碼:
源碼裏最開始定義的變量:tables
,defaultTable
,keywords
。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,所以沒有高亮。