<commit_before>Range = require 'range'
_ = require 'underscore'
require 'underscore-extensions'

module.exports =
class LanguageMode
  buffer = null
  grammar = null
  editSession = null
  pairedCharacters:
    '(': ')'
    '[': ']'
    '{': '}'
    '"': '"'
    "'": "'"

  constructor: (@editSession) ->
    @buffer = @editSession.buffer
    @reloadGrammar()
    @bracketAnchorRanges = []

    _.adviseBefore @editSession, 'insertText', (text) =>
      return true if @editSession.hasMultipleCursors()

      cursorBufferPosition = @editSession.getCursorBufferPosition()
      previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
      nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])

      if @isOpeningBracket(text) and not @editSession.getSelection().isEmpty()
        @wrapSelectionInBrackets(text)
        return false

      hasWordAfterCursor = /\w/.test(nextCharacter)
      hasWordBeforeCursor = /\w/.test(previousCharacter)

      autoCompleteOpeningBracket = @isOpeningBracket(text) and not hasWordAfterCursor and not (@isQuote(text) and hasWordBeforeCursor)
      skipOverExistingClosingBracket = false
      if @isClosingBracket(text) and nextCharacter == text
        if bracketAnchorRange = @bracketAnchorRanges.filter((anchorRange) -> anchorRange.getBufferRange().end.isEqual(cursorBufferPosition))[0]
          skipOverExistingClosingBracket = true

      if skipOverExistingClosingBracket
        bracketAnchorRange.destroy()
        _.remove(@bracketAnchorRanges, bracketAnchorRange)
        @editSession.moveCursorRight()
        false
      else if autoCompleteOpeningBracket
        @editSession.insertText(text + @pairedCharacters[text])
        @editSession.moveCursorLeft()
        range = [cursorBufferPosition, cursorBufferPosition.add([0, text.length])]
        @bracketAnchorRanges.push @editSession.addAnchorRange(range)
        false

    _.adviseBefore @editSession, 'backspace', =>
      return if @editSession.hasMultipleCursors()
      return unless @editSession.getSelection().isEmpty()

      cursorBufferPosition = @editSession.getCursorBufferPosition()
      previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
      nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
      if @pairedCharacters[previousCharacter] is nextCharacter
        @editSession.transact =>
          @editSession.moveCursorLeft()
          @editSession.delete()
          @editSession.delete()
        false

  wrapSelectionInBrackets: (bracket) ->
    pair = @pairedCharacters[bracket]
    @editSession.mutateSelectedText (selection) =>
      return if selection.isEmpty()

      range = selection.getBufferRange()
      options = reverse: selection.isReversed()
      wrappedText = "#{bracket}#{selection.getText()}#{pair}"
      selection.insertText(wrappedText)
      selectionStart = range.start.add([0, 1])
      if range.start.row is range.end.row
        selectionEnd = range.end.add([0, 1])
      else<commit_msg>Inline selected text wrapped in brackets<commit_after>Range = require 'range'
_ = require 'underscore'
require 'underscore-extensions'

module.exports =
class LanguageMode
  buffer = null
  grammar = null
  editSession = null
  pairedCharacters:
    '(': ')'
    '[': ']'
    '{': '}'
    '"': '"'
    "'": "'"

  constructor: (@editSession) ->
    @buffer = @editSession.buffer
    @reloadGrammar()
    @bracketAnchorRanges = []

    _.adviseBefore @editSession, 'insertText', (text) =>
      return true if @editSession.hasMultipleCursors()

      cursorBufferPosition = @editSession.getCursorBufferPosition()
      previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
      nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])

      if @isOpeningBracket(text) and not @editSession.getSelection().isEmpty()
        @wrapSelectionInBrackets(text)
        return false

      hasWordAfterCursor = /\w/.test(nextCharacter)
      hasWordBeforeCursor = /\w/.test(previousCharacter)

      autoCompleteOpeningBracket = @isOpeningBracket(text) and not hasWordAfterCursor and not (@isQuote(text) and hasWordBeforeCursor)
      skipOverExistingClosingBracket = false
      if @isClosingBracket(text) and nextCharacter == text
        if bracketAnchorRange = @bracketAnchorRanges.filter((anchorRange) -> anchorRange.getBufferRange().end.isEqual(cursorBufferPosition))[0]
          skipOverExistingClosingBracket = true

      if skipOverExistingClosingBracket
        bracketAnchorRange.destroy()
        _.remove(@bracketAnchorRanges, bracketAnchorRange)
        @editSession.moveCursorRight()
        false
      else if autoCompleteOpeningBracket
        @editSession.insertText(text + @pairedCharacters[text])
        @editSession.moveCursorLeft()
        range = [cursorBufferPosition, cursorBufferPosition.add([0, text.length])]
        @bracketAnchorRanges.push @editSession.addAnchorRange(range)
        false

    _.adviseBefore @editSession, 'backspace', =>
      return if @editSession.hasMultipleCursors()
      return unless @editSession.getSelection().isEmpty()

      cursorBufferPosition = @editSession.getCursorBufferPosition()
      previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
      nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
      if @pairedCharacters[previousCharacter] is nextCharacter
        @editSession.transact =>
          @editSession.moveCursorLeft()
          @editSession.delete()
          @editSession.delete()
        false

  wrapSelectionInBrackets: (bracket) ->
    pair = @pairedCharacters[bracket]
    @editSession.mutateSelectedText (selection) =>
      return if selection.isEmpty()

      range = selection.getBufferRange()
      options = reverse: selection.isReversed()
      selection.insertText("#{bracket}#{selection.getText()}#{pair}")
      selectionStart = range.start.add([0, 1])
      if range.start.row is range.end.row
        selectionEnd = range.end.add([0, 1])
      else
{'fraction_non_alphanumeric': 0.11244283236082636, 'fraction_numerical': 0.004415707301687431, 'mean_word_length': 3.889745566692367, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 17, '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': '2947575', 'n_tokens_mistral': 1788, 'n_tokens_neox': 1724, 'n_words': 302}