command_help.dart 6.64 KB
Newer Older
1 2 3 4 5 6
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math' as math;

7
import 'logger.dart';
8
import 'platform.dart';
9 10 11 12 13
import 'terminal.dart';

const String fire = '🔥';
const int maxLineWidth = 84;

14
/// Encapsulates the help text construction and printing.
15
class CommandHelp {
16
  CommandHelp({
17 18 19 20
    required Logger logger,
    required AnsiTerminal terminal,
    required Platform platform,
    required OutputPreferences outputPreferences,
21 22 23 24 25 26 27 28 29 30 31 32 33
  }) : _logger = logger,
       _terminal = terminal,
       _platform = platform,
       _outputPreferences = outputPreferences;

  final Logger _logger;

  final AnsiTerminal _terminal;

  final Platform _platform;

  final OutputPreferences _outputPreferences;

34 35 36 37
  // COMMANDS IN ALPHABETICAL ORDER.
  // Uppercase first, then lowercase.
  // When updating this, update all the tests in command_help_test.dart accordingly.

38
  late final CommandHelpOption I = _makeOption(
39
    'I',
40
    'Toggle oversized image inversion.',
41 42 43
    'debugInvertOversizedImages',
  );

44
  late final CommandHelpOption L = _makeOption(
45 46 47 48
    'L',
    'Dump layer tree to the console.',
    'debugDumpLayerTree',
  );
49

50 51 52 53 54
  late final CommandHelpOption M = _makeOption(
    'M',
    'Write SkSL shaders to a unique file in the project directory.',
  );

55
  late final CommandHelpOption P = _makeOption(
56 57 58 59
    'P',
    'Toggle performance overlay.',
    'WidgetsApp.showPerformanceOverlay',
  );
60

61
  late final CommandHelpOption R = _makeOption(
62 63 64
    'R',
    'Hot restart.',
  );
65

66
  late final CommandHelpOption S = _makeOption(
67 68 69 70
    'S',
    'Dump accessibility tree in traversal order.',
    'debugDumpSemantics',
  );
71

72
  late final CommandHelpOption U = _makeOption(
73 74 75 76
    'U',
    'Dump accessibility tree in inverse hit test order.',
    'debugDumpSemantics',
  );
77

78
  late final CommandHelpOption a = _makeOption(
79 80 81 82
    'a',
    'Toggle timeline events for all widget build methods.',
    'debugProfileWidgetBuilds',
  );
83

84
  late final CommandHelpOption b = _makeOption(
85
    'b',
86
    'Toggle platform brightness (dark and light mode).',
87 88 89
    'debugBrightnessOverride',
  );

90
  late final CommandHelpOption c = _makeOption(
91 92 93
    'c',
    'Clear the screen',
  );
94

95
  late final CommandHelpOption d = _makeOption(
96 97 98
    'd',
    'Detach (terminate "flutter run" but leave application running).',
  );
99

100 101 102 103 104 105
  late final CommandHelpOption f = _makeOption(
    'f',
    'Dump focus tree to the console.',
    'debugDumpFocusTree',
  );

106
  late final CommandHelpOption g = _makeOption(
107 108 109 110
    'g',
    'Run source code generators.'
  );

111
  late final CommandHelpOption hWithDetails = _makeOption(
112 113 114
    'h',
    'Repeat this help message.',
  );
115

116 117 118 119 120
  late final CommandHelpOption hWithoutDetails = _makeOption(
    'h',
    'List all available interactive commands.',
  );

121
  late final CommandHelpOption i = _makeOption(
122 123 124 125
    'i',
    'Toggle widget inspector.',
    'WidgetsApp.showWidgetInspectorOverride',
  );
126

127 128
  late final CommandHelpOption j = _makeOption(
    'j',
129
    'Dump frame raster stats for the current frame. (Unsupported for web)',
130 131
  );

132 133 134 135 136
  late final CommandHelpOption k = _makeOption(
    'k',
    'Toggle CanvasKit rendering.',
  );

137
  late final CommandHelpOption o = _makeOption(
138 139 140 141
    'o',
    'Simulate different operating systems.',
    'defaultTargetPlatform',
  );
142

143
  late final CommandHelpOption p = _makeOption(
144 145 146 147
    'p',
    'Toggle the display of construction lines.',
    'debugPaintSizeEnabled',
  );
148

149
  late final CommandHelpOption q = _makeOption(
150 151 152
    'q',
    'Quit (terminate the application on the device).',
  );
153

154
  late final CommandHelpOption r = _makeOption(
155 156 157
    'r',
    'Hot reload. $fire$fire$fire',
  );
158

159
  late final CommandHelpOption s = _makeOption(
160 161 162
    's',
    'Save a screenshot to flutter.png.',
  );
163

164
  late final CommandHelpOption t = _makeOption(
165 166 167 168
    't',
    'Dump rendering tree to the console.',
    'debugDumpRenderTree',
  );
169

170 171 172 173 174
  late final CommandHelpOption v = _makeOption(
    'v',
    'Open Flutter DevTools.',
  );

175
  late final CommandHelpOption w = _makeOption(
176 177 178 179
    'w',
    'Dump widget hierarchy to the console.',
    'debugDumpApp',
  );
180

181 182
  // When updating the list above, see the notes above the list regarding order
  // and tests.
183

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  CommandHelpOption _makeOption(String key, String description, [
    String inParenthesis = '',
  ]) {
    return CommandHelpOption(
      key,
      description,
      inParenthesis: inParenthesis,
      logger: _logger,
      terminal: _terminal,
      platform: _platform,
      outputPreferences: _outputPreferences,
    );
  }
}

/// Encapsulates printing help text for a single option.
class CommandHelpOption {
  CommandHelpOption(
    this.key,
    this.description, {
    this.inParenthesis = '',
205 206 207 208
    required Logger logger,
    required Terminal terminal,
    required Platform platform,
    required OutputPreferences outputPreferences,
209 210 211 212 213 214 215
  }) : _logger = logger,
       _terminal = terminal,
       _platform = platform,
       _outputPreferences = outputPreferences;

  final Logger _logger;

216
  final Terminal _terminal;
217 218

  final Platform _platform;
219

220
  final OutputPreferences _outputPreferences;
221

222
  /// The key associated with this command.
223
  final String key;
224
  /// A description of what this command does.
225
  final String description;
226
  /// Text shown in parenthesis to give the context.
227 228
  final String inParenthesis;

229
  bool get _hasTextInParenthesis => inParenthesis.isNotEmpty;
230 231 232 233 234 235

  int get _rawMessageLength => key.length + description.length;

  @override
  String toString() {
    final StringBuffer message = StringBuffer();
236
    message.writeAll(<String>[_terminal.bolden(key), description], ' ');
237 238 239
    if (!_hasTextInParenthesis) {
      return message.toString();
    }
240

241 242
    bool wrap = false;
    final int maxWidth = math.max(
243
      _outputPreferences.wrapColumn,
244 245 246 247 248 249 250 251 252 253 254 255 256
      maxLineWidth,
    );
    final int adjustedMessageLength = _platform.stdoutSupportsAnsi
      ? _rawMessageLength + 1
      : message.length;
    int width = maxWidth - adjustedMessageLength;
    final String parentheticalText = '($inParenthesis)';
    if (width < parentheticalText.length) {
      width = maxWidth;
      wrap = true;
    }
    if (wrap) {
      message.write('\n');
257
    }
258 259 260
    // pad according to the raw text
    message.write(''.padLeft(width - parentheticalText.length));
    message.write(_terminal.color(parentheticalText, TerminalColor.grey));
261

262
    // Terminals seem to require this because we have both bolded and colored
263 264 265 266 267
    // a line. Otherwise the next line comes out bold until a reset bold.
    if (_terminal.supportsColor) {
      message.write(AnsiTerminal.resetBold);
    }

268 269 270 271
    return message.toString();
  }

  void print() {
272
    _logger.printStatus(toString());
273 274
  }
}