matchItems static method

List<CommandPaletteMatch> matchItems(
  1. List<CommandPaletteItem> items,
  2. String query
)

Returns ranked matches for query with deterministic scoring and explainable evidence.

Public for testing and parity-validation workflows.

Implementation

static List<CommandPaletteMatch> matchItems(
  List<CommandPaletteItem> items,
  String query,
) {
  final normalizedQuery = query.trim().toLowerCase();

  final matches = <CommandPaletteMatch>[];
  for (var index = 0; index < items.length; index++) {
    final item = items[index];
    if (!item.enabled) continue;

    final evidence = <String, double>{};
    final label = item.label.toLowerCase();
    final description = item.description?.toLowerCase();
    final group = item.group?.toLowerCase();
    double score = 0;

    if (normalizedQuery.isEmpty) {
      evidence['query:empty'] = 1.0;
    } else {
      if (label == normalizedQuery) {
        score += 10000;
        evidence['label:exact'] = 10000;
      }

      if (label.startsWith(normalizedQuery)) {
        score += 6000;
        evidence['label:prefix'] = 6000;
      }

      if (label.contains(normalizedQuery)) {
        score += 4000;
        evidence['label:contains'] = 4000;
      }

      if (description != null && description.contains(normalizedQuery)) {
        score += 1800;
        evidence['description:contains'] = 1800;
      }

      if (group != null && group.contains(normalizedQuery)) {
        score += 1200;
        evidence['group:contains'] = 1200;
      }

      final subseq = _subsequenceScore(normalizedQuery, label);
      if (subseq > 0) {
        score += subseq;
        evidence['label:subsequence'] = subseq;
      }

      final typo = _typoScore(normalizedQuery, label);
      if (typo > 0) {
        score += typo;
        evidence['label:typo'] = typo;
      }
    }

    if (normalizedQuery.isEmpty || score > 0) {
      matches.add(
        CommandPaletteMatch(
          item: item,
          score: score,
          evidence: evidence,
          originalIndex: index,
        ),
      );
    }
  }

  if (normalizedQuery.isEmpty) {
    matches.sort(
      (lhs, rhs) => lhs.originalIndex.compareTo(rhs.originalIndex),
    );
  } else {
    matches.sort((lhs, rhs) {
      final byScore = rhs.score.compareTo(lhs.score);
      if (byScore != 0) return byScore;

      final byLabel = lhs.item.label.compareTo(rhs.item.label);
      if (byLabel != 0) return byLabel;

      return lhs.originalIndex.compareTo(rhs.originalIndex);
    });
  }

  return matches;
}