<commit_before>{EventEmitter} = require 'events'
{Point, Range} = require 'atom'
HoleView = require './view/hole'
HoleBoundary = require './view/hole'


# A Hole has 2 kinds of views
# 1. the {! !} pair
# 2. the highlighting

class Hole extends EventEmitter

  startMarker: null
  endMarker: null

  oldStart: null
  oldEnd: null


  constructor: (@agda, @index, startIndex, endIndex) ->

    startLeft  = @oldStart = @fromIndex startIndex
    startRight             = @fromIndex (startIndex + 2)
    endLeft                = @fromIndex endIndex
    endRight   = @oldEnd   = @fromIndex (endIndex + 2)

    @startMarker = @agda.editor.markBufferRange new Range(startLeft, startRight),
      type: 'hole'
    @endMarker = @agda.editor.markBufferRange new Range(endLeft, endRight),
      type: 'hole'

    @startMarker.on 'changed', (event) =>
      changed = @trimMarker()
      if changed
        @emit 'resized', @getStart(), @getEnd()

    @endMarker.on 'changed', (event) =>
      changed = @trimMarker()
      if changed
        @emit 'resized', @getStart(), @getEnd()

    # view
    view = new HoleView @agda, @

    # kick off
    @emit 'resized', @getStart(), @getEnd()

  # with boundaries {! #$% !}
  getText:        -> @agda.editor.getTextInRange       new Range(@startMarker.bufferMarker.getStartPosition(), @endMarker.bufferMarker.getEndPosition())
  setText: (text) -> @agda.editor.setTextInBufferRange new Range(@startMarker.bufferMarker.getStartPosition(), @endMarker.bufferMarker.getEndPosition()), text
  setTextInRange: (text, range) -> @agda.editor.setTextInBufferRange range, text

  # without boundaries
  getContent:        -> @agda.editor.getTextInRange       new Range(@startMarker.bufferMarker.getEndPosition(), @endMarker.bufferMarker.getStartPosition())
  setContent: (text) -> @agda.editor.setTextInBufferRange new Range(@startMarker.bufferMarker.getEndPosition(), @endMarker.bufferMarker.getStartPosition()), text

  getStart: -> @startMarker.bufferMarker.getStartPosition()
  setStart: (startLeft) ->
    startRight = @translate startLeft, 2
    @startMarker.bufferMarker.setRange new Range startLeft, startRight

  getEnd: -> @endMarker.bufferMarker.getEndPosition()
  setEnd: (endRight) ->
    endLeft = @translate endRight, -2
    @endMarker.bufferMarker.setRange new Range endLeft, endRight


  getRange: ->
    start = @startMarker.bufferMarker.getStartPosition()
    end = @endMarker.bufferMarker.getEndPosition()
    new Range start, end

  setRange: (range) ->
    startRange = new Range range.start, @translate range.start, 2
    endRange   = new Range @translate range.end, -2, range.end

    @startMarker.setRange startRange
    @endMarker.setRange endRange

  # toIndex :: Position -> Character Index
  toIndex: (pos) -> @agda.editor.getBuffer().characterIndexForPosition pos

  # fromIndex :: Character Index -> Position
  fromIndex: (ind) -> @agda.editor.getBuffer().positionForCharacterIndex ind

  # trimMarker :: IO Changed
  #   recalculate the boundary of the marker
  trimMarker: ->
    text = @getText()


    # integrity of the boundaries
    newStartIndex = text.indexOf '{!'
    newEndIndex   = text.indexOf '!}'

    # the entire hole got destroyed, so be it
    if newStartIndex is -1 and newEndIndex is -1
      @emit 'destroyed'
      return true   # changed

    # attempt to damage boundaries, we should restore it
    else if newStartIndex is -1 or newEndIndex is -1
      @restoreBoundary()
      return false # not changed




    # determine if the marker doesn't match the boundary
    # if so, bend the marker back

    left  = text.indexOf('{!')
    right = text.length - text.indexOf('!}') - 2
    if left isnt 0
      @setStart(@translate @getStart(), left)

    if right isnt 0
      @setEnd(@translate @getEnd(), -right)

    # see if the boundaries really changed  (optimization stuff)
    newStart = @getStart()
    newEnd = @getEnd()

    # console.log '{!', @oldStart.toArray(), '=>', newStart.toArray()
    # console.log '!}', @oldEnd.toArray(), '=>', newEnd.toArray()
    changed = false

    if not @oldStart.isEqual newStart
      # console.log '{!', @oldStart.toArray(), '=>', newStart.toArray()
      @oldStart = newStart
      changed = true

    if not @oldEnd.isEqual newEnd
      # console.log '!}', @oldEnd.toArray(),   '=>', newEnd.toArray()
      @oldEnd = newEnd
      changed = true

    return changed

  restoreBoundary: ->
    @setTextInRange '{!', @startMarker.bufferMarker.range
    @setTextInRange '!}', @endMarker.bufferMarker.range

  removeBoundary: -> @setText @getContent().replace(/^\s\s*/, '').replace(/\s\s*$/, '')

  destroy: ->
    @startMarker.destroy()
    @endMarker.destroy()

    @emit 'destroyed'


  # respecests character index
  translate: (pos, n) -> @fromIndex((@toIndex pos) + n)


module.exports = Hole<commit_msg>content accessing now stripes trailing spaces<commit_after>{EventEmitter} = require 'events'
{Point, Range} = require 'atom'
HoleView = require './view/hole'
HoleBoundary = require './view/hole'


# A Hole has 2 kinds of views
# 1. the {! !} pair
# 2. the highlighting

class Hole extends EventEmitter

  startMarker: null
  endMarker: null

  oldStart: null
  oldEnd: null


  constructor: (@agda, @index, startIndex, endIndex) ->

    startLeft  = @oldStart = @fromIndex startIndex
    startRight             = @fromIndex (startIndex + 2)
    endLeft                = @fromIndex endIndex
    endRight   = @oldEnd   = @fromIndex (endIndex + 2)

    @startMarker = @agda.editor.markBufferRange new Range(startLeft, startRight),
      type: 'hole'
    @endMarker = @agda.editor.markBufferRange new Range(endLeft, endRight),
      type: 'hole'

    @startMarker.on 'changed', (event) =>
      changed = @trimMarker()
      if changed
        @emit 'resized', @getStart(), @getEnd()

    @endMarker.on 'changed', (event) =>
      changed = @trimMarker()
      if changed
        @emit 'resized', @getStart(), @getEnd()

    # view
    view = new HoleView @agda, @

    # kick off
    @emit 'resized', @getStart(), @getEnd()

  # with boundaries {! #$% !}
  getText:        -> @agda.editor.getTextInRange       new Range(@startMarker.bufferMarker.getStartPosition(), @endMarker.bufferMarker.getEndPosition())
  setText: (text) -> @agda.editor.setTextInBufferRange new Range(@startMarker.bufferMarker.getStartPosition(), @endMarker.bufferMarker.getEndPosition()), text
  setTextInRange: (text, range) -> @agda.editor.setTextInBufferRange range, text

  # without boundaries and spaces
  getContent: ->
    content = @agda.editor.getTextInRange new Range(@startMarker.bufferMarker.getEndPosition(), @endMarker.bufferMarker.getStartPosition())
    return content.replace(/^\s\s*/, '').replace(/\s\s*$/, '')
  setContent: (text) ->
    text = text.replace(/^\s\s*/, '').replace(/\s\s*$/, '')
    @agda.editor.setTextInBufferRange new Range(@startMarker.bufferMarker.getEndPosition(), @endMarker.bufferMarker.getStartPosition()), text

  getStart: -> @startMarker.bufferMarker.getStartPosition()
  setStart: (startLeft) ->
    startRight = @translate startLeft, 2
    @startMarker.bufferMarker.setRange new Range startLeft, startRight

  getEnd: -> @endMarker.bufferMarker.getEndPosition()
  setEnd: (endRight) ->
    endLeft = @translate endRight, -2
    @endMarker.bufferMarker.setRange new Range endLeft, endRight


  getRange: ->
    start = @startMarker.bufferMarker.getStartPosition()
    end = @endMarker.bufferMarker.getEndPosition()
    new Range start, end

  setRange: (range) ->
    startRange = new Range range.start, @translate range.start, 2
    endRange   = new Range @translate range.end, -2, range.end

    @startMarker.setRange startRange
    @endMarker.setRange endRange

  # toIndex :: Position -> Character Index
  toIndex: (pos) -> @agda.editor.getBuffer().characterIndexForPosition pos

  # fromIndex :: Character Index -> Position
  fromIndex: (ind) -> @agda.editor.getBuffer().positionForCharacterIndex ind

  # trimMarker :: IO Changed
  #   recalculate the boundary of the marker
  trimMarker: ->
    text = @getText()


    # integrity of the boundaries
    newStartIndex = text.indexOf '{!'
    newEndIndex   = text.indexOf '!}'

    # the entire hole got destroyed, so be it
    if newStartIndex is -1 and newEndIndex is -1
      @emit 'destroyed'
      return true   # changed

    # attempt to damage boundaries, we should restore it
    else if newStartIndex is -1 or newEndIndex is -1
      @restoreBoundary()
      return false # not changed




    # determine if the marker doesn't match the boundary
    # if so, bend the marker back

    left  = text.indexOf('{!')
    right = text.length - text.indexOf('!}') - 2
    if left isnt 0
      @setStart(@translate @getStart(), left)

    if right isnt 0
      @setEnd(@translate @getEnd(), -right)

    # see if the boundaries really changed  (optimization stuff)
    newStart = @getStart()
    newEnd = @getEnd()

    # console.log '{!', @oldStart.toArray(), '=>', newStart.toArray()
    # console.log '!}', @oldEnd.toArray(), '=>', newEnd.toArray()
    changed = false

    if not @oldStart.isEqual newStart
      # console.log '{!', @oldStart.toArray(), '=>', newStart.toArray()
      @oldStart = newStart
      changed = true

    if not @oldEnd.isEqual newEnd
      # console.log '!}', @oldEnd.toArray(),   '=>', newEnd.toArray()
      @oldEnd = newEnd
      changed = true

    return changed

  restoreBoundary: ->
    @setTextInRange '{!', @startMarker.bufferMarker.range
    @setTextInRange '!}', @endMarker.bufferMarker.range

  removeBoundary: -> @setText @getContent()

  destroy: ->
    @startMarker.destroy()
    @endMarker.destroy()

    @emit 'destroyed'


  # respecests character index
  translate: (pos, n) -> @fromIndex((@toIndex pos) + n)


module.exports = Hole
{'fraction_non_alphanumeric': 0.1317267435923619, 'fraction_numerical': 0.003267640151128357, 'mean_word_length': 3.318342151675485, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 57, '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': '4462774', 'n_tokens_mistral': 3061, 'n_tokens_neox': 2930, 'n_words': 766}