您的位置:首页 > 编程语言

在线代码编辑器 CodeMirror 使用简介

2017-11-21 19:31 1076 查看

在线代码编辑器 CodeMirror 使用简介

CodeMirror是一款在线的支持语法高亮的代码编辑器 github源码

特点:

支持100多种语言

支持多语言混合

代码自动提示

代码折叠

键盘绑定事件

编辑模式 VimEmacsSublime Text

很多的方法和插件…

几十个demo可供参考

已经应用CodeMirror的产品

使用:

基本的用法

<!-- 引入codemirror 外部基本资源js css -->
<link rel="stylesheet" href="http://codemirror.net/lib/codemirror.css">
<script src="http://codemirror.net/lib/codemirror.js"></script>
<!-- 引入mode  此处为js mode-->
<script src="http://codemirror.net/mode/javascript/javascript.js"></script>

<body>
<!-- 创建编辑区域1 -->
<form>
<textarea id="myTextarea"></textarea>
</form>
<!-- 创建编辑区域2 -->
<div id="code"></div>
</body>


推荐的使用方法

编辑器将会替换
textarea
,和
textarea平级
,自动把
textarea
隐藏掉
(display: none)


// 创建实例  这种方法在options 里写value属性是没有用的,自3.0版本改掉了
// 对于生成实例的步骤,react用户注意,要在真实dom生成之后再调用
const myTextarea = document.getElementById('myTextarea')
const editor = CodeMirror.fromTextArea(myTextarea, {
lineNumbers: true,
mode: 'javascript' // 设置mode 对应的也要这之前引入相应的js
});


编辑器将被追加到
div里边


// 编辑器将被追加到div 里边
var myCodeMirror2 = CodeMirror(document.getElementById("code"), {
lineNumbers: true,
value: "function myScript(){return 100;}\n",
mode:  "javascript"
});


编辑器将
替换
元素

var myTextArea = document.getElementById("code");
var editor = CodeMirror(function(elt) {
myTextArea.parentNode.replaceChild(elt, myTextArea);
}, {
value: 'select * from table6666',
lineNumbers: true,
});


更多场景,就要通过
options
配置 和
eitor
的方法去实现了

常用Configuration options 配置介绍

value: string | CodeMirror.Doc

编辑器的初始值(文本),可以是字符串或者CodeMirror文档对象

mode: string | object

通用的或者在
CodeMirror
中使用的与
mode
相关联的MIME,当不设置这个值的时候,会默认使用第一个载入的
mode
定义文件。一般地,会使用关联的mime类型来设置这个值;除此之外,也可以使用一个带有name属性的对象来作为值
(如:{name: “javascript”, json: true})
。可以通过访问
CodeMirror.modes
CodeMirror.mime
Modes`获取定义的mode和MIME

lineSeparator: string | null

明确指定编辑器使用的行分割符(换行符)。默认(值为
null
)情况下,文档会被
CRLF
(以及单独的CR, LF)分割,单独的LF会在所有的输出中用作换行符(如:
getValue
)。当指定了换行字符串,行就只会被指定的串分割。

theme: string

主题样式,主题对应的样式类名为
.cm-s-[name]
,参考其他主题,也可以自定义主题样式

indentUnit: integer

缩进为多少个空格,默认为
2


smartIndent: boolean

换行的时候是否使用模式提供的上下文相关的缩进(或只是缩进与之前的行对其), 默认
true


tabSize: integer

一个tab有几个空格,默认是
4


indentWithTabs: boolean

在缩进时,是否需要把
n*tab
宽度个空格替换成
n
tab
字符,默认为
false


keyMap: string

配置快捷键图,编辑模式。默认
defaul
,这是
codemirror.js
本身定义的唯一键映射。其他选项参考key map

extraKeys: object

可以为编辑器绑定额外的键盘事件。

lineWrapping: boolean

当一行特别长的时候,是滚动还是换行。默认为
false
(滚动)

lineNumbers: boolean

是否在编辑器左侧显示行号

firstLineNumber: interger

第一行的行号,默认为
1


lineNumberFormatter: function(line: integer) → string

自定义行号

fixedGutter: boolean

是否在内容水平滚动的时候,行号也跟着滚动,(默认为true)

readOnly: boolean

编辑器是否可以编辑
(默认false)


showCursorWhenSelecting: boolean

选中的时候,是否显示光标,默认
false


lineWiseCopyCut: boolean

在没有选择时进行复制或剪切,将复制或剪切光标所在的行

undoDepth: integer

编辑器存储的撤消级别的最大数量,默认
200


autofocus: boolean

自动获取焦点

dragDrop: boolean

是否启用拖放功能,就是把文件拖进来自动打开。

allowDropFileTypes: array

设置可以拖放的文件类型

常用的可绑定的事件 Events

editor.on('change', (instance, change) => {
// instance  指CodeMirror实例对象
// .....
do what you want
})


CodeMirror 提供了很多的方法,这些方法允许客户端对各种情况做出不同的行为,这些事件可以通过
on
off
来绑定和解除绑定处理函数

change (instance: CodeMirror, changeObj: object)

编辑器发生改变的时候触发(不建议在
change
事件中做过多的操作,比如
setState
,否则会导致卡顿)

beforeChange (instance: CodeMirror, changeObj: object)

在更改之前触发,可以选择修改更改的内容或者取消更改,
changeObj
提供了
cancel()
update
的方法

cursorActivity (instance: CodeMirror)

当改变、光标移动、选择的时候触发

keyHandled (instance: CodeMirror, name: string, event: Event)

快捷键映射
(key map)
中的快捷键被处理
(handle)
后触发

inputRead (instance: CodeMirror, changeObj: object)

当用户输入,或者粘贴时触发,(和
change
区别:撤销,恢复不会触发)

viewportChange (instance: CodeMirror, from: number, to: number)

每当编辑器的视图窗口发生更改(由于滚动,编辑或其他因素)时触发

gutterClick (instance: CodeMirror, line: integer, gutter: string, clickEvent: Event)

当编辑区域的行号被点击时触发,
line
是从
0
开始的,
gutter
为行号的
class


gutterContextMenu (instance: CodeMirror, line: integer, gutter: string, contextMenu: Event: Event)

编辑器行号
(contextmenu)
右键出现上下午菜单的时候触发

focus (instance: CodeMirror, event: Event)

编辑器获取到焦点的时候触发

blur (instance: CodeMirror, event: Event)

失去焦点时触发

scroll (instance: CodeMirror)

滚动的时候触发

optionChange (instance: CodeMirror, option: string)

当配置项别改变的时候触发
(setOption)


update (instance: CodeMirror)

CodeMirror
更新其
DOM
显示时触发

mousedown, dblclick, touchstart, contextmenu, keydown, keypress, keyup, cut, copy, paste, dragstart, dragenter, dragover, dragleave, drop (instance: CodeMirror, event: Event)

dom
的原生事件

CodeMirror API

文档操作

editor.getValue() // 当前编辑器的content


getValue (?separator: string) → string

获取编辑器的内容,你可以传入一个特殊的字符串,去分割行,默认
'\n'


setValue (content: string)

设置编辑器的内容,实例初始化的时候可以通过
option:value
,或者写入
textarea
里指定编辑器的内容。实例生成之后,通过这个方法去设置编辑器的内容。

getRange (from: {line, ch}, to: {line, ch}, ?separator: string) → string

获取编辑器指定位置的内容,可以传入特定的行分割符,
line
第几行,
ch
第几列,都是从
0
开始

replaceRange (replacement: string, from: {line, ch}, to: {line, ch}, ?origin: string)

用给定的字符串替换或插入指定的地方

getLine (n: integer) → string

获取指定行的内容
(0 开始)


lineCount () → integer

获取编辑器一共有多少行

getLineHandle (num: integer) → LineHandle

获取指定行的实例对象

getLineNumber (handle: LineHandle) → integer

根据行的实例,获取行的行号
(0开始)


eachLine(f: (line: LineHandle)) 或者 (start: integer, end: integer, f: (line: LineHandle))

遍历整个文档,或者如果给出了开始和结束行号,则从开始到(不包括)结束的范围,并且为每一行调用
f
,传递行句柄。这是访问一系列行处理程序比为每个行调用
getLineHandle
更快的方法

光标和选择

getSelection (?lineSep: string) → string

获取选中的内容,可以传入一个行分割符默认
'\n'
,返回的是字符串。当有有多个选中的区域,他们之间的链接就是这个分割符

getSelections (?lineSep: string) → array

获取多个选中的内容,返回的是一个数组,其他同上。

replaceSelection (replacement: string, ?select: string)

用给定的字符串替换选中的。可选的
select
当传入
'around'
时,替换完成后会自动选中新插入的文本,
'start'
时,替换完后光标在最开始的位置

replaceSelections(replacements: array, ?select: string)

用数组中的字符替换选中的内容,替换的数组的长度应该和选中的数组的长度保持一致

getCursor (?start: string) → {line, ch}

返回光标所在的位置

listSelections () → array<{anchor, head}>

返回当前被选中的
Range
实例

somethingSelected () → boolean

当选中任何内容,将会返回
true


setSelection (anchor: {line, ch}, ?head: {line, ch}, ?options: object)

给定位置,设置选中的区域,如果
head
没传,
head
默认为
anchor


options有以下选项:

scroll: boolean

是否将选中的区域滚动到可视范围。

origin: string

确定选择历史事件是否可以与前一个合并。具体:

Determines whether the selection history event may be merged with the previous one. When an origin starts with the character +, and the last recorded selection had the same origin and was similar (close in time, both collapsed or both non-collapsed), the new one will replace the old one. When it starts with *, it will always replace the previous event (if that had the same origin). Built-in motion uses the “+move” origin. User input uses the “+input” origin.

bias: number

确定选择端点落入原子范围内时应调整的方向(具体我也不清楚)

Determine the direction into which the selection endpoints should be adjusted when they fall inside an atomic range. Can be either -1 (backward) or 1 (forward). When not given, the bias will be based on the relative position of the old selection—the editor will try to move further away from that, to prevent getting stuck.

setCursor (pos: {line, ch}|number, ?ch: number, ?options: object)

设置光标位置。可以传参数
{line, ch}
对象,也可以将这两个值作为两个参数传入。将在给定位置用一个空的选择来替换所有的选择,
options
setSelection
options
参数

setSelections (ranges: array<{anchor, head}>, ?primary: integer, ?options: object)

设置一组新的选择。给定数组中至少有一个选择。当
primary
是一个数字,它决定哪个选择是主要的。如果没有给出,则主索引从前一个选择中获取,如果前一个选择的范围小于新的范围,则将其设置为最后一个范围。
options
setSelection
options
参数

addSelection (anchor: {line, ch}, ?head: {line, ch})

添加一个新的选择到现有的选择,并使其成为主要的选择

extendSelection (from: {line, ch}, ?to: {line, ch}, ?options: object)

setSelection
类似。区别在于,当按下shift键或设置了extending标志时(指的是设置为true),只会移动head的位置,
anchor
会被留在当前位置。参数
to
是可选的,传此参数用于确保区域(
region
,比如单词或段落)能被完整选择。当前有多个选区时,会清除掉主选区。参数
options
setSelection


extendSelections (heads: array<{line, ch}>, ?options: object)

相当于一次执行所有选择的extendSelection

extendSelectionsBy(f: function(range: {anchor, head}) → {line, ch}), ?options: object)

将给定的函数应用于所有现有的选择,并调用
extendSelections


hasFocus() → boolean

编辑器当前是否有焦点

配置的设置方法

// 映射Tab键以插入空格而不是制表符
editor.setOption("extraKeys", {
Tab: function(cm) {
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
cm.replaceSelection(spaces);
}
});


setOption (option: string, value: any)

更改编辑器的配置。
option
应该是一个选项的名称,
value
应该是该选项的有效值

getOption (option: string) → any

检索此编辑器实例
option
的值

setSize (width: number|string, height: number|string)

设置编辑器的
宽高


scrollTo(x: number, y: number)

主动让编辑器滚动

getScrollInfo () → {left, top, width, height, clientWidth, clientHeight}

获取表示当前滚动位置,可滚动区域的大小以及可见区域的大小(减号滚动条)的
{left,top,width,height,clientWidth,clientHeight}


getMode () → object

获取编辑器的模式对象。请注意,这不同于
getOption(“mode”)
。当前返回的是模式实例化对象

isReadOnly() → boolean

返回编辑器当前是否允许编辑。

getWrapperElement () → Element

返回代表当前编辑器的
DOM


CodeMirror.fromTextArea(textArea: TextAreaElement, ?config: object)
,这个方法创建的实例有以下几个方法:

save ()

将编辑器的内容复制到
textarea
中,这样表单中的textarea的值就会和编辑器同步,以方便表单验证

toTextArea ()

删除编辑器,并恢复原始文本区(内容与编辑器的当前内容保持一致)

getTextArea () → TextAreaElement

返回实例所基于的
textarea


CodeMirror
提供了很多的快捷键去完成编写 具体参考

实际应用实例

CodeMirror
mobx
react
中的应用demo

场景:编辑器支持可编辑,代码高亮,代码提示

// code.js 此处codemirror是npm包
import {Component} from 'react'
import {observer} from 'mobx-react'
// 如果是安装包的形式,这样引入
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/'
// 引入mode
import 'codemirror/mode/sql/sql'
// 引入代码提示
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/show-hint'
// 上边两个是定义提示的前提,下边定义自动提示是哪种模式,此处为sql
import 'codemirror/addon/hint/sql-hint'
// 引入keymap
import 'codemirror/addon/comment/comment'
import 'codemirror/keymap/sublime'

@observer
export default class Code extends Component {
render() {
return (
<form>
<textarea ref={p => this.codeDom = p}> placeholder="code goes here..." >
{
value // 如果是异步获取的value,可以通过setValue赋值
}
</textarea>
</form>
)
}
componentDidMount() {
this.editor = CodeMirror.fromTextArea(this.codeDom, {
lineNumbers: true,
keyMap: 'sublime',
indentUnit: 4,
tabSize: 4,
mode: 'text/x-mysql',
showCursorWhenSelecting: true,
//  这是针对sql有自定义表和字段的,这样可以把自己的表和字段也放入提示里。如果数据是异步请求获取的,可以通过editor.setOption('hintOptions', data)
hintOptions: {
tables: {
table1: [ 'col_A', 'col_B', 'col_C' ],
table2: [ 'other_columns1', 'other_columns2' ],
},
}
})

// 将自动提示绑定到change事件上,这样输入的时候就可以看到联想的关键词
this.editor.on('change', (instance, change) => {
// 自动补全的时候,也会触发change事件,所有坐下判断,以免死循环,正则是为了不让空格,换行之类的也提示
// 通过change对象你可以自定义一些规则去判断是否提示
if (change.origin !== 'complete' && /\w|\./g.test(change.text[0])) {
instance.showHint()
}
})
}

// 获取编辑器的内容,以便提交
getTextareaCode = () => this.editor.getValue()

}


效果如下:



自动提示的时候,当只有一个匹配选项
CodeMirror
会自动帮你选,这样会影响用户输入其他前几个字符一样的单词,导致无法编辑相应的词,所以应该让用户自己去选。改掉
源码
show-hint.js
中的选中逻辑。

finishUpdate: function(data, first) {
if (this.data) CodeMirror.signal(this.data, "update");

var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();

if (data && this.data && isNewCompletion(this.data, data)) return;
this.data = data;

if (data && data.list.length) {
// 将这几行注释掉
// if (picked && data.list.length == 1) {
//   this.pick(data, 0);
// } else {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
// }
}
}


CodeMirror
提供了很多内置的
API
,提高了可扩展性,可自定义
mode
,可自定义
hint
,等等,在此都不一一列举了。就整理这么多了,还有很多很多我没有涉及到的,欢迎补充,谢谢
^_^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CodeMirror