CodeMirror中文說明文檔

文檔大綱

本文檔並未完全翻譯完成,我需要你的幫助。前往GitHub編輯

自定義Mode

Mode 通常由一个 JavaScript 文件组成。 在最简单的情况下,该文件为编程语言定义了词法分析器(Token 生成器),该函数将字符流作为输入, 生成 token ,然后返回该 token 的样式。 更高级的 Mode 也可以处理该语言的缩进。

本节介绍了常用的 Mode 接口。 许多 Mode 直接参考本节编写,因为它有很多控制细节,但是为了快速开始,你可以基于 Demo 修改。

調用 CodeMirror.defineMode 向 CodeMirror 注册 Mode。 第一个参数为 Mode 的名称,应为小写的字符串,最好是 Mode 的文件名(如 "xml"xml.js 中定义)。 第二个参数是一个函数,该函数的第一个参数为 CodeMirror 配置对象(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 函數查找提供了支持。