expandVar function

String expandVar(
  1. String path, {
  2. Map<String, String> map = const {},
})

expand variables in a string path using provided map collections and and built-in dynamic variable

Variables can be:

  • User-defined: Enclosed in a specific format (e.g., "$name", "${name}", or "%name%"), resolved from the map.
  • Built-in dynamic:
    • CURDIR: Current directory.
    • CURDATE, CURDATETIME: Current date/time (e.g., 20250829, 20250829090226).
    • AGODATE<N><UNIT>, AGODATETIME<N><UNIT>: \n Relative dates/times (e.g., AGODATE1DAY, AGODATETIME1WEEK).
      • <N> is a number,
      • <UNIT> is a time unit (e.g., SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR).
// assume the current user is 'kaguya',
final env = Platform.environment;
print(expandVar(r'$HOME', map:env)); // macos: /Users/kaguya, linux: /home/kaguya
print(expandVar(r'%USERPROFILE%', map:env)); // windows: C:\Users\kaguya
// assume the current time is 2025-10-11 16:31:50
print(expandVar(r'$CURDATE'));      // 20251011
print(expandVar(r'$AGODATE1DAY'));  // 20251010
print(expandVar(r'$CURDATETIME'));  // 20251011163150
print(expandVar(r'$AGODATE1HOUR')); // 20251011153150

Implementation

String expandVar(String path, {Map<String, String> map = const {}}) {
  // if (map.isEmpty) map = environ;
  map = Map<String, String>.from(map);
  if (path.contains('CURDATE') || path.contains('CURDATETIME')) {
    final iso8601 = DateTime.now().toLocal().toIso8601String().split('.').first;
    var [date, time] = iso8601.split('T');
    date = date.replaceAll('-', '');
    time = time.replaceAll(':', '');
    map['CURDATE'] = date;
    map['CURDATETIME'] = '$date$time';
  }
  if (path.contains('CURDIR')) {
    map['CURDIR'] = Directory.current.path;
  }
  if (path.contains('AGODATE') || path.contains('AGODATETIME')) {
    final Map<String, String> mapping = {};
    final matches = varInputRegexp.allMatches(path);
    for (var match in matches) {
      String name = match[2] ?? match[3] ?? match[4] ?? '';
      if (name.isNotEmpty) {
        final m = varTimeAgoRegexp.firstMatch(name);
        if (m != null) {
          final [agoType, agoValue, agoUnit] = m.groups([1, 2, 3]);
          final value = valueAgoInput('$agoType', '$agoValue $agoUnit');
          mapping[name] = value.isEmpty ? name : value;
        }
      }
    }
    map.addAll(mapping);
  }

  return path.replaceAllMapped(
    varInputRegexp, // match ${VAR} OR $VAR
    (match) {
      String? name = match[2] ?? match[3] ?? match[4];
      if (name case String _ when map.containsKey(name)) return map[name]!;

      return match.group(0) ?? '';
    },
  );
}