Implement some custom rules using CodeMirror

Because the project needed a text editor that could implement custom rules, several libraries were compared and CodeMirror was chosen

The advantages of CodeMirror

  1. Documentation is complete and easy to understand
  2. The Demo is rich
  3. Strong scalability

Today we are going to implement some custom language rules that give you an idea of how to use CodeMirror, but are not necessarily practical:

  1. Custom keyword highlighting
  2. Enter an open parenthesis and a close parenthesis automatically appears
  3. The left and right brackets are highlighted
  4. User-defined code completion drop – down dialog box

As a first step, we could either go to Github and pull down the CodeMirror code, or use NPM to install it, and then use several key files

<link rel="stylesheet" href=".. /lib/codemirror.css"> <script src=".. /lib/ codemiror.js "></script> // autocomplete <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 is the default text < textarea id =" editor "> hello world $123 aaa $< / textarea >Copy the code

Two core files are essential, and various addons are optional

// Define the keywords we need to highlight
const myHighlightList = [
    'hello'.'hello'.'$aaa$'
]
CodeMirror.defineMode('myMode', (config) => {
    return {
        /** The token method is used to highlight keywords, and CodeMirror calls the token method in turn by iterating through each character from left to right. The stream argument can be used to control the granularity of the traversal. For example, if I call the stream.eatwhile (/\s/) method, all Spaces following the current cursor will be matched to the stream, and the value of stream.current() will be all matched Spaces. * * /
        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: blue, CodeMirror: keyword {color: #708; } atom {color: #219; } number {color: #164; } and so on, see the codemiror.css definition **/
            if (exist) {
                return 'def'
            }

            stream.next()
        }
    }
})

// Define the words you want to auto-complete
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

    // Each time after pressing Alt+/, this method is executed, which filters the current input character and the text in myHintList for prefix matching, to achieve the function of searching while typing
    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.// Whether to display the line number
    extraKeys: { "Alt-/": "autocomplete" }, // Define autocomplete shortcut keys
    matchBrackets: true.// Whether to add matching parenthesis highlighting
    mode: 'myMode' // Custom mode name
});

// Press the open parenthesis to automatically add the close parenthesis
// Same with curly braces
editor.addKeyMap({
    name: 'autoInsertParentheses'."' ('": (cm) = > {
        const cur = cm.getCursor()

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