2014-07-25 84 views
15

使用Ace代碼編輯器可以鎖定或只讀一段代碼,但仍允許在會話期間寫入或編輯其他代碼行?王牌編輯器:鎖定或只讀代碼段

+0

你只需要一段或多段?可以將完整的分段刪除?如果選擇包括只讀段的一部分並且用戶按下刪除,那麼所選文本的其餘部分是否應該刪除? –

+0

我也需要這個功能! – ufucuk

回答

20

這裏是一個解決方案的開始:

$(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/

的主要工作部件是:

  1. 創建開始和結束的王牌主播其追蹤「只讀」部分的位置,因爲其周圍的文檔發生變化。
  2. 創建一個範圍來封裝錨點
  3. 添加一個自定義的keyhandler來檢查當前即將發生的按鍵是否會影響只讀範圍並取消它,如果是的話。
  4. 添加自定義粘貼/剪切處理,以防止右鍵菜單和瀏覽器菜單中選擇剪切/粘貼操作
+0

我很難理解'before'函數中發生了什麼,但是我知道'origArgs'從來沒有定義過,並且導致'preventReadOnly'在試圖在剪切或粘貼後調用next()時發出嘔吐。 – Southerneer

+0

好抓!我編輯了before()實現,使用'.call'並傳遞'args',而不是像您注意到的那樣未定義的'origArgs'。 – bzwheeler

+0

addKeyboardHandler在這裏做什麼?請解釋一下。 – rjohari23

1

我建議別的東西更方便,更可靠的防止範圍進行修改(檢查它!)

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; 
}