Skip to content

Commit 6bfae93

Browse files
AlexV525christopherfujino
authored andcommitted
flutter config --list (flutter#135401)
Resolves flutter#81831. The PR improves the `config` command in below ways: - Does not print the settings in usages or other options. - Adds the `--list` flag to print the full settings list. - Separates usages for settings and analytics. - Prints the restart tip when clearing features.
1 parent 915bea3 commit 6bfae93

File tree

3 files changed

+89
-41
lines changed

3 files changed

+89
-41
lines changed

packages/flutter_tools/lib/src/commands/config.dart

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ import '../runner/flutter_command_runner.dart';
1515

1616
class ConfigCommand extends FlutterCommand {
1717
ConfigCommand({ bool verboseHelp = false }) {
18+
argParser.addFlag(
19+
'list',
20+
help: 'List all settings and their current values.',
21+
negatable: false,
22+
);
1823
argParser.addFlag('analytics',
1924
hide: !verboseHelp,
2025
help: 'Enable or disable reporting anonymously tool usage statistics and crash reports.\n'
@@ -73,37 +78,7 @@ class ConfigCommand extends FlutterCommand {
7378
bool get shouldUpdateCache => false;
7479

7580
@override
76-
String get usageFooter {
77-
// List all config settings. for feature flags, include whether they
78-
// are available.
79-
final Map<String, Feature> featuresByName = <String, Feature>{};
80-
final String channel = globals.flutterVersion.channel;
81-
for (final Feature feature in allFeatures) {
82-
final String? configSetting = feature.configSetting;
83-
if (configSetting != null) {
84-
featuresByName[configSetting] = feature;
85-
}
86-
}
87-
String values = globals.config.keys
88-
.map<String>((String key) {
89-
String configFooter = '';
90-
if (featuresByName.containsKey(key)) {
91-
final FeatureChannelSetting setting = featuresByName[key]!.getSettingForChannel(channel);
92-
if (!setting.available) {
93-
configFooter = '(Unavailable)';
94-
}
95-
}
96-
return ' $key: ${globals.config.getValue(key)} $configFooter';
97-
}).join('\n');
98-
if (values.isEmpty) {
99-
values = ' No settings have been configured.';
100-
}
101-
final bool analyticsEnabled = globals.flutterUsage.enabled &&
102-
!globals.flutterUsage.suppressAnalytics;
103-
return
104-
'\nSettings:\n$values\n\n'
105-
'Analytics reporting is currently ${analyticsEnabled ? 'enabled' : 'disabled'}.';
106-
}
81+
String get usageFooter => '\n$analyticsUsage';
10782

10883
/// Return null to disable analytics recording of the `config` command.
10984
@override
@@ -121,6 +96,11 @@ class ConfigCommand extends FlutterCommand {
12196
' flutter config --android-studio-dir "/opt/Android Studio"');
12297
}
12398

99+
if (boolArg('list')) {
100+
globals.printStatus(settingsText);
101+
return FlutterCommandResult.success();
102+
}
103+
124104
if (boolArg('machine')) {
125105
await handleMachine();
126106
return FlutterCommandResult.success();
@@ -133,6 +113,7 @@ class ConfigCommand extends FlutterCommand {
133113
globals.config.removeValue(configSetting);
134114
}
135115
}
116+
globals.printStatus(requireReloadTipText);
136117
return FlutterCommandResult.success();
137118
}
138119

@@ -195,7 +176,7 @@ class ConfigCommand extends FlutterCommand {
195176
if (argResults == null || argResults!.arguments.isEmpty) {
196177
globals.printStatus(usage);
197178
} else {
198-
globals.printStatus('\nYou may need to restart any open editors for them to read new settings.');
179+
globals.printStatus('\n$requireReloadTipText');
199180
}
200181

201182
return FlutterCommandResult.success();
@@ -234,4 +215,50 @@ class ConfigCommand extends FlutterCommand {
234215
globals.printStatus('Setting "$keyName" value to "$keyValue".');
235216
}
236217
}
218+
219+
/// List all config settings. for feature flags, include whether they are available.
220+
String get settingsText {
221+
final Map<String, Feature> featuresByName = <String, Feature>{};
222+
final String channel = globals.flutterVersion.channel;
223+
for (final Feature feature in allFeatures) {
224+
final String? configSetting = feature.configSetting;
225+
if (configSetting != null) {
226+
featuresByName[configSetting] = feature;
227+
}
228+
}
229+
final Set<String> keys = <String>{
230+
...allFeatures.map((Feature e) => e.configSetting).whereType<String>(),
231+
...globals.config.keys,
232+
};
233+
final Iterable<String> settings = keys.map<String>((String key) {
234+
Object? value = globals.config.getValue(key);
235+
value ??= '(Not set)';
236+
final StringBuffer buffer = StringBuffer(' $key: $value');
237+
if (featuresByName.containsKey(key)) {
238+
final FeatureChannelSetting setting = featuresByName[key]!.getSettingForChannel(channel);
239+
if (!setting.available) {
240+
buffer.write(' (Unavailable)');
241+
}
242+
}
243+
return buffer.toString();
244+
});
245+
final StringBuffer buffer = StringBuffer();
246+
buffer.writeln('All Settings:');
247+
if (settings.isEmpty) {
248+
buffer.writeln(' No configs have been configured.');
249+
} else {
250+
buffer.writeln(settings.join('\n'));
251+
}
252+
return buffer.toString();
253+
}
254+
255+
/// List the status of the analytics reporting.
256+
String get analyticsUsage {
257+
final bool analyticsEnabled =
258+
globals.flutterUsage.enabled && !globals.flutterUsage.suppressAnalytics;
259+
return 'Analytics reporting is currently ${analyticsEnabled ? 'enabled' : 'disabled'}.';
260+
}
261+
262+
/// Raising the reload tip for setting changes.
263+
final String requireReloadTipText = 'You may need to restart any open editors for them to read new settings.';
237264
}

packages/flutter_tools/test/commands.shard/hermetic/config_test.dart

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
1212
import 'package:flutter_tools/src/build_info.dart';
1313
import 'package:flutter_tools/src/cache.dart';
1414
import 'package:flutter_tools/src/commands/config.dart';
15+
import 'package:flutter_tools/src/features.dart';
1516
import 'package:flutter_tools/src/globals.dart' as globals;
1617
import 'package:flutter_tools/src/reporting/reporting.dart';
1718
import 'package:flutter_tools/src/version.dart';
@@ -48,6 +49,23 @@ void main() {
4849
}
4950

5051
group('config', () {
52+
testUsingContext('prints all settings with --list', () async {
53+
final ConfigCommand configCommand = ConfigCommand();
54+
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
55+
await commandRunner.run(<String>['config', '--list']);
56+
expect(
57+
testLogger.statusText,
58+
'All Settings:\n'
59+
'${allFeatures
60+
.where((Feature e) => e.configSetting != null)
61+
.map((Feature e) => ' ${e.configSetting}: (Not set)')
62+
.join('\n')}'
63+
'\n\n',
64+
);
65+
}, overrides: <Type, Generator>{
66+
Usage: () => testUsage,
67+
});
68+
5169
testUsingContext('throws error on excess arguments', () {
5270
final ConfigCommand configCommand = ConfigCommand();
5371
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
@@ -196,6 +214,7 @@ void main() {
196214

197215
await commandRunner.run(<String>[
198216
'config',
217+
'--list'
199218
]);
200219

201220
expect(
@@ -270,20 +289,21 @@ void main() {
270289
Usage: () => testUsage,
271290
});
272291

273-
testUsingContext('analytics reported disabled when suppressed', () async {
292+
testUsingContext('analytics reported with help usages', () async {
274293
final ConfigCommand configCommand = ConfigCommand();
275-
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
294+
createTestCommandRunner(configCommand);
276295

277296
testUsage.suppressAnalytics = true;
278-
279-
await commandRunner.run(<String>[
280-
'config',
281-
]);
282-
283297
expect(
284-
testLogger.statusText,
298+
configCommand.usage,
285299
containsIgnoringWhitespace('Analytics reporting is currently disabled'),
286300
);
301+
302+
testUsage.suppressAnalytics = false;
303+
expect(
304+
configCommand.usage,
305+
containsIgnoringWhitespace('Analytics reporting is currently enabled'),
306+
);
287307
}, overrides: <Type, Generator>{
288308
Usage: () => testUsage,
289309
});

packages/flutter_tools/test/integration.shard/command_output_test.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ void main() {
7171
expect(result.stdout, contains('Shutdown hooks complete'));
7272
});
7373

74-
testWithoutContext('flutter config contains all features', () async {
74+
testWithoutContext('flutter config --list contains all features', () async {
7575
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
7676
final ProcessResult result = await processManager.run(<String>[
7777
flutterBin,
7878
'config',
79+
'--list'
7980
]);
8081

8182
// contains all of the experiments in features.dart

0 commit comments

Comments
 (0)