Introduce applicationConfigHome (#66)
* Introduce applicationConfigHome
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c546fd4..871b010 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.3.4
+
+- Introduce `applicationConfigHome` for making it easy to consistently find the
+ user-specific application configuration folder.
+
## 0.3.3
- Reverted `meta` constraint to `^1.3.0`.
diff --git a/lib/cli_util.dart b/lib/cli_util.dart
index 0cc408d..0fdd211 100644
--- a/lib/cli_util.dart
+++ b/lib/cli_util.dart
@@ -59,3 +59,66 @@
/// Return the path to the current Dart SDK.
String getSdkPath() => path.dirname(path.dirname(Platform.resolvedExecutable));
+
+/// Get the user-specific application configuration folder for the current
+/// platform.
+///
+/// This is a location appropriate for storing application specific
+/// configuration for the current user. The [productName] should be unique to
+/// avoid clashes with other applications on the same machine. This method won't
+/// actually create the folder, merely return the recommended location for
+/// storing user-specific application configuration.
+///
+/// The folder location depends on the platform:
+/// * `%APPDATA%\<productName>` on **Windows**,
+/// * `$HOME/Library/Application Support/<productName>` on **Mac OS**,
+/// * `$XDG_CONFIG_HOME/<productName>` on **Linux**
+/// (if `$XDG_CONFIG_HOME` is defined), and,
+/// * `$HOME/.config/<productName>` otherwise.
+///
+/// This aims follows best practices for each platform, honoring the
+/// [XDG Base Directory Specification][1] on Linux and [File System Basics][2]
+/// on Mac OS.
+///
+/// Throws if `%APPDATA%` or `$HOME` is 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
+String applicationConfigHome(String productName) =>
+ path.join(_configHome, productName);
+
+String get _configHome {
+ if (Platform.isWindows) {
+ final appdata = Platform.environment['APPDATA'];
+ if (appdata == null) {
+ throw StateError('Environment variable %APPDATA% is not defined!');
+ }
+ return appdata;
+ }
+
+ if (Platform.isMacOS) {
+ return path.join(_home, 'Library', 'Application Support');
+ }
+
+ if (Platform.isLinux) {
+ final xdgConfigHome = Platform.environment['XDG_CONFIG_HOME'];
+ if (xdgConfigHome != null) {
+ return xdgConfigHome;
+ }
+ // XDG Base Directory Specification says to use $HOME/.config/ when
+ // $XDG_CONFIG_HOME isn't defined.
+ return path.join(_home, '.config');
+ }
+
+ // We have no guidelines, perhaps we should just do: $HOME/.config/
+ // same as XDG specification would specify as fallback.
+ return path.join(_home, '.config');
+}
+
+String get _home {
+ final home = Platform.environment['HOME'];
+ if (home == null) {
+ throw StateError('Environment variable \$HOME is not defined!');
+ }
+ return home;
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index a5ab878..7efbd13 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: cli_util
-version: 0.3.3
+version: 0.3.4
description: A library to help in building Dart command-line apps.
repository: https://github.com/dart-lang/cli_util
diff --git a/test/cli_util_test.dart b/test/cli_util_test.dart
index 2c2c770..95ba0fb 100644
--- a/test/cli_util_test.dart
+++ b/test/cli_util_test.dart
@@ -36,4 +36,10 @@
expect(isSdkDir(Directory(getSdkPath())), true);
});
});
+
+ group('applicationConfigHome', () {
+ test('returns a string', () {
+ expect(applicationConfigHome('dart'), isA<String>());
+ });
+ });
}