getStrings method

SocialContext<T> getStrings(
  1. String socialString,
  2. List<T> perspectives
)

Converts a string such as

%1N smile%1s at %2 with %1his eyes sparkling in the light of %3.

Returns an object which can be used to send the right string to the right observer.

If no number is provided after a % (per cent) sign, defaultIndex is used.

If no suffix name is provided, defaultSuffix is assumed.

Assuming the defaults haven't been changed, this means % will be expanded to 51n.

Make the suffix names upper case to have the strings rendered with their first letter capitalised.

Implementation

SocialContext<T> getStrings(String socialString, List<T> perspectives) {
  final Map<T, String> targetedStrings = <T, String>{
    for (final perspective in perspectives) perspective: socialString
  };
  final String defaultString =
      socialString.replaceAllMapped(suffixRegExp, (Match m) {
    final fullString = m.group(0);
    if (fullString == null) {
      throw Exception('RegExp group(0) returned null.');
    }
    var indexString = m.group(1);
    if (indexString == null || indexString.isEmpty) {
      indexString = defaultIndex;
    }
    final int index = int.parse(indexString);
    if (index > perspectives.length || index < 1) {
      throw NoSuchIndexError(index, perspectives.length);
    }
    final T perspective = perspectives[index - 1];
    var suffixName = m.group(2);
    if (suffixName == null || suffixName.isEmpty) {
      suffixName = defaultSuffix;
    }
    final suffix = suffixes[suffixName.toLowerCase()];
    if (suffix == null) {
      throw NoSuchSuffixError(suffixName.toLowerCase());
    }
    final SuffixResult result = suffix(perspective);
    var filterName = m.group(3);
    if (filterName != null) {
      filterName = filterName.substring(1);
      final filter = filters[filterName];
      if (filter == null) {
        throw NoSuchFilter(filterName);
      }
      result.applyFilter(filter);
    }
    if (startsAsUpperCase(suffixName)) {
      result.applyFilter(toTitleCase);
    }
    for (final entry in targetedStrings.entries) {
      final p = entry.key;
      final currentValue = targetedStrings[p];
      if (currentValue == null) {
        throw Exception('Somehow `currentValue` is null.');
      }
      final String value;
      if (p == perspective) {
        value = result.firstPerson;
      } else {
        value = result.secondPerson;
      }
      targetedStrings[p] = currentValue.replaceFirst(fullString, value);
    }
    return result.secondPerson;
  });
  return SocialContext<T>(targetedStrings, defaultString);
}