CodeMirror 中文用户手册

目录

本文档并未完全翻译完成,我需要你的帮助。前往GitHub编辑

自定义Mode

一种语言的 Mode 通常由一个 JavaScript 文件来定义。
Mode 要实现的基本功能是:根据输入的字符串解析出 Token,并说明与之对应的 CSS 样式。
更完善的 Mode 还能处理缩进。

本章介绍了最基础的 Mode 接口。
为了快速上手,你可以基于 简易 Demo 修改。

可以调用 CodeMirror.defineMode 函数来向 CodeMirror 注册一个 Mode。
第一个参数是 Mode 的名称,应该是由小写字母组成的字符串,最好是 Mode 的文件名(如名:"xml",文件:xml.js)。
第二个参数是一个函数,该函数的第一个参数为 CodeMirror 构造函数的配置对象, 该函数的第二个可选参数为 Mode 的配置对象(如 mode),返回值为 Mode 对象。

通常,应该将 defineMode 函数的第二个参数作为 Mode 的作用域(Mode 不应暴露任何内容给全局),即在该函数内完成整个 Mode 的编写。

Mode 的主要工作是解析编辑器的内容。Mode 的复杂度取决于语言和所需功能的复杂度。 有些解析器可能是无状态的,表示一次只查看代码的一个元素(token),没有任何记忆。然而,通常都需要记住一些东西。 这是通过使用 state 对象实现的,在读取 token 时会被传递,并且 token 生成器可以对其进行更改。

使用 status 的 Mode 必须在其对象上定义 startState 函数。 该函数没有参数,生成在文档开头处使用的 status 对象。

Mode 对象最重要的部分是 token(stream, state) 函数。               所有 Mode 都必须定义此方法。 该函数从 stream 参数中提取 token,可选的更新状态,并返回样式字符串,或 null 表示 token 无需样式。 对于返回的样式字符串,建议使用在主题中定义的 'standard' 名(带有 cm- 前缀)。 如果主题中没有,你也可以编写新的CSS文件来自定义。

token 一般是类似 "variable""comment" 的字符串。 可以返回多种样式(用空格分隔),例如,对于看起来像字符串但又不像的(例如,缺少其右引号),可以使用 "string error" 。 当以 "line-""line-background-" 作为前缀时,该样式将作用于整行, 类似 addLineClass 函数, 在 "line-" 时为 "text" 设置样式, 在 "line-background-" 时为 "background" 设置样式。

token 函数的 stream 对象封装了一行的源码(token 不会跨行)和当前位置。提供以下API:

eol() → boolean
当 stream 在行尾时返回 true。
sol() → boolean
当 stream 在行首时返回 true。
peek() → string
返回流中的下一个字符但不前进下标。在行尾时返回 null
next() → string
返回流中的下一个字符且前进下标。在该行没有剩余字符时返回 null
eat(match: string|regexp|function(char: string) → boolean) → string
match 可以是字符串、正则表达式或一个参数为字符串并返回 boolean 值的函数。 如果 stream 中的下一个字符与参数项匹配,将会被消耗掉并返回。否则返回 undefined
eatWhile(match: string|regexp|function(char: string) → boolean) → boolean
重复调用 eat 直到截止。当所有的单词都被消耗掉后返回 true。
eatSpace() → boolean
eatWhile 匹配空格的快捷函数。
skipToEnd()
移动当前位置到行尾。
skipTo(str: string) → boolean
如果再当前行上找到指定的字符,则跳转到下个字符的开始位置(如果没有找到则不跳转)。找到时返回 true。
match(pattern: string, ?consume: boolean, ?caseFold: boolean) → boolean
match(pattern: regexp, ?consume: boolean) → array<string>
consume 为 true 时,类似多字符的 eat 函数, 为 false 或未指定时,不会更新 stream 的位置。 pattern 可以是字符串或由 ^ 开头的正则表达式。 当为字符串时,caseFold 为 true 时则不区分大小写。 当为正则表达式时,match 的返回值是一个数组,可以用来提取匹配结果。
backUp(n: integer)
后退 n 个字符。 后退超过当前 token 的开始位置时会导致终端,请当心。
column() → integer
返回当前 token 开始位置的列。
indentation() → integer
返回当前行缩进的数量(以空格为单位),不是 tab 符号。
current() → string
返回当前 token 开始位置到当前 stream 位置之间的字符串。
lookAhead(n: number) → ?string
返回当前行后的 n (>0) 行,用来跨行扫描。 注意:你需要小心地使用该函数,跨太多的行会降低 Mode 状态的缓存效率。
baseToken() → ?{type: ?string, size: number}
通过 addOverlay 函数添加的 Mode 可以使用该函数来检查当前Mode 下的 Token 。

默认情况下,解析文档时会跳过空白行。 对于具有大量空白行的语言,您可以在模式中定义一个 blankLine(state) 函数,每当遇到空白行时都会调用该方法,用来更新解析器状态。

因为状态对象是可变的,所以CodeMirror会保留所有有效的状态副本,以便在任意行上重新解析。 使用的默认算法是,在创建一个新的状态对象时从旧对象继承所有属性。 所有值为数组的属性都会被复制(因为数组倾向于用作可变堆栈)。 当这不正确时(例如,由数组变成非数组时),Mode 对象应定义一个 copyState 方法,来实现安全复制。

如果希望 Mode 提供智能缩进 (通过 indentLine 函数以及 indentAutonewlineAndIndent 命令,绑定额外的快捷键。), 则必须在 Mode 对象上定义一个 indent(state, textAfter) 函数。

缩进方法应检查 state 对象,并可选检查 textAfter 字符串,该字符串包含要缩进的行上的文本,并返回一个数字,即要缩进的空格量。 通常应该考虑 indentUnit 选项。 缩进方法可以返回 CodeMirror.Pass 来说明无法提供精确的缩进。

为了与注释插件良好配合,Mode 可以定义 lineComment(开始行注释的字符串), blockCommentStartblockCommentEnd(开始和结束注释的字符串) 和 blockCommentLead(在注释快中新增注释行的头部注释字符串)。 所有这些都是可选的。

最后,Mode 可以定义 electricCharselectricInput 属性, 当键入某些单词并启用 electricChars 选项时,会自动重新缩进行。 electricChars 可以是一个字符串,当键入该字符串中的任意字符时,都会触发重新缩进。 通常,更合适的方法是使用 electricInput,它应该包含一个正则表达式,在该行光标之前的部分与正则表达式匹配时触发缩进。 它通常应以 $ 字符结尾,以便在与正则相匹配的字符刚被输入时触发,而不是在输入之后触发。

因此,总而言之,模式必须提供 token 函数, 并且它可以提供 startStatecopyStateindent 函数。 参考 mode/diff/diff.js,和更复杂的 mode/clike/clike.js

将一个 Mode 的功能委托给另外一个 Mode 实现,对于 Mode 嵌套很有用。 参考 HTML 混合 Mode mode/htmlmixed/htmlmixed.js。 这种模式的一个示例是混合模式HTML模式。 要实现这种嵌套,通常必须自己创建 Mode 对象并复制 State。 要创建模式对象,请使用 CodeMirror.getMode(options, parserConfig) 函数, 第一个参数与 Mode 构造函数一样的配置对象, 第二个参数与 mode 配置相同。 若要复制状态对象,请调用CodeMirror.copyState(mode, state),其中mode 基于 state 创建的。

在嵌套 Mode 下,建议添加 innerMode 方法,给定一个状态对象, 返回一个 {state, mode} 对象,具有内部 Mode 及其当前位置状态。 工具类如 tag closer 会用来获取上下文信息。 使用 CodeMirror.innerMode 辅助函数,从一个模式和一个状态开始,递归到最底层的Mode和state。

为了在嵌套解析器中正确缩进,建议为打算嵌套的 Mode 的 startState 函数提供一个可选参数,为代码块提供基本缩进。 JavaScript和CSS解析器执行此操作,例如,以使 HTML 混合 Mode 内的JavaScript和CSS代码正确缩进。

鼓励将您的 Mode 或您的 Mode 的特定配置与 MIME 相关联。 例如,JavaScript Mode 与 text/javascript 关联,并将其 JSON 变体与 application/json 关联。 为此,请调用 CodeMirror.defineMIME(mime, modeSpec), 其中 modeSpec 可以是 Mode 的字符串或对象,如 mode 选项中所示。

如果想要为 Mode 对象增加属性(通常与 getHelpers 一起使用), 则它应该包含 modeProps 属性,包含一个对象。 该对象的属性将被复制到实际 Mode 对象。

有时,从外部代码添加或覆盖 Mode 对象的属性很有用。 CodeMirror.extendMode 函数可为 Mode 对象添加属性来生成具体的 Mode。 它的第一个参数是 Mode 的名称,第二个参数需要添加的属性的对象。 这为以后通过 getMode 函数查找提供了支持。