如何使用 ACE 编辑器突出显示代码?

Posted

技术标签:

【中文标题】如何使用 ACE 编辑器突出显示代码?【英文标题】:How can I highlight code with ACE editor? 【发布时间】:2012-02-08 13:54:00 【问题描述】:

我想用语法高亮显示十几个小的 sn-ps 代码,然后通过单击它们使它们可使用 ACE Editor 进行编辑,因为我认为这比为每个代码设置完整的编辑器要快得多。我看到有一个simple command for setting up an ACE editor:

<div id="editor">some text</div>
<script src="src/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
window.onload = function() 
    var editor = ace.edit("editor");
;
</script>

有没有一种简单的方法来调用 API 以仅突出显示文本而不设置编辑器?理想的 API 会接收一些文本并返回带有可用于突出显示的标签的 html。我知道有专门的 JavaScript 突出显示库,但我想尝试对正在显示的文本和正在编辑的文本使用相同的荧光笔。

【问题讨论】:

Ace Editor 具有只读模式,基本上只显示编辑器,但您仍然会得到完整编辑器的开销。不过,速度并不是一个大问题——更多的是编辑器的大小。我用它在一些网站上进行编辑和显示,效果很好。 @RickStrahl 我很高兴知道如何设置只读模式。因为我能找到的最接近的例子是static_highlight,但它使用了 kitchensink 框架。我会更喜欢像editor.mode = readonly 这样的单行。 【参考方案1】:

突出显示单词:

var range = new Range(rowStart, columnStart, rowEnd, columnEnd);
var marker = editor.getSession().addMarker(range,"ace_selected_word", "text");

删除突出显示的单词:

editor.getSession().removeMarker(marker);

突出显示该行:

editor.getSession().addMarker(range,"ace_active_line","background");

【讨论】:

【参考方案2】:

首先,您要将行号声明为全局变量。

var erroneousLine;

这是 highlightError 函数,它以行号 (lineNumber) 作为其参数。这可以从错误消息或使用editor.selection.getCursor().row 获取当前行或其他内容触发。

function highlightError(lineNumber) 
  unhighlightError();
  var Range = ace.require("ace/range").Range
  erroneousLine = editor.session.addMarker(new Range(lineNumber, 0, lineNumber, 144), "errorHighlight", "fullLine");

请注意,我已经声明了errorHighlight,这就是突出显示的方式。在您的 CSS 中放置以下内容:

.errorHighlight
  position:absolute;
  z-index:20;
  background-color:#F4B9B7;

这个函数取消高亮已经高亮的行

function unhighlightError()
  editor.getSession().removeMarker(erroneousLine);

【讨论】:

【参考方案3】:

有一个服务器端版本的荧光笔(在 node.js 中运行)available,很可能很容易移植到基于 Web 的 javascript。

【讨论】:

【参考方案4】:

一个想法:

function highlightSyntax(text) 
    var res = [];

    var Tokenizer = ace.require('ace/tokenizer').Tokenizer;
    var Rules = ace.require('ace/mode/sql_highlight_rules').SqlHighlightRules;
    var Text = ace.require('ace/layer/text').Text;

    var tok = new Tokenizer(new Rules().getRules());
    var lines = text.split('\n');

    lines.forEach(function(line) 
      var renderedTokens = [];
      var tokens = tok.getLineTokens(line);

      if (tokens && tokens.tokens.length) 
        new Text(document.createElement('div')).$renderSimpleLine(renderedTokens, tokens.tokens);
      

      res.push('<div class="ace_line">' + renderedTokens.join('') + '</div>');
    );

    return '<div class="ace_editor ace-tomorrow"><div class="ace_layer" style="position: static;">' + res.join('') + '</div></div>';

此函数应在给定文本中突出显示 SQL 语法(ace-tomorrow 主题),而无需加载整个编辑器,也无需装订线。

【讨论】:

从 1.4.8 版开始仍然有效,但只需更改您要添加子元素的 HTML 元素的 renderedTokens 数组。 看起来很有希望,但在最新版本的 Ace 中,我得到了 Uncaught TypeError: e.appendChild is not a function【参考方案5】:

我认为这已经很晚了,但我仍然会写,以防它可以帮助别人。

我最终在 typescript 中创建了一个简单的函数,它可以找到要突出显示的范围的坐标并滚动到它:

highlighText(text: string) 
    const value = this.aceEditor.session.getValue();
    const startRow = value.substr(0, value.indexOf(text)).split(/\r\n|\r|\n/).length - 1;
    const startCol = this.aceEditor.session.getLine(startRow).indexOf(text);
    const endRowOffset = text.split(/\r\n|\r|\n/).length;
    const endRow = startRow + endRowOffset - 1;
    const endCollOffset = text.split(/\r\n|\r|\n/)[endRowOffset - 1].length;
    const endCol = startCol + (endCollOffset > 1 ? endCollOffset + 1 : endCollOffset);
    const range = new ace.Range(startRow, startCol, endRow, endCol);

    this.aceEditor.session.selection.setRange(range);
    this.aceEditor.scrollToLine(startRow, true, true, () => );
  

【讨论】:

以上是关于如何使用 ACE 编辑器突出显示代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ACE 编辑器中突出显示某行?

Ace Editor 选择的文本未正确突出显示

在不选择整个编辑器的情况下为 ace 编辑器设置值

如何在文本突出显示期间保留语法突出显示

如何仅突出显示最后编辑的行?

确定 JavaScript 语法在 ACE 的更改处理程序中是不是有效