代码镜像的新模式:检测流中的空行

new mode for codemirror : Detecting an empty line in a stream

本文关键字:检测 模式 新模式 镜像 代码      更新时间:2023-09-26

我正在尝试为代码镜像开发一个简单的模式。此模式将为段落交替涂上蓝色和绿色。段落之间的分隔是空行或只包含空格的行。

这是一个有效的代码版本,但有一个大问题是没有检测到空行:

CodeMirror.defineMode("rt", function() {
  return {
    startState: function() {return {state1: true};},
    token: function(stream, state) {
    if (stream.match(/'s's*/)!=null){ # this fails to detect empty lines
        state.state1 = !state.state1;
    }
    stream.skipToEnd();
    if (state.state1)  { return "status1"; } 
    return "status2";
    }
  };
});

如果我将其应用于以下文本:

line 1
line 2 # the next line is just a backspace and is not detected
line 3
line 4 # the next line is a few spaces followed by a backspace, it is detected
line 5
line 6

它以一种颜色从第1行到第4行以及以另一种颜色为第5行到第6行着色。

我正试图找到一种方法来更新我的代码,以便它检测第2行和第3行之间的空行。有办法做到这一点吗?

您可以在javascript regexp中使用['b]检测退格:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

BTW /'s's*/可以简化为/'s+/,但如果您想检测"空行或仅包含空格的行",则可以使用/'s*/

此外,如果您不关心正则表达式的实际结果数组,则可以使用test():https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test

您可以使用^来指示行的开始,使用$来指示行结束。

因此,代码将是大致,如下所示:

CodeMirror.defineMode("rt", function() {
  return {
    startState: function() {
      return {
        state1: true
      };
    },
    token: function(stream, state) {
      if ( /^'s*$/m.test(stream) ) {
        state.state1 = !state.state1;
      }
      stream.skipToEnd();
      return state.state1 ? "status1" : "status2";
    }
  };
});

m标志用于指定多行输入字符串应被视为多行。如果使用m标志,^和$在输入字符串中任何一行的开头或结尾匹配,而不是在整个字符串的开头或末尾匹配。示例:http://www.w3schools.com/jsref/jsref_regexp_m.asp

codemirror的文档说明:

默认情况下,标记文档时会跳过空行。对于具有重要空行的语言,可以定义blankLine(state)方法,只要空行被传递,以便它可以更新解析器状态。

(http://codemirror.net/doc/manual.html#modeapi)

以下代码有效(添加了blankLine函数):

CodeMirror.defineMode("rt", function() {
  return {
    startState: function() {return {state1: true};},
    blankLine: function (state){ state.state1 = !state.state1; },
    token: function(stream, state) {
    console.log(stream)
    if (stream.match(/^'s*$/)!=null){
        state.state1 = !state.state1;
    }
    stream.skipToEnd();
    if (state.state1)  { return "status1"; } 
    return "status2";
    }
  };
});