Ace Editor:锁定或只读代码段

Posted

技术标签:

【中文标题】Ace Editor:锁定或只读代码段【英文标题】:Ace Editor: Lock or Readonly Code Segment 【发布时间】:2014-09-17 11:26:52 【问题描述】:

使用 Ace 代码编辑器可以锁定或只读一段代码,但仍允许在会话期间编写或编辑其他代码行吗?

【问题讨论】:

您只需要一段还是多段?可以删除整个段吗?如果选择包括部分只读段并且用户按下删除,是否应该删除其余选定文本? 【参考方案1】:

这是解决方案的开始:

$(function() 
    var editor     = ace.edit("editor1")
        , session  = editor.getSession()
        , Range    = require("ace/range").Range
        , range    = new Range(1, 4, 1, 10)
        , markerId = session.addMarker(range, "readonly-highlight");

    session.setMode("ace/mode/javascript");
    editor.keyBinding.addKeyboardHandler(
        handleKeyboard : function(data, hash, keyString, keyCode, event) 
            if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;

            if (intersects(range)) 
                return command:"null", passEvent:false;
            
        
    );

    before(editor, 'onPaste', preventReadonly);
    before(editor, 'onCut',   preventReadonly);

    range.start  = session.doc.createAnchor(range.start);
    range.end    = session.doc.createAnchor(range.end);
    range.end.$insertRight = true;

    function before(obj, method, wrapper) 
        var orig = obj[method];
        obj[method] = function() 
            var args = Array.prototype.slice.call(arguments);
            return wrapper.call(this, function()
                return orig.apply(obj, args);
            , args);
        

        return obj[method];
    

    function intersects(range) 
        return editor.getSelectionRange().intersects(range);
    

    function preventReadonly(next, args) 
        if (intersects(range)) return;
        next();
    
);

看到它在这个小提琴中工作:http://jsfiddle.net/bzwheeler/btsxgena/

主要工作部分是:

    创建开始和结束 ace 锚点,以跟踪“只读”部分的位置,因为它周围的文档发生变化。 创建一个范围来封装锚点 添加自定义键处理程序以检查当前即将发生的按键是否会影响只读范围,如果是,则取消它。 添加自定义粘贴/剪切处理程序以防止右键单击菜单和浏览器菜单剪切/粘贴操作

【讨论】:

我无法理解 'before' 函数中发生了什么,但我知道 'origArgs' 从未定义过,并且在尝试调用 next() 之后会导致 'preventReadOnly' 呕吐剪切或粘贴。 好收获!我编辑了 before() 实现以使用 .call 并传递 args 而不是 origArgs,正如您所注意到的那样,它是未定义的。 addKeyboardHandler 在这里做什么?请解释一下。 如何使多行只读。通过传递数组范围,即开始和结束。【参考方案2】:

您可以通过监听exec 事件来做到这一点:

// Prevent editing first and last line of editor
editor.commands.on("exec", function(e)  
  var rowCol = editor.selection.getCursor();
  if ((rowCol.row === 0) || ((rowCol.row + 1) === editor.session.getLength())) 
    e.preventDefault();
    e.stopPropagation();
  
);

来源:https://jsfiddle.net/tripflex/y0huvc1b/

【讨论】:

虽然这种方法既好又简单,但它的主要问题是它不会阻止您删除第一行和第二行之间的换行符,从而无法在此之后进行编辑。此外,如果您使用箭头键移动光标,它会卡在第一行和最后一行。【参考方案3】:

我建议使用其他更简单、更可靠的方法来防止修改范围(检查一下!)

var old$tryReplace = editor.$tryReplace;
editor.$tryReplace = function(range, replacement) 
    return intersects(range)?null:old$tryReplace.apply(this, arguments);                        

var session = editor.getSession();
var oldInsert = session.insert;
session.insert = function(position, text) 
    return oldInsert.apply(this, [position, outsideRange(position)?text:""]);

var oldRemove = session.remove;
session.remove = function(range) 
    return intersects(range)?false:oldRemove.apply(this, arguments);                        

var oldMoveText = session.moveText;
session.moveText = function(fromRange, toPosition, copy) 
    if (intersects(fromRange) || !outsideRange(toPosition)) return fromRange;
    return oldMoveText.apply(this, arguments)


outsideRange = function (position) 
    var s0 = range.start;
    if (position.row < s0.row || (position.row == s0.row && position.column <= s0.column)) return true; // position must be before range.start
    var e0 = range.end;
    if (position.row > e0.row || (position.row == e0.row && position.column >= e0.column)) return true; // or after range.end
    return false;

intersects = function(withRange) 
    var e = withRange.end, s0 = range.start, s = withRange.start, e0 = range.end;
    if (e.row < s0.row || (e.row == s0.row && e.column <= s0.column)) return false; // withRange.end must be before range.start
    if (s.row > e0.row || (s.row == e0.row && s.column >= e0.column)) return false; // or withRange.start must be after range.end
    return true;

【讨论】:

以上是关于Ace Editor:锁定或只读代码段的主要内容,如果未能解决你的问题,请参考以下文章

适当使用同步或锁定一段代码

程序段详解

ACE Editor 常用Api

python测试开发django -144.Ace Editor 在线编辑python代码

给定文件扩展名,如何为 Ace Editor 自动选择“模式”

vue2-ace-editor代码编辑器使用