CodeMirror入門指南

Z_Xu發表於2018-07-12

使用CodeMirror實現一些自定義的規則

因為專案中需要一個能夠實現自定義規則的文字編輯器,對比了幾個庫,最終還是選用了CodeMirror

CodeMirror的優點

  1. 文件完善,簡單易懂
  2. Demo豐富
  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>
複製程式碼

兩個核心檔案是必不可少的,其他的各種addons則是選配

// 定義我們需要高亮的關鍵字
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 })
    }
})
複製程式碼

CodeMirror入門指南