<commit_before>#= underscore
#= require rangy/rangy-core
#= require tandem/position

class TandemRange
  @getNativeSelection: (editor) ->
    rangySel = rangy.getSelection(editor.iframe.contentWindow)
    return null unless rangySel.anchorNode? && rangySel.focusNode?
    if !rangySel.isBackwards()
      [anchorNode, anchorOffset, focusNode, focusOffset] = [rangySel.anchorNode, rangySel.anchorOffset, rangySel.focusNode, rangySel.focusOffset]
    else
      [focusNode, focusOffset, anchorNode, anchorOffset] = [rangySel.anchorNode, rangySel.anchorOffset, rangySel.focusNode, rangySel.focusOffset]
    return {
      anchorNode    : anchorNode
      anchorParent  : anchorNode.parentNode
      anchorOffset  : anchorOffset
      focusNode     : focusNode
      focusParent   : focusNode.parentNode
      focusOffset   : focusOffset
    }

  @getSelection: (editor) ->
    nativeSel = TandemRange.getNativeSelection(editor)
    return null unless nativeSel?
    start = new Tandem.Position(editor, nativeSel.anchorNode, nativeSel.anchorOffset)
    end = new Tandem.Position(editor, nativeSel.focusNode, nativeSel.focusOffset)
    return new TandemRange(editor, start, end)

  @setSelection: (editor, range) ->
    rangySel = rangy.getSelection(editor.iframe.contentWindow)
    rangySelRange = range.getRangy()
    rangySel.setSingleRange(rangySelRange)



  # constructor: (TandemEditor editor, Number startIndex, Number endIndex) ->
  # constructor: (TandemEditor editor, Object start, Object end) ->
  constructor: (@editor, @start, @end) ->
    # TODO initialize with index
    @start = new Tandem.Position(@editor, @start) if _.isNumber(@start)
    @end = new Tandem.Position(@editor, @end) if _.isNumber(@end)

  equals: (range) ->
    return false unless range?
    return range.start.leafNode == @start.leafNode && range.end.leafNode == @end.leafNode && range.start.offset == @start.offset && range.end.offset == @end.offset
      
  getAttributeIntersection: (ignoreValue = false) ->
    startLeaf = this.start.getLeaf()
    endLeaf = this.end.getLeaf()
    # TODO Fix race condition that makes check necessary... should always be able to return attribute intersection
    return {} if !startLeaf? || !endLeaf?
    if this.isCollapsed()
      return startLeaf.getAttributes()
    leaves = this.getLeaves()
    leaves.pop() if leaves.length > 0 && @end.offset == 0
    leaves.splice(0, 1) if leaves.length > 0 && @start.offset == leaves[0].text.length
    attributes = if leaves.length > 0 then leaves[0].getAttributes() else {}
    _.all(leaves, (leaf) ->
      _.each(attributes, (value, key) ->
        delete attributes[key] if leaf.attributes[key] != value && !ignoreValue<commit_msg>distinguish between mixed value and missing value<commit_after>#= underscore
#= require rangy/rangy-core
#= require tandem/position

class TandemRange
  @getNativeSelection: (editor) ->
    rangySel = rangy.getSelection(editor.iframe.contentWindow)
    return null unless rangySel.anchorNode? && rangySel.focusNode?
    if !rangySel.isBackwards()
      [anchorNode, anchorOffset, focusNode, focusOffset] = [rangySel.anchorNode, rangySel.anchorOffset, rangySel.focusNode, rangySel.focusOffset]
    else
      [focusNode, focusOffset, anchorNode, anchorOffset] = [rangySel.anchorNode, rangySel.anchorOffset, rangySel.focusNode, rangySel.focusOffset]
    return {
      anchorNode    : anchorNode
      anchorParent  : anchorNode.parentNode
      anchorOffset  : anchorOffset
      focusNode     : focusNode
      focusParent   : focusNode.parentNode
      focusOffset   : focusOffset
    }

  @getSelection: (editor) ->
    nativeSel = TandemRange.getNativeSelection(editor)
    return null unless nativeSel?
    start = new Tandem.Position(editor, nativeSel.anchorNode, nativeSel.anchorOffset)
    end = new Tandem.Position(editor, nativeSel.focusNode, nativeSel.focusOffset)
    return new TandemRange(editor, start, end)

  @setSelection: (editor, range) ->
    rangySel = rangy.getSelection(editor.iframe.contentWindow)
    rangySelRange = range.getRangy()
    rangySel.setSingleRange(rangySelRange)



  # constructor: (TandemEditor editor, Number startIndex, Number endIndex) ->
  # constructor: (TandemEditor editor, Object start, Object end) ->
  constructor: (@editor, @start, @end) ->
    # TODO initialize with index
    @start = new Tandem.Position(@editor, @start) if _.isNumber(@start)
    @end = new Tandem.Position(@editor, @end) if _.isNumber(@end)

  equals: (range) ->
    return false unless range?
    return range.start.leafNode == @start.leafNode && range.end.leafNode == @end.leafNode && range.start.offset == @start.offset && range.end.offset == @end.offset
      
  getAttributeIntersection: (ignoreValue = false) ->
    startLeaf = this.start.getLeaf()
    endLeaf = this.end.getLeaf()
    # TODO Fix race condition that makes check necessary... should always be able to return attribute intersection
    return {} if !startLeaf? || !endLeaf?
    if this.isCollapsed()
      return startLeaf.getAttributes()
    leaves = this.getLeaves()
    leaves.pop() if leaves.length > 0 && @end.offset == 0
    leaves.splice(0, 1) if leaves.length > 0 && @start.offset == leaves[0].text.length
    attributes = if leaves.length > 0 then leaves[0].getAttributes() else {}
    _.all(leaves, (leaf) ->
      _.each(attributes, (value, key) ->
        attributes[key] = 'mixed' if leaf.attributes[key] != value && !ignoreValue
{'fraction_non_alphanumeric': 0.1154058531198233, 'fraction_numerical': 0.0029449659488312166, 'mean_word_length': 3.8345195729537367, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2708719', 'n_tokens_mistral': 1709, 'n_tokens_neox': 1616, 'n_words': 391}