Make applicationConfigHome failures catchable (#68)

It is not always possible to resolve any environment variables - but we still might want to query for the directory if it exists.
diff --git a/lib/cli_util.dart b/lib/cli_util.dart
index 0fdd211..430c294 100644
--- a/lib/cli_util.dart
+++ b/lib/cli_util.dart
@@ -80,7 +80,8 @@
 /// [XDG Base Directory Specification][1] on Linux and [File System Basics][2]
 /// on Mac OS.
 ///
-/// Throws if `%APPDATA%` or `$HOME` is undefined.
+/// Throws an [EnvironmentNotFoundException] if `%APPDATA%` or `$HOME` is needed
+/// but undefined.
 ///
 /// [1]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
 /// [2]: https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1
@@ -91,7 +92,8 @@
   if (Platform.isWindows) {
     final appdata = Platform.environment['APPDATA'];
     if (appdata == null) {
-      throw StateError('Environment variable %APPDATA% is not defined!');
+      throw EnvironmentNotFoundException(
+          'Environment variable %APPDATA% is not defined!');
     }
     return appdata;
   }
@@ -118,7 +120,17 @@
 String get _home {
   final home = Platform.environment['HOME'];
   if (home == null) {
-    throw StateError('Environment variable \$HOME is not defined!');
+    throw EnvironmentNotFoundException(
+        'Environment variable \$HOME is not defined!');
   }
   return home;
 }
+
+class EnvironmentNotFoundException implements Exception {
+  final String message;
+  EnvironmentNotFoundException(this.message);
+  @override
+  String toString() {
+    return message;
+  }
+}
diff --git a/test/cli_util_test.dart b/test/cli_util_test.dart
index 32dcdfc..510e12d 100644
--- a/test/cli_util_test.dart
+++ b/test/cli_util_test.dart
@@ -49,5 +49,21 @@
       // just a dummy check that some part of the path exists.
       expect(Directory(p.joinAll(path.take(2))).existsSync(), isTrue);
     });
+
+    test('Throws IOException when run with empty environment', () {
+      final scriptPath = p.join('test', 'print_config_home.dart');
+      final result = Process.runSync(
+        Platform.resolvedExecutable,
+        [scriptPath],
+        environment: {},
+        includeParentEnvironment: false,
+      );
+      final varName = Platform.isWindows ? '%APPDATA%' : r'$HOME';
+      expect(
+        (result.stdout as String).trim(),
+        'Caught: Environment variable $varName is not defined!',
+      );
+      expect(result.exitCode, 0);
+    });
   });
 }
diff --git a/test/print_config_home.dart b/test/print_config_home.dart
new file mode 100644
index 0000000..7667ff7
--- /dev/null
+++ b/test/print_config_home.dart
@@ -0,0 +1,9 @@
+import 'package:cli_util/cli_util.dart';
+
+void main() {
+  try {
+    print(applicationConfigHome('dart'));
+  } on EnvironmentNotFoundException catch (e) {
+    print('Caught: $e');
+  }
+}