protected _findInLine()

in src/addons/search/SearchHelper.ts [124:177]


  protected _findInLine(term: string, y: number, searchOptions: ISearchOptions = {}): ISearchResult {
    if (this._terminal._core.buffer.lines.get(y).isWrapped) {
      return;
    }

    const stringLine = this.translateBufferLineToStringWithWrap(y, true);
    const searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();
    const searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();
    let searchIndex = -1;

    if (searchOptions.regex) {
      const searchRegex = RegExp(searchTerm, 'g');
      const foundTerm = searchRegex.exec(searchStringLine);
      if (foundTerm && foundTerm[0].length > 0) {
        searchIndex = searchRegex.lastIndex - foundTerm[0].length;
        term = foundTerm[0];
      }
    } else {
      searchIndex = searchStringLine.indexOf(searchTerm);
    }

    if (searchIndex >= 0) {
      // Adjust the row number and search index if needed since a "line" of text can span multiple rows
      if (searchIndex >= this._terminal.cols) {
        y += Math.floor(searchIndex / this._terminal.cols);
        searchIndex = searchIndex % this._terminal.cols;
      }
      if (searchOptions.wholeWord && !this._isWholeWord(searchIndex, searchStringLine, term)) {
        return;
      }

      const line = this._terminal._core.buffer.lines.get(y);

      for (let i = 0; i < searchIndex; i++) {
        const charData = line.get(i);
        // Adjust the searchIndex to normalize emoji into single chars
        const char = charData[1/*CHAR_DATA_CHAR_INDEX*/];
        if (char.length > 1) {
          searchIndex -= char.length - 1;
        }
        // Adjust the searchIndex for empty characters following wide unicode
        // chars (eg. CJK)
        const charWidth = charData[2/*CHAR_DATA_WIDTH_INDEX*/];
        if (charWidth === 0) {
          searchIndex++;
        }
      }
      return {
        term,
        col: searchIndex,
        row: y
      };
    }
  }