tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

source-search.js (3840B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 import buildQuery from "../build-query";
      6 
      7 /**
      8 * @memberof utils/source-search
      9 * @static
     10 */
     11 function SearchState() {
     12  this.posFrom = this.posTo = this.query = null;
     13  this.overlay = null;
     14  this.results = [];
     15 }
     16 
     17 /**
     18 * @memberof utils/source-search
     19 * @static
     20 */
     21 function getSearchState(cm) {
     22  const state = cm.state.search || (cm.state.search = new SearchState());
     23  return state;
     24 }
     25 
     26 function isWhitespace(query) {
     27  return !query.match(/\S/);
     28 }
     29 
     30 export function getMatchIndex(count, currentIndex, rev) {
     31  if (!rev) {
     32    if (currentIndex == count - 1) {
     33      return 0;
     34    }
     35 
     36    return currentIndex + 1;
     37  }
     38 
     39  if (currentIndex == 0) {
     40    return count - 1;
     41  }
     42 
     43  return currentIndex - 1;
     44 }
     45 
     46 /**
     47 * If there's a saved search, selects the next results.
     48 * Otherwise, creates a new search and selects the first
     49 * result.
     50 *
     51 * @memberof utils/source-search
     52 * @static
     53 */
     54 function doSearch(
     55  ctx,
     56  rev,
     57  query,
     58  keepSelection,
     59  modifiers,
     60  { shouldScroll = true }
     61 ) {
     62  const { editor } = ctx;
     63  if (!query || isWhitespace(query)) {
     64    editor.clearSearchMatches();
     65    return null;
     66  }
     67  const regexQuery = buildQuery(query, modifiers, {
     68    ignoreSpaces: true,
     69    // regex must be global for the overlay
     70    isGlobal: true,
     71  });
     72 
     73  if (editor.searchState.query?.toString() !== regexQuery.toString()) {
     74    editor.highlightSearchMatches(regexQuery, "cm-highlight");
     75  }
     76  const cursor = editor.getNextSearchCursor(rev);
     77  if (!cursor) {
     78    return null;
     79  }
     80  editor.setPositionContentMarker({
     81    id: editor.markerTypes.ACTIVE_SELECTION_MARKER,
     82    positionClassName: "cm-matchhighlight",
     83    positions: [{ from: cursor.from, to: cursor.to }],
     84  });
     85  if (shouldScroll) {
     86    editor.scrollToPosition(cursor.from);
     87  }
     88  return editor.getPositionFromSearchCursor(cursor);
     89 }
     90 
     91 export function searchSourceForHighlight(
     92  ctx,
     93  rev,
     94  query,
     95  keepSelection,
     96  modifiers
     97 ) {
     98  const { editor } = ctx;
     99  if (!query || isWhitespace(query)) {
    100    editor.clearSearchMatches();
    101    return;
    102  }
    103 
    104  const regexQuery = buildQuery(query, modifiers, {
    105    ignoreSpaces: true,
    106    // regex must be global for the overlay
    107    isGlobal: true,
    108  });
    109 
    110  if (editor.searchState.query?.toString() !== regexQuery.toString()) {
    111    editor.highlightSearchMatches(regexQuery, "cm-highlight");
    112  }
    113 }
    114 
    115 /**
    116 * Remove overlay.
    117 *
    118 * @memberof utils/source-search
    119 * @static
    120 */
    121 export function removeOverlay(ctx) {
    122  const state = getSearchState(ctx.cm);
    123  ctx.cm.removeOverlay(state.overlay);
    124  const { line, ch } = ctx.cm.getCursor();
    125  ctx.cm.doc.setSelection({ line, ch }, { line, ch }, { scroll: false });
    126 }
    127 
    128 /**
    129 * Clears the currently saved search.
    130 *
    131 * @memberof utils/source-search
    132 * @static
    133 */
    134 export function clearSearch(ctx) {
    135  const { editor } = ctx;
    136  editor.clearSearchMatches();
    137  editor.removePositionContentMarker("active-selection-marker");
    138 }
    139 
    140 /**
    141 * Starts a new search.
    142 *
    143 * @memberof utils/source-search
    144 * @static
    145 */
    146 export function find(ctx, query, keepSelection, modifiers, options) {
    147  clearSearch(ctx);
    148  return doSearch(ctx, false, query, keepSelection, modifiers, options);
    149 }
    150 
    151 /**
    152 * Finds the next item based on the currently saved search.
    153 *
    154 * @memberof utils/source-search
    155 * @static
    156 */
    157 export function findNext(ctx, query, keepSelection, modifiers) {
    158  return doSearch(ctx, false, query, keepSelection, modifiers, {});
    159 }
    160 
    161 /**
    162 * Finds the previous item based on the currently saved search.
    163 *
    164 * @memberof utils/source-search
    165 * @static
    166 */
    167 export function findPrev(ctx, query, keepSelection, modifiers) {
    168  return doSearch(ctx, true, query, keepSelection, modifiers, {});
    169 }
    170 
    171 export { buildQuery };