diff --git a/packages/melos/bin/melos.dart b/packages/melos/bin/melos.dart index a0e684894..74d96ca74 100644 --- a/packages/melos/bin/melos.dart +++ b/packages/melos/bin/melos.dart @@ -29,6 +29,7 @@ Future main(List arguments) async { message: 'There is a new version of $packageName available ' '($latestVersion). Would you like to update?', defaultsTo: true, + defaultsToWithoutPrompt: false, ); if (shouldUpdate) { await pubUpdater.update(packageName: packageName); diff --git a/packages/melos/lib/src/commands/run.dart b/packages/melos/lib/src/commands/run.dart index 80bca3fc1..1037f83a9 100644 --- a/packages/melos/lib/src/commands/run.dart +++ b/packages/melos/lib/src/commands/run.dart @@ -15,7 +15,7 @@ mixin _RunMixin on _Melos { if (script == null) { throw ScriptNotFoundException._( - scriptName!, + scriptName, config.scripts.keys.toList(), ); } @@ -40,7 +40,7 @@ mixin _RunMixin on _Melos { resultLogger.child(successLabel); } - Future _pickScript(MelosWorkspaceConfig config) async { + Future _pickScript(MelosWorkspaceConfig config) async { // using toList as Maps may be unordered final scripts = config.scripts.values.toList(); @@ -56,16 +56,15 @@ mixin _RunMixin on _Melos { return '$styledName$styledDescription'; }).toList(); - final selectedScript = prompts.choose( + final selectedScript = promptChoice( AnsiStyles.white('Select a script to run in this workspace'), scriptChoices, interactive: false, + requirePrompt: true, ); final selectedScriptIndex = scriptChoices.indexOf(selectedScript!); - if (selectedScriptIndex == -1) return null; - return scripts[selectedScriptIndex].name; } @@ -124,7 +123,7 @@ mixin _RunMixin on _Melos { selectedPackage = choices[0]; } else { // Prompt user to select a package. - selectedPackage = prompts.choose( + selectedPackage = promptChoice( [ AnsiStyles.white('Select a package to run the '), AnsiStyles.cyan(script.name), diff --git a/packages/melos/lib/src/commands/runner.dart b/packages/melos/lib/src/commands/runner.dart index 4ad7ff878..d7f4688da 100644 --- a/packages/melos/lib/src/commands/runner.dart +++ b/packages/melos/lib/src/commands/runner.dart @@ -13,7 +13,6 @@ import 'package:mustache_template/mustache.dart'; import 'package:path/path.dart' as p; import 'package:path/path.dart'; import 'package:pool/pool.dart'; -import 'package:prompts/prompts.dart' as prompts; import 'package:pub_semver/pub_semver.dart'; import 'package:pubspec/pubspec.dart'; import 'package:yaml/yaml.dart'; diff --git a/packages/melos/lib/src/commands/version.dart b/packages/melos/lib/src/commands/version.dart index b78608c00..51fdde620 100644 --- a/packages/melos/lib/src/commands/version.dart +++ b/packages/melos/lib/src/commands/version.dart @@ -180,6 +180,7 @@ mixin _VersionMixin on _RunMixin { promptForMessage = promptBool( message: 'Do you want to provide an additional changelog entry ' 'message?', + defaultsToWithoutPrompt: false, ); } diff --git a/packages/melos/lib/src/common/utils.dart b/packages/melos/lib/src/common/utils.dart index c6910f739..885422e8e 100644 --- a/packages/melos/lib/src/common/utils.dart +++ b/packages/melos/lib/src/common/utils.dart @@ -30,6 +30,7 @@ import 'package:yaml/yaml.dart'; import '../logging.dart'; import '../package.dart'; import '../workspace.dart'; +import 'exception.dart'; import 'io.dart'; import 'platform.dart'; @@ -156,12 +157,91 @@ bool isPubspecOverridesSupported([String dartTool = 'dart']) => bool canRunPubGetConcurrently([String dartTool = 'dart']) => currentDartVersion(dartTool).compareTo(Version.parse('2.16.0')) >= 0; -String promptInput(String message, {String? defaultsTo}) { - return prompts.get(message, defaultsTo: defaultsTo); +T _promptWithTerminal( + T Function() runPrompt, { + required String message, + T? defaultsTo, + T? defaultsToWithoutPrompt, + bool requirePrompt = false, +}) { + if (stdin.hasTerminal) { + return runPrompt(); + } + + if (!requirePrompt) { + if (defaultsToWithoutPrompt is T) { + return defaultsToWithoutPrompt; + } + + if (defaultsTo is T) { + return defaultsTo; + } + } + + throw PromptException(message); +} + +class PromptException extends MelosException { + PromptException(this.message); + + final String message; + + @override + String toString() => 'Was unable to prompt for input:\n$message'; +} + +String promptInput( + String message, { + String? defaultsTo, + String? defaultsToWithoutPrompt, + bool requirePrompt = false, +}) { + return _promptWithTerminal( + () => prompts.get(message, defaultsTo: defaultsTo), + message: message, + defaultsTo: defaultsTo, + defaultsToWithoutPrompt: defaultsToWithoutPrompt, + requirePrompt: requirePrompt, + ); } -bool promptBool({String message = 'Continue?', bool defaultsTo = false}) { - return prompts.getBool(message, defaultsTo: defaultsTo); +bool promptBool({ + String message = 'Continue?', + bool defaultsTo = false, + bool? defaultsToWithoutPrompt, + bool requirePrompt = false, +}) { + return _promptWithTerminal( + () => prompts.getBool(message, defaultsTo: defaultsTo), + message: message, + defaultsTo: defaultsTo, + defaultsToWithoutPrompt: defaultsToWithoutPrompt, + requirePrompt: requirePrompt, + ); +} + +T? promptChoice( + String message, + Iterable options, { + T? defaultsTo, + T? defaultsToWithoutPrompt, + String prompt = 'Enter your choice', + bool interactive = true, + bool requirePrompt = false, +}) { + return _promptWithTerminal( + () => prompts.choose( + message, + options, + defaultsTo: defaultsTo, + prompt: prompt, + interactive: interactive, + ), + message: message, + defaultsTo: defaultsTo, + defaultsToWithoutPrompt: defaultsToWithoutPrompt, + requirePrompt: requirePrompt, + ); } bool get isCI {