86 && settings.isSet(QQmlFormatSettings::s_indentWidthSetting)) {
87 setIndentWidth(settings.value(QQmlFormatSettings::s_indentWidthSetting).toInt()
);
90 if (!isMarked(
Settings::UseTabs) && settings.isSet(QQmlFormatSettings::s_useTabsSetting)) {
91 setTabsEnabled(settings.value(QQmlFormatSettings::s_useTabsSetting).toBool()
);
95 && settings.isSet(QQmlFormatSettings::s_maxColumnWidthSetting)) {
100 && settings.isSet(QQmlFormatSettings::s_normalizeSetting)) {
105 setNewline(QQmlFormatOptions::parseEndings(
106 settings.value(QQmlFormatSettings::s_newlineSetting).toString()));
110 && settings.isSet(QQmlFormatSettings::s_objectsSpacingSetting)) {
115 && settings.isSet(QQmlFormatSettings::s_functionsSpacingSetting)) {
120 && settings.isSet(QQmlFormatSettings::s_sortImportsSetting)) {
121 setSortImports(settings.value(QQmlFormatSettings::s_sortImportsSetting).toBool()
);
125 && settings.isSet(QQmlFormatSettings::s_singleLineEmptyObjectsSetting)) {
130 && settings.isSet(QQmlFormatSettings::s_semiColonRuleSetting)) {
131 const auto semicolonRule = parseSemicolonRule(
132 settings.value(QQmlFormatSettings::s_semiColonRuleSetting).toString());
133 if (!semicolonRule.has_value()) {
134 qWarning().noquote() <<
"Invalid semicolon rule in settings file, using 'always'";
135 setSemicolonRule(QQmlJS::Dom::LineWriterOptions::SemicolonRule::Always);
137 setSemicolonRule(semicolonRule.value());
145 QCommandLineParser parser;
146 parser.setApplicationDescription(
147 "Formats QML files according to the QML Coding Conventions.\n"_L1
148 "Options below the \"Formatting options\" section can also be set via .qmlformat.ini"_L1
149 " unless --ignore-settings is used"_L1);
150 parser.addHelpOption();
151 parser.addVersionOption();
157 QCommandLineOption({
"V"_L1,
"verbose"_L1 },
158 QStringLiteral(
"Verbose mode. Outputs more detailed information.")));
160 QCommandLineOption writeDefaultsOption(
161 QStringList() <<
"write-defaults"_L1,
162 QLatin1String(
"Writes defaults settings to .qmlformat.ini and exits (Warning: This "
163 "will overwrite any existing settings and comments!)"_L1));
164 parser.addOption(writeDefaultsOption);
166 QCommandLineOption outputOptionsOption(
167 QStringList() <<
"output-options"_L1,
168 QLatin1String(
"Output available options and their defaults values in JSON format."_L1));
169 parser.addOption(outputOptionsOption);
171 QCommandLineOption ignoreSettings(QStringList() <<
"ignore-settings"_L1,
172 QLatin1String(
"Ignores all settings files and only takes "
173 "command line options into consideration"_L1));
174 parser.addOption(ignoreSettings);
176 QCommandLineOption filesOption(
177 {
"F"_L1,
"files"_L1 },
"Format all files listed in file, in-place"_L1,
"file"_L1);
178 parser.addOption(filesOption);
181 QCommandLineOption dryrunOption(
182 QStringList() <<
"dry-run"_L1,
183 QStringLiteral(
"Prints the settings file that would be used for this instance."
184 "This is useful to see what settings would be used "
185 "without actually performing anything."));
186 parser.addOption(dryrunOption);
188 QCommandLineOption settingsOption(
189 {
"s"_L1,
"settings"_L1 },
190 QStringLiteral(
"Use the specified .qmlformat.ini file as the only configuration source."
191 "Overrides any per-directory configuration lookup."),
193 parser.addOption(settingsOption);
195 parser.addOption(QCommandLineOption(
196 {
"i"_L1,
"inplace"_L1 },
197 QStringLiteral(
"Edit file in-place instead of outputting to stdout.")));
201 parser.addOption(QCommandLineOption({
"f"_L1,
"force"_L1 },
203 "Continue even if an error has occurred.\n<><><><><><><><><>\nFormatting options\n<><><><><><><><><>"_L1
205 u"Continue even if an error has occurred.\n♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦\nFormatting options\n♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦"_s
213 parser.addOption(QCommandLineOption({
"t"_L1,
"tabs"_L1 },
214 QStringLiteral(
"Use tabs instead of spaces.")));
216 parser.addOption(QCommandLineOption({
"w"_L1,
"indent-width"_L1 },
217 QStringLiteral(
"How many spaces are used when indenting."),
218 "width"_L1,
"4"_L1));
220 QCommandLineOption columnWidthOption(
221 {
"W"_L1,
"column-width"_L1 },
222 QStringLiteral(
"Breaks the line into multiple lines if exceedes the specified width. "
223 "Use -1 to disable line wrapping. (default)"),
224 "width"_L1,
"-1"_L1);
225 parser.addOption(columnWidthOption);
226 parser.addOption(QCommandLineOption({
"n"_L1,
"normalize"_L1 },
227 QStringLiteral(
"Reorders the attributes of the objects "
228 "according to the QML Coding Guidelines.")));
231 parser.addOption(QCommandLineOption(
232 {
"l"_L1,
"newline"_L1 },
233 QStringLiteral(
"Override the new line format to use (native macos unix windows)."),
234 "newline"_L1,
"native"_L1));
236 parser.addOption(QCommandLineOption(
237 QStringList() <<
"objects-spacing"_L1,
238 QStringLiteral(
"Ensure spaces between objects (only works with normalize option).")));
240 parser.addOption(QCommandLineOption(
241 QStringList() <<
"functions-spacing"_L1,
242 QStringLiteral(
"Ensure spaces between functions (only works with normalize option).")));
245 QCommandLineOption({
"S"_L1,
"sort-imports"_L1 },
246 QStringLiteral(
"Sort imports alphabetically "
247 "(Warning: this might change semantics if a given "
248 "name identifies types in multiple modules!).")));
250 parser.addOption(QCommandLineOption(
251 QStringList() <<
"single-line-empty-objects"_L1,
252 QStringLiteral(
"Write empty objects on a single line (only works with normalize option).")));
254 QCommandLineOption semicolonRuleOption(
255 QStringList() <<
"semicolon-rule"_L1,
256 QStringLiteral(
"Specify the semicolon rule to use (always, essential).\n"
257 "always: always adds semicolon [default].\n"
258 "essential: adds only when ASI wouldn't be relied on."),
259 "rule"_L1,
"always"_L1);
260 parser.addOption(semicolonRuleOption);
262 parser.addPositionalArgument(
"filenames"_L1,
"files to be processed by qmlformat"_L1);
264 parser.process(args);
266 if (parser.isSet(writeDefaultsOption)) {
271 if (parser.isSet(outputOptionsOption)) {
276 if (parser.positionalArguments().empty() && !parser.isSet(filesOption)) {
277 options.addError(
"Error: Expected at least one input file."_L1);
281 bool indentWidthOkay =
false;
282 const int indentWidth = parser.value(
"indent-width"_L1).toInt(&indentWidthOkay);
283 if (!indentWidthOkay) {
284 options.addError(
"Error: Invalid value passed to -w"_L1);
289 if (!parser.value(
"files"_L1).isEmpty()) {
290 const QString path = parser.value(
"files"_L1);
292 if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) {
293 options.addError(
"Error: Could not open file \""_L1 + path +
"\" for option -F."_L1);
297 QTextStream in(&file);
298 while (!in.atEnd()) {
299 QString file = in.readLine();
304 files.push_back(file);
307 if (files.isEmpty()) {
308 options.addError(
"Error: File \""_L1 + path +
"\" for option -F is empty."_L1);
312 for (
const auto &file : std::as_const(files)) {
313 if (!QFile::exists(file)) {
314 options.addError(
"Error: Entry \""_L1 + file +
"\" of file \""_L1 + path
315 +
"\" passed to option -F could not be found."_L1);
320 const auto &args = parser.positionalArguments();
321 for (
const auto &file : args) {
322 if (!QFile::exists(file)) {
323 options.addError(
"Error: Could not find file \""_L1 + file +
"\"."_L1);
330 options.setIsVerbose(parser.isSet(
"verbose"_L1));
331 options.setIsInplace(parser.isSet(
"inplace"_L1));
332 options.setForceEnabled(parser.isSet(
"force"_L1));
333 options.setIgnoreSettingsEnabled(parser.isSet(
"ignore-settings"_L1));
335 if (parser.isSet(
"tabs"_L1)) {
339 if (parser.isSet(
"normalize"_L1)) {
343 if (parser.isSet(
"objects-spacing"_L1)) {
347 if (parser.isSet(
"functions-spacing"_L1)) {
351 if (parser.isSet(
"sort-imports"_L1)) {
355 if (parser.isSet(
"single-line-empty-objects"_L1)) {
359 if (parser.isSet(
"indent-width"_L1)) {
364 if (parser.isSet(
"newline"_L1)) {
366 options.setNewline(QQmlFormatOptions::parseEndings(parser.value(
"newline"_L1)));
369 if (parser.isSet(settingsOption)) {
371 const auto value = parser.value(settingsOption);
372 if (value.isEmpty()) {
373 options.addError(
"Error: No settings file specified for option -s."_L1);
376 if (!QFile::exists(value)) {
377 options.addError(
"Error: Could not find file \""_L1 + value +
"\"."_L1);
380 options.setSettingsFile(value);
383 if (parser.isSet(semicolonRuleOption)) {
385 const auto value = parser.value(semicolonRuleOption);
386 auto semicolonRule = parseSemicolonRule(value);
387 if (!semicolonRule.has_value()) {
388 options.addError(
"Error: Invalid value passed to --semicolon-rule. Must be 'always' or 'essential'."_L1);
391 options.setSemicolonRule(semicolonRule.value());
393 options.setFiles(files);
394 options.setArguments(parser.positionalArguments());
396 if (parser.isSet(columnWidthOption)) {
397 bool isValidValue =
false;
398 const int maxColumnWidth = parser.value(columnWidthOption).toInt(&isValidValue);
399 if (!isValidValue || maxColumnWidth < -1) {
400 options.addError(
"Error: Invalid value passed to -W. Must be an integer >= -1"_L1);