<commit_before>/* eslint default-case: 0 */

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { clipboard, remote } from 'electron';
import MainInput from '../../components/MainInput';
import ResultsList from '../../components/ResultsList';
import styles from './styles.css';
import define from 'lib/define';
import * as searchActions from '../../actions/search';
import escapeStringRegexp from 'escape-string-regexp';

import { debounce, bind } from 'lodash-decorators';

import {
  INPUT_HEIGHT,
  RESULT_HEIGHT,
  WINDOW_WIDTH,
  MIN_VISIBLE_RESULTS,
} from '../../constants/ui';

/**
 * Get current electron window
 *
 * @return {BrowserWindow}
 */
function currentWindow() {
  return remote.getCurrentWindow();
}

class Search extends Component {
  static propTypes = {
    actions: PropTypes.shape({
      reset: PropTypes.func,
      moveCursor: PropTypes.func,
      updateTerm: PropTypes.func,
      changeVisibleResults: PropTypes.func,
      selectElement: PropTypes.func,
    }),
    results: PropTypes.array,
    selected: PropTypes.number,
    visibleResults: PropTypes.number,
    term: PropTypes.string,
    prevTerm: PropTypes.string,
  }
  constructor(props) {
    super(props);
    currentWindow().on('hide', this.props.actions.reset);
  }
  componentDidUpdate(prevProps) {
    const { results } = this.props;
    if (results.length !== prevProps.results.length) {
      // Resize electron window when results count changed
      this.updateElectronWindow();
    }
  }
  componentWillMount() {
    // Listen for window.resize and change default space for results to user's value
    window.addEventListener('resize', this.onWindowResize);
    // Listen for document keydown to handle hot keys
    document.addEventListener('keydown', this.onKeyDown);
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.onWindowResize);
    document.removeEventListener('keyDown', this.onKeyDown);
  }

  /**
   * Handle resize window and change count of visible results depends on window size
   */
  @bind()
  @debounce(100)
  onWindowResize() {
    if (this.props.results.length <= MIN_VISIBLE_RESULTS) {
      return false;
    }
    let visibleResults = Math.floor((window.outerHeight - INPUT_HEIGHT) / RESULT_HEIGHT);
    visibleResults = Math.max(MIN_VISIBLE_RESULTS, visibleResults);
    if (visibleResults !== this.props.visibleResults) {
      this.props.actions.changeVisibleResults(visibleResults);
    }
  }

  /**
   * Handle keyboard shortcuts
   */
  @bind()
  onKeyDown(event) {
    const highlighted = this.highlightedResult();
    // TODO: go to first result on cmd+up and last result on cmd+down
    // TODO: global shortcuts priorities
    if (highlighted && highlighted.onKeyDown) {
      highlighted.onKeyDown(event);
    }
    if (event.defaultPrevented) {
      return;
    }
    if (event.metaKey) {
      if (event.keyCode === 68) {
        // define word on cmd+d
        define(this.props.term);
        event.preventDefault();
        return;
      }
      if (event.keyCode === 8) {
        // Clean search term on cmd+backspace
        this.props.actions.reset();
      }
      if (event.keyCode === 67) {
        // Copy to clipboard on cmd+c
        const text = this.highlightedResult().clipboard;
        if (text) {
          clipboard.writeText(text);
          this.props.actions.reset();
        }
        event.preventDefault();
        return;
      }
      if (event.keyCode >= 49 && event.keyCode <= 57) {
        // Select element by number
        const number = Math.abs(49 - event.keyCode);
        const result = this.props.results[number];
        if (result) {
          return this.selectItem(result);
        }
      }
    }
    switch (event.keyCode) {
      case 9:
        event.preventDefault();
        this.autocomplete();
        break;
      case 40:
        this.props.actions.moveCursor(1);
        event.preventDefault();
        break;
      case 38:
        if (this.props.results.length > 0) {
          this.props.actions.moveCursor(-1);
        } else if (this.props.prevTerm) {
          this.props.actions.updateTerm(this.props.prevTerm);<commit_msg>Allow to copy selected text from preview if no clipboard option provided for result<commit_after>/* eslint default-case: 0 */

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { clipboard, remote } from 'electron';
import MainInput from '../../components/MainInput';
import ResultsList from '../../components/ResultsList';
import styles from './styles.css';
import define from 'lib/define';
import * as searchActions from '../../actions/search';
import escapeStringRegexp from 'escape-string-regexp';

import { debounce, bind } from 'lodash-decorators';

import {
  INPUT_HEIGHT,
  RESULT_HEIGHT,
  WINDOW_WIDTH,
  MIN_VISIBLE_RESULTS,
} from '../../constants/ui';

/**
 * Get current electron window
 *
 * @return {BrowserWindow}
 */
function currentWindow() {
  return remote.getCurrentWindow();
}

class Search extends Component {
  static propTypes = {
    actions: PropTypes.shape({
      reset: PropTypes.func,
      moveCursor: PropTypes.func,
      updateTerm: PropTypes.func,
      changeVisibleResults: PropTypes.func,
      selectElement: PropTypes.func,
    }),
    results: PropTypes.array,
    selected: PropTypes.number,
    visibleResults: PropTypes.number,
    term: PropTypes.string,
    prevTerm: PropTypes.string,
  }
  constructor(props) {
    super(props);
    currentWindow().on('hide', this.props.actions.reset);
  }
  componentDidUpdate(prevProps) {
    const { results } = this.props;
    if (results.length !== prevProps.results.length) {
      // Resize electron window when results count changed
      this.updateElectronWindow();
    }
  }
  componentWillMount() {
    // Listen for window.resize and change default space for results to user's value
    window.addEventListener('resize', this.onWindowResize);
    // Listen for document keydown to handle hot keys
    document.addEventListener('keydown', this.onKeyDown);
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.onWindowResize);
    document.removeEventListener('keyDown', this.onKeyDown);
  }

  /**
   * Handle resize window and change count of visible results depends on window size
   */
  @bind()
  @debounce(100)
  onWindowResize() {
    if (this.props.results.length <= MIN_VISIBLE_RESULTS) {
      return false;
    }
    let visibleResults = Math.floor((window.outerHeight - INPUT_HEIGHT) / RESULT_HEIGHT);
    visibleResults = Math.max(MIN_VISIBLE_RESULTS, visibleResults);
    if (visibleResults !== this.props.visibleResults) {
      this.props.actions.changeVisibleResults(visibleResults);
    }
  }

  /**
   * Handle keyboard shortcuts
   */
  @bind()
  onKeyDown(event) {
    const highlighted = this.highlightedResult();
    // TODO: go to first result on cmd+up and last result on cmd+down
    // TODO: global shortcuts priorities
    if (highlighted && highlighted.onKeyDown) {
      highlighted.onKeyDown(event);
    }
    if (event.defaultPrevented) {
      return;
    }
    if (event.metaKey) {
      if (event.keyCode === 68) {
        // define word on cmd+d
        define(this.props.term);
        event.preventDefault();
        return;
      }
      if (event.keyCode === 8) {
        // Clean search term on cmd+backspace
        this.props.actions.reset();
      }
      if (event.keyCode === 67) {
        // Copy to clipboard on cmd+c
        const text = this.highlightedResult().clipboard;
        if (text) {
          clipboard.writeText(text);
          this.props.actions.reset();
          event.preventDefault();
        }
        return;
      }
      if (event.keyCode >= 49 && event.keyCode <= 57) {
        // Select element by number
        const number = Math.abs(49 - event.keyCode);
        const result = this.props.results[number];
        if (result) {
          return this.selectItem(result);
        }
      }
    }
    switch (event.keyCode) {
      case 9:
        event.preventDefault();
        this.autocomplete();
        break;
      case 40:
        this.props.actions.moveCursor(1);
        event.preventDefault();
        break;
      case 38:
        if (this.props.results.length > 0) {
          this.props.actions.moveCursor(-1);
        } else if (this.props.prevTerm) {
          this.props.actions.updateTerm(this.props.prevTerm);
{'fraction_non_alphanumeric': 0.12155212716222534, 'fraction_numerical': 0.005376344086021506, 'mean_word_length': 2.7399475524475525, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '4017014', 'n_tokens_mistral': 2489, 'n_tokens_neox': 2456, 'n_words': 594}