Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions lib/src/installer/completion_installation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,24 @@ class CompletionInstallation {
);
}

String get _shellRCFilePath =>
_resolveHome(configuration!.shellRCFile, environment);
final _missingFiles = <String>[];
String? __shellRCFilePath;
String get _shellRCFilePath {
String? firstPath;
if (__shellRCFilePath == null) {
for (final fileName in configuration!.shellRCFiles) {
final filePath = _resolveHome(fileName, environment);
firstPath ??= filePath;
if (File(filePath).existsSync()) {
__shellRCFilePath = filePath;
return __shellRCFilePath!;
}
_missingFiles.add(filePath);
}
__shellRCFilePath = firstPath;
}
return __shellRCFilePath!;
}

/// Write a source to the completion global script in the shell configuration
/// file, which its location is described by the [configuration].
Expand All @@ -290,9 +306,17 @@ class CompletionInstallation {

final shellRCFile = File(_shellRCFilePath);
if (!shellRCFile.existsSync()) {
var message = '';
if (_missingFiles.length > 1) {
message =
'No configuration files where found at '
'\n ${_missingFiles.join('\n ')}';
} else {
message = 'No configuration file found at ${shellRCFile.path}';
}
throw CompletionInstallationException(
rootCommand: rootCommand,
message: 'No configuration file found at ${shellRCFile.path}',
message: message,
);
}

Expand Down
13 changes: 8 additions & 5 deletions lib/src/installer/shell_completion_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ShellCompletionConfiguration {
/// {@macro shell_completion_configuration}
const ShellCompletionConfiguration._({
required this.shell,
required this.shellRCFile,
required this.shellRCFiles,
required this.sourceLineTemplate,
required this.scriptTemplate,
});
Expand All @@ -42,9 +42,12 @@ class ShellCompletionConfiguration {
/// {@macro system_shell}
final SystemShell shell;

/// The location of a config file that is run upon shell start.
/// A preferential ordered list of locations of a config file that is run upon
/// shell start. The list is to allow multiple options eg both .bash_profile
/// and .bashrc. The first option will be tried first and and if the file
/// doesn't exist the next one will be tried.
/// Eg: .bash_profile or .zshrc
final String shellRCFile;
final List<String> shellRCFiles;

/// Generates a line to sources of a script file.
final SourceStringTemplate sourceLineTemplate;
Expand All @@ -61,7 +64,7 @@ class ShellCompletionConfiguration {
@visibleForTesting
final zshConfiguration = ShellCompletionConfiguration._(
shell: SystemShell.zsh,
shellRCFile: '~/.zshrc',
shellRCFiles: const ['~/.zshrc'],
sourceLineTemplate: (String scriptPath) {
return '[[ -f $scriptPath ]] && . $scriptPath || true';
},
Expand Down Expand Up @@ -94,7 +97,7 @@ fi
@visibleForTesting
final bashConfiguration = ShellCompletionConfiguration._(
shell: SystemShell.bash,
shellRCFile: '~/.bash_profile',
shellRCFiles: const ['~/.bashrc', '~/.bash_profile'],
sourceLineTemplate: (String scriptPath) {
return '[ -f $scriptPath ] && . $scriptPath || true';
},
Expand Down
86 changes: 86 additions & 0 deletions test/src/installer/completion_installation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,92 @@ void main() {
);
},
);

test(
'installing completion for .bashrc',
() {
final bashInstallation = CompletionInstallation(
logger: logger,
isWindows: false,
environment: {
'HOME': tempDir.path,
},
configuration: bashConfiguration,
);

final configDir = bashInstallation.completionConfigDir;

final bashProfile = File(path.join(tempDir.path, '.bash_profile'))
..createSync();

bashInstallation.install('very_good');

// Different format needed for matching cli output
expect(bashProfile.readAsStringSync(), '''
\n## [Completion]
## Completion scripts setup. Remove the following line to uninstall
[ -f ${configDir.path}/bash-config.bash ] && . ${configDir.path}/bash-config.bash || true
## [/Completion]

''');
},
);

test(
'installing completion for .bash_profile',
() {
final bashInstallation = CompletionInstallation(
logger: logger,
isWindows: false,
environment: {
'HOME': tempDir.path,
},
configuration: bashConfiguration,
);

final configDir = bashInstallation.completionConfigDir;

final bashRc = File(path.join(tempDir.path, '.bashrc'))..createSync();

bashInstallation.install('very_good');

// Different format needed for matching cli output
expect(bashRc.readAsStringSync(), '''
\n## [Completion]
## Completion scripts setup. Remove the following line to uninstall
[ -f ${configDir.path}/bash-config.bash ] && . ${configDir.path}/bash-config.bash || true
## [/Completion]

''');
},
);

test(
'missing .bashrc and .bash_profile',
() {
final bashInstallation = CompletionInstallation(
logger: logger,
isWindows: false,
environment: {
'HOME': tempDir.path,
},
configuration: bashConfiguration,
);

expect(
() => bashInstallation.install('very_good'),
throwsA(
isA<CompletionInstallationException>().having(
(e) => e.message,
'message',
'No configuration files where found at '
'\n ${path.join(tempDir.path, '.bashrc')}'
'\n ${path.join(tempDir.path, '.bash_profile')}',
),
),
);
},
);
});

group('uninstall', () {
Expand Down
12 changes: 8 additions & 4 deletions test/src/installer/shell_completion_configuration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ void main() {
expect(zshConfiguration.shell, SystemShell.zsh);
});

test('shellRCFile', () {
expect(zshConfiguration.shellRCFile, '~/.zshrc');
test('shellRCFiles', () {
expect(zshConfiguration.shellRCFiles.first, '~/.zshrc');
});

test('sourceStringTemplate', () {
Expand Down Expand Up @@ -68,8 +68,12 @@ fi
expect(bashConfiguration.shell, SystemShell.bash);
});

test('shellRCFile', () {
expect(bashConfiguration.shellRCFile, '~/.bash_profile');
test('shellRCFiles first', () {
expect(bashConfiguration.shellRCFiles.first, '~/.bashrc');
});

test('shellRCFiles last', () {
expect(bashConfiguration.shellRCFiles.last, '~/.bash_profile');
});

test('sourceStringTemplate', () {
Expand Down