splitAutoCompletingMatches method

List<List<RegExpMatch>> splitAutoCompletingMatches(
  1. List<String> splitText,
  2. String stateName, {
  3. int matchMode = 3,
})

Match wd10 to width_10 matchMode: 1 // all rules match at least one splitText 2 // fast match one and don't match other splitTexts 3 // strict mode, all splitTexts must have match.

Implementation

List<List<RegExpMatch>> splitAutoCompletingMatches(
    List<String> splitText, String stateName,
    {int matchMode = 3}) {
  assert(_runtimeContext != null);

  ///  一个 rule 对应 每个splitText在该rule中对应的 text 位置
  var matches = <List<RegExpMatch>>[];

  _runtimeContext![stateName]?.whereType<JParse>().forEach((jparse) {
    if (jparse.isConst && jparse is! GroupJParse) {
      matches.addAll(enumSplitMatches(splitText, jparse.constants!,
          matchMode: matchMode));
    } else if (jparse is GroupJParse &&
        jparse.groupDTokens.any((dtoken) => dtoken?.isEnum ?? false)) {
      // print(element.pattern);
      var constantRules = jparse.groupDTokens
          .map<List<String>>((dtoken) => _enumAllGiven(dtoken, stateName))
          .toList(growable: false);
      if (jparse.groupDTokens.any((dtoken) => dtoken is Templates)) {
        // List<List<Map<String, dynamic>>> message = [];
        var templateRes = <List<List<dynamic>>>[];

        //处理模板
        jparse.groupDTokens.forEach((dtoken) {
          var temp = <List<dynamic>>[];
          if (dtoken is Templates) {
            /// 处理变量
            var enumStrings = <int, Map<String, List<String>>>{};
            var dtokenVars = dtoken.vars;
            if (dtokenVars != null) {
              final enumvars = dtokenVars.enumvars;
              final enumnone = dtokenVars.enumnone;
              final patterns = dtokenVars.patterns;
              for (var i = 0; i < enumvars.length; i++) {
                // step1: 优先根据 pattern 从 splittext 提取
                if (patterns != null) {
                  var range =
                      splitTextRange(patterns[i] as String, splitText);
                  if (range.isNotEmpty) {
                    enumStrings[i] = {
                      'value': [range.join()],
                      'depart': range
                    };
                  }
                }
                // step2: 其次从枚举值中提取
                if (enumStrings[i] == null) {
                  var enums = _enumAllGiven(enumvars[i], stateName);
                  if (enums.isNotEmpty) {
                    enumStrings[i] = {'value': enums, 'depart': []};
                  }
                }
                // step3: 最后从enumnone中提取兜底数据
                if (enumStrings[i] == null && enumnone != null) {
                  enumStrings[i] = {
                    'value': [enumnone[i]],
                    'depart': []
                  };
                }
              }
            }

            /// 替换变量
            dtoken.templates.forEach((template) {
              List<String> splits;

              /// 情况1: 没有变量直接添加
              if ((splits = template.split(r'\$'))
                  .every((item) => !item.contains(r'$'))) {
                temp.add([splits.join(r'$'), []]);
                return;
              }

              /// 情况2:有变量但没有定义变量则退出
              if (dtoken.vars == null) return;
              var splitExpands = <List<List<String>>>[
                [splits, []]
              ];

              /// 情况3:有变量有定义
              /// 从 enumStrings 中去取
              /// ($/$1)对应第一个 $2对应第二个 $3对应第三个 依次类推..
              /// index   0           1           2 ..
              final varLength = dtokenVars?.enumvars.length ?? 0;
              for (var varIndex = varLength - 1; varIndex >= 0; varIndex--) {
                var _splitExpands =
                    splitExpands.expand<List<List<String>>>((splitSL) {
                  var parts = splitSL[0];
                  var matched = splitSL[1];
                  if (parts.any((part) =>
                      part.contains(varName(varIndex, varLength)))) {
                    // 情况3.1:定义了变量但是 enumStrings没有 则去除该条规则
                    if (enumStrings[varIndex] == null) return [];
                    var res = <List<List<String>>>[];
                    enumStrings[varIndex]?['value']?.forEach((varValue) {
                      res.add([
                        parts
                            .map((part) => part.replaceAll(
                                varName(varIndex, varLength), varValue))
                            .toList(),
                        [...matched, ...enumStrings[varIndex]!['depart']!]
                      ]);
                    });
                    // []..add([splitSL[0], splitSL[1]]);
                    return res;
                  } else {
                    return [splitSL];
                  }
                }).toList();
                splitExpands = _splitExpands;
                temp.addAll(splitExpands
                    .map<List<dynamic>>((splitItem) =>
                        [splitItem[0].join(r'$'), splitItem[1]])
                    .toList());
              }
            });

            // return [[_inject(dtoken.templates[0],listVars), departVars]]
          }

          /// 占位
          templateRes.add(temp);
        });
        matches.addAll(enumSplitMatches(splitText, constantRules,
            matchMode: matchMode,
            templates: templateRes
                .map((e) => e.map<String>((e) => e[0] as String).toList())
                .toList(),
            matchedFromTemplate: templateRes
                .map((e) => e
                    .map<List<String>>((e) =>
                        e[1].isEmpty ? <String>[] : e[1] as List<String>)
                    .toList())
                .toList()));
      }
      matches.addAll(
          enumSplitMatches(splitText, constantRules, matchMode: matchMode));
    }
  });
  return matches;
}