aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/editor/findOccurrences.ts
blob: 00dffc9650b082321700a9722350ebc42429a367 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
 *
 * SPDX-License-Identifier: EPL-2.0
 */

import {
  type Range,
  RangeSet,
  type TransactionSpec,
  type EditorState,
} from '@codemirror/state';
import { Decoration } from '@codemirror/view';

import defineDecorationSetExtension from './defineDecorationSetExtension';

export interface IOccurrence {
  from: number;

  to: number;
}

const [setOccurrencesInteral, findOccurrences] = defineDecorationSetExtension();

const writeDecoration = Decoration.mark({
  class: 'cm-problem-write',
});

const readDecoration = Decoration.mark({
  class: 'cm-problem-read',
});

export function setOccurrences(
  write: IOccurrence[],
  read: IOccurrence[],
): TransactionSpec {
  const decorations: Range<Decoration>[] = [];
  write.forEach(({ from, to }) => {
    decorations.push(writeDecoration.range(from, to));
  });
  read.forEach(({ from, to }) => {
    decorations.push(readDecoration.range(from, to));
  });
  const rangeSet = RangeSet.of(decorations, true);
  return setOccurrencesInteral(rangeSet);
}

export function isCursorWithinOccurence(state: EditorState): boolean {
  const occurrences = state.field(findOccurrences, false);
  if (occurrences === undefined) {
    return false;
  }
  const {
    selection: {
      main: { from, to },
    },
  } = state;
  let found = false;
  occurrences.between(from, to, (decorationFrom, decorationTo) => {
    if (decorationFrom <= from && to <= decorationTo) {
      found = true;
      return false;
    }
    return undefined;
  });
  return found;
}

export default findOccurrences;