diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart index b00ada9b611..c8a03b6cc16 100644 --- a/packages/flutter_tools/lib/src/base/terminal.dart +++ b/packages/flutter_tools/lib/src/base/terminal.dart @@ -90,16 +90,29 @@ class AnsiTerminal { /// Prompts the user to input a chraracter within the accepted list. /// Reprompts if inputted character is not in the list. /// + /// `prompt` is the text displayed prior to waiting for user input each time. + /// `defaultChoiceIndex`, if given, will be the character in `acceptedCharacters` + /// in the index given if the user presses enter without any key input. + /// `displayAcceptedCharacters` prints also the accepted keys next to the `prompt` if true. + /// /// Throws a [TimeoutException] if a `timeout` is provided and its duration /// expired without user input. Duration resets per key press. Future promptForCharInput( List acceptedCharacters, { String prompt, + int defaultChoiceIndex, bool displayAcceptedCharacters: true, Duration timeout, }) async { assert(acceptedCharacters != null); assert(acceptedCharacters.isNotEmpty); + List charactersToDisplay = acceptedCharacters; + if (defaultChoiceIndex != null) { + assert(defaultChoiceIndex >= 0 && defaultChoiceIndex < acceptedCharacters.length); + charactersToDisplay = new List.from(charactersToDisplay); + charactersToDisplay[defaultChoiceIndex] = bolden(charactersToDisplay[defaultChoiceIndex]); + acceptedCharacters.add('\n'); + } String choice; singleCharMode = true; while( @@ -110,7 +123,7 @@ class AnsiTerminal { if (isNotEmpty(prompt)) { printStatus(prompt, emphasis: true, newline: false); if (displayAcceptedCharacters) - printStatus(' [${acceptedCharacters.join("|")}]', newline: false); + printStatus(' [${charactersToDisplay.join("|")}]', newline: false); printStatus(': ', emphasis: true, newline: false); } Future inputFuture = onCharInput.first; @@ -120,6 +133,8 @@ class AnsiTerminal { printStatus(choice); } singleCharMode = false; + if (defaultChoiceIndex != null && choice == '\n') + choice = acceptedCharacters[defaultChoiceIndex]; return choice; } } diff --git a/packages/flutter_tools/lib/src/ios/code_signing.dart b/packages/flutter_tools/lib/src/ios/code_signing.dart index 56773a46b24..5a917dba522 100644 --- a/packages/flutter_tools/lib/src/ios/code_signing.dart +++ b/packages/flutter_tools/lib/src/ios/code_signing.dart @@ -153,6 +153,7 @@ Future _chooseSigningIdentity(List validCodeSigningIdentities) a ..add('a'), prompt: 'Please select a certificate for code signing', displayAcceptedCharacters: true, + defaultChoiceIndex: 0, // Just pressing enter chooses the first one. ); if (choice == 'a') diff --git a/packages/flutter_tools/test/src/base/terminal_test.dart b/packages/flutter_tools/test/src/base/terminal_test.dart index 85a4c01be7e..d8bb11d0b52 100644 --- a/packages/flutter_tools/test/src/base/terminal_test.dart +++ b/packages/flutter_tools/test/src/base/terminal_test.dart @@ -21,6 +21,7 @@ void main() { testUsingContext('character prompt', () async { mockStdInStream = new Stream.fromFutures(>[ new Future.value('d'), // Not in accepted list. + new Future.value('\n'), // Not in accepted list new Future.value('b'), ]).asBroadcastStream(); final String choice = @@ -29,10 +30,32 @@ void main() { prompt: 'Please choose something', ); expect(choice, 'b'); - expect(testLogger.statusText, ''' -Please choose something [a|b|c]: d -Please choose something [a|b|c]: b -'''); + expect( + testLogger.statusText, + 'Please choose something [a|b|c]: d\n' + 'Please choose something [a|b|c]: \n' + '\n' + 'Please choose something [a|b|c]: b\n' + ); + }); + + testUsingContext('default character choice without displayAcceptedCharacters', () async { + mockStdInStream = new Stream.fromFutures(>[ + new Future.value('\n'), // Not in accepted list + ]).asBroadcastStream(); + final String choice = + await terminalUnderTest.promptForCharInput( + ['a', 'b', 'c'], + prompt: 'Please choose something', + displayAcceptedCharacters: false, + defaultChoiceIndex: 1, // which is b. + ); + expect(choice, 'b'); + expect( + testLogger.statusText, + 'Please choose something: \n' + '\n' + ); }); }); } diff --git a/packages/flutter_tools/test/src/ios/code_signing_test.dart b/packages/flutter_tools/test/src/ios/code_signing_test.dart index 437b6ba94c3..53de45093f8 100644 --- a/packages/flutter_tools/test/src/ios/code_signing_test.dart +++ b/packages/flutter_tools/test/src/ios/code_signing_test.dart @@ -189,7 +189,7 @@ void main() { expect( testLogger.statusText, - contains('Please select a certificate for code signing [1|2|3|a]: 3') + contains('Please select a certificate for code signing [1|2|3|a]: 3') ); expect( testLogger.statusText, @@ -228,6 +228,9 @@ class MockStdIn extends Mock implements IOSink {} Stream mockTerminalStdInStream; class TestTerminal extends AnsiTerminal { + @override + String bolden(String message) => '$message'; + @override Stream get onCharInput { return mockTerminalStdInStream;