<commit_before>import 'babel/polyfill'

import React from 'react/addons'
import getEventKey from 'react/lib/getEventKey'
import Mousetrap from 'mousetrap'
import parseHtml from '../core/htmlparser'
import writeHtml from '../core/htmlwriter'
import writeText from '../core/textwriter'
import {emptyNode} from '../core/dom'

const batchedUpdates = React.addons.batchedUpdates
const T = React.PropTypes
const MIME_TYPE_TEXT_PLAIN = 'text/plain'
const MIME_TYPE_TEXT_HTML = 'text/html'
const MIME_TYPE_RITZY_RICH_TEXT = 'application/x-ritzy-rt'

// alphabet lower case +
// alphabet upper case case +
// numerals +
// space +
// special chars (_KEYCODE_MAP in mousetrap) +
// keys requiring shift (_SHIFT_MAP in mousetrap) +
// { and } which were missing from mousetrap _SHIFT_MAP
// common special chars (TODO)
// TODO non-english language/char entry
/* eslint-disable comma-spacing */
const ALL_CHARS = [
  'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
  'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  '0','1','2','3','4','5','6','7','8','9',
  'space',
  '*','+','-','.','/',';','=',',','-','.','/','`','[','\\',']','\'',
  '~','!','@','#','$','%','^','&','*','(',')','_','+',':','\"','<','>','?','|',
  '{','}',
  'é','è'
]
/* eslint-enable comma-spacing */

export default React.createClass({
  propTypes: {
    id: T.number.isRequired,
    position: T.number.isRequired,
    insertChars: T.func.isRequired,
    insertCharsBatch: T.func.isRequired,
    navigateLeft: T.func.isRequired,
    navigateRight: T.func.isRequired,
    navigateUp: T.func.isRequired,
    navigateDown: T.func.isRequired,
    navigatePageUp: T.func.isRequired,
    navigatePageDown: T.func.isRequired,
    navigateStart: T.func.isRequired,
    navigateStartLine: T.func.isRequired,
    navigateEnd: T.func.isRequired,
    navigateEndLine: T.func.isRequired,
    navigateWordLeft: T.func.isRequired,
    navigateWordRight: T.func.isRequired,
    selectionLeft: T.func.isRequired,
    selectionRight: T.func.isRequired,
    selectionUp: T.func.isRequired,
    selectionDown: T.func.isRequired,
    selectionPageUp: T.func.isRequired,
    selectionPageDown: T.func.isRequired,
    selectionStart: T.func.isRequired,
    selectionStartLine: T.func.isRequired,
    selectionEnd: T.func.isRequired,
    selectionEndLine: T.func.isRequired,
    selectionWordLeft: T.func.isRequired,
    selectionWordRight: T.func.isRequired,
    selectionAll: T.func.isRequired,
    eraseCharBack: T.func.isRequired,
    eraseCharForward: T.func.isRequired,
    eraseWordBack: T.func.isRequired,
    eraseWordForward: T.func.isRequired,
    eraseSelection: T.func.isRequired,
    toggleBold: T.func.isRequired,
    toggleItalics: T.func.isRequired,
    toggleUnderline: T.func.isRequired,
    toggleStrikethrough: T.func.isRequired,
    toggleSuperscript: T.func.isRequired,
    toggleSubscript: T.func.isRequired,
    getSelection: T.func.isRequired
  },

  mixins: [React.addons.PureRenderMixin],

  componentDidMount() {
    // React does not batch setState calls inside events raised by mousetrap, create a wrapper to do that
    this.input = React.findDOMNode(this.refs.input)
    this.hiddenContainer = React.findDOMNode(this.refs.hiddenContainer)
    this.ieClipboardDiv = React.findDOMNode(this.refs.ieClipboardDiv)

    // for HTML paste support in IE -- ignored by Chrome/Firefox
    this.input.addEventListener('beforepaste', () => {
      if (document.activeElement !== this.ieClipboardDiv) {
        this._focusIeClipboardDiv()
      }
    }, true)

    let keyBindingsReal = new Mousetrap(this.input)

    // the wrapper function returns the function that will be called by Mousetrap with two args: keyEvent and combo
    let wrapperFunction = (handler) => (keyEvent, combo) => {
      let returnValue
      batchedUpdates(() => returnValue = handler(keyEvent, combo))
      return returnValue
    }
    let keyBindings = {
      bind(binding, handler) {
        keyBindingsReal.bind(binding, wrapperFunction(handler))
      }
    }

    // TODO probably ALL_CHARS should be handled via onInput instead to avoid keycode translation
    keyBindings.bind(ALL_CHARS, this._handleKeyChar)
    keyBindings.bind(['up', 'down', 'left', 'right'], this._handleKeyArrow)
    keyBindings.bind(['shift+up', 'shift+down', 'shift+left', 'shift+right'], this._handleKeySelectionArrow)
    keyBindings.bind(['pageup', 'pagedown'], this._handleKeyNavigationPage)
    keyBindings.bind(['shift+pageup', 'shift+pagedown'], this._handleKeySelectionPage)
    keyBindings.bind(['ctrl+home', 'home', 'ctrl+end', 'end'], this._handleKeyNavigationHomeEnd)
    keyBindings.bind(['ctrl+shift+home', 'shift+home', 'ctrl+shift+end', 'shift+end'], this._handleKeySelectionHomeEnd)
    keyBindings.bind(['ctrl+left', 'ctrl+right'], this._handleKeyNavigationWord)
    keyBindings.bind(['shift+ctrl+left', 'shift+ctrl+right'], this._handleKeySelectionWord)
    keyBindings.bind('ctrl+a', this._handleKeySelectionAll)
    keyBindings.bind('backspace', this._handleKeyBackspace)
    keyBindings.bind('del', this._handleKeyDelete)
    keyBindings.bind('ctrl+backspace', this._handleKeyWordBackspace)
    keyBindings.bind('ctrl+del', this._handleKeyWordDelete)
    //keyBindings.bind('ctrl+s', this._handleKeySave)
    //keyBindings.bind('tab', this._handleKeyTab)
    keyBindings.bind('enter', this._handleKeyEnter)
    //keyBindings.bind('ctrl+z', this._handleUndo)<commit_msg>Temporarily revert: Eliminate extra render cycles on keypresses<commit_after>import 'babel/polyfill'

import React from 'react/addons'
import getEventKey from 'react/lib/getEventKey'
import Mousetrap from 'mousetrap'
import parseHtml from '../core/htmlparser'
import writeHtml from '../core/htmlwriter'
import writeText from '../core/textwriter'
import {emptyNode} from '../core/dom'

//const batchedUpdates = React.addons.batchedUpdates
const T = React.PropTypes
const MIME_TYPE_TEXT_PLAIN = 'text/plain'
const MIME_TYPE_TEXT_HTML = 'text/html'
const MIME_TYPE_RITZY_RICH_TEXT = 'application/x-ritzy-rt'

// alphabet lower case +
// alphabet upper case case +
// numerals +
// space +
// special chars (_KEYCODE_MAP in mousetrap) +
// keys requiring shift (_SHIFT_MAP in mousetrap) +
// { and } which were missing from mousetrap _SHIFT_MAP
// common special chars (TODO)
// TODO non-english language/char entry
/* eslint-disable comma-spacing */
const ALL_CHARS = [
  'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
  'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  '0','1','2','3','4','5','6','7','8','9',
  'space',
  '*','+','-','.','/',';','=',',','-','.','/','`','[','\\',']','\'',
  '~','!','@','#','$','%','^','&','*','(',')','_','+',':','\"','<','>','?','|',
  '{','}',
  'é','è'
]
/* eslint-enable comma-spacing */

export default React.createClass({
  propTypes: {
    id: T.number.isRequired,
    position: T.number.isRequired,
    insertChars: T.func.isRequired,
    insertCharsBatch: T.func.isRequired,
    navigateLeft: T.func.isRequired,
    navigateRight: T.func.isRequired,
    navigateUp: T.func.isRequired,
    navigateDown: T.func.isRequired,
    navigatePageUp: T.func.isRequired,
    navigatePageDown: T.func.isRequired,
    navigateStart: T.func.isRequired,
    navigateStartLine: T.func.isRequired,
    navigateEnd: T.func.isRequired,
    navigateEndLine: T.func.isRequired,
    navigateWordLeft: T.func.isRequired,
    navigateWordRight: T.func.isRequired,
    selectionLeft: T.func.isRequired,
    selectionRight: T.func.isRequired,
    selectionUp: T.func.isRequired,
    selectionDown: T.func.isRequired,
    selectionPageUp: T.func.isRequired,
    selectionPageDown: T.func.isRequired,
    selectionStart: T.func.isRequired,
    selectionStartLine: T.func.isRequired,
    selectionEnd: T.func.isRequired,
    selectionEndLine: T.func.isRequired,
    selectionWordLeft: T.func.isRequired,
    selectionWordRight: T.func.isRequired,
    selectionAll: T.func.isRequired,
    eraseCharBack: T.func.isRequired,
    eraseCharForward: T.func.isRequired,
    eraseWordBack: T.func.isRequired,
    eraseWordForward: T.func.isRequired,
    eraseSelection: T.func.isRequired,
    toggleBold: T.func.isRequired,
    toggleItalics: T.func.isRequired,
    toggleUnderline: T.func.isRequired,
    toggleStrikethrough: T.func.isRequired,
    toggleSuperscript: T.func.isRequired,
    toggleSubscript: T.func.isRequired,
    getSelection: T.func.isRequired
  },

  mixins: [React.addons.PureRenderMixin],

  componentDidMount() {
    // React does not batch setState calls inside events raised by mousetrap, create a wrapper to do that
    this.input = React.findDOMNode(this.refs.input)
    this.hiddenContainer = React.findDOMNode(this.refs.hiddenContainer)
    this.ieClipboardDiv = React.findDOMNode(this.refs.ieClipboardDiv)

    // for HTML paste support in IE -- ignored by Chrome/Firefox
    this.input.addEventListener('beforepaste', () => {
      if (document.activeElement !== this.ieClipboardDiv) {
        this._focusIeClipboardDiv()
      }
    }, true)

    let keyBindings = new Mousetrap(this.input)
    //let keyBindingsReal = new Mousetrap(this.input)
    //
    // the wrapper function returns the function that will be called by Mousetrap with two args: keyEvent and combo
    //let wrapperFunction = (handler) => (keyEvent, combo) => {
    //  let returnValue
    //  batchedUpdates(() => returnValue = handler(keyEvent, combo))
    //  return returnValue
    //}
    //let keyBindings = {
    //  bind(binding, handler) {
    //    keyBindingsReal.bind(binding, wrapperFunction(handler))
    //  }
    //}

    // TODO probably ALL_CHARS should be handled via onInput instead to avoid keycode translation
    keyBindings.bind(ALL_CHARS, this._handleKeyChar)
    keyBindings.bind(['up', 'down', 'left', 'right'], this._handleKeyArrow)
    keyBindings.bind(['shift+up', 'shift+down', 'shift+left', 'shift+right'], this._handleKeySelectionArrow)
    keyBindings.bind(['pageup', 'pagedown'], this._handleKeyNavigationPage)
    keyBindings.bind(['shift+pageup', 'shift+pagedown'], this._handleKeySelectionPage)
    keyBindings.bind(['ctrl+home', 'home', 'ctrl+end', 'end'], this._handleKeyNavigationHomeEnd)
    keyBindings.bind(['ctrl+shift+home', 'shift+home', 'ctrl+shift+end', 'shift+end'], this._handleKeySelectionHomeEnd)
    keyBindings.bind(['ctrl+left', 'ctrl+right'], this._handleKeyNavigationWord)
    keyBindings.bind(['shift+ctrl+left', 'shift+ctrl+right'], this._handleKeySelectionWord)
    keyBindings.bind('ctrl+a', this._handleKeySelectionAll)
    keyBindings.bind('backspace', this._handleKeyBackspace)
    keyBindings.bind('del', this._handleKeyDelete)
    keyBindings.bind('ctrl+backspace', this._handleKeyWordBackspace)
    keyBindings.bind('ctrl+del', this._handleKeyWordDelete)
    //keyBindings.bind('ctrl+s', this._handleKeySave)
    //keyBindings.bind('tab', this._handleKeyTab)
    keyBindings.bind('enter', this._handleKeyEnter)
    //keyBindings.bind('ctrl+z', this._handleUndo)
{'fraction_non_alphanumeric': 0.1728980322003578, 'fraction_numerical': 0.0017889087656529517, 'mean_word_length': 4.497050147492625, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, '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': '787158', 'n_tokens_mistral': 3733, 'n_tokens_neox': 3715, 'n_words': 658}