aboutsummaryrefslogtreecommitdiff
path: root/src/services/completion/completion.js
blob: df83d03d143f4ed20e4398f661306e03458b4d9a (plain)
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
70
import { reduce, find } from 'lodash'

export const replaceWord = (str, toReplace, replacement) => {
  return str.slice(0, toReplace.start) + replacement + str.slice(toReplace.end)
}

export const wordAtPosition = (str, pos) => {
  const words = splitIntoWords(str)
  const wordsWithPosition = addPositionToWords(words)

  return find(wordsWithPosition, ({ start, end }) => start <= pos && end > pos)
}

export const addPositionToWords = (words) => {
  return reduce(words, (result, word) => {
    const data = {
      word,
      start: 0,
      end: word.length
    }

    if (result.length > 0) {
      const previous = result.pop()

      data.start += previous.end
      data.end += previous.end

      result.push(previous)
    }

    result.push(data)

    return result
  }, [])
}

export const splitIntoWords = (str) => {
  // Split at word boundaries
  const regex = /\b/
  const triggers = /[@#:]+$/

  let split = str.split(regex)

  // Add trailing @ and # to the following word.
  const words = reduce(split, (result, word) => {
    if (result.length > 0) {
      let previous = result.pop()
      const matches = previous.match(triggers)
      if (matches) {
        previous = previous.replace(triggers, '')
        word = matches[0] + word
      }
      result.push(previous)
    }
    result.push(word)

    return result
  }, [])

  return words
}

const completion = {
  wordAtPosition,
  addPositionToWords,
  splitIntoWords,
  replaceWord
}

export default completion