UNPKG

25.8 kBSource Map (JSON)View Raw
1{"version":3,"sources":["webpack://SearchAddon/webpack/universalModuleDefinition","webpack://SearchAddon/webpack/bootstrap","webpack://SearchAddon/./src/SearchAddon.ts"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","_linesCacheTimeoutId","activate","terminal","this","_terminal","dispose","findNext","term","searchOptions","Error","length","clearSelection","currentSelection","startCol","startRow","hasSelection","incremental","getSelectionPosition","endRow","startColumn","endColumn","_initLinesCache","searchPosition","result","_findInLine","y","buffer","active","baseY","rows","_selectResult","findPrevious","cols","row","col","Math","max","_linesCache","Array","_cursorMoveListener","onCursorMove","_destroyLinesCache","_resizeListener","onResize","clearTimeout","setTimeout","undefined","_isWholeWord","searchIndex","line","indexOf","isReverseSearch","firstLine","getLine","isWrapped","stringLine","_translateBufferLineToStringWithWrap","searchTerm","caseSensitive","toLowerCase","searchStringLine","resultIndex","regex","searchRegex","RegExp","foundTerm","exec","slice","lastIndex","lastIndexOf","floor","wholeWord","cell","getCell","char","getChars","getWidth","lineIndex","trimRight","lineWrapsToNext","lineString","nextLine","translateToString","substring","select","viewportY","scrollLines","SearchAddon"],"mappings":"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","file":"xterm-addon-search.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"SearchAddon\"] = factory();\n\telse\n\t\troot[\"SearchAddon\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Terminal, IDisposable, ITerminalAddon, ISelectionPosition } from 'xterm';\n\nexport interface ISearchOptions {\n regex?: boolean;\n wholeWord?: boolean;\n caseSensitive?: boolean;\n incremental?: boolean;\n}\n\nexport interface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n}\n\nconst NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\;:\"\\',./<>?';\nconst LINES_CACHE_TIME_TO_LIVE = 15 * 1000; // 15 secs\n\nexport class SearchAddon implements ITerminalAddon {\n private _terminal: Terminal | undefined;\n\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: string[] | undefined;\n private _linesCacheTimeoutId = 0;\n private _cursorMoveListener: IDisposable | undefined;\n private _resizeListener: IDisposable | undefined;\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n }\n\n public dispose(): void { }\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 The search term.\n * @param searchOptions Search options.\n * @return Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions): boolean {\n if (!this._terminal) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return false;\n }\n\n let startCol = 0;\n let startRow = 0;\n let currentSelection: ISelectionPosition | undefined;\n if (this._terminal.hasSelection()) {\n const incremental = searchOptions ? searchOptions.incremental : false;\n // Start from the selection end if there is a selection\n // For incremental search, use existing row\n currentSelection = this._terminal.getSelectionPosition()!;\n startRow = incremental ? currentSelection.startRow : currentSelection.endRow;\n startCol = incremental ? currentSelection.startColumn : currentSelection.endColumn;\n }\n\n this._initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n\n // Search from startRow + 1 to end\n if (!result) {\n\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n // If the current line is wrapped line, increase index of column to ignore the previous scan\n // Otherwise, reset beginning column index to zero with set new unwrapped line index\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && currentSelection) {\n searchPosition.startRow = currentSelection.startRow;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\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 The search term.\n * @param searchOptions Search options.\n * @return Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions): boolean {\n if (!this._terminal) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return false;\n }\n\n const isReverseSearch = true;\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows;\n let startCol = this._terminal.cols;\n let result: ISearchResult | undefined;\n const incremental = searchOptions ? searchOptions.incremental : false;\n let currentSelection: ISelectionPosition | undefined;\n if (this._terminal.hasSelection()) {\n currentSelection = this._terminal.getSelectionPosition()!;\n // Start from selection start if there is a selection\n startRow = currentSelection.startRow;\n startCol = currentSelection.startColumn;\n }\n\n this._initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n if (incremental) {\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!(result && result.row === startRow && result.col === startCol)) {\n result = this._findInLine(term, searchPosition, searchOptions, true);\n }\n } else {\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n }\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, return true.\n if (!result && currentSelection) return true;\n\n // Set selection and scroll if a result was found\n return this._selectResult(result);\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n private _initLinesCache(): void {\n const terminal = this._terminal!;\n if (!this._linesCache) {\n this._linesCache = new Array(terminal.buffer.active.length);\n this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache());\n this._resizeListener = terminal.onResize(() => this._destroyLinesCache());\n }\n\n window.clearTimeout(this._linesCacheTimeoutId);\n this._linesCacheTimeoutId = window.setTimeout(() => this._destroyLinesCache(), LINES_CACHE_TIME_TO_LIVE);\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n if (this._cursorMoveListener) {\n this._cursorMoveListener.dispose();\n this._cursorMoveListener = undefined;\n }\n if (this._resizeListener) {\n this._resizeListener.dispose();\n this._resizeListener = undefined;\n }\n if (this._linesCacheTimeoutId) {\n window.clearTimeout(this._linesCacheTimeoutId);\n this._linesCacheTimeoutId = 0;\n }\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly adjacent to it.\n * @param searchIndex starting indext of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return (((searchIndex === 0) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex - 1]) !== -1)) &&\n (((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex + term.length]) !== -1)));\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line, which may contain\n * subsequent terminal lines if the text is wrapped. If the provided line number is part of a wrapped text line that\n * started on an earlier line then it is skipped since it will be properly searched when the terminal line that the\n * text starts on is searched.\n * @param term The search term.\n * @param position The position to start the search.\n * @param searchOptions Search options.\n * @return The search result if it was found.\n */\n protected _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n const terminal = this._terminal!;\n let row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n const firstLine = terminal.buffer.active.getLine(row);\n if (firstLine && firstLine.isWrapped) {\n if (isReverseSearch) {\n searchPosition.startCol += terminal.cols;\n return;\n }\n\n // This will iterate until we find the line start.\n // When we find it, we will search using the calculated start column.\n searchPosition.startRow--;\n searchPosition.startCol += terminal.cols;\n return this._findInLine(term, searchPosition, searchOptions);\n }\n let stringLine = this._linesCache ? this._linesCache[row] : void 0;\n if (stringLine === void 0) {\n stringLine = this._translateBufferLineToStringWithWrap(row, true);\n if (this._linesCache) {\n this._linesCache[row] = stringLine;\n }\n }\n\n const searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n const searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, 'g');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..col\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, col))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(col));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = col + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (col - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, col - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, col);\n }\n }\n\n if (resultIndex >= 0) {\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple rows\n if (resultIndex >= terminal.cols) {\n row += Math.floor(resultIndex / terminal.cols);\n resultIndex = resultIndex % terminal.cols;\n }\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n const line = terminal.buffer.active.getLine(row);\n\n if (line) {\n for (let i = 0; i < resultIndex; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n resultIndex -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const charWidth = cell.getWidth();\n if (charWidth === 0) {\n resultIndex++;\n }\n }\n }\n return {\n term,\n col: resultIndex,\n row\n };\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param line The line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n private _translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string {\n const terminal = this._terminal!;\n let lineString = '';\n let lineWrapsToNext: boolean;\n\n do {\n const nextLine = terminal.buffer.active.getLine(lineIndex + 1);\n lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n const line = terminal.buffer.active.getLine(lineIndex);\n if (!line) {\n break;\n }\n lineString += line.translateToString(!lineWrapsToNext && trimRight).substring(0, terminal.cols);\n lineIndex++;\n } while (lineWrapsToNext);\n\n return lineString;\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 | undefined): boolean {\n const terminal = this._terminal!;\n if (!result) {\n terminal.clearSelection();\n return false;\n }\n terminal.select(result.col, result.row, result.term.length);\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (terminal.buffer.active.viewportY + terminal.rows) || result.row < terminal.buffer.active.viewportY) {\n let scroll = result.row - terminal.buffer.active.viewportY;\n scroll = scroll - Math.floor(terminal.rows / 2);\n terminal.scrollLines(scroll);\n }\n return true;\n }\n}\n"],"sourceRoot":""}
\No newline at end of file