Codemirror提示关键词/自动提示 实现及问题解决

8,711 阅读3分钟

Codemirror是一个不错的Web代码编辑库,可以方便简单的集成。没有自动提示功能的代码编辑器是没有灵魂的,Codemirror的自动提示功能是使用show-hint库进行的,我们可以调用showHint方法或者autoComplete方法来显示提示框。

普遍的用法:

var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "text/x-java", 
lineNumbers: true,
theme: "dracula",
matchBrackets: true,	//括号匹配
//readOnly: true,       
});

假设我们在Vue里面使用它做一个SQL编辑器,我们可以安装Vue-Codemirror更方便的使用组件。

npm i vue-codemirror --save

然后引用这个组件:

import { codemirror } from "vue-codemirror";

import "codemirror/lib/codemirror.css";
import "codemirror/theme/idea.css";
import "codemirror/theme/panda-syntax.css";
import "codemirror/addon/hint/show-hint.css";

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

这里面idea.csspanda-syntax.css都是主题样式文件,更多主题可以看这里:主题

<codemirror ref="editQuerySQL" v-model="query.sql" :options="cmOptions"></codemirror>

 cmOptions: {
        tabSize: 4,
        lineNumbers: true,
        line: true,
        indentWithTabs: true,
        smartIndent: true,
        autofocus: false,
        mode: "text/x-mariadb",
        theme: "idea",
        hintOptions: {
          completeSingle: false
        }
      },
      
    //显示提示  
     this.editQuerySQL.on("cursorActivity", () => {
        this.editQuerySQL.showHint();
      });  
      

mode是代码类型,比如SQL,JS,HTML等,Codemirror支持超过100种语言,更多语言

如果我们需要动态改变主题:

    this.editQuerySQL.setOption("theme", this.editorSQLTheme);

现在编辑器就可以使用了:

  • 问题一

如果选中了提示框里面的词(使用鼠标或者回车键)之后会无法删除,不能直接使用删除键进行删除,而只能使用鼠标选中整个删除词。

默认情况下,如果我们输入了提示词列表的某个首字母,会自动认为我们选中了某个提示词。

例如,现在我们使用了sql-hint,如果我们输入了S,不使用鼠标选中提示框里的任何词,它会将select关键字认为是我们选择的。但是这样非常困扰人,因为我们很可能是想输入其他以S开头的某个任意的词语。

上面这两个现象都是由于一个默认配置引起的。

在Codemirror官方文档show-hint部分可以看到

这个completeSingle的作用是当只敲击了一个单个的字母时,在不打开提示框的情况下,是否认为这个字母是提示语的一部分。默认为true。

如果是true,那么如果我们只输入了S,输入结束的时候会变成Select。如果为False,那么就不会这样,而是正常的和其他代码编辑器一样单个处理。

所以我们将其设置为 fasle:

 hintOptions: {
          completeSingle: false
        }

这样以上两个问题都解决了。

问题二:

输入结束会出现这样的情况:

这是因为我们使用的是cursorActivity事件:

可以看到cursorActivity事件:当光标或选区移动或对编辑器内容进行任何更改时,将触发该事件。 我们选择完一个关键词,光标就发生了变化,所以会触发提示的显示。

还有一个inputRead事件:每当从隐藏的文本区域中读取新输入(由用户键入或粘贴)时,就会触发。

我们使用这个事件,就会只有我们的手动操作才会触发提示框显示。

  this.editQuerySQL.on("inputRead", () => {
        this.editQuerySQL.showHint();
    });