Начало работы с CodeMirror

внешний интерфейс Открытый исходный код

Реализуйте некоторые пользовательские правила с помощью CodeMirror.

Поскольку проекту нужен текстовый редактор, который может реализовывать пользовательские правила, я сравнил несколько библиотек и, наконец, выбрал CodeMirror.

Преимущества CodeMirror

  1. Хорошо документировано, легко понять
  2. Демо богато
  3. Сильная масштабируемость

Сегодня мы реализуем некоторые пользовательские языковые правила, эти правила предназначены только для того, чтобы дать вам предварительное представление о том, как использовать CodeMirror, не обязательно практическое:

  1. Подсветка пользовательских ключевых слов
  2. Введите открывающие скобки, чтобы автоматически отображались закрывающие скобки
  3. Левая и правая скобки выделены
  4. Раскрывающееся меню завершения пользовательского кода

Приступаем к работе, первый шаг, мы можем пойти на github, чтобы сбросить код CodeMirror, или установить его с помощью npm, а затем использовать несколько ключевых файлов внутри

// 核心文件
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
// 自动补全提示框
<script src="../addon/hint/show-hint.js"></script>
<link rel="stylesheet" href="../addon/hint/show-hint.css">
// 左右括号颜色高亮
<script src="../addon/edit/matchbrackets.js"></script>

// textarea内是预设的文本
<textarea id="editor">123 hello world $aaa$</textarea>

Два основных файла необходимы, другие различные дополнения не являются обязательными.

// 定义我们需要高亮的关键字
const myHighlightList = [
    'hello',
    '你好',
    '$aaa$'
]
CodeMirror.defineMode('myMode', (config) => {
    return {
        /**
            这个token方法就是用来标亮关键字的,
            CodeMirror会自上而下,从左往右得遍历每一个字符,依次调用token方法。
            stream参数可以用来控制遍历的粒度,比如我调用方法 stream.eatWhile(/\s/),
            那么当前cursor后面所有的空格会被匹配到stream中,stream.current()的值就是所有匹配到的空格。
        **/
        token: (stream) => {
            if (stream.eatSpace()) { return null }

            stream.eatWhile(/[\$\w\u4e00-\u9fa5]/)

            const cur = stream.current()
            const exist = myHighlightList.some((item) => {
                return item === cur
            })

            /**
             def 表示蓝色,CodeMirror为我们定义了许多颜色,其他还有:
            keyword {color: #708;} 
            atom {color: #219;}
            number {color: #164;}
            等等,具体可以看codemirror.css文件中的定义
            **/
            if (exist) {
                return 'def'
            }

            stream.next()
        }
    }
})

// 定义想要自动补全的words
const myHintList = [
    'hint1',
    'hint2',
    'ha2',
    'ha3'
]
CodeMirror.registerHelper("hint", "myMode", function (cm) {
    var cur = cm.getCursor(), token = cm.getTokenAt(cur);
    var start = token.start, end = cur.ch
    var str = token.string

    // 每次按下 Alt+/ 后会执行这个方法,这里将当前输入的字符和myHintList内的文本做前缀匹配过滤,实现一边输入一边查找的功能
    const list = myHintList.filter((item) => {
        return item.indexOf(str) === 0
    })

    if (list.length) return {
        list: list,
        from: CodeMirror.Pos(cur.line, start),
        to: CodeMirror.Pos(cur.line, end)
    };
});

const editor = CodeMirror.fromTextArea(document.getElementById("editor"), {
    lineNumbers: true, // 是否显示行号
    extraKeys: { "Alt-/": "autocomplete" }, // 定义自动补全的快捷键
    matchBrackets: true, // 是否添加匹配括号高亮
    mode: 'myMode' // 自定义的mode名称
});

// 这里实现的功能就是按下左括号,自动添加右括号
// 中括号,大括号同理
editor.addKeyMap({
    name: 'autoInsertParentheses',
    "'('": (cm) => {
        const cur = cm.getCursor()

        cm.replaceRange('()', cur, cur, '+insert')
        cm.doc.setCursor({ line: cur.line, ch: cur.ch + 1 })
    }
})