CodeMirror入门

使用CodeMirror实现一些自定义的规则

因为项目中需要一个能够实现自定义规则的文本编辑器,对比了几个库,最终还是选用了CodeMirror

CodeMirror的优点

  1. 文档完善,简单易懂
  2. Demo丰富
  3. 可扩展性强

今天我们就来实现一些自定义的语言规则,这些规则只是让大家对CodeMirror的使用方法有一个初步的了解,并不一定实用:

  1. 自定义关键字高亮
  2. 输入左括号自动出现右括号
  3. 左右括号颜色高亮
  4. 自定义代码补全下拉提示框

开工,第一步,我们可以去github上把CodeMirror的代码拉下来,或者用npm安装也可以,然后使用到了里面的几个关键文件

1
2
3
4
5
6
7
8
9
10
11
// 核心文件
<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则是选配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// 定义我们需要高亮的关键字
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 })
}
})
posted @ 2019-04-02 15:38  深夜钢琴师  阅读(846)  评论(3编辑  收藏  举报