<commit_before>{CompositeDisposable, Range, TextBuffer} = require 'atom'
_ = require 'underscore-plus'
TextManipulation = require './text-manipulation'


module.exports =
  subscriptions: null

  activate: (state) ->
    # Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
    @subscriptions = new CompositeDisposable

    # Register package commands
    @subscriptions.add atom.commands.add 'atom-text-editor',
      'list-edit:select': => @selectCmd()
      'list-edit:cut':    => @cutCmd()
      'list-edit:copy':   => @copyCmd()
      'list-edit:paste':  => @pasteCmd()
      'list-edit:delete': => @deleteCmd()

  deactivate: ->
    @subscriptions.dispose()

  serialize: ->
    listEditViewState: @listEditView.serialize()

  selectCmd: ->
    console.log 'Executing command list-edit-select'
    @withSelectedList (editor, textBuffer, bufferText, selectionIxRange, listElements) ->
      if listElements.length == 0
        atom.notifications.addWarning 'List selection in empty list.'
      else
        [selStart,selEnd] = TextManipulation.getSelectionForRange listElements, selectionIxRange
        # TODO: handle empty selection? We currently cannot create this

        if selEnd > listElements.length
          atom.notifications.addWarning 'List selection end outside list.'
          # won't happen for start, since we use this to select the list in the first place
          # TODO: maybe make this less strict, as selection in sublists is now asymmetric:
          #       in "[1,[a,b],2]": "[a," selects entire sublist element, but ",b]" fails with warning.
        else
          console.log 'List elements'
          console.log e.show() for e in listElements
          console.log 'Selection: ' + selStart + ' <-> ' + selEnd
          console.log (TextManipulation.getRangeForIxRange textBuffer, [listElements[selStart].eltStart, listElements[selEnd-1].eltEnd])

          editor.setSelectedBufferRange(TextManipulation.getRangeForIxRange textBuffer,
                                        [listElements[selStart].eltStart, listElements[selEnd-1].eltEnd])

  cutCmd: ->
    console.log 'Executing command list-edit-cut'
    # select
    # copy
    # delete

    #  1 elt:  remove, including whitespace
    # >1 elts: if not last, remove, put pre whitespace on pre whitespace of next element
    #         if last, put post whitespace on previous element

    # Not cut, but some test code to easily visualize ranges
    @withSelectedList (editor, textBuffer, bufferText, selectionIxRange, listElements) ->
      cursorPos = editor.getCursorBufferPosition()
      console.log 'cursor row ' + cursorPos.row + ' col ' + cursorPos.column

      bufferRanges = _.map listElements, (elt) ->
        TextManipulation.getRangeForIxRange textBuffer, [elt.eltStart, elt.eltEnd]

      console.log 'bufferRanges:'
      console.log bufferRanges

      if bufferRanges? && bufferRanges.length > 0
        editor.setSelectedBufferRanges(bufferRanges)

  copyCmd: ->
    console.log 'Executing command list-edit-copy'
    @withSelectedList (editor, textBuffer, bufferText, selectionIxRange, listElements) ->
      if listElements.length == 0
        atom.notifications.addWarning 'List selection in empty list.'
        # TODO: clear the clipboard here?
      else
        [selStart,selEnd] = TextManipulation.getSelectionForRange listElements, selectionIxRange

        # TODO: probably want to put this in withSelectedList
        if selEnd > listElements.length
          atom.notifications.addWarning 'List selection end outside list.'
          # won't happen for start, since we use this to select the list in the first place
          # TODO: maybe make this less strict, as selection in sublists is now asymmetric:
          #       in "[1,[a,b],2]": "[a," selects entire sublist element, but ",b]" fails with warning.
        else
          selectionText = bufferText.slice listElements[selStart].eltStart, listElements[selEnd-1].eltEnd
          #console.log "Copied: '#{selectionText}'"
          atom.clipboard.write selectionText, @mkListEditMeta()

  pasteCmd: ->
    console.log 'Executing command list-edit-paste'

    # On element, replace element with stripped clipboard, while preserving whitespace
    #   1 elt,  make up bracket space, just use sep+' ' for now
    # > 1 elts, before first element: newElt.whitespace = element[0].whitespace, element[0].whitespace.pre =element[1].whitespace.pre
    #           after last element:   newElt.whitespace = element[n-1].whitespace, element[n-1].whitespace.post =element[n-2].whitespace.post
    #           between i and i+1:    newElt.whitespace.pre = element[i+1].whitepace.pre, newElt.whitespace.post = element[i].whitepace.post
    # maybe always using third rule and having special cases for i=0 and i = n-1 is elegant? (patching the existing elt's whitespace in those cases may make it less elegant)

    # maybe declare bracketRightWhitespace bracketLeftWhitespace, separatorLeftWhitespace and separatorRightWhitespace
    # and use those to format the necessary elements? Or maybe not, as explicit distinction may not be necessary

    # for testing, use digits as whitespace

    # need some function to determing if we're on the element, before, or after
    # setPreWhitespace
    # getPreWhitespace
    #           patch next or previous element's whitespace

    # [bracket-space-1ELTbracket-space2]<commit_msg>Crude implementation of list-edit-cut<commit_after>{CompositeDisposable, Range, TextBuffer} = require 'atom'
_ = require 'underscore-plus'
TextManipulation = require './text-manipulation'


module.exports =
  subscriptions: null

  activate: (state) ->
    # Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
    @subscriptions = new CompositeDisposable

    # Register package commands
    @subscriptions.add atom.commands.add 'atom-text-editor',
      'list-edit:select': => @selectCmd()
      'list-edit:cut':    => @cutCmd()
      'list-edit:copy':   => @copyCmd()
      'list-edit:paste':  => @pasteCmd()
      'list-edit:delete': => @deleteCmd()

  deactivate: ->
    @subscriptions.dispose()

  serialize: ->
    listEditViewState: @listEditView.serialize()

  selectCmd: ->
    console.log 'Executing command list-edit-select'
    @withSelectedList (editor, textBuffer, bufferText, selectionIxRange, listElements) ->
      if listElements.length == 0
        atom.notifications.addWarning 'List selection in empty list.'
      else
        [selStart,selEnd] = TextManipulation.getSelectionForRange listElements, selectionIxRange
        # TODO: handle empty selection? We currently cannot create this

        if selEnd > listElements.length
          atom.notifications.addWarning 'List selection end outside list.'
          # won't happen for start, since we use this to select the list in the first place
          # TODO: maybe make this less strict, as selection in sublists is now asymmetric:
          #       in "[1,[a,b],2]": "[a," selects entire sublist element, but ",b]" fails with warning.
        else
          console.log 'List elements'
          console.log e.show() for e in listElements
          console.log 'Selection: ' + selStart + ' <-> ' + selEnd
          console.log (TextManipulation.getRangeForIxRange textBuffer, [listElements[selStart].eltStart, listElements[selEnd-1].eltEnd])

          editor.setSelectedBufferRange(TextManipulation.getRangeForIxRange textBuffer,
                                        [listElements[selStart].eltStart, listElements[selEnd-1].eltEnd])

  cutCmd: ->
    console.log 'Executing command list-edit-cut'
    # select
    # copy
    # delete

    #  1 elt:  remove, including whitespace
    # >1 elts: if not last, remove, put pre whitespace on pre whitespace of next element
    #         if last, put post whitespace on previous element
    # [pre1ELT1post1,pre2ELT2post2,pre3ELT3post3]
    # [pre1ELT1post1,pre2ELT3post3]

    # spec:
    # if newElts.length > 0
    #   if cut == 0  # then newElts[0] will exist, so not the last one and no need to fix post
    #     newElts[0].pre = cutElts[0].pre
    #   else
    #    if cut == newElts.length # newElts.length > 1, so newElts[n-1] exists, not first and no need to fix pre
    #      newElts[n-1].post = cutElts[m].post

    @withSelectedList (editor, textBuffer, bufferText, selectionIxRange, listElements) ->
      if listElements.length == 0
        atom.notifications.addWarning 'List cut in empty list.'
        # TODO: clear the clipboard here?
      else
        # TODO: move to wrapper
        [selStart,selEnd] = TextManipulation.getSelectionForRange listElements, selectionIxRange

        # TODO: probably want to put this in withSelectedList
        if selEnd > listElements.length
          atom.notifications.addWarning 'List selection end outside list.'
          # won't happen for start, since we use this to select the list in the first place
          # TODO: maybe make this less strict, as selection in sublists is now asymmetric:
          #       in "[1,[a,b],2]": "[a," selects entire sublist element, but ",b]" fails with warning.
        else
          # TODO: refactor copy so we can call it here
          cutStart = selStart
          cutEnd = selEnd
          console.log 'List elements'
          console.log e.show() for e in listElements
          console.log 'Selection: ' + cutStart + ' <-> ' + cutEnd

          # copy selected elements to clipboard
          selectionText = bufferText.slice listElements[cutStart].eltStart, listElements[cutEnd-1].eltEnd
          atom.clipboard.write selectionText, @mkListEditMeta()

          # elts[0 .. cutStart .. cutEnd .. n-1]
          newLength = listElements.length - (cutEnd - cutStart) # +1 since cut range is inclusive
          console.log newLength

          if newLength == 0
            cutIxRange = [listElements[cutStart].start, listElements[cutEnd-1].end]
            newWhitespace = ''
          else
            if cutStart == 0  # newLength > 0, so not the last one and no need to fix post (and elts[cutEnd] exists)
              cutIxRange = [ listElements[0].start, listElements[cutEnd].eltStart ]
              newWhitespace = listElements[0].leadingWhitespace  # newElts[0].pre = cutElts[0].pre
            else # listElements[cutStart-1] exists
              if cutEnd < listElements.length
                cutIxRange = [ listElements[cutStart-1].end, listElements[cutEnd-1].end] # remove from preceding separator until post whitespace of last cut elt
                newWhitespace = ''
              else
                cutIxRange = [ listElements[cutStart-1].eltEnd, listElements[cutEnd-1].end]
                newWhitespace = listElements[cutEnd-1].trailingWhitespace   #newlistElements[n-1].post = cutElts[m].post
          console.log 'cut index range:' + cutIxRange
          console.log 'inserted: "' + newWhitespace + '"'
          cutRange = TextManipulation.getRangeForIxRange textBuffer, cutIxRange
          console.log cutRange.start
          # editor.setSelectedBufferRange cutRange # for debugging: select the range that will be cut
          textBuffer.setTextInRange cutRange, newWhitespace

  # Store first pre, last post, one middle, and column of opening bracket for handling empty/one elt insertions (column is only for multi line lists)
  copyCmd: ->
    console.log 'Executing command list-edit-copy'
    @withSelectedList (editor, textBuffer, bufferText, selectionIxRange, listElements) ->
      if listElements.length == 0
        atom.notifications.addWarning 'List copy in empty list.'
        # TODO: clear the clipboard here?
      else
        [selStart,selEnd] = TextManipulation.getSelectionForRange listElements, selectionIxRange

        # TODO: probably want to put this in withSelectedList
        if selEnd > listElements.length
          atom.notifications.addWarning 'List selection end outside list.'
          # won't happen for start, since we use this to select the list in the first place
          # TODO: maybe make this less strict, as selection in sublists is now asymmetric:
          #       in "[1,[a,b],2]": "[a," selects entire sublist element, but ",b]" fails with warning.
        else
          selectionText = bufferText.slice listElements[selStart].eltStart, listElements[selEnd-1].eltEnd
          # Clip includes separators, which seems logical when we use it for a non-list paste
          #console.log "Copied: '#{selectionText}'"
          atom.clipboard.write selectionText, @mkListEditMeta()

  pasteCmd: ->
    console.log 'Executing command list-edit-paste'
    clip = atom.clipboard.readWithMetadata()
    clipMeta = @getListEditMeta clip
    if not clipMeta
      atom.notifications.addError 'Clipboard does not contain list-edit clip.'
      # TODO: For now this is an error, but we can probably still do something with it in the future
    else
      console.log 'Clipboard contains list-edit clip'

    # On element, replace element with stripped clipboard, while preserving whitespace
    #   1 elt,  make up bracket space, just use sep+' ' for now
    # > 1 elts, before first element: newElt.whitespace = element[0].whitespace, element[0].whitespace.pre =element[1].whitespace.pre
    #           after last element:   newElt.whitespace = element[n-1].whitespace, element[n-1].whitespace.post =element[n-2].whitespace.post
    #           between i and i+1:    newElt.whitespace.pre = element[i+1].whitepace.pre, newElt.whitespace.post = element[i].whitepace.post
    # maybe always using third rule and having special cases for i=0 and i = n-1 is elegant? (patching the existing elt's whitespace in those cases may make it less elegant)

    # maybe declare bracketRightWhitespace bracketLeftWhitespace, separatorLeftWhitespace and separatorRightWhitespace
    # and use those to format the necessary elements? Or maybe not, as explicit distinction may not be necessary

    # for testing, use digits as whitespace

    # need some function to determing if we're on the element, before, or after
    # setPreWhitespace
    # getPreWhitespace
    #           patch next or previous element's whitespace

    # [bracket-space-1ELTbracket-space2]
{'fraction_non_alphanumeric': 0.08952916373858047, 'fraction_numerical': 0.006746310611384399, 'mean_word_length': 2.945383975602994, 'pattern_counts': {'":': 5, '<': 7, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1637948', 'n_tokens_mistral': 4057, 'n_tokens_neox': 3928, 'n_words': 1255}