Unverified Commit c23d9cd4 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tools] Print emojis in Windows Terminal (#50446)

parent 5f465897
...@@ -36,58 +36,122 @@ class CommandHelp { ...@@ -36,58 +36,122 @@ class CommandHelp {
final OutputPreferences _outputPreferences; final OutputPreferences _outputPreferences;
CommandHelpOption _L; CommandHelpOption _L;
CommandHelpOption get L => _L ??= _makeOption('L', 'Dump layer tree to the console.', 'debugDumpLayerTree'); CommandHelpOption get L => _L ??= _makeOption(
'L',
'Dump layer tree to the console.',
'debugDumpLayerTree',
);
CommandHelpOption _P; CommandHelpOption _P;
CommandHelpOption get P => _P ??= _makeOption('P', 'Toggle performance overlay.', 'WidgetsApp.showPerformanceOverlay'); CommandHelpOption get P => _P ??= _makeOption(
'P',
'Toggle performance overlay.',
'WidgetsApp.showPerformanceOverlay',
);
CommandHelpOption _R; CommandHelpOption _R;
CommandHelpOption get R => _R ??= _makeOption('R', 'Hot restart.'); CommandHelpOption get R => _R ??= _makeOption(
'R',
'Hot restart.',
);
CommandHelpOption _S; CommandHelpOption _S;
CommandHelpOption get S => _S ??= _makeOption('S', 'Dump accessibility tree in traversal order.', 'debugDumpSemantics'); CommandHelpOption get S => _S ??= _makeOption(
'S',
'Dump accessibility tree in traversal order.',
'debugDumpSemantics',
);
CommandHelpOption _U; CommandHelpOption _U;
CommandHelpOption get U => _U ??= _makeOption('U', 'Dump accessibility tree in inverse hit test order.', 'debugDumpSemantics'); CommandHelpOption get U => _U ??= _makeOption(
'U',
'Dump accessibility tree in inverse hit test order.',
'debugDumpSemantics',
);
CommandHelpOption _a; CommandHelpOption _a;
CommandHelpOption get a => _a ??= _makeOption('a', 'Toggle timeline events for all widget build methods.', 'debugProfileWidgetBuilds'); CommandHelpOption get a => _a ??= _makeOption(
'a',
'Toggle timeline events for all widget build methods.',
'debugProfileWidgetBuilds',
);
CommandHelpOption _c; CommandHelpOption _c;
CommandHelpOption get c => _c ??= _makeOption('c', 'Clear the screen'); CommandHelpOption get c => _c ??= _makeOption(
'c',
'Clear the screen',
);
CommandHelpOption _d; CommandHelpOption _d;
CommandHelpOption get d => _d ??= _makeOption('d', 'Detach (terminate "flutter run" but leave application running).'); CommandHelpOption get d => _d ??= _makeOption(
'd',
'Detach (terminate "flutter run" but leave application running).',
);
CommandHelpOption _h; CommandHelpOption _h;
CommandHelpOption get h => _h ??= _makeOption('h', 'Repeat this help message.'); CommandHelpOption get h => _h ??= _makeOption(
'h',
'Repeat this help message.',
);
CommandHelpOption _i; CommandHelpOption _i;
CommandHelpOption get i => _i ??= _makeOption('i', 'Toggle widget inspector.', 'WidgetsApp.showWidgetInspectorOverride'); CommandHelpOption get i => _i ??= _makeOption(
'i',
'Toggle widget inspector.',
'WidgetsApp.showWidgetInspectorOverride',
);
CommandHelpOption _o; CommandHelpOption _o;
CommandHelpOption get o => _o ??= _makeOption('o', 'Simulate different operating systems.', 'defaultTargetPlatform'); CommandHelpOption get o => _o ??= _makeOption(
'o',
'Simulate different operating systems.',
'defaultTargetPlatform',
);
CommandHelpOption _p; CommandHelpOption _p;
CommandHelpOption get p => _p ??= _makeOption('p', 'Toggle the display of construction lines.', 'debugPaintSizeEnabled'); CommandHelpOption get p => _p ??= _makeOption(
'p',
'Toggle the display of construction lines.',
'debugPaintSizeEnabled',
);
CommandHelpOption _q; CommandHelpOption _q;
CommandHelpOption get q => _q ??= _makeOption('q', 'Quit (terminate the application on the device).'); CommandHelpOption get q => _q ??= _makeOption(
'q',
'Quit (terminate the application on the device).',
);
CommandHelpOption _r; CommandHelpOption _r;
CommandHelpOption get r => _r ??= _makeOption('r', 'Hot reload. $fire$fire$fire'); CommandHelpOption get r => _r ??= _makeOption(
'r',
'Hot reload. $fire$fire$fire',
);
CommandHelpOption _s; CommandHelpOption _s;
CommandHelpOption get s => _s ??= _makeOption('s', 'Save a screenshot to flutter.png.'); CommandHelpOption get s => _s ??= _makeOption(
's',
'Save a screenshot to flutter.png.',
);
CommandHelpOption _t; CommandHelpOption _t;
CommandHelpOption get t => _t ??= _makeOption('t', 'Dump rendering tree to the console.', 'debugDumpRenderTree'); CommandHelpOption get t => _t ??= _makeOption(
't',
'Dump rendering tree to the console.',
'debugDumpRenderTree',
);
CommandHelpOption _w; CommandHelpOption _w;
CommandHelpOption get w => _w ??= _makeOption('w', 'Dump widget hierarchy to the console.', 'debugDumpApp'); CommandHelpOption get w => _w ??= _makeOption(
'w',
'Dump widget hierarchy to the console.',
'debugDumpApp',
);
CommandHelpOption _z; CommandHelpOption _z;
CommandHelpOption get z => _z ??= _makeOption('z', 'Toggle elevation checker.'); CommandHelpOption get z => _z ??= _makeOption(
'z',
'Toggle elevation checker.',
);
CommandHelpOption _makeOption(String key, String description, [ CommandHelpOption _makeOption(String key, String description, [
String inParenthesis = '', String inParenthesis = '',
...@@ -142,25 +206,30 @@ class CommandHelpOption { ...@@ -142,25 +206,30 @@ class CommandHelpOption {
String toString() { String toString() {
final StringBuffer message = StringBuffer(); final StringBuffer message = StringBuffer();
message.writeAll(<String>[_terminal.bolden(key), description], ' '); message.writeAll(<String>[_terminal.bolden(key), description], ' ');
if (!_hasTextInParenthesis) {
return message.toString();
}
if (_hasTextInParenthesis) {
bool wrap = false; bool wrap = false;
final int maxWidth = math.max(_outputPreferences.wrapColumn ?? 0, maxLineWidth); final int maxWidth = math.max(
int width = maxWidth - (_platform.stdoutSupportsAnsi ? _rawMessageLength + 1 : message.length); _outputPreferences.wrapColumn ?? 0,
maxLineWidth,
);
final int adjustedMessageLength = _platform.stdoutSupportsAnsi
? _rawMessageLength + 1
: message.length;
int width = maxWidth - adjustedMessageLength;
final String parentheticalText = '($inParenthesis)'; final String parentheticalText = '($inParenthesis)';
if (width < parentheticalText.length) { if (width < parentheticalText.length) {
width = maxWidth; width = maxWidth;
wrap = true; wrap = true;
} }
if (wrap) { if (wrap) {
message.write('\n'); message.write('\n');
} }
// pad according to the raw text // pad according to the raw text
message.write(''.padLeft(width - parentheticalText.length)); message.write(''.padLeft(width - parentheticalText.length));
message.write(_terminal.color(parentheticalText, TerminalColor.grey)); message.write(_terminal.color(parentheticalText, TerminalColor.grey));
}
return message.toString(); return message.toString();
} }
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
import 'dart:async'; import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
...@@ -179,15 +178,13 @@ class StdoutLogger extends Logger { ...@@ -179,15 +178,13 @@ class StdoutLogger extends Logger {
@required Stdio stdio, @required Stdio stdio,
@required OutputPreferences outputPreferences, @required OutputPreferences outputPreferences,
@required TimeoutConfiguration timeoutConfiguration, @required TimeoutConfiguration timeoutConfiguration,
@required Platform platform,
StopwatchFactory stopwatchFactory = const StopwatchFactory(), StopwatchFactory stopwatchFactory = const StopwatchFactory(),
}) })
: _stdio = stdio, : _stdio = stdio,
_terminal = terminal, _terminal = terminal,
_timeoutConfiguration = timeoutConfiguration, _timeoutConfiguration = timeoutConfiguration,
_outputPreferences = outputPreferences, _outputPreferences = outputPreferences,
_stopwatchFactory = stopwatchFactory, _stopwatchFactory = stopwatchFactory;
_platform = platform;
@override @override
final AnsiTerminal _terminal; final AnsiTerminal _terminal;
...@@ -197,7 +194,6 @@ class StdoutLogger extends Logger { ...@@ -197,7 +194,6 @@ class StdoutLogger extends Logger {
final TimeoutConfiguration _timeoutConfiguration; final TimeoutConfiguration _timeoutConfiguration;
final Stdio _stdio; final Stdio _stdio;
final StopwatchFactory _stopwatchFactory; final StopwatchFactory _stopwatchFactory;
final Platform _platform;
Status _status; Status _status;
...@@ -306,8 +302,8 @@ class StdoutLogger extends Logger { ...@@ -306,8 +302,8 @@ class StdoutLogger extends Logger {
onFinish: _clearStatus, onFinish: _clearStatus,
stdio: _stdio, stdio: _stdio,
timeoutConfiguration: _timeoutConfiguration, timeoutConfiguration: _timeoutConfiguration,
platform: _platform,
stopwatch: _stopwatchFactory.createStopwatch(), stopwatch: _stopwatchFactory.createStopwatch(),
terminal: _terminal,
)..start(); )..start();
} else { } else {
_status = SummaryStatus( _status = SummaryStatus(
...@@ -352,7 +348,6 @@ class WindowsStdoutLogger extends StdoutLogger { ...@@ -352,7 +348,6 @@ class WindowsStdoutLogger extends StdoutLogger {
@required Stdio stdio, @required Stdio stdio,
@required OutputPreferences outputPreferences, @required OutputPreferences outputPreferences,
@required TimeoutConfiguration timeoutConfiguration, @required TimeoutConfiguration timeoutConfiguration,
@required Platform platform,
StopwatchFactory stopwatchFactory = const StopwatchFactory(), StopwatchFactory stopwatchFactory = const StopwatchFactory(),
}) : super( }) : super(
terminal: terminal, terminal: terminal,
...@@ -360,13 +355,14 @@ class WindowsStdoutLogger extends StdoutLogger { ...@@ -360,13 +355,14 @@ class WindowsStdoutLogger extends StdoutLogger {
outputPreferences: outputPreferences, outputPreferences: outputPreferences,
timeoutConfiguration: timeoutConfiguration, timeoutConfiguration: timeoutConfiguration,
stopwatchFactory: stopwatchFactory, stopwatchFactory: stopwatchFactory,
platform: platform,
); );
@override @override
void writeToStdOut(String message) { void writeToStdOut(String message) {
// TODO(jcollins-g): wrong abstraction layer for this, move to [Stdio]. // TODO(jcollins-g): wrong abstraction layer for this, move to [Stdio].
final String windowsMessage = message final String windowsMessage = _terminal.supportsEmoji
? message
: message.replaceAll('🔥', '')
.replaceAll('✗', 'X') .replaceAll('✗', 'X')
.replaceAll('✓', '√'); .replaceAll('✓', '√');
_stdio.stdoutWrite(windowsMessage); _stdio.stdoutWrite(windowsMessage);
...@@ -681,19 +677,18 @@ abstract class Status { ...@@ -681,19 +677,18 @@ abstract class Status {
@required Duration timeout, @required Duration timeout,
@required TimeoutConfiguration timeoutConfiguration, @required TimeoutConfiguration timeoutConfiguration,
@required Stopwatch stopwatch, @required Stopwatch stopwatch,
@required bool supportsColor, @required AnsiTerminal terminal,
@required Platform platform,
VoidCallback onFinish, VoidCallback onFinish,
SlowWarningCallback slowWarningCallback, SlowWarningCallback slowWarningCallback,
}) { }) {
if (supportsColor) { if (terminal.supportsColor) {
return AnsiSpinner( return AnsiSpinner(
timeout: timeout, timeout: timeout,
onFinish: onFinish, onFinish: onFinish,
slowWarningCallback: slowWarningCallback, slowWarningCallback: slowWarningCallback,
timeoutConfiguration: timeoutConfiguration, timeoutConfiguration: timeoutConfiguration,
stopwatch: stopwatch, stopwatch: stopwatch,
platform: platform, terminal: terminal,
)..start(); )..start();
} }
return SilentStatus( return SilentStatus(
...@@ -862,12 +857,12 @@ class AnsiSpinner extends Status { ...@@ -862,12 +857,12 @@ class AnsiSpinner extends Status {
@required Duration timeout, @required Duration timeout,
@required TimeoutConfiguration timeoutConfiguration, @required TimeoutConfiguration timeoutConfiguration,
@required Stopwatch stopwatch, @required Stopwatch stopwatch,
@required Platform platform, @required AnsiTerminal terminal,
VoidCallback onFinish, VoidCallback onFinish,
this.slowWarningCallback, this.slowWarningCallback,
Stdio stdio, Stdio stdio,
}) : _stdio = stdio ?? globals.stdio, }) : _stdio = stdio ?? globals.stdio,
_isWindows = platform.isWindows, _terminal = terminal,
super( super(
timeout: timeout, timeout: timeout,
onFinish: onFinish, onFinish: onFinish,
...@@ -878,7 +873,7 @@ class AnsiSpinner extends Status { ...@@ -878,7 +873,7 @@ class AnsiSpinner extends Status {
final String _backspaceChar = '\b'; final String _backspaceChar = '\b';
final String _clearChar = ' '; final String _clearChar = ' ';
final Stdio _stdio; final Stdio _stdio;
final bool _isWindows; final AnsiTerminal _terminal;
bool timedOut = false; bool timedOut = false;
...@@ -886,7 +881,7 @@ class AnsiSpinner extends Status { ...@@ -886,7 +881,7 @@ class AnsiSpinner extends Status {
Timer timer; Timer timer;
// Windows console font has a limited set of Unicode characters. // Windows console font has a limited set of Unicode characters.
List<String> get _animation => _isWindows List<String> get _animation => !_terminal.supportsEmoji
? const <String>[r'-', r'\', r'|', r'/'] ? const <String>[r'-', r'\', r'|', r'/']
: const <String>['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']; : const <String>['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
...@@ -984,7 +979,7 @@ class AnsiStatus extends AnsiSpinner { ...@@ -984,7 +979,7 @@ class AnsiStatus extends AnsiSpinner {
this.padding = kDefaultStatusPadding, this.padding = kDefaultStatusPadding,
@required Duration timeout, @required Duration timeout,
@required Stopwatch stopwatch, @required Stopwatch stopwatch,
@required Platform platform, @required AnsiTerminal terminal,
VoidCallback onFinish, VoidCallback onFinish,
Stdio stdio, Stdio stdio,
TimeoutConfiguration timeoutConfiguration, TimeoutConfiguration timeoutConfiguration,
...@@ -997,7 +992,7 @@ class AnsiStatus extends AnsiSpinner { ...@@ -997,7 +992,7 @@ class AnsiStatus extends AnsiSpinner {
stdio: stdio, stdio: stdio,
timeoutConfiguration: timeoutConfiguration, timeoutConfiguration: timeoutConfiguration,
stopwatch: stopwatch, stopwatch: stopwatch,
platform: platform, terminal: terminal,
); );
final String message; final String message;
......
...@@ -86,7 +86,10 @@ class OutputPreferences { ...@@ -86,7 +86,10 @@ class OutputPreferences {
} }
class AnsiTerminal { class AnsiTerminal {
AnsiTerminal({@required io.Stdio stdio, @required Platform platform}) AnsiTerminal({
@required io.Stdio stdio,
@required Platform platform,
})
: _stdio = stdio, : _stdio = stdio,
_platform = platform; _platform = platform;
...@@ -121,7 +124,16 @@ class AnsiTerminal { ...@@ -121,7 +124,16 @@ class AnsiTerminal {
bool get supportsColor => _platform.stdoutSupportsAnsi ?? false; bool get supportsColor => _platform.stdoutSupportsAnsi ?? false;
final RegExp _boldControls = RegExp('(${RegExp.escape(resetBold)}|${RegExp.escape(bold)})'); // Assume unicode emojis are supported when not on Windows.
// If we are on Windows, unicode emojis are supported in Windows Terminal,
// which sets the WT_SESSION environment variable. See:
// https://github.com/microsoft/terminal/blob/master/doc/user-docs/index.md#tips-and-tricks
bool get supportsEmoji => !_platform.isWindows
|| _platform.environment.containsKey('WT_SESSION');
final RegExp _boldControls = RegExp(
'(${RegExp.escape(resetBold)}|${RegExp.escape(bold)})',
);
/// Whether we are interacting with the flutter tool via the terminal. /// Whether we are interacting with the flutter tool via the terminal.
/// ///
......
...@@ -127,14 +127,12 @@ Future<T> runInContext<T>( ...@@ -127,14 +127,12 @@ Future<T> runInContext<T>(
stdio: globals.stdio, stdio: globals.stdio,
outputPreferences: outputPreferences, outputPreferences: outputPreferences,
timeoutConfiguration: timeoutConfiguration, timeoutConfiguration: timeoutConfiguration,
platform: globals.platform,
) )
: StdoutLogger( : StdoutLogger(
terminal: globals.terminal, terminal: globals.terminal,
stdio: globals.stdio, stdio: globals.stdio,
outputPreferences: outputPreferences, outputPreferences: outputPreferences,
timeoutConfiguration: timeoutConfiguration, timeoutConfiguration: timeoutConfiguration,
platform: globals.platform,
), ),
MacOSWorkflow: () => const MacOSWorkflow(), MacOSWorkflow: () => const MacOSWorkflow(),
MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(), MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
......
...@@ -258,8 +258,7 @@ class Doctor { ...@@ -258,8 +258,7 @@ class Doctor {
slowWarningCallback: () => validator.slowWarning, slowWarningCallback: () => validator.slowWarning,
timeoutConfiguration: timeoutConfiguration, timeoutConfiguration: timeoutConfiguration,
stopwatch: Stopwatch(), stopwatch: Stopwatch(),
supportsColor: globals.terminal.supportsColor, terminal: globals.terminal,
platform: globals.platform,
); );
ValidationResult result; ValidationResult result;
try { try {
......
...@@ -314,9 +314,8 @@ class XcodeProjectInterpreter { ...@@ -314,9 +314,8 @@ class XcodeProjectInterpreter {
final Status status = Status.withSpinner( final Status status = Status.withSpinner(
timeout: const TimeoutConfiguration().fastOperation, timeout: const TimeoutConfiguration().fastOperation,
timeoutConfiguration: const TimeoutConfiguration(), timeoutConfiguration: const TimeoutConfiguration(),
platform: _platform,
stopwatch: Stopwatch(), stopwatch: Stopwatch(),
supportsColor: _terminal.supportsColor, terminal: _terminal,
); );
final List<String> showBuildSettingsCommand = <String>[ final List<String> showBuildSettingsCommand = <String>[
_executable, _executable,
......
...@@ -204,9 +204,11 @@ void main() { ...@@ -204,9 +204,11 @@ void main() {
Logger: () => StdoutLogger( Logger: () => StdoutLogger(
outputPreferences: OutputPreferences.test(), outputPreferences: OutputPreferences.test(),
stdio: mockStdio, stdio: mockStdio,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), terminal: AnsiTerminal(
stdio: mockStdio,
platform: const LocalPlatform(),
),
timeoutConfiguration: const TimeoutConfiguration(), timeoutConfiguration: const TimeoutConfiguration(),
platform: FakePlatform(),
), ),
WebSocketConnector: () => (String url, {CompressionOptions compression}) async => throw const SocketException('test'), WebSocketConnector: () => (String url, {CompressionOptions compression}) async => throw const SocketException('test'),
}); });
...@@ -283,10 +285,12 @@ void main() { ...@@ -283,10 +285,12 @@ void main() {
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Logger: () => StdoutLogger( Logger: () => StdoutLogger(
outputPreferences: outputPreferences, outputPreferences: outputPreferences,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), terminal: AnsiTerminal(
stdio: mockStdio,
platform: const LocalPlatform(),
),
stdio: mockStdio, stdio: mockStdio,
timeoutConfiguration: const TimeoutConfiguration(), timeoutConfiguration: const TimeoutConfiguration(),
platform: FakePlatform(),
), ),
}); });
...@@ -301,10 +305,12 @@ void main() { ...@@ -301,10 +305,12 @@ void main() {
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Logger: () => StdoutLogger( Logger: () => StdoutLogger(
outputPreferences: outputPreferences, outputPreferences: outputPreferences,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), terminal: AnsiTerminal(
stdio: mockStdio,
platform: const LocalPlatform(),
),
stdio: mockStdio, stdio: mockStdio,
timeoutConfiguration: const TimeoutConfiguration(), timeoutConfiguration: const TimeoutConfiguration(),
platform: FakePlatform(),
), ),
}); });
...@@ -320,10 +326,12 @@ void main() { ...@@ -320,10 +326,12 @@ void main() {
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Logger: () => StdoutLogger( Logger: () => StdoutLogger(
outputPreferences: outputPreferences, outputPreferences: outputPreferences,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), terminal: AnsiTerminal(
stdio: mockStdio,
platform: const LocalPlatform(),
),
stdio: mockStdio, stdio: mockStdio,
timeoutConfiguration: const TimeoutConfiguration(), timeoutConfiguration: const TimeoutConfiguration(),
platform: FakePlatform(),
), ),
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment