Skip to content

Commit

Permalink
fix: handle prompts when no terminal is attached to stdio (#370)
Browse files Browse the repository at this point in the history
Fixes #356
  • Loading branch information
blaugold authored Sep 7, 2022
1 parent 1ab2e29 commit 81e850e
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 11 deletions.
1 change: 1 addition & 0 deletions packages/melos/bin/melos.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Future<void> main(List<String> 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);
Expand Down
11 changes: 5 additions & 6 deletions packages/melos/lib/src/commands/run.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ mixin _RunMixin on _Melos {

if (script == null) {
throw ScriptNotFoundException._(
scriptName!,
scriptName,
config.scripts.keys.toList(),
);
}
Expand All @@ -40,7 +40,7 @@ mixin _RunMixin on _Melos {
resultLogger.child(successLabel);
}

Future<String?> _pickScript(MelosWorkspaceConfig config) async {
Future<String> _pickScript(MelosWorkspaceConfig config) async {
// using toList as Maps may be unordered
final scripts = config.scripts.values.toList();

Expand All @@ -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;
}

Expand Down Expand Up @@ -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),
Expand Down
1 change: 0 additions & 1 deletion packages/melos/lib/src/commands/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
1 change: 1 addition & 0 deletions packages/melos/lib/src/commands/version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ mixin _VersionMixin on _RunMixin {
promptForMessage = promptBool(
message: 'Do you want to provide an additional changelog entry '
'message?',
defaultsToWithoutPrompt: false,
);
}

Expand Down
88 changes: 84 additions & 4 deletions packages/melos/lib/src/common/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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>(
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<T>(
String message,
Iterable<T> 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 {
Expand Down

0 comments on commit 81e850e

Please sign in to comment.