clarity-pattern-parser 11.3.10 → 11.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/dist/ast/Node.test.d.ts +1 -0
  3. package/dist/grammar/Grammar.test.d.ts +1 -0
  4. package/dist/grammar/patterns.test.d.ts +1 -0
  5. package/dist/index.browser.js +196 -113
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.esm.js +196 -113
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +196 -113
  10. package/dist/index.js.map +1 -1
  11. package/dist/intellisense/AutoComplete.d.ts +26 -8
  12. package/dist/intellisense/AutoComplete.test.d.ts +2 -0
  13. package/dist/intellisense/SuggestionOption.d.ts +18 -2
  14. package/dist/intellisense/css/cssValue.d.ts +3 -0
  15. package/dist/intellisense/css/divider.d.ts +3 -0
  16. package/dist/intellisense/css/hex.d.ts +3 -0
  17. package/dist/intellisense/css/method.d.ts +3 -0
  18. package/dist/intellisense/css/name.d.ts +3 -0
  19. package/dist/intellisense/css/number.d.ts +3 -0
  20. package/dist/intellisense/css/optionalSpaces.d.ts +2 -0
  21. package/dist/intellisense/css/spaces.d.ts +3 -0
  22. package/dist/intellisense/css/unit.d.ts +3 -0
  23. package/dist/intellisense/css/value.d.ts +3 -0
  24. package/dist/intellisense/css/values.d.ts +3 -0
  25. package/dist/intellisense/javascript/Javascript.test.d.ts +1 -0
  26. package/dist/intellisense/javascript/arrayLiteral.d.ts +2 -0
  27. package/dist/intellisense/javascript/assignment.d.ts +3 -0
  28. package/dist/intellisense/javascript/deleteStatement.d.ts +2 -0
  29. package/dist/intellisense/javascript/escapedCharacter.d.ts +3 -0
  30. package/dist/intellisense/javascript/exponent.d.ts +3 -0
  31. package/dist/intellisense/javascript/expression.d.ts +3 -0
  32. package/dist/intellisense/javascript/fraction.d.ts +3 -0
  33. package/dist/intellisense/javascript/infixOperator.d.ts +3 -0
  34. package/dist/intellisense/javascript/integer.d.ts +3 -0
  35. package/dist/intellisense/javascript/invocation.d.ts +2 -0
  36. package/dist/intellisense/javascript/keywords.d.ts +2 -0
  37. package/dist/intellisense/javascript/literal.d.ts +3 -0
  38. package/dist/intellisense/javascript/name.d.ts +2 -0
  39. package/dist/intellisense/javascript/numberLiteral.d.ts +2 -0
  40. package/dist/intellisense/javascript/objectAccess.d.ts +2 -0
  41. package/dist/intellisense/javascript/objectLiteral.d.ts +3 -0
  42. package/dist/intellisense/javascript/optionalSpaces.d.ts +2 -0
  43. package/dist/intellisense/javascript/parameters.d.ts +3 -0
  44. package/dist/intellisense/javascript/prefixOperator.d.ts +3 -0
  45. package/dist/intellisense/javascript/propertyAccess.d.ts +3 -0
  46. package/dist/intellisense/javascript/stringLiteral.d.ts +3 -0
  47. package/dist/patterns/Context.test.d.ts +1 -0
  48. package/dist/patterns/Cursor.test.d.ts +1 -0
  49. package/dist/patterns/CursorHistory.test.d.ts +1 -0
  50. package/dist/patterns/Expression.test.d.ts +1 -0
  51. package/dist/patterns/FiniteRepeat.test.d.ts +1 -0
  52. package/dist/patterns/InfiniteRepeat.test.d.ts +1 -0
  53. package/dist/patterns/Literal.test.d.ts +1 -0
  54. package/dist/patterns/Not.test.d.ts +1 -0
  55. package/dist/patterns/Optional.test.d.ts +1 -0
  56. package/dist/patterns/Options.test.d.ts +1 -0
  57. package/dist/patterns/PrecedenceTree.test.d.ts +1 -0
  58. package/dist/patterns/Reference.test.d.ts +1 -0
  59. package/dist/patterns/Regex.test.d.ts +1 -0
  60. package/dist/patterns/Repeat.test.d.ts +1 -0
  61. package/dist/patterns/Sequence.test.d.ts +1 -0
  62. package/dist/patterns/TakeUntil.test.d.ts +1 -0
  63. package/dist/query/query.test.d.ts +1 -0
  64. package/dist/query/selector.test.d.ts +1 -0
  65. package/jest.config.js +3 -1
  66. package/jest.coverage.config.js +2 -0
  67. package/package.json +7 -6
  68. package/src/grammar/Grammar.test.ts +1 -0
  69. package/src/grammar/Grammar.ts +2 -0
  70. package/src/grammar/patterns.test.ts +36 -0
  71. package/src/grammar/spec.md +233 -84
  72. package/src/intellisense/AutoComplete.test.ts +627 -158
  73. package/src/intellisense/AutoComplete.ts +233 -110
  74. package/src/intellisense/SuggestionOption.ts +25 -2
  75. package/src/intellisense/css/optionalSpaces.ts +1 -1
  76. package/src/intellisense/css/value.ts +1 -1
  77. package/src/patterns/Expression.ts +4 -2
  78. package/src/patterns/Literal.test.ts +1 -1
  79. package/src/patterns/Options.test.ts +1 -1
  80. package/src/patterns/PrecedenceTree.ts +31 -7
  81. package/src/patterns/Reference.test.ts +1 -1
  82. package/src/patterns/Regex.test.ts +3 -3
  83. package/src/patterns/Sequence.test.ts +1 -1
  84. package/tsconfig.json +1 -1
  85. package/dist/Cursor.d.ts +0 -37
  86. package/dist/CursorHistory.d.ts +0 -27
  87. package/dist/TextSuggester.d.ts +0 -48
  88. package/dist/ast/Visitor.d.ts +0 -31
  89. package/dist/grammar/patterns/andLiteral.d.ts +0 -4
  90. package/dist/grammar/patterns/inlinePattern.d.ts +0 -1
  91. package/dist/grammar/patterns/orLiteral.d.ts +0 -2
  92. package/dist/patterns/And.d.ts +0 -41
  93. package/dist/patterns/DepthCache.d.ts +0 -6
  94. package/dist/patterns/ExpressionPattern.d.ts +0 -66
  95. package/dist/patterns/LookAhead.d.ts +0 -8
  96. package/dist/patterns/Or.d.ts +0 -36
  97. package/dist/patterns/Recursive.d.ts +0 -12
  98. package/dist/patterns/RightAssociatedPattern.d.ts +0 -31
  99. package/dist/patterns/arePatternsEqual.d.ts +0 -2
  100. package/dist/patterns/getNextPattern.d.ts +0 -2
  101. package/dist/types.d.ts +0 -797
  102. package/src/generator/generator.test.ts +0 -27
  103. package/src/generator/generator.ts +0 -103
  104. package/src/generator/igenerator.ts +0 -6
  105. package/src/generator/ivisitor.ts +0 -23
  106. package/src/generator/typescriptVisitor.ts +0 -158
package/dist/index.esm.js CHANGED
@@ -2717,13 +2717,36 @@ class PrecedenceTree {
2717
2717
  }
2718
2718
  _compileAtomNode() {
2719
2719
  let node = this._atomNode;
2720
- if (this._prefixNode != null && this._atomNode != null) {
2721
- node = this._prefixNode.findRoot();
2722
- this._prefixPlaceholder.replaceWith(this._atomNode);
2720
+ if (this._prefixNode != null && this._postfixNode != null && this._atomNode != null) {
2721
+ let firstNode = this._prefixNode;
2722
+ let secondNode = this._postfixNode;
2723
+ let firstPlaceholder = this._prefixPlaceholder;
2724
+ let secondPlaceholder = this._postfixPlaceholder;
2725
+ const prefixName = this._prefixNode.name;
2726
+ const postfixName = this._postfixNode.name;
2727
+ const prefixPrecedence = this._getPrecedence(prefixName);
2728
+ const postfixPrecedence = this._getPrecedence(postfixName);
2729
+ // The Precedence is the index of the patterns, so its lower not higher :\
2730
+ if (prefixPrecedence > postfixPrecedence) {
2731
+ firstNode = this._postfixNode;
2732
+ secondNode = this._prefixNode;
2733
+ firstPlaceholder = this._postfixPlaceholder;
2734
+ secondPlaceholder = this._prefixPlaceholder;
2735
+ }
2736
+ node = firstNode.findRoot();
2737
+ firstPlaceholder.replaceWith(this._atomNode);
2738
+ secondPlaceholder.replaceWith(node);
2739
+ node = secondNode;
2723
2740
  }
2724
- if (this._postfixNode != null && node != null) {
2725
- this._postfixPlaceholder.replaceWith(node);
2726
- node = this._postfixNode;
2741
+ else {
2742
+ if (this._prefixNode != null && this._atomNode != null) {
2743
+ node = this._prefixNode.findRoot();
2744
+ this._prefixPlaceholder.replaceWith(this._atomNode);
2745
+ }
2746
+ if (this._postfixNode != null && node != null) {
2747
+ this._postfixPlaceholder.replaceWith(node);
2748
+ node = this._postfixNode;
2749
+ }
2727
2750
  }
2728
2751
  this._prefixNode = null;
2729
2752
  this._atomNode = null;
@@ -2831,7 +2854,7 @@ class Expression {
2831
2854
  }
2832
2855
  _organizePatterns(patterns) {
2833
2856
  const finalPatterns = [];
2834
- patterns.forEach((pattern) => {
2857
+ patterns.forEach((pattern, index) => {
2835
2858
  if (this._isAtom(pattern)) {
2836
2859
  const atom = pattern.clone();
2837
2860
  atom.parent = this;
@@ -2842,6 +2865,7 @@ class Expression {
2842
2865
  const name = this._extractName(pattern);
2843
2866
  const prefix = this._extractPrefix(pattern);
2844
2867
  prefix.parent = this;
2868
+ this._precedenceMap[name] = index;
2845
2869
  this._prefixPatterns.push(prefix);
2846
2870
  this._prefixNames.push(name);
2847
2871
  finalPatterns.push(prefix);
@@ -2850,6 +2874,7 @@ class Expression {
2850
2874
  const name = this._extractName(pattern);
2851
2875
  const postfix = this._extractPostfix(pattern);
2852
2876
  postfix.parent = this;
2877
+ this._precedenceMap[name] = index;
2853
2878
  this._postfixPatterns.push(postfix);
2854
2879
  this._postfixNames.push(name);
2855
2880
  finalPatterns.push(postfix);
@@ -2858,7 +2883,7 @@ class Expression {
2858
2883
  const name = this._extractName(pattern);
2859
2884
  const binary = this._extractBinary(pattern);
2860
2885
  binary.parent = this;
2861
- this._precedenceMap[name] = this._binaryPatterns.length;
2886
+ this._precedenceMap[name] = index;
2862
2887
  this._binaryPatterns.push(binary);
2863
2888
  this._binaryNames.push(name);
2864
2889
  if (pattern.type === "right-associated") {
@@ -3656,6 +3681,8 @@ class Grammar {
3656
3681
  return this._isRecursivePattern(name, pattern);
3657
3682
  }
3658
3683
  _isRecursivePattern(name, pattern) {
3684
+ // Because we don't know if the pattern is a sequence with a reference we have to just assume it is.
3685
+ // The better solution here would be to not have options at all and just use expresssion pattern instead.
3659
3686
  if (pattern.type === "reference") {
3660
3687
  return true;
3661
3688
  }
@@ -4007,26 +4034,30 @@ class AutoComplete {
4007
4034
  this._options = options;
4008
4035
  this._text = "";
4009
4036
  }
4037
+ suggestFor(text) {
4038
+ return this.suggestForWithCursor(new Cursor(text));
4039
+ }
4010
4040
  suggestForWithCursor(cursor) {
4011
4041
  cursor.moveTo(0);
4012
4042
  this._cursor = cursor;
4013
4043
  this._text = cursor.text;
4014
4044
  this._cursor.startRecording();
4015
4045
  if (cursor.length === 0) {
4016
- return {
4046
+ const suggestion = {
4017
4047
  isComplete: false,
4018
- options: this._createSuggestionsFromRoot(),
4048
+ options: this._createSuggestionOptionsFromMatch(),
4019
4049
  error: new ParseError(0, 0, this._pattern),
4020
4050
  errorAtIndex: 0,
4021
4051
  cursor,
4022
4052
  ast: null
4023
4053
  };
4054
+ return suggestion;
4024
4055
  }
4025
4056
  let errorAtIndex = null;
4026
4057
  let error = null;
4027
4058
  const ast = this._pattern.parse(this._cursor);
4028
4059
  const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === this._text;
4029
- const options = this._getAllOptions();
4060
+ const options = this._getAllSuggestionsOptions();
4030
4061
  if (!isComplete && options.length > 0 && !this._cursor.hasError) {
4031
4062
  const startIndex = options.reduce((lowestIndex, o) => {
4032
4063
  return Math.min(lowestIndex, o.startIndex);
@@ -4073,150 +4104,202 @@ class AutoComplete {
4073
4104
  }
4074
4105
  return 0;
4075
4106
  }
4076
- suggestFor(text) {
4077
- return this.suggestForWithCursor(new Cursor(text));
4078
- }
4079
- _getAllOptions() {
4080
- const errorMatches = this._getOptionsFromErrors();
4081
- const leafMatches = this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
4107
+ _getAllSuggestionsOptions() {
4108
+ const errorMatchOptions = this._createSuggestionOptionsFromErrors();
4109
+ const leafMatchOptions = this._cursor.leafMatches.map((m) => this._createSuggestionOptionsFromMatch(m)).flat();
4082
4110
  const finalResults = [];
4083
- [...leafMatches, ...errorMatches].forEach(m => {
4111
+ [...leafMatchOptions, ...errorMatchOptions].forEach(m => {
4084
4112
  const index = finalResults.findIndex(f => m.text === f.text);
4085
4113
  if (index === -1) {
4086
4114
  finalResults.push(m);
4087
4115
  }
4088
4116
  });
4089
- return finalResults;
4117
+ return getFurthestOptions(finalResults);
4090
4118
  }
4091
- _getOptionsFromErrors() {
4119
+ _createSuggestionOptionsFromErrors() {
4092
4120
  // These errored because the length of the string.
4093
4121
  const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length);
4094
- const suggestions = errors.map(e => {
4095
- const tokens = this._getTokensForPattern(e.pattern);
4096
- const adjustedTokens = new Set();
4097
- const currentText = this._cursor.getChars(e.startIndex, e.lastIndex);
4098
- tokens.forEach((token) => {
4099
- if (token.startsWith(currentText) && token.length > currentText.length) {
4100
- const difference = token.length - currentText.length;
4101
- const suggestedText = token.slice(-difference);
4102
- adjustedTokens.add(suggestedText);
4103
- }
4104
- });
4105
- return Array.from(adjustedTokens).map(t => {
4106
- return {
4107
- text: t,
4108
- startIndex: e.lastIndex,
4109
- };
4110
- });
4111
- });
4112
- return suggestions.flat();
4113
- }
4114
- _createSuggestionsFromRoot() {
4115
- const suggestions = [];
4116
- const tokens = [...this._pattern.getTokens(), ...this._getTokensForPattern(this._pattern)];
4117
- for (const token of tokens) {
4118
- if (suggestions.findIndex(s => s.text === token) === -1) {
4119
- suggestions.push(this._createSuggestion("", token));
4120
- }
4121
- }
4122
- return suggestions;
4123
- }
4124
- _createSuggestionsFromMatch(match) {
4125
- if (match.pattern == null) {
4126
- return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
4127
- }
4128
- if (match.node != null) {
4129
- const textStartingMatch = this._text.slice(match.node.startIndex, match.node.endIndex);
4130
- const currentPatternsTokens = this._getTokensForPattern(match.pattern);
4131
- /**
4132
- * Compares tokens to current text and extracts remainder tokens
4133
- * - IE. **currentText:** *abc*, **baseToken:** *abcdef*, **trailingToken:** *def*
4134
- */
4135
- const trailingTokens = currentPatternsTokens.reduce((acc, token) => {
4136
- if (token.startsWith(textStartingMatch)) {
4137
- const sliced = token.slice(textStartingMatch.length);
4138
- if (sliced !== '') {
4139
- acc.push(sliced);
4140
- }
4141
- }
4142
- return acc;
4143
- }, []);
4122
+ const errorSuggestionOptions = errors.map(parseError => {
4123
+ const currentText = this._cursor.getChars(parseError.startIndex, parseError.lastIndex);
4124
+ const compositeSuggestions = this._getCompositeSuggestionsForPattern(parseError.pattern);
4125
+ const trimmedErrorCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, compositeSuggestions);
4126
+ return this._createSuggestions(parseError.lastIndex, trimmedErrorCompositeSuggestions);
4127
+ }).flat();
4128
+ const dedupedErrorSuggestionOptions = this._deDupeCompositeSuggestions(errorSuggestionOptions);
4129
+ return dedupedErrorSuggestionOptions;
4130
+ }
4131
+ _createSuggestionOptionsFromMatch(match) {
4132
+ if ((match === null || match === void 0 ? void 0 : match.pattern) == null) {
4133
+ const compositeSuggestions = this._getCompositeSuggestionsForPattern(this._pattern);
4134
+ return this._createSuggestions(-1, compositeSuggestions);
4135
+ }
4136
+ if ((match === null || match === void 0 ? void 0 : match.node) != null) {
4137
+ const currentText = this._text.slice(match.node.startIndex, match.node.endIndex);
4138
+ /**Captures suggestions for a "completed" match pattern that still has existing possible suggestions.
4139
+ * particularly relevant when working with set/custom tokens.
4140
+ */
4141
+ const matchCompositeSuggestions = this._getCompositeSuggestionsForPattern(match.pattern);
4142
+ const trimmedMatchCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, matchCompositeSuggestions);
4144
4143
  const leafPatterns = match.pattern.getNextPatterns();
4145
- const leafTokens = leafPatterns.reduce((acc, leafPattern) => {
4146
- acc.push(...this._getTokensForPattern(leafPattern));
4147
- return acc;
4148
- }, []);
4149
- const allTokens = [...trailingTokens, ...leafTokens];
4150
- return this._createSuggestions(match.node.lastIndex, allTokens);
4144
+ const leafCompositeSuggestions = leafPatterns.flatMap(leafPattern => this._getCompositeSuggestionsForPattern(leafPattern));
4145
+ const allCompositeSuggestions = [...leafCompositeSuggestions, ...trimmedMatchCompositeSuggestions,];
4146
+ const dedupedCompositeSuggestions = this._deDupeCompositeSuggestions(allCompositeSuggestions);
4147
+ return this._createSuggestions(match.node.lastIndex, dedupedCompositeSuggestions);
4151
4148
  }
4152
4149
  else {
4153
4150
  return [];
4154
4151
  }
4155
4152
  }
4156
- _getTokensForPattern(pattern) {
4157
- const augmentedTokens = this._getAugmentedTokens(pattern);
4153
+ /**
4154
+ * Compares suggestions with provided text and removes completed sub-sequences and preceding text
4155
+ * - IE. **currentText:** *abc*, **sequence:** *[{ab}{cd}{ef}*
4156
+ * - refines to {d}{ef}
4157
+ */
4158
+ _trimSuggestionsByExistingText(currentText, compositeSuggestions) {
4159
+ const trimmedSuggestions = compositeSuggestions.reduce((acc, compositeSuggestion) => {
4160
+ if (compositeSuggestion.text.startsWith(currentText)) {
4161
+ const filteredSegments = this._filterCompletedSubSegments(currentText, compositeSuggestion);
4162
+ const slicedSuggestionText = compositeSuggestion.text.slice(currentText.length);
4163
+ if (slicedSuggestionText !== '') {
4164
+ const refinedCompositeSuggestion = {
4165
+ text: slicedSuggestionText,
4166
+ suggestionSequence: filteredSegments,
4167
+ };
4168
+ acc.push(refinedCompositeSuggestion);
4169
+ }
4170
+ }
4171
+ return acc;
4172
+ }, []);
4173
+ return trimmedSuggestions;
4174
+ }
4175
+ /** Removed segments already accounted for in the existing text.
4176
+ * ie. sequence pattern segments ≈ [{look}, {an example}, {phrase}]
4177
+ * fullText = "look an"
4178
+ * remove {look} segment as its already been completed by the existing text.
4179
+ */
4180
+ _filterCompletedSubSegments(currentText, compositeSuggestion) {
4181
+ let elementsToRemove = [];
4182
+ let workingText = currentText;
4183
+ compositeSuggestion.suggestionSequence.forEach(segment => {
4184
+ /**sub segment has been completed, remove it from the sequence */
4185
+ if (workingText.startsWith(segment.text)) {
4186
+ workingText = workingText.slice(segment.text.length);
4187
+ elementsToRemove.push(segment);
4188
+ }
4189
+ });
4190
+ const filteredSegments = compositeSuggestion.suggestionSequence.filter(segment => !elementsToRemove.includes(segment));
4191
+ return filteredSegments;
4192
+ }
4193
+ _getCompositeSuggestionsForPattern(pattern) {
4194
+ const suggestionsToReturn = [];
4195
+ const leafPatterns = pattern.getPatterns();
4196
+ // for when pattern has no leafPatterns and only returns itself
4197
+ if (leafPatterns.length === 1 && leafPatterns[0].id === pattern.id) {
4198
+ const currentCustomTokens = this._getCustomTokens(pattern);
4199
+ const currentTokens = pattern.getTokens();
4200
+ const allTokens = [...currentCustomTokens, ...currentTokens];
4201
+ const leafCompositeSuggestions = allTokens.map(token => {
4202
+ const segment = {
4203
+ text: token,
4204
+ pattern: pattern,
4205
+ };
4206
+ const compositeSuggestion = {
4207
+ text: token,
4208
+ suggestionSequence: [segment],
4209
+ };
4210
+ return compositeSuggestion;
4211
+ });
4212
+ suggestionsToReturn.push(...leafCompositeSuggestions);
4213
+ }
4214
+ else {
4215
+ const currentCustomTokens = this._getCustomTokens(pattern);
4216
+ const patternsSuggestionList = currentCustomTokens.map(token => {
4217
+ const segment = {
4218
+ text: token,
4219
+ pattern: pattern,
4220
+ };
4221
+ const patternSuggestion = {
4222
+ text: token,
4223
+ suggestionSequence: [segment],
4224
+ };
4225
+ return patternSuggestion;
4226
+ });
4227
+ const leafCompositeSuggestions = leafPatterns.map(lp => this._getCompositeSuggestionsForPattern(lp)).flat();
4228
+ suggestionsToReturn.push(...patternsSuggestionList, ...leafCompositeSuggestions);
4229
+ }
4158
4230
  if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
4159
4231
  const nextPatterns = pattern.getNextPatterns();
4160
- const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
4161
- acc.push(...this._getTokensForPattern(pattern));
4232
+ const nextPatternedTokensList = nextPatterns.reduce((acc, pattern) => {
4233
+ const patternedTokensList = this._getCompositeSuggestionsForPattern(pattern);
4234
+ acc.push(...patternedTokensList);
4162
4235
  return acc;
4163
4236
  }, []);
4164
- // using set to prevent duplicates
4165
- const tokens = new Set();
4166
- for (const token of augmentedTokens) {
4167
- for (const nextPatternToken of nextPatternTokens) {
4168
- tokens.add(token + nextPatternToken);
4237
+ const compositeSuggestionList = [];
4238
+ for (const currentSuggestion of suggestionsToReturn) {
4239
+ for (const nextSuggestionWithSubElements of nextPatternedTokensList) {
4240
+ const augmentedTokenWithPattern = {
4241
+ text: currentSuggestion.text + nextSuggestionWithSubElements.text,
4242
+ suggestionSequence: [...currentSuggestion.suggestionSequence, ...nextSuggestionWithSubElements.suggestionSequence],
4243
+ };
4244
+ compositeSuggestionList.push(augmentedTokenWithPattern);
4169
4245
  }
4170
4246
  }
4171
- return [...tokens];
4247
+ return compositeSuggestionList;
4172
4248
  }
4173
4249
  else {
4174
- return augmentedTokens;
4250
+ const dedupedSuggestions = this._deDupeCompositeSuggestions(suggestionsToReturn);
4251
+ return dedupedSuggestions;
4175
4252
  }
4176
4253
  }
4177
- _getAugmentedTokens(pattern) {
4178
- var _a, _b;
4254
+ _getCustomTokens(pattern) {
4255
+ var _a;
4179
4256
  const customTokensMap = this._options.customTokens || {};
4180
- const leafPatterns = pattern.getPatterns();
4181
- /** Using Set to
4182
- * - prevent duplicates
4183
- * - prevent mutation of original customTokensMap
4184
- */
4185
- const customTokensForPattern = new Set((_a = customTokensMap[pattern.name]) !== null && _a !== void 0 ? _a : []);
4186
- for (const lp of leafPatterns) {
4187
- const augmentedTokens = (_b = customTokensMap[lp.name]) !== null && _b !== void 0 ? _b : [];
4188
- const lpsCombinedTokens = [...lp.getTokens(), ...augmentedTokens];
4189
- for (const token of lpsCombinedTokens) {
4190
- customTokensForPattern.add(token);
4257
+ const customTokens = (_a = customTokensMap[pattern.name]) !== null && _a !== void 0 ? _a : [];
4258
+ const allTokens = [...customTokens];
4259
+ return allTokens;
4260
+ }
4261
+ _deDupeCompositeSuggestions(suggestions) {
4262
+ if (this._options.disableDedupe) {
4263
+ return suggestions;
4264
+ }
4265
+ const seen = new Set();
4266
+ const unique = [];
4267
+ for (const suggestion of suggestions) {
4268
+ // Create a unique key based on text and subElements
4269
+ const subElementsKey = suggestion.suggestionSequence
4270
+ .map(sub => ` ${sub.pattern.name} - ${sub.text} `)
4271
+ .sort()
4272
+ .join('|');
4273
+ const key = `${suggestion.text}|${subElementsKey}`;
4274
+ if (!seen.has(key)) {
4275
+ seen.add(key);
4276
+ unique.push(suggestion);
4191
4277
  }
4192
4278
  }
4193
- return [...customTokensForPattern];
4279
+ return unique;
4194
4280
  }
4195
- _createSuggestions(lastIndex, tokens) {
4281
+ _createSuggestions(lastIndex, compositeSuggestionList) {
4196
4282
  let textToIndex = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
4197
- const suggestionStrings = [];
4198
4283
  const options = [];
4199
- for (const token of tokens) {
4284
+ for (const compositeSuggestion of compositeSuggestionList) {
4200
4285
  // concatenated for start index identification inside createSuggestion
4201
- const suggestion = textToIndex + token;
4202
- const alreadyExist = suggestionStrings.includes(suggestion);
4203
- const isSameAsText = suggestion === this._text;
4204
- if (!alreadyExist && !isSameAsText) {
4205
- suggestionStrings.push(suggestion);
4206
- const suggestionOption = this._createSuggestion(this._cursor.text, suggestion);
4207
- options.push(suggestionOption);
4208
- }
4286
+ const existingTextWithSuggestion = textToIndex + compositeSuggestion.text;
4287
+ existingTextWithSuggestion === this._text;
4288
+ const suggestionOption = this._createSuggestionOption(this._cursor.text, existingTextWithSuggestion, compositeSuggestion.suggestionSequence);
4289
+ options.push(suggestionOption);
4290
+ // }
4209
4291
  }
4210
4292
  const reducedOptions = getFurthestOptions(options);
4211
4293
  reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
4212
4294
  return reducedOptions;
4213
4295
  }
4214
- _createSuggestion(fullText, suggestion) {
4296
+ _createSuggestionOption(fullText, suggestion, segments) {
4215
4297
  const furthestMatch = findMatchIndex(suggestion, fullText);
4216
4298
  const text = suggestion.slice(furthestMatch);
4217
4299
  const option = {
4218
4300
  text: text,
4219
4301
  startIndex: furthestMatch,
4302
+ suggestionSequence: segments,
4220
4303
  };
4221
4304
  return option;
4222
4305
  }