mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
refactor: Centralize table formatting logic into a new formatTable utility function. (#182196)
This resolves https://github.com/flutter/flutter/issues/180949 This is follow-up on https://github.com/flutter/flutter/pull/180098
This commit is contained in:
parent
d802cab600
commit
ac3aa6dad6
@ -45,7 +45,7 @@ dependencies:
|
||||
term_glyph: 1.2.2
|
||||
test_api: 0.7.9
|
||||
typed_data: 1.4.0
|
||||
unified_analytics: 8.0.10
|
||||
unified_analytics: 8.0.11
|
||||
url_launcher_android: 6.3.28
|
||||
url_launcher_ios: 6.4.0
|
||||
url_launcher_linux: 3.2.2
|
||||
@ -68,4 +68,4 @@ dev_dependencies:
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
# PUBSPEC CHECKSUM: nepob0
|
||||
# PUBSPEC CHECKSUM: fv45lk
|
||||
|
||||
@ -611,3 +611,38 @@ extension StackTraceTransform<T> on Stream<T> {
|
||||
final utf8LineDecoder = StreamTransformer<List<int>, String>.fromBind(
|
||||
(stream) => stream.transformWithCallSite(utf8.decoder).transform(const LineSplitter()),
|
||||
);
|
||||
|
||||
/// Formats a list of rows into a table with aligned columns.
|
||||
///
|
||||
/// [table] is a list of rows, where each row is a list of strings.
|
||||
/// [separator] is the string used to separate columns (default is ' • ').
|
||||
///
|
||||
/// Returns a list of strings, where each string is a formatted row.
|
||||
List<String> formatTable(List<List<String>> table, {String separator = ' • ', int indent = 0}) {
|
||||
if (table.isEmpty) {
|
||||
return <String>[];
|
||||
}
|
||||
|
||||
// Calculate column widths
|
||||
if (table.first.isEmpty) {
|
||||
throw Exception('Table header cannot be empty');
|
||||
}
|
||||
final indices = List<int>.generate(table.first.length - 1, (int i) => i);
|
||||
final widths = List<int>.filled(indices.length, 0);
|
||||
for (final row in table) {
|
||||
for (final i in indices) {
|
||||
widths[i] = math.max(widths[i], row[i].length);
|
||||
}
|
||||
}
|
||||
|
||||
final String indentString = ' ' * indent;
|
||||
|
||||
// Join columns into lines of text
|
||||
return table.map<String>((List<String> row) {
|
||||
final String formatted = indices
|
||||
.map<String>((int i) => row[i].padRight(widths[i]))
|
||||
.followedBy(<String>[row.last])
|
||||
.join(separator);
|
||||
return '$indentString$formatted';
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:multicast_dns/multicast_dns.dart';
|
||||
@ -118,23 +117,8 @@ class RunningAppsCommand extends FlutterCommand {
|
||||
table.add(<String>['$projectName ($mode)', deviceString, platform, vmServiceUri, age]);
|
||||
}
|
||||
|
||||
// TODO(jwren): consider combining this logic with the logic in `flutter devices`,
|
||||
// see https://github.com/flutter/flutter/issues/180949
|
||||
// Calculate column widths
|
||||
final indices = List<int>.generate(table[0].length - 1, (int i) => i);
|
||||
List<int> widths = indices.map<int>((int i) => 0).toList();
|
||||
for (final row in table) {
|
||||
widths = indices.map<int>((int i) => math.max(widths[i], row[i].length)).toList();
|
||||
}
|
||||
|
||||
// Join columns into lines of text
|
||||
for (final row in table) {
|
||||
final String rowString = indices
|
||||
.map<String>((int i) => row[i].padRight(widths[i]))
|
||||
.followedBy(<String>[row.last])
|
||||
.join(' • ');
|
||||
_logger.printStatus(' $rowString');
|
||||
}
|
||||
_logger.printStatus(formatTable(table, indent: 2).join('\n'));
|
||||
return FlutterCommandResult.success();
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
@ -859,21 +858,8 @@ abstract class Device {
|
||||
]);
|
||||
}
|
||||
|
||||
// Calculate column widths
|
||||
final indices = List<int>.generate(table[0].length - 1, (int i) => i);
|
||||
List<int> widths = indices.map<int>((int i) => 0).toList();
|
||||
for (final row in table) {
|
||||
widths = indices.map<int>((int i) => math.max(widths[i], row[i].length)).toList();
|
||||
}
|
||||
|
||||
// Join columns into lines of text
|
||||
return <String>[
|
||||
for (final List<String> row in table)
|
||||
indices
|
||||
.map<String>((int i) => row[i].padRight(widths[i]))
|
||||
.followedBy(<String>[row.last])
|
||||
.join(' • '),
|
||||
];
|
||||
return formatTable(table);
|
||||
}
|
||||
|
||||
static Future<void> printDevices(
|
||||
|
||||
@ -20,7 +20,7 @@ dependencies:
|
||||
completion: 1.0.2
|
||||
coverage: 1.15.0
|
||||
crypto: 3.0.7
|
||||
ffi: 2.1.5
|
||||
ffi: 2.2.0
|
||||
file: 7.0.1
|
||||
flutter_template_images: 5.0.0
|
||||
html: 0.15.6
|
||||
@ -54,7 +54,7 @@ dependencies:
|
||||
http_multi_server: 3.2.2
|
||||
convert: 3.1.2
|
||||
async: 2.13.0
|
||||
unified_analytics: 8.0.10
|
||||
unified_analytics: 8.0.11
|
||||
pubspec_parse: 1.5.0
|
||||
|
||||
graphs: 2.3.2
|
||||
@ -113,7 +113,7 @@ dependencies:
|
||||
watcher: 1.2.1
|
||||
web: 1.1.1
|
||||
web_socket: 1.0.1
|
||||
yaml_edit: 2.2.3
|
||||
yaml_edit: 2.2.4
|
||||
mdns_dart: ^2.1.0
|
||||
|
||||
dev_dependencies:
|
||||
@ -129,4 +129,4 @@ dartdoc:
|
||||
# Exclude this package from the hosted API docs.
|
||||
nodoc: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 8kslb0
|
||||
# PUBSPEC CHECKSUM: j77gl7
|
||||
|
||||
@ -568,4 +568,53 @@ needs to be wrapped.
|
||||
await validCompleter.future;
|
||||
await errorCompleter.future;
|
||||
});
|
||||
|
||||
testWithoutContext('formatTable', () {
|
||||
expect(formatTable(<List<String>>[]), isEmpty);
|
||||
|
||||
expect(() => formatTable(<List<String>>[<String>[]]), throwsException);
|
||||
expect(() => formatTable(<List<String>>[<String>[], <String>[]]), throwsException);
|
||||
|
||||
expect(
|
||||
formatTable(<List<String>>[
|
||||
<String>['Col1', 'Col2'],
|
||||
<String>['Value1', 'Value2'],
|
||||
]).join('\n'),
|
||||
'''
|
||||
Col1 • Col2
|
||||
Value1 • Value2''',
|
||||
);
|
||||
|
||||
expect(
|
||||
formatTable(<List<String>>[
|
||||
<String>['A', 'B', 'C'],
|
||||
<String>['LongValue', 'Short', 'Tiny'],
|
||||
]).join('\n'),
|
||||
'''
|
||||
A • B • C
|
||||
LongValue • Short • Tiny''',
|
||||
);
|
||||
|
||||
expect(
|
||||
formatTable(<List<String>>[
|
||||
<String>['A', 'B'],
|
||||
<String>['1', '2'],
|
||||
], separator: ' | ').join('\n'),
|
||||
'''
|
||||
A | B
|
||||
1 | 2''',
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('formatTable with indent', () {
|
||||
expect(
|
||||
formatTable(<List<String>>[
|
||||
<String>['A', 'B'],
|
||||
<String>['1', '2'],
|
||||
], indent: 2).join('\n'),
|
||||
'''
|
||||
A • B
|
||||
1 • 2''',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
12
pubspec.lock
12
pubspec.lock
@ -214,10 +214,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: ffi
|
||||
sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c
|
||||
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "2.2.0"
|
||||
ffigen:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -955,10 +955,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: video_player_avfoundation
|
||||
sha256: f46e9e20f1fe429760cf4dc118761336320d1bec0f50d255930c2355f2defb5b
|
||||
sha256: f93b93a3baa12ca0ff7d00ca8bc60c1ecd96865568a01ff0c18a99853ee201a5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.9.1"
|
||||
version: "2.9.3"
|
||||
video_player_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1099,10 +1099,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: yaml_edit
|
||||
sha256: ec709065bb2c911b336853b67f3732dd13e0336bd065cc2f1061d7610ddf45e3
|
||||
sha256: "07c9e63ba42519745182b88ca12264a7ba2484d8239958778dfe4d44fe760488"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
version: "2.2.4"
|
||||
sdks:
|
||||
dart: ">=3.10.3 <4.0.0"
|
||||
flutter: ">=3.38.4"
|
||||
|
||||
@ -101,7 +101,7 @@ dependencies:
|
||||
device_info: 2.0.3
|
||||
device_info_platform_interface: 2.0.1
|
||||
fake_async: 1.3.3
|
||||
ffi: 2.1.5
|
||||
ffi: 2.2.0
|
||||
file: 7.0.1
|
||||
fixnum: 1.1.1
|
||||
flutter_gallery_assets: 1.0.2
|
||||
@ -186,7 +186,7 @@ dependencies:
|
||||
vector_math: 2.2.0
|
||||
video_player: 2.10.1
|
||||
video_player_android: 2.9.1
|
||||
video_player_avfoundation: 2.9.1
|
||||
video_player_avfoundation: 2.9.3
|
||||
video_player_platform_interface: 6.6.0
|
||||
video_player_web: 2.4.0
|
||||
vm_service: 15.0.2
|
||||
@ -211,9 +211,9 @@ dependencies:
|
||||
lints: 6.1.0
|
||||
pedantic: 1.11.1
|
||||
quiver: 3.2.2
|
||||
yaml_edit: 2.2.3
|
||||
yaml_edit: 2.2.4
|
||||
|
||||
dev_dependencies:
|
||||
ffigen: 20.1.1
|
||||
|
||||
# PUBSPEC CHECKSUM: q8irkm
|
||||
# PUBSPEC CHECKSUM: r03o20
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user