{"version":3,"file":"search.js","sources":["../../../src/addons/search/search.ts","../../../src/addons/search/SearchHelper.ts","../../../node_modules/browser-pack/_prelude.js"],"sourcesContent":["/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { SearchHelper } from './SearchHelper';\n\ndeclare var exports: any;\ndeclare var module: any;\ndeclare var define: any;\ndeclare var require: any;\ndeclare var window: any;\n\n(function (addon) {\n  if (typeof window !== 'undefined' && 'Terminal' in window) {\n    /**\n     * Plain browser environment\n     */\n    addon(window.Terminal);\n  } else if (typeof exports === 'object' && typeof module === 'object') {\n    /**\n     * CommonJS environment\n     */\n    module.exports = addon(require('../../Terminal').Terminal);\n  } else if (typeof define === 'function') {\n    /**\n     * Require.js is available\n     */\n    define(['../../xterm'], addon);\n  }\n})((Terminal: any) => {\n  /**\n   * Find the next instance of the term, then scroll to and select it. If it\n   * doesn't exist, do nothing.\n   * @param term Tne search term.\n   * @return Whether a result was found.\n   */\n  Terminal.prototype.findNext = function(term: string): boolean {\n    if (!this._searchHelper) {\n      this.searchHelper = new SearchHelper(this);\n    }\n    return (<SearchHelper>this.searchHelper).findNext(term);\n  };\n\n  /**\n   * Find the previous instance of the term, then scroll to and select it. If it\n   * doesn't exist, do nothing.\n   * @param term Tne search term.\n   * @return Whether a result was found.\n   */\n  Terminal.prototype.findPrevious = function(term: string): boolean {\n    if (!this._searchHelper) {\n      this.searchHelper = new SearchHelper(this);\n    }\n    return (<SearchHelper>this.searchHelper).findPrevious(term);\n  };\n});\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n// import { ITerminal } from '../../Interfaces';\n// import { translateBufferLineToString } from '../../utils/BufferLine';\n\ninterface ISearchResult {\n  term: string;\n  col: number;\n  row: number;\n}\n\n/**\n * A class that knows how to search the terminal and how to display the results.\n */\nexport class SearchHelper {\n  constructor(private _terminal: any) {\n    // TODO: Search for multiple instances on 1 line\n    // TODO: Don't use the actual selection, instead use a \"find selection\" so multiple instances can be highlighted\n    // TODO: Highlight other instances in the viewport\n    // TODO: Support regex, case sensitivity, etc.\n  }\n\n  /**\n   * Find the next instance of the term, then scroll to and select it. If it\n   * doesn't exist, do nothing.\n   * @param term Tne search term.\n   * @return Whether a result was found.\n   */\n  public findNext(term: string): boolean {\n    if (!term || term.length === 0) {\n      return false;\n    }\n\n    let result: ISearchResult;\n\n    let startRow = this._terminal.buffer.ydisp;\n    if (this._terminal.selectionManager.selectionEnd) {\n      // Start from the selection end if there is a selection\n      startRow = this._terminal.selectionManager.selectionEnd[1];\n    }\n\n    // Search from ydisp + 1 to end\n    for (let y = startRow + 1; y < this._terminal.buffer.ybase + this._terminal.rows; y++) {\n      result = this._findInLine(term, y);\n      if (result) {\n        break;\n      }\n    }\n\n    // Search from the top to the current ydisp\n    if (!result) {\n      for (let y = 0; y < startRow; y++) {\n        result = this._findInLine(term, y);\n        if (result) {\n          break;\n        }\n      }\n    }\n\n    // Set selection and scroll if a result was found\n    return this._selectResult(result);\n  }\n\n  /**\n   * Find the previous instance of the term, then scroll to and select it. If it\n   * doesn't exist, do nothing.\n   * @param term Tne search term.\n   * @return Whether a result was found.\n   */\n  public findPrevious(term: string): boolean {\n    if (!term || term.length === 0) {\n      return false;\n    }\n\n    let result: ISearchResult;\n\n    let startRow = this._terminal.buffer.ydisp;\n    if (this._terminal.selectionManager.selectionStart) {\n      // Start from the selection end if there is a selection\n      startRow = this._terminal.selectionManager.selectionStart[1];\n    }\n\n    // Search from ydisp + 1 to end\n    for (let y = startRow - 1; y >= 0; y--) {\n      result = this._findInLine(term, y);\n      if (result) {\n        break;\n      }\n    }\n\n    // Search from the top to the current ydisp\n    if (!result) {\n      for (let y = this._terminal.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {\n        result = this._findInLine(term, y);\n        if (result) {\n          break;\n        }\n      }\n    }\n\n    // Set selection and scroll if a result was found\n    return this._selectResult(result);\n  }\n\n  /**\n   * Searches a line for a search term.\n   * @param term Tne search term.\n   * @param y The line to search.\n   * @return The search result if it was found.\n   */\n  private _findInLine(term: string, y: number): ISearchResult {\n    const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase();\n    const lowerTerm = term.toLowerCase();\n    const searchIndex = lowerStringLine.indexOf(lowerTerm);\n    if (searchIndex >= 0) {\n      return {\n        term,\n        col: searchIndex,\n        row: y\n      };\n    }\n  }\n\n  /**\n   * Selects and scrolls to a result.\n   * @param result The result to select.\n   * @return Whethera result was selected.\n   */\n  private _selectResult(result: ISearchResult): boolean {\n    if (!result) {\n      return false;\n    }\n    this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length);\n    this._terminal.scrollLines(result.row - this._terminal.buffer.ydisp, false);\n    return true;\n  }\n}\n",null],"names":[],"mappings":"AEAA;;;ADiBA;AACA;AAAA;AAKA;AAQA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAQA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AA1Ha;;;;;;;ADZb;AAQA;AACA;AAIA;AACA;AAAA;AAIA;AACA;AAAA;AAIA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;;;"}