diff --git a/lib/src/installer/completion_installation.dart b/lib/src/installer/completion_installation.dart index 41921d1..065ad03 100644 --- a/lib/src/installer/completion_installation.dart +++ b/lib/src/installer/completion_installation.dart @@ -226,18 +226,16 @@ class CompletionInstallation { ); } - String get _shellRCFilePath => - _resolveHome(configuration!.shellRCFile, environment); - /// Write a source to the completion global script in the shell configuration /// file, which its location is described by the [configuration]. @visibleForTesting void writeToShellConfigFile(String rootCommand) { final configuration = this.configuration!; + final shellRunCommandFile = configuration.shell.runCommandFile(); logger.info( 'Adding dart cli completion config entry ' - 'to $_shellRCFilePath', + 'to ${shellRunCommandFile.path}', ); final completionConfigDirPath = completionConfigDir.path; @@ -247,26 +245,25 @@ class CompletionInstallation { configuration.completionConfigForShellFileName, ); - final shellRCFile = File(_shellRCFilePath); - - if (!shellRCFile.existsSync()) { + if (!shellRunCommandFile.existsSync()) { throw CompletionInstallationException( rootCommand: rootCommand, - message: 'No configuration file found at ${shellRCFile.path}', + message: 'No configuration file found at ${shellRunCommandFile.path}', ); } final containsLine = - shellRCFile.readAsStringSync().contains(completionConfigPath); + shellRunCommandFile.readAsStringSync().contains(completionConfigPath); if (containsLine) { - logger.warn('A completion config entry was already found on' - ' $_shellRCFilePath.'); + logger.warn( + '''A completion config entry was already found on ${shellRunCommandFile.path}.''', + ); return; } _sourceScriptOnFile( - configFile: shellRCFile, + configFile: shellRunCommandFile, scriptName: 'Completion', description: 'Completion scripts setup. ' 'Remove the following line to uninstall', @@ -280,13 +277,16 @@ class CompletionInstallation { /// Tells the user to source the shell configuration file. void _logSourceInstructions(String rootCommand) { final level = logger.level; + final configuration = this.configuration!; + final shellRunCommandFile = configuration.shell.runCommandFile(); + logger ..level = Level.info ..info( '\n' 'Completion files installed. To enable completion, run the following ' 'command in your shell:\n' - '${lightCyan.wrap('source $_shellRCFilePath')}' + '${lightCyan.wrap('source ${shellRunCommandFile.path}}')}' '\n', ) ..level = level; @@ -321,13 +321,3 @@ ${configuration!.sourceLineTemplate(scriptPath)} logger.info('Added config to $configFilePath'); } } - -/// Resolve the home from a path string -String _resolveHome( - String originalPath, - Map environment, -) { - final after = originalPath.split('~/').last; - final home = path.absolute(environment['HOME']!); - return path.join(home, after); -} diff --git a/lib/src/installer/shell_completion_configuration.dart b/lib/src/installer/shell_completion_configuration.dart index 36b18d9..f9eff3f 100644 --- a/lib/src/installer/shell_completion_configuration.dart +++ b/lib/src/installer/shell_completion_configuration.dart @@ -21,7 +21,6 @@ class ShellCompletionConfiguration { /// {@macro shell_completion_configuration} const ShellCompletionConfiguration._({ required this.shell, - required this.shellRCFile, required this.sourceLineTemplate, required this.scriptTemplate, }); @@ -41,10 +40,6 @@ class ShellCompletionConfiguration { /// {@macro system_shell} final SystemShell shell; - /// The location of a config file that is run upon shell start. - /// Eg: .bash_profile or .zshrc - final String shellRCFile; - /// Generates a line to sources of a script file. final SourceStringTemplate sourceLineTemplate; @@ -60,7 +55,6 @@ class ShellCompletionConfiguration { @visibleForTesting final zshConfiguration = ShellCompletionConfiguration._( shell: SystemShell.zsh, - shellRCFile: '~/.zshrc', sourceLineTemplate: (String scriptPath) { return '[[ -f $scriptPath ]] && . $scriptPath || true'; }, @@ -93,7 +87,6 @@ fi @visibleForTesting final bashConfiguration = ShellCompletionConfiguration._( shell: SystemShell.bash, - shellRCFile: '~/.bash_profile', sourceLineTemplate: (String scriptPath) { return '[ -f $scriptPath ] && . $scriptPath || true'; }, diff --git a/lib/src/system_shell.dart b/lib/src/system_shell.dart index 1ce1568..e989cda 100644 --- a/lib/src/system_shell.dart +++ b/lib/src/system_shell.dart @@ -9,17 +9,41 @@ import 'package:path/path.dart' as path; /// {@endtemplate} enum SystemShell { /// The Zsh shell: https://www.zsh.org/ - zsh('zsh'), + zsh( + 'zsh', + runCommandFileName: '.zshrc', + ), /// GNU Bash shell: https://www.gnu.org/software/bash/ - bash('bash'); + bash( + 'bash', + runCommandFileName: '.bash_profile', + ); /// {@macro system_shell} - const SystemShell(this.name); + const SystemShell(this.name, {required String runCommandFileName}) + : _runCommandFileName = runCommandFileName; /// A descriptive string to identify the shell among others. final String name; + /// The name of a config file that is run upon shell start. + /// + /// For example: `.bash_profile` or `.zshrc`. + final String _runCommandFileName; + + /// Retrieves, from the current environment, the run command (RC) [File] + /// for the shell. + /// + /// It is assumed that the RC file is located at the user's home directory. + File runCommandFile({Map? environmentOverride}) { + final environment = environmentOverride ?? Platform.environment; + + final home = path.absolute(environment['HOME']!); + final runCommandFilePath = path.join(home, _runCommandFileName); + return File(runCommandFilePath); + } + /// Identifies the current shell based on the [Platform.environment]. /// /// Pass [environmentOverride] to override the default value of diff --git a/test/src/installer/shell_completion_configuration_test.dart b/test/src/installer/shell_completion_configuration_test.dart index fc58cf3..b073145 100644 --- a/test/src/installer/shell_completion_configuration_test.dart +++ b/test/src/installer/shell_completion_configuration_test.dart @@ -15,10 +15,6 @@ void main() { expect(zshConfiguration.shell, SystemShell.zsh); }); - test('shellRCFile', () { - expect(zshConfiguration.shellRCFile, '~/.zshrc'); - }); - test('sourceStringTemplate', () { final result = zshConfiguration.sourceLineTemplate('./pans/snaps'); expect(result, '[[ -f ./pans/snaps ]] && . ./pans/snaps || true'); @@ -66,10 +62,6 @@ fi expect(bashConfiguration.shell, SystemShell.bash); }); - test('shellRCFile', () { - expect(bashConfiguration.shellRCFile, '~/.bash_profile'); - }); - test('sourceStringTemplate', () { final result = bashConfiguration.sourceLineTemplate('./pans/snaps'); expect(result, '[ -f ./pans/snaps ] && . ./pans/snaps || true'); diff --git a/test/src/system_shell_test.dart b/test/src/system_shell_test.dart index fa819af..3d498a8 100644 --- a/test/src/system_shell_test.dart +++ b/test/src/system_shell_test.dart @@ -1,4 +1,5 @@ import 'package:cli_completion/parser.dart'; +import 'package:path/path.dart' as path; import 'package:test/test.dart'; void main() { @@ -13,6 +14,26 @@ void main() { }); }); + group('runCommandFile', () { + const environment = {'HOME': '/foo/bar'}; + + test('bash path is correct', () { + const shell = SystemShell.bash; + final file = shell.runCommandFile(environmentOverride: environment); + + final expectedPath = path.join(environment['HOME']!, '.bash_profile'); + expect(file.path, equals(expectedPath)); + }); + + test('zsh path is correct', () { + const shell = SystemShell.zsh; + final file = shell.runCommandFile(environmentOverride: environment); + + final expectedPath = path.join(environment['HOME']!, '.zshrc'); + expect(file.path, equals(expectedPath)); + }); + }); + group('current', () { test('instantiated without env', () { expect(