11

是否可以在Codemirror Text Editor中显示隐藏字符(如回车字符),但我在其文档中没有找到任何关于它的配置参考。有可能这样做吗?

4

3 回答 3

4

这可以通过覆盖和带有空格和 EOL 符号的预定义样式的帮助来完成:

cm.addOverlay({
    name: 'invisibles',
    token:  function nextToken(stream) {
        var ret,
            spaces  = 0,
            peek    = stream.peek() === ' ';

        if (peek) {
            while (peek && spaces < Maximum) {
                ++spaces;

                stream.next();
                peek = stream.peek() === ' ';
            }

            ret = 'whitespace whitespace-' + spaces;
        } else {
            while (!stream.eol() && !peek) {
                stream.next();

                peek = stream.peek() === ' ';
            }

            ret = 'cm-eol';
        }

        return ret;
    }
});

为此,您可以使用插件CodeMirror Show Invisibles

于 2015-02-27T07:36:22.837 回答
3

回车由 CodeMirror 专门解释(当它自己时,它会创建一个换行符,当它在换行符前面时,它会被忽略),所以在这种情况下,不,你不能。

但其他非打印字符(例如\b)默认会显示为红点,您可以调整相关的 CSS 类cm-invalidchar来自定义它们的外观。

于 2013-10-09T10:43:12.050 回答
0

是的,您可以使用 overlay.js 和任何模式语言。只有您需要为您想要的每种模式定义叠加层,但所有模式都使用相同的 javascript 代码。

window.onload = function() {
  CodeMirror.defineMode("javascript-hidden-chars", function(config, parserConfig) {
    var alterList = ["alter1", "alter2"];
    var spacesCount = 0;
    var hiddenCharsOverlay = {
      token: function(stream, state) {
        if (stream.match(/(?= )/)) {
          let alterSpace = spacesCount++ % alterList.length;
          stream.eat(/ /);
          return `space special-chars ${alterList[alterSpace]}`;
        }
        while (stream.next() != null && !stream.match(" ", false)) {}
        return null;
      }
    };
    return CodeMirror.overlayMode(
      CodeMirror.getMode(
        config,
        parserConfig.backdrop || "javascript"
      ),
      hiddenCharsOverlay
    );
  });
  var editorSimple = CodeMirror(document.querySelector("#simple-parser"), {
    lineNumbers: true,
    lineWrapping: true,
    foldGutter: true,
    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
    mode: "javascript-hidden-chars",
    value: `// Demo code (the actual new parser character stream implementation)

function StringStream(string) {
  this.pos = 0;
  this.string = string;
}

StringStream.prototype = {
  done: function() {return this.pos >= this.string.length;},
  peek: function() {return this.string.charAt(this.pos);},
  next: function() {
    if (this.pos < this.string.length)
      return this.string.charAt(this.pos++);
  },
  eat: function(match) {
    var ch = this.string.charAt(this.pos);
    if (typeof match == "string") var ok = ch == match;
    else var ok = ch && match.test ? match.test(ch) : match(ch);
    if (ok) {this.pos++; return ch;}
  },
  eatWhile: function(match) {
    var start = this.pos;
    while (this.eat(match));
    if (this.pos > start) return this.string.slice(start, this.pos);
  },
  backUp: function(n) {this.pos -= n;},
  column: function() {return this.pos;},
  eatSpace: function() {
    var start = this.pos;
    while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
    return this.pos - start;
  },
  match: function(pattern, consume, caseInsensitive) {
    if (typeof pattern == "string") {
      function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
      if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
        if (consume !== false) this.pos += str.length;
        return true;
      }
    }
    else {
      var match = this.string.slice(this.pos).match(pattern);
      if (match && consume !== false) this.pos += match[0].length;
      return match;
    }
  }
};
`
  });
}
body {
  background: #4CB8C4;
  /* fallback for old browsers */
  background: -webkit-linear-gradient(to right, #3CD3AD, #4CB8C4);
  /* Chrome 10-25, Safari 5.1-6 */
  background: linear-gradient(to right, #3CD3AD, #4CB8C4);
  /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}

.container-editor {
  font-size: 15px;
}

.CodeMirror-code div:not(:last-child) .CodeMirror-line:after {
  content: "↵";
  text-align: center;
  opacity: 0.5;
  z-index: 1;
  height: inherit;
  position: absolute;
  white-space: nowrap;
  pointer-events: none;
}

.cm-special-chars,
.cm-tab {
  position: relative;
  opacity: 0.5;
}

.cm-special-chars:after,
.cm-tab:after {
  opacity: 0.4;
  text-align: center;
  left: 0;
  top: 0;
  width: 100%;
  position: absolute;
  overflow: hidden;
  white-space: nowrap;
  pointer-events: none;
}

.cm-space {
  white-space: break-spaces;
  word-break: break-all;
}

.cm-space:after {
  content: '·';
  width: inherit;
}

.cm-tab {
  white-space: pre-wrap;
}

.cm-tab:after {
  content: '<---';
  direction: rtl;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.1/codemirror.min.css" />
<link rel="stylesheet" href="https://codemirror.net/addon/fold/foldgutter.css" />

<div id="simple-parser" class="container-editor"></div>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.1/codemirror.min.js"></script>
<script type="text/javascript" src="https://codemirror.net/mode/javascript/javascript.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/mode/overlay.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/foldcode.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/foldgutter.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/comment-fold.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/indent-fold.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/brace-fold.js"></script>

于 2021-10-14T15:09:09.650 回答