【问题标题】:Codemirror: Own Module KeywordsCodemirror:自己的模块关键字
【发布时间】:2015-10-02 08:18:09
【问题描述】:

我尝试编写我的 owm 模块,为我们自己的 codemirror 脚本语言。我知道我挂在我们的关键字上。

我有这个测试代码:

Window(EditWin, SELECT_MULTIPLE, NO_SIZE, 310, 87, 500, 60, T("Sitzungsdatum", "Session date"))
{
     Prompt(SessionDatePmt, 11, 4, T("Sitzungsdatum", "Session date"))
     Date(SessionDate, 175, 4, 88)

     Button(SystemDateAsSessionDateBtn, 290, 3, 190, 10, T("Übernehme Systemdatum", "Get system date"))
     [ SELECT: SystemObject Call(SystemDate) PutObject(, SessionDate) ]
}

我们的一些关键字是:

  • 窗口
  • SELECT_MULTIPLE
  • NO_SIZE
  • 提示
  • 日期
  • 按钮
  • 选择
  • 系统对象
  • 致电
  • 放置对象

对于我的正则表达式,我使用了一个名为 cons 的数组,其中包含所有关键字。

然后我像这样加入所有数组条目:

var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))\\b");

直到那里一切正常。我得到的正则表达式在普通的 javascript match() 中工作。我什至使用 jQuery 获取我网站的文本,然后使用正则表达式,得到了我想要的。

但是,当我这样做时:

if (stream.match(keywordRegex)) return 'keyword';

在 Codemirror 中,SessionDate 的日期也是匹配的。

这是我的整个 Codemirror 模式:

(function(mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
        mod(require("../../lib/codemirror"));
    else if (typeof define == "function" && define.amd) // AMD
        define(["../../lib/codemirror"], mod);
    else // Plain browser env
        mod(CodeMirror);
})(function(CodeMirror) {
    "use strict";
    CodeMirror.defineMode("testmode", function() {
        var cons = ['Window', 'SELECT_MULTIPLE', 'NO_SIZE', 'PROMPT', 'Date', 'Button', 'Select', 'SystemObject', 'Call', 'PutObject'];
        var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))\\b");
        var numLiteral = /(-|\+)?([0-9]+(\.[0-9]*)?|0x[0-9a-f]+)/;
        return {
            token: function(stream, state) {
                if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))
                    return "string";


                if (stream.match(keywordRegex)) return 'keyword';
                if (stream.match(/({|})/)) return "bracket";
                if (stream.match(numLiteral)) return "number";
                if (stream.match(/(->)/)) return "arrow";


                stream.next();
                return null;
            },
            startState: function() {
              return {
                pair: false,
                pairStart: false,
                keyCol: 0,
                inlinePairs: 0,
                inlineList: 0,
                literal: false,
                escaped: false
              };
            }
        };
    });

    CodeMirror.defineMIME("application/testmode", "testmode");
});

编辑:

根据要求,这是一个工作的 plunker:

http://plnkr.co/edit/bPyuJd?p=preview

您可以看到,我没有关键字“SessionDate”,但是由于关键字“Date”,“SessionDate”的“Date”也被突出显示。

【问题讨论】:

  • 只是一个疯狂的猜测:您正在为每个令牌消耗一个字符一个字符.. keywordRegex(和所有其他)不应该锚定到 ^ 吗?
  • 我按要求添加了一个工作示例。字符串或行开头的“^”也不能解决我的问题:/但感谢您的尝试! :D
  • 试试var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))\\b(?![^()]*\\))");,它只会避免在圆括号内突出显示。不过,不确定您是否需要这个。
  • 感谢您的回答,但不,不完全是。当我有(EditWin, SELECT_MULTIPLE) 时,EditWin 应该是黑色的(未突出显示)并且 SELECT_MULTIPLE 应该作为关键字突出显示。如果我有 (Date, SessionDate) 之类的东西,那么 SessionDate 应该是 unhighlightet,但 Date 应该作为关键字突出显示。 \b 应该可以完成这项工作,但它在 codemirror 中不起作用。

标签: javascript regex codemirror codemirror-modes


【解决方案1】:

看来我找到了解决它的方法。有no support for anchors in Code Mirror

(^ 正则表达式标记不能像您期望的那样工作 由于 JavaScript 正则表达式的限制,此上下文 API。)

因此,使用 2 个正则表达式作为字符串开始条件和一个中间字符串位置,对于字符串开始位置,使用stream.sol() 检查位置:

var keywordRegex = new RegExp("("+cons.join("|")+")(?=\\W)");
var midkeywordRegex = new RegExp("\\W("+cons.join("|")+")(?=\\W)");

...

if (stream.sol() && stream.match(/('([^']|\\.)*'?|"([^"]|\\.)*"?)/))
    return "iv-string";

if (stream.sol() && stream.match(keywordRegex)) return 'keyword';
if (stream.match(midkeywordRegex)) return 'keyword';

Updated plunker

【讨论】:

  • 唯一的缺点是开头的非单词字符也会被高亮。如果它不是空格,那可能不太好,但我目前还没有办法让它变得更好。
  • 不错的收获! JavaScript 不允许的列表中又多了一项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
相关资源
最近更新 更多