From 6d46ff7e9ba8edeecee937e2fde04dce97e43c9e Mon Sep 17 00:00:00 2001 From: includecmath Date: Thu, 3 Sep 2020 08:30:04 +0800 Subject: [PATCH] [flutter_tools] flutter run should allow exit when make choose for devices. (#64403) --- .../flutter_tools/lib/src/base/terminal.dart | 1 + .../lib/src/base/user_messages.dart | 2 +- packages/flutter_tools/lib/src/device.dart | 7 ++- .../test/general.shard/device_test.dart | 49 ++++++++++++++++--- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart index bdabd7feba..e0e2b4b796 100644 --- a/packages/flutter_tools/lib/src/base/terminal.dart +++ b/packages/flutter_tools/lib/src/base/terminal.dart @@ -285,6 +285,7 @@ class AnsiTerminal implements Terminal { if (displayAcceptedCharacters) { logger.printStatus(' [${charactersToDisplay.join("|")}]', newline: false); } + // prompt ends with ': ' logger.printStatus(': ', emphasis: true, newline: false); } choice = await keystrokes.first; diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart index 7cc3da062c..3d28c62b6a 100644 --- a/packages/flutter_tools/lib/src/base/user_messages.dart +++ b/packages/flutter_tools/lib/src/base/user_messages.dart @@ -256,7 +256,7 @@ class UserMessages { 'Found $count devices with name or id matching $deviceId:'; String get flutterMultipleDevicesFound => 'Multiple devices found:'; String flutterChooseDevice(int option, String name, String deviceId) => '[$option]: $name ($deviceId)'; - String get flutterChooseOne => 'Please choose one:'; + String get flutterChooseOne => 'Please choose one (To quit, press "q/Q")'; String get flutterSpecifyDeviceWithAllOption => 'More than one device connected; please specify a device with ' "the '-d ' flag, or use '-d all' to act on all devices."; diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 84d0a052fd..52fff93b14 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -14,6 +14,7 @@ import 'android/android_sdk.dart'; import 'android/android_workflow.dart'; import 'application_package.dart'; import 'artifacts.dart'; +import 'base/common.dart'; import 'base/config.dart'; import 'base/context.dart'; import 'base/dds.dart'; @@ -283,6 +284,9 @@ abstract class DeviceManager { Future _chooseOneOfAvailableDevices(List devices) async { _displayDeviceOptions(devices); final String userInput = await _readUserInput(devices.length); + if (userInput.toLowerCase() == 'q') { + throwToolExit(''); + } return devices[int.parse(userInput)]; } @@ -297,7 +301,8 @@ abstract class DeviceManager { Future _readUserInput(int deviceCount) async { globals.terminal.usesTerminalUi = true; final String result = await globals.terminal.promptForCharInput( - [ for (int i = 0; i < deviceCount; i++) '$i' ], + [ for (int i = 0; i < deviceCount; i++) '$i', 'q', 'Q'], + displayAcceptedCharacters: false, logger: globals.logger, prompt: userMessages.flutterChooseOne); return result; diff --git a/packages/flutter_tools/test/general.shard/device_test.dart b/packages/flutter_tools/test/general.shard/device_test.dart index f2e62eca77..b7a96c2d53 100644 --- a/packages/flutter_tools/test/general.shard/device_test.dart +++ b/packages/flutter_tools/test/general.shard/device_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/artifacts.dart'; @@ -208,7 +209,8 @@ void main() { ]; when(mockStdio.stdinHasTerminal).thenReturn(true); - when(globals.terminal.promptForCharInput(['0', '1'], + when(globals.terminal.promptForCharInput(['0', '1', 'q', 'Q'], + displayAcceptedCharacters: false, logger: globals.logger, prompt: globals.userMessages.flutterChooseOne) ).thenAnswer((Invocation invocation) async => '0'); @@ -232,8 +234,9 @@ void main() { ]; when(mockStdio.stdinHasTerminal).thenReturn(true); - when(globals.terminal.promptForCharInput(['0', '1'], - logger: globals.logger, + when(globals.terminal.promptForCharInput(['0', '1', 'q', 'Q'], + displayAcceptedCharacters: false, + logger: globals.logger, prompt: globals.userMessages.flutterChooseOne) ).thenAnswer((Invocation invocation) async => '1'); @@ -256,8 +259,9 @@ void main() { ]; when(mockStdio.stdinHasTerminal).thenReturn(true); - when(globals.terminal.promptForCharInput(['0', '1'], - logger: globals.logger, + when(globals.terminal.promptForCharInput(['0', '1', 'q', 'Q'], + displayAcceptedCharacters: false, + logger: globals.logger, prompt: globals.userMessages.flutterChooseOne) ).thenAnswer((Invocation invocation) async => '0'); @@ -280,8 +284,9 @@ void main() { ]; when(mockStdio.stdinHasTerminal).thenReturn(true); - when(globals.terminal.promptForCharInput(['0', '1'], - logger: globals.logger, + when(globals.terminal.promptForCharInput(['0', '1', 'q', 'Q'], + displayAcceptedCharacters: false, + logger: globals.logger, prompt: globals.userMessages.flutterChooseOne) ).thenAnswer((Invocation invocation) async => '1'); @@ -307,7 +312,8 @@ void main() { ]; when(mockStdio.stdinHasTerminal).thenReturn(true); - when(globals.terminal.promptForCharInput(['0', '1', '2', '3'], + when(globals.terminal.promptForCharInput(['0', '1', '2', '3', 'q', 'Q'], + displayAcceptedCharacters: false, logger: globals.logger, prompt: globals.userMessages.flutterChooseOne) ).thenAnswer((Invocation invocation) async => '2'); @@ -325,6 +331,33 @@ void main() { Cache: () => cache, }); + testUsingContext('exit from choose one of available devices', () async { + final List devices = [ + ephemeralOne, + ephemeralTwo, + ]; + + when(mockStdio.stdinHasTerminal).thenReturn(true); + when(globals.terminal.promptForCharInput(['0', '1', 'q', 'Q'], + displayAcceptedCharacters: false, + logger: globals.logger, + prompt: globals.userMessages.flutterChooseOne) + ).thenAnswer((Invocation invocation) async => 'q'); + + try { + final DeviceManager deviceManager = TestDeviceManager(devices); + await deviceManager.findTargetDevices(FlutterProject.current()); + } on ToolExit catch (e) { + expect(e.exitCode, null); + expect(e.message, ''); + } + }, overrides: { + Stdio: () => mockStdio, + AnsiTerminal: () => MockTerminal(), + Artifacts: () => Artifacts.test(), + Cache: () => cache, + }); + testUsingContext('Removes a single unsupported device', () async { final List devices = [ unsupported,