command_line.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "common/command_line.h"
  5. #include <memory>
  6. #include "common/raw_string_ostream.h"
  7. #include "llvm/ADT/DenseMap.h"
  8. #include "llvm/ADT/PointerIntPair.h"
  9. #include "llvm/Support/FormatVariadic.h"
  10. // Recursion is used for subcommands. This should be okay since recursion is
  11. // limited by command line architecture.
  12. // NOLINTBEGIN(misc-no-recursion)
  13. namespace Carbon::CommandLine {
  14. auto operator<<(llvm::raw_ostream& output, ParseResult result)
  15. -> llvm::raw_ostream& {
  16. switch (result) {
  17. case ParseResult::MetaSuccess:
  18. return output << "MetaSuccess";
  19. case ParseResult::Success:
  20. return output << "Success";
  21. }
  22. CARBON_FATAL("Corrupt parse result!");
  23. }
  24. auto operator<<(llvm::raw_ostream& output, ArgKind kind) -> llvm::raw_ostream& {
  25. switch (kind) {
  26. case ArgKind::Flag:
  27. return output << "Boolean";
  28. case ArgKind::Integer:
  29. return output << "Integer";
  30. case ArgKind::String:
  31. return output << "String";
  32. case ArgKind::OneOf:
  33. return output << "OneOf";
  34. case ArgKind::MetaActionOnly:
  35. return output << "MetaActionOnly";
  36. case ArgKind::Invalid:
  37. return output << "Invalid";
  38. }
  39. CARBON_FATAL("Corrupt argument kind!");
  40. }
  41. auto operator<<(llvm::raw_ostream& output, CommandKind kind)
  42. -> llvm::raw_ostream& {
  43. switch (kind) {
  44. case CommandKind::Invalid:
  45. return output << "Invalid";
  46. case CommandKind::RequiresSubcommand:
  47. return output << "RequiresSubcommand";
  48. case CommandKind::Action:
  49. return output << "Action";
  50. case CommandKind::MetaAction:
  51. return output << "MetaAction";
  52. }
  53. CARBON_FATAL("Corrupt command kind!");
  54. }
  55. template <typename T, typename ToPrintable>
  56. static auto PrintListOfAlternatives(llvm::raw_ostream& output,
  57. llvm::ArrayRef<T> alternatives,
  58. ToPrintable to_printable) -> void {
  59. for (const auto& alternative : alternatives.drop_back()) {
  60. output << "`" << to_printable(alternative)
  61. << (alternatives.size() > 2 ? "`, " : "` ");
  62. }
  63. if (alternatives.size() > 1) {
  64. output << "or ";
  65. }
  66. output << "`" << to_printable(alternatives.back()) << "`";
  67. }
  68. Arg::Arg(ArgInfo info) : info(info) {}
  69. Arg::~Arg() {
  70. switch (kind) {
  71. case Kind::Flag:
  72. case Kind::Integer:
  73. case Kind::String:
  74. case Kind::MetaActionOnly:
  75. case Kind::Invalid:
  76. // Nothing to do!
  77. break;
  78. case Kind::OneOf:
  79. value_strings.~decltype(value_strings)();
  80. value_action.~ValueActionT();
  81. if (has_default) {
  82. default_action.~DefaultActionT();
  83. }
  84. break;
  85. }
  86. }
  87. Command::Command(CommandInfo info, Command* parent)
  88. : info(info), parent(parent) {}
  89. class MetaPrinter {
  90. public:
  91. // `out` must not be null.
  92. explicit MetaPrinter(llvm::raw_ostream* out) : out_(out) {}
  93. // Registers this meta printer with a command through the provided builder.
  94. //
  95. // This adds meta subcommands or options to print both help and version
  96. // information for the command.
  97. auto RegisterWithCommand(const Command& command, CommandBuilder& builder)
  98. -> void;
  99. auto PrintHelp(const Command& command) const -> void;
  100. auto PrintHelpForSubcommandName(const Command& command,
  101. llvm::StringRef subcommand_name) const
  102. -> void;
  103. auto PrintVersion(const Command& command) const -> void;
  104. auto PrintSubcommands(const Command& command) const -> void;
  105. private:
  106. // The indent is calibrated to allow a short and long option after a two
  107. // character indent on the prior line to be visually recognized as separate
  108. // from the hanging indent.
  109. //
  110. // Visual guide: | -x, --extract
  111. // | Hanging indented.
  112. static constexpr llvm::StringRef BlockIndent = " ";
  113. // Width limit for parent command options in usage rendering.
  114. static constexpr int MaxParentOptionUsageWidth = 8;
  115. // Width limit for the leaf command options in usage rendering.
  116. static constexpr int MaxLeafOptionUsageWidth = 16;
  117. static constexpr CommandInfo HelpCommandInfo = {
  118. .name = "help",
  119. .help = R"""(
  120. Prints help information for the command, including a description, command line
  121. usage, and details of each subcommand and option that can be provided.
  122. )""",
  123. .help_short = R"""(
  124. Prints help information.
  125. )""",
  126. };
  127. static constexpr ArgInfo HelpArgInfo = {
  128. .name = "help",
  129. .value_name = "(full|short)",
  130. .help = R"""(
  131. Prints help information for the command, including a description, command line
  132. usage, and details of each option that can be provided.
  133. )""",
  134. .help_short = HelpCommandInfo.help_short,
  135. };
  136. // Provide a customized description for help on a subcommand to avoid
  137. // confusion with the top-level help.
  138. static constexpr CommandInfo SubHelpCommandInfo = {
  139. .name = "help",
  140. .help = R"""(
  141. Prints help information for the subcommand, including a description, command
  142. line usage, and details of each further subcommand and option that can be
  143. provided.
  144. )""",
  145. .help_short = R"""(
  146. Prints subcommand help information.
  147. )""",
  148. };
  149. static constexpr ArgInfo SubHelpArgInfo = {
  150. .name = "help",
  151. .value_name = "(full|short)",
  152. .help = R"""(
  153. Prints help information for the subcommand, including a description, command
  154. line usage, and details of each option that can be provided.
  155. )""",
  156. .help_short = SubHelpCommandInfo.help_short,
  157. };
  158. static constexpr ArgInfo HelpSubcommandArgInfo = {
  159. .name = "subcommand",
  160. .help = R"""(
  161. Which subcommand to print help information for.
  162. )""",
  163. };
  164. static constexpr CommandInfo VersionCommandInfo = {
  165. .name = "version",
  166. .help = R"""(
  167. Prints the version of this command.
  168. )""",
  169. };
  170. static constexpr ArgInfo VersionArgInfo = {
  171. .name = "version",
  172. .help = VersionCommandInfo.help,
  173. };
  174. // A general helper for rendering a text block.
  175. auto PrintTextBlock(llvm::StringRef indent, llvm::StringRef text) const
  176. -> void;
  177. // Helpers for version and build information printing.
  178. auto PrintRawVersion(const Command& command, llvm::StringRef indent) const
  179. -> void;
  180. auto PrintRawBuildInfo(const Command& command, llvm::StringRef indent) const
  181. -> void;
  182. // Helpers for printing components of help and usage output for arguments,
  183. // including options and positional arguments.
  184. auto PrintArgValueUsage(const Arg& arg) const -> void;
  185. auto PrintOptionUsage(const Arg& option) const -> void;
  186. auto PrintOptionShortName(const Arg& arg) const -> void;
  187. auto PrintArgShortValues(const Arg& arg) const -> void;
  188. auto PrintArgLongValues(const Arg& arg, llvm::StringRef indent) const -> void;
  189. auto PrintArgHelp(const Arg& arg, llvm::StringRef indent) const -> void;
  190. // Helpers for printing command usage summaries.
  191. auto PrintRawUsageCommandAndOptions(
  192. const Command& command,
  193. int max_option_width = MaxLeafOptionUsageWidth) const -> void;
  194. auto PrintRawUsage(const Command& command, llvm::StringRef indent) const
  195. -> void;
  196. auto PrintUsage(const Command& command) const -> void;
  197. // Helpers to print various sections of `PrintHelp` that only occur within
  198. // that output.
  199. auto PrintHelpSubcommands(const Command& command) const -> void;
  200. auto PrintHelpPositionalArgs(const Command& command) const -> void;
  201. auto PrintHelpOptions(const Command& command) const -> void;
  202. llvm::raw_ostream* out_;
  203. // A flag that may be configured during command line parsing to select between
  204. // long and short form help output.
  205. bool short_help_ = false;
  206. // The requested subcommand to print help information for.
  207. llvm::StringRef help_subcommand_;
  208. };
  209. auto MetaPrinter::RegisterWithCommand(const Command& command,
  210. CommandBuilder& builder) -> void {
  211. bool is_subcommand = command.parent;
  212. bool has_subcommands = !command.subcommands.empty();
  213. // If this command has subcommands, we prefer that model for access meta
  214. // actions, but still silently support using the flags. But we never want to
  215. // *add* subcommands if they aren't already being used.
  216. if (has_subcommands) {
  217. builder.AddSubcommand(
  218. is_subcommand ? SubHelpCommandInfo : HelpCommandInfo,
  219. [&](CommandBuilder& sub_b) {
  220. sub_b.AddStringPositionalArg(HelpSubcommandArgInfo, [&](auto& arg_b) {
  221. arg_b.Set(&help_subcommand_);
  222. });
  223. sub_b.Meta([this, &command]() {
  224. if (help_subcommand_.empty()) {
  225. PrintHelp(command);
  226. } else {
  227. PrintHelpForSubcommandName(command, help_subcommand_);
  228. }
  229. });
  230. });
  231. // Only add version printing support if there is a version string
  232. // configured for this command.
  233. if (!command.info.version.empty()) {
  234. builder.AddSubcommand(VersionCommandInfo, [&](CommandBuilder& sub_b) {
  235. sub_b.Meta([this, &command]() { PrintVersion(command); });
  236. });
  237. }
  238. }
  239. builder.AddOneOfOption(
  240. is_subcommand ? SubHelpArgInfo : HelpArgInfo, [&](auto& arg_b) {
  241. arg_b.HelpHidden(has_subcommands);
  242. arg_b.SetOneOf(
  243. {
  244. arg_b.OneOfValue("full", false).Default(true),
  245. arg_b.OneOfValue("short", true),
  246. },
  247. &short_help_);
  248. arg_b.MetaAction([this, &command]() { PrintHelp(command); });
  249. });
  250. // Only add version printing support if there is a version string configured
  251. // for this command.
  252. if (!command.info.version.empty()) {
  253. builder.AddMetaActionOption(VersionArgInfo, [&](auto& arg_b) {
  254. arg_b.HelpHidden(has_subcommands);
  255. arg_b.MetaAction([this, &command]() { PrintVersion(command); });
  256. });
  257. }
  258. }
  259. auto MetaPrinter::PrintHelp(const Command& command) const -> void {
  260. // TODO: begin using the short setting to customize the output.
  261. (void)short_help_;
  262. const CommandInfo& info = command.info;
  263. if (!info.version.empty()) {
  264. // We use the version string as a header for the command help when present.
  265. PrintRawVersion(command, /*indent=*/"");
  266. *out_ << "\n";
  267. }
  268. if (!command.info.help.empty()) {
  269. PrintTextBlock("", info.help);
  270. *out_ << "\n";
  271. }
  272. if (!info.build_info.empty()) {
  273. *out_ << "Build info:\n";
  274. PrintRawBuildInfo(command, /*indent=*/" ");
  275. *out_ << "\n";
  276. }
  277. PrintUsage(command);
  278. PrintHelpSubcommands(command);
  279. PrintHelpPositionalArgs(command);
  280. PrintHelpOptions(command);
  281. if (!info.help_epilogue.empty()) {
  282. *out_ << "\n";
  283. PrintTextBlock("", info.help_epilogue);
  284. }
  285. // End with a blank line for the long help to make it easier to separate from
  286. // anything that follows in the shell.
  287. *out_ << "\n";
  288. }
  289. auto MetaPrinter::PrintHelpForSubcommandName(
  290. const Command& command, llvm::StringRef subcommand_name) const -> void {
  291. for (const auto& subcommand : command.subcommands) {
  292. if (subcommand->info.name == subcommand_name) {
  293. PrintHelp(*subcommand);
  294. return;
  295. }
  296. }
  297. // TODO: This should really be connected up so that parsing can return an
  298. // Error instead of ParseResult::MetaSuccess in this case.
  299. *out_ << "error: could not find a subcommand named '" << subcommand_name
  300. << "'\n";
  301. }
  302. auto MetaPrinter::PrintVersion(const Command& command) const -> void {
  303. CARBON_CHECK(
  304. !command.info.version.empty(),
  305. "Printing should not be enabled without a version string configured.");
  306. PrintRawVersion(command, /*indent=*/"");
  307. if (!command.info.build_info.empty()) {
  308. *out_ << "\n";
  309. // If there is build info to print, we also render that without any indent.
  310. PrintRawBuildInfo(command, /*indent=*/"");
  311. }
  312. }
  313. auto MetaPrinter::PrintSubcommands(const Command& command) const -> void {
  314. PrintListOfAlternatives(*out_, llvm::ArrayRef(command.subcommands),
  315. [](const std::unique_ptr<Command>& subcommand) {
  316. return subcommand->info.name;
  317. });
  318. }
  319. auto MetaPrinter::PrintRawVersion(const Command& command,
  320. llvm::StringRef indent) const -> void {
  321. // Newlines are trimmed from the version string an a closing newline added but
  322. // no other formatting is performed.
  323. *out_ << indent << command.info.version.trim('\n') << "\n";
  324. }
  325. auto MetaPrinter::PrintRawBuildInfo(const Command& command,
  326. llvm::StringRef indent) const -> void {
  327. // Print the build info line-by-line without any wrapping in case it
  328. // contains line-oriented formatted text, but drop leading and trailing blank
  329. // lines.
  330. llvm::SmallVector<llvm::StringRef, 128> lines;
  331. command.info.build_info.trim('\n').split(lines, "\n");
  332. for (auto line : lines) {
  333. *out_ << indent << line << "\n";
  334. }
  335. }
  336. auto MetaPrinter::PrintTextBlock(llvm::StringRef indent,
  337. llvm::StringRef text) const -> void {
  338. // Strip leading and trailing newlines to make it easy to use multiline raw
  339. // string literals that will naturally have those.
  340. text = text.trim('\n');
  341. // For empty text, print nothing at all. The caller formatting will work to
  342. // handle this gracefully.
  343. if (text.empty()) {
  344. return;
  345. }
  346. // Remove line breaks from the text that would typically be removed when
  347. // rendering it as Markdown. The goal is to preserve:
  348. //
  349. // - Blank lines as paragraph separators.
  350. // - Line breaks after list items or other structural components in Markdown.
  351. // - Fenced regions exactly as they appear.
  352. //
  353. // And within paragraphs (including those nested in lists), reflow the
  354. // paragraph intelligently to the column width. There are TODOs below about
  355. // both lists and reflowing.
  356. llvm::SmallVector<llvm::StringRef, 128> input_lines;
  357. text.split(input_lines, "\n");
  358. for (int i = 0, size = input_lines.size(); i < size;) {
  359. if (input_lines[i].empty()) {
  360. // Blank lines are preserved.
  361. *out_ << "\n";
  362. ++i;
  363. continue;
  364. }
  365. if (input_lines[i].starts_with("```")) {
  366. // Fenced regions are preserved verbatim.
  367. llvm::StringRef fence =
  368. input_lines[i].slice(0, input_lines[i].find_first_not_of("`"));
  369. do {
  370. *out_ << indent << input_lines[i] << "\n";
  371. ++i;
  372. } while (i < size && !input_lines[i].starts_with(fence));
  373. if (i >= size) {
  374. // Don't error on malformed text blocks, just print what we've got.
  375. break;
  376. }
  377. // Including the close of the fence.
  378. *out_ << indent << input_lines[i] << "\n";
  379. ++i;
  380. continue;
  381. }
  382. if (input_lines[i].starts_with(" ")) {
  383. // Indented code blocks ar preserved verbatim, but we don't support tabs
  384. // in the indent for simplicity.
  385. do {
  386. *out_ << indent << input_lines[i] << "\n";
  387. ++i;
  388. } while (i < size && input_lines[i].starts_with(" "));
  389. continue;
  390. }
  391. // TODO: Detect other Markdown structures, especially lists and tables.
  392. // Otherwise, collect all of the lines until the end or the next blank line
  393. // as a block of text.
  394. //
  395. // TODO: This is where we should re-flow.
  396. llvm::StringRef space = indent;
  397. do {
  398. *out_ << space << input_lines[i].trim();
  399. space = " ";
  400. ++i;
  401. } while (i < size && !input_lines[i].empty());
  402. *out_ << "\n";
  403. }
  404. }
  405. auto MetaPrinter::PrintArgValueUsage(const Arg& arg) const -> void {
  406. if (!arg.info.value_name.empty()) {
  407. *out_ << arg.info.value_name;
  408. return;
  409. }
  410. if (arg.kind == Arg::Kind::OneOf) {
  411. *out_ << "(";
  412. llvm::ListSeparator sep("|");
  413. for (llvm::StringRef value_string : arg.value_strings) {
  414. *out_ << sep << value_string;
  415. }
  416. *out_ << ")";
  417. return;
  418. }
  419. *out_ << "...";
  420. }
  421. auto MetaPrinter::PrintOptionUsage(const Arg& option) const -> void {
  422. if (option.kind == Arg::Kind::Flag) {
  423. *out_ << "--" << (option.default_flag ? "no-" : "") << option.info.name;
  424. return;
  425. }
  426. *out_ << "--" << option.info.name;
  427. if (option.kind != Arg::Kind::MetaActionOnly) {
  428. *out_ << (option.has_default ? "[" : "") << "=";
  429. PrintArgValueUsage(option);
  430. if (option.has_default) {
  431. *out_ << "]";
  432. }
  433. }
  434. }
  435. auto MetaPrinter::PrintOptionShortName(const Arg& arg) const -> void {
  436. CARBON_CHECK(!arg.info.short_name.empty(), "No short name to use.");
  437. *out_ << "-" << arg.info.short_name;
  438. }
  439. auto MetaPrinter::PrintArgShortValues(const Arg& arg) const -> void {
  440. CARBON_CHECK(
  441. arg.kind == Arg::Kind::OneOf,
  442. "Only one-of arguments have interesting value snippets to print.");
  443. llvm::ListSeparator sep;
  444. for (llvm::StringRef value_string : arg.value_strings) {
  445. *out_ << sep << value_string;
  446. }
  447. }
  448. auto MetaPrinter::PrintArgLongValues(const Arg& arg,
  449. llvm::StringRef indent) const -> void {
  450. *out_ << indent << "Possible values:\n";
  451. // TODO: It would be good to add help text for each value and then print it
  452. // here.
  453. for (auto [i, value_string] : llvm::enumerate(arg.value_strings)) {
  454. *out_ << indent << "- " << value_string;
  455. if (arg.has_default && static_cast<int>(i) == arg.default_value_index) {
  456. *out_ << " (default)";
  457. }
  458. *out_ << "\n";
  459. }
  460. }
  461. auto MetaPrinter::PrintArgHelp(const Arg& arg, llvm::StringRef indent) const
  462. -> void {
  463. // Print out the main help text.
  464. PrintTextBlock(indent, arg.info.help);
  465. // Then print out any help based on the values.
  466. switch (arg.kind) {
  467. case Arg::Kind::Integer:
  468. if (arg.has_default) {
  469. *out_ << "\n";
  470. *out_ << indent << "Default value: " << arg.default_integer << "\n";
  471. }
  472. break;
  473. case Arg::Kind::String:
  474. if (arg.has_default) {
  475. *out_ << "\n";
  476. *out_ << indent << "Default value: " << arg.default_string << "\n";
  477. }
  478. break;
  479. case Arg::Kind::OneOf:
  480. *out_ << "\n";
  481. PrintArgLongValues(arg, indent);
  482. break;
  483. case Arg::Kind::Flag:
  484. case Arg::Kind::MetaActionOnly:
  485. // No value help.
  486. break;
  487. case Arg::Kind::Invalid:
  488. CARBON_FATAL("Argument configured without any action or kind!");
  489. }
  490. }
  491. auto MetaPrinter::PrintRawUsageCommandAndOptions(const Command& command,
  492. int max_option_width) const
  493. -> void {
  494. // Recursively print parent usage first with a compressed width.
  495. if (command.parent) {
  496. PrintRawUsageCommandAndOptions(*command.parent, MaxParentOptionUsageWidth);
  497. *out_ << " ";
  498. }
  499. *out_ << command.info.name;
  500. // Buffer the options rendering so we can limit its length.
  501. RawStringOstream buffer_out;
  502. MetaPrinter buffer_printer(&buffer_out);
  503. bool have_short_flags = false;
  504. for (const auto& arg : command.options) {
  505. if (static_cast<int>(buffer_out.size()) > max_option_width) {
  506. break;
  507. }
  508. // We can summarize positive boolean flags with a short name using a
  509. // sequence of short names in a single rendered argument.
  510. if (arg->kind == Arg::Kind::Flag && !arg->default_flag &&
  511. !arg->info.short_name.empty()) {
  512. if (!have_short_flags) {
  513. have_short_flags = true;
  514. buffer_out << "-";
  515. }
  516. buffer_out << arg->info.short_name;
  517. }
  518. }
  519. llvm::StringRef space = have_short_flags ? " " : "";
  520. for (const auto& option : command.options) {
  521. if (static_cast<int>(buffer_out.size()) > max_option_width) {
  522. break;
  523. }
  524. if (option->is_help_hidden || option->meta_action) {
  525. // Skip hidden and options with meta actions attached.
  526. continue;
  527. }
  528. if (option->kind == Arg::Kind::Flag && !option->default_flag &&
  529. !option->info.short_name.empty()) {
  530. // Handled with short names above.
  531. continue;
  532. }
  533. buffer_out << space;
  534. buffer_printer.PrintOptionUsage(*option);
  535. space = " ";
  536. }
  537. if (!buffer_out.empty()) {
  538. if (static_cast<int>(buffer_out.size()) <= max_option_width) {
  539. *out_ << " [" << buffer_out.TakeStr() << "]";
  540. } else {
  541. buffer_out.clear();
  542. *out_ << " [OPTIONS]";
  543. }
  544. }
  545. }
  546. auto MetaPrinter::PrintRawUsage(const Command& command,
  547. llvm::StringRef indent) const -> void {
  548. if (!command.info.usage.empty()) {
  549. PrintTextBlock(indent, command.info.usage);
  550. return;
  551. }
  552. if (command.kind != Command::Kind::RequiresSubcommand) {
  553. // We're a valid leaf command, so synthesize a full usage line.
  554. *out_ << indent;
  555. PrintRawUsageCommandAndOptions(command);
  556. if (!command.positional_args.empty()) {
  557. bool open_optional = false;
  558. for (auto [i, arg] : llvm::enumerate(command.positional_args)) {
  559. *out_ << " ";
  560. if (i != 0 && command.positional_args[i - 1]->is_append) {
  561. *out_ << "-- ";
  562. }
  563. if (!arg->is_required && !open_optional) {
  564. *out_ << "[";
  565. open_optional = true;
  566. }
  567. *out_ << "<" << arg->info.name << ">";
  568. if (arg->is_append) {
  569. *out_ << "...";
  570. }
  571. }
  572. if (open_optional) {
  573. *out_ << "]";
  574. }
  575. }
  576. *out_ << "\n";
  577. }
  578. // If we have subcommands, also recurse into them so each one can print their
  579. // usage lines.
  580. for (const auto& subcommand : command.subcommands) {
  581. if (subcommand->is_help_hidden ||
  582. subcommand->kind == Command::Kind::MetaAction) {
  583. continue;
  584. }
  585. PrintRawUsage(*subcommand, indent);
  586. }
  587. }
  588. auto MetaPrinter::PrintUsage(const Command& command) const -> void {
  589. if (!command.parent) {
  590. *out_ << "Usage:\n";
  591. } else {
  592. *out_ << "Subcommand `" << command.info.name << "` usage:\n";
  593. }
  594. PrintRawUsage(command, " ");
  595. }
  596. auto MetaPrinter::PrintHelpSubcommands(const Command& command) const -> void {
  597. bool first_subcommand = true;
  598. for (const auto& subcommand : command.subcommands) {
  599. if (subcommand->is_help_hidden) {
  600. continue;
  601. }
  602. if (first_subcommand) {
  603. first_subcommand = false;
  604. if (!command.parent) {
  605. *out_ << "\nSubcommands:";
  606. } else {
  607. *out_ << "\nSubcommand `" << command.info.name << "` subcommands:";
  608. }
  609. }
  610. *out_ << "\n";
  611. *out_ << " " << subcommand->info.name << "\n";
  612. PrintTextBlock(BlockIndent, subcommand->info.help);
  613. }
  614. }
  615. auto MetaPrinter::PrintHelpPositionalArgs(const Command& command) const
  616. -> void {
  617. bool first_positional_arg = true;
  618. for (const auto& positional_arg : command.positional_args) {
  619. if (positional_arg->is_help_hidden) {
  620. continue;
  621. }
  622. if (first_positional_arg) {
  623. first_positional_arg = false;
  624. if (!command.parent) {
  625. *out_ << "\nPositional arguments:";
  626. } else {
  627. *out_ << "\nSubcommand `" << command.info.name
  628. << "` positional arguments:";
  629. }
  630. }
  631. *out_ << "\n";
  632. *out_ << " " << positional_arg->info.name << "\n";
  633. PrintArgHelp(*positional_arg, BlockIndent);
  634. }
  635. }
  636. auto MetaPrinter::PrintHelpOptions(const Command& command) const -> void {
  637. bool first_option = true;
  638. for (const auto& option : command.options) {
  639. if (option->is_help_hidden) {
  640. continue;
  641. }
  642. if (first_option) {
  643. first_option = false;
  644. if (!command.parent && command.subcommands.empty()) {
  645. // Only one command level.
  646. *out_ << "\nOptions:";
  647. } else if (!command.parent) {
  648. *out_ << "\nCommand options:";
  649. } else {
  650. *out_ << "\nSubcommand `" << command.info.name << "` options:";
  651. }
  652. }
  653. *out_ << "\n";
  654. *out_ << " ";
  655. if (!option->info.short_name.empty()) {
  656. PrintOptionShortName(*option);
  657. *out_ << ", ";
  658. } else {
  659. *out_ << " ";
  660. }
  661. PrintOptionUsage(*option);
  662. *out_ << "\n";
  663. PrintArgHelp(*option, BlockIndent);
  664. }
  665. }
  666. class Parser {
  667. public:
  668. // `out` must not be null.
  669. explicit Parser(llvm::raw_ostream* out, CommandInfo command_info,
  670. llvm::function_ref<auto(CommandBuilder&)->void> build);
  671. auto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args)
  672. -> ErrorOr<ParseResult>;
  673. private:
  674. friend CommandBuilder;
  675. // For the option and subcommand maps, we use somewhat large small size
  676. // buffers (16) as there is no real size pressure on these and its nice to
  677. // avoid heap allocation in the small cases.
  678. using OptionMapT =
  679. llvm::SmallDenseMap<llvm::StringRef, llvm::PointerIntPair<Arg*, 1, bool>,
  680. 16>;
  681. using SubcommandMapT = llvm::SmallDenseMap<llvm::StringRef, Command*, 16>;
  682. // This table is sized to be 128 so that it can hold ASCII characters. We
  683. // don't need any more than this and using a direct table indexed by the
  684. // character's numeric value makes for a convenient map.
  685. using ShortOptionTableT = std::array<OptionMapT::mapped_type*, 128>;
  686. auto PopulateMaps(const Command& command) -> void;
  687. auto SetOptionDefault(const Arg& option) -> void;
  688. auto ParseNegatedFlag(const Arg& flag, std::optional<llvm::StringRef> value)
  689. -> ErrorOr<Success>;
  690. auto ParseFlag(const Arg& flag, std::optional<llvm::StringRef> value)
  691. -> ErrorOr<Success>;
  692. auto ParseIntegerArgValue(const Arg& arg, llvm::StringRef value)
  693. -> ErrorOr<Success>;
  694. auto ParseStringArgValue(const Arg& arg, llvm::StringRef value)
  695. -> ErrorOr<Success>;
  696. auto ParseOneOfArgValue(const Arg& arg, llvm::StringRef value)
  697. -> ErrorOr<Success>;
  698. auto ParseArg(const Arg& arg, bool short_spelling,
  699. std::optional<llvm::StringRef> value, bool negated_name = false)
  700. -> ErrorOr<Success>;
  701. auto SplitValue(llvm::StringRef& unparsed_arg)
  702. -> std::optional<llvm::StringRef>;
  703. auto ParseLongOption(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;
  704. auto ParseShortOptionSeq(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;
  705. auto FinalizeParsedOptions() -> ErrorOr<Success>;
  706. auto ParsePositionalArg(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;
  707. auto ParseSubcommand(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;
  708. auto ParsePositionalSuffix(llvm::ArrayRef<llvm::StringRef> unparsed_args)
  709. -> ErrorOr<Success>;
  710. auto FinalizeParse() -> ErrorOr<ParseResult>;
  711. // When building a command, it registers arguments and potentially subcommands
  712. // that are meta actions to print things to standard out, so we build a meta
  713. // printer for that here.
  714. MetaPrinter meta_printer_;
  715. Command root_command_;
  716. const Command* command_;
  717. OptionMapT option_map_;
  718. ShortOptionTableT short_option_table_;
  719. SubcommandMapT subcommand_map_;
  720. int positional_arg_index_ = 0;
  721. bool appending_to_positional_arg_ = false;
  722. ActionT arg_meta_action_;
  723. };
  724. auto Parser::PopulateMaps(const Command& command) -> void {
  725. option_map_.clear();
  726. for (const auto& option : command.options) {
  727. option_map_.insert({option->info.name, {option.get(), false}});
  728. }
  729. short_option_table_.fill(nullptr);
  730. for (auto& map_entry : option_map_) {
  731. const Arg* option = map_entry.second.getPointer();
  732. if (option->info.short_name.empty()) {
  733. continue;
  734. }
  735. CARBON_CHECK(option->info.short_name.size() == 1,
  736. "Short option names must have exactly one character.");
  737. unsigned char short_char = option->info.short_name[0];
  738. CARBON_CHECK(short_char < short_option_table_.size(),
  739. "Short option name outside of the expected range.");
  740. short_option_table_[short_char] = &map_entry.second;
  741. }
  742. subcommand_map_.clear();
  743. for (const auto& subcommand : command.subcommands) {
  744. subcommand_map_.insert({subcommand->info.name, subcommand.get()});
  745. }
  746. }
  747. auto Parser::SetOptionDefault(const Arg& option) -> void {
  748. CARBON_CHECK(option.has_default, "No default value available!");
  749. switch (option.kind) {
  750. case Arg::Kind::Flag:
  751. *option.flag_storage = option.default_flag;
  752. break;
  753. case Arg::Kind::Integer:
  754. *option.integer_storage = option.default_integer;
  755. break;
  756. case Arg::Kind::String:
  757. *option.string_storage = option.default_string;
  758. break;
  759. case Arg::Kind::OneOf:
  760. option.default_action(option);
  761. break;
  762. case Arg::Kind::MetaActionOnly:
  763. CARBON_FATAL("Can't set a default value for a meta action!");
  764. case Arg::Kind::Invalid:
  765. CARBON_FATAL("Option configured without any action or kind!");
  766. }
  767. }
  768. auto Parser::ParseNegatedFlag(const Arg& flag,
  769. std::optional<llvm::StringRef> value)
  770. -> ErrorOr<Success> {
  771. if (flag.kind != Arg::Kind::Flag) {
  772. return Error(
  773. "cannot use a negated flag name by prefixing it with `no-` when it "
  774. "isn't a boolean flag argument");
  775. }
  776. if (value) {
  777. return Error(
  778. "cannot specify a value when using a flag name prefixed with `no-` -- "
  779. "that prefix implies a value of `false`");
  780. }
  781. *flag.flag_storage = false;
  782. return Success();
  783. }
  784. auto Parser::ParseFlag(const Arg& flag, std::optional<llvm::StringRef> value)
  785. -> ErrorOr<Success> {
  786. CARBON_CHECK(flag.kind == Arg::Kind::Flag, "Incorrect kind: {0}", flag.kind);
  787. if (!value || *value == "true") {
  788. *flag.flag_storage = true;
  789. } else if (*value == "false") {
  790. *flag.flag_storage = false;
  791. } else {
  792. return Error(llvm::formatv(
  793. "invalid value specified for the boolean flag `--{0}`: {1}",
  794. flag.info.name, *value));
  795. }
  796. return Success();
  797. }
  798. auto Parser::ParseIntegerArgValue(const Arg& arg, llvm::StringRef value)
  799. -> ErrorOr<Success> {
  800. CARBON_CHECK(arg.kind == Arg::Kind::Integer, "Incorrect kind: {0}", arg.kind);
  801. int integer_value;
  802. // Note that this method returns *true* on error!
  803. if (value.getAsInteger(/*Radix=*/0, integer_value)) {
  804. return Error(llvm::formatv(
  805. "cannot parse value for option `--{0}` as an integer: {1}",
  806. arg.info.name, value));
  807. }
  808. if (!arg.is_append) {
  809. *arg.integer_storage = integer_value;
  810. } else {
  811. arg.integer_sequence->push_back(integer_value);
  812. }
  813. return Success();
  814. }
  815. auto Parser::ParseStringArgValue(const Arg& arg, llvm::StringRef value)
  816. -> ErrorOr<Success> {
  817. CARBON_CHECK(arg.kind == Arg::Kind::String, "Incorrect kind: {0}", arg.kind);
  818. if (!arg.is_append) {
  819. *arg.string_storage = value;
  820. } else {
  821. arg.string_sequence->push_back(value);
  822. }
  823. return Success();
  824. }
  825. auto Parser::ParseOneOfArgValue(const Arg& arg, llvm::StringRef value)
  826. -> ErrorOr<Success> {
  827. CARBON_CHECK(arg.kind == Arg::Kind::OneOf, "Incorrect kind: {0}", arg.kind);
  828. if (!arg.value_action(arg, value)) {
  829. RawStringOstream error;
  830. error << "option `--" << arg.info.name << "=";
  831. llvm::printEscapedString(value, error);
  832. error << "` has an invalid value `";
  833. llvm::printEscapedString(value, error);
  834. error << "`; valid values are: ";
  835. PrintListOfAlternatives(error, arg.value_strings,
  836. [](llvm::StringRef x) { return x; });
  837. return Error(error.TakeStr());
  838. }
  839. return Success();
  840. }
  841. auto Parser::ParseArg(const Arg& arg, bool short_spelling,
  842. std::optional<llvm::StringRef> value, bool negated_name)
  843. -> ErrorOr<Success> {
  844. // If this argument has a meta action, replace the current meta action with
  845. // it.
  846. if (arg.meta_action) {
  847. arg_meta_action_ = arg.meta_action;
  848. }
  849. // Boolean flags have special parsing logic.
  850. if (negated_name) {
  851. return ParseNegatedFlag(arg, value);
  852. }
  853. if (arg.kind == Arg::Kind::Flag) {
  854. return ParseFlag(arg, value);
  855. }
  856. std::string name;
  857. if (short_spelling) {
  858. name = llvm::formatv("`-{0}` (short for `--{1}`)", arg.info.short_name,
  859. arg.info.name);
  860. } else {
  861. name = llvm::formatv("`--{0}`", arg.info.name);
  862. }
  863. if (!value) {
  864. // We can't have a positional argument without a value, so we know this is
  865. // an option and handle it as such.
  866. if (arg.kind == Arg::Kind::MetaActionOnly) {
  867. // Nothing further to do here, this is only a meta-action.
  868. return Success();
  869. }
  870. if (!arg.has_default) {
  871. return Error(llvm::formatv(
  872. "option {0} requires a value to be provided and none was", name));
  873. }
  874. SetOptionDefault(arg);
  875. return Success();
  876. }
  877. // There is a value to parse as part of the argument.
  878. switch (arg.kind) {
  879. case Arg::Kind::Integer:
  880. return ParseIntegerArgValue(arg, *value);
  881. case Arg::Kind::String:
  882. return ParseStringArgValue(arg, *value);
  883. case Arg::Kind::OneOf:
  884. return ParseOneOfArgValue(arg, *value);
  885. case Arg::Kind::MetaActionOnly:
  886. // TODO: Improve message.
  887. return Error(llvm::formatv(
  888. "option {0} cannot be used with a value, and '{1}' was provided",
  889. name, value));
  890. case Arg::Kind::Flag:
  891. case Arg::Kind::Invalid:
  892. CARBON_FATAL("Invalid kind!");
  893. }
  894. }
  895. auto Parser::SplitValue(llvm::StringRef& unparsed_arg)
  896. -> std::optional<llvm::StringRef> {
  897. // Split out a value if present.
  898. std::optional<llvm::StringRef> value;
  899. auto index = unparsed_arg.find('=');
  900. if (index != llvm::StringRef::npos) {
  901. value = unparsed_arg.substr(index + 1);
  902. unparsed_arg = unparsed_arg.substr(0, index);
  903. }
  904. return value;
  905. }
  906. auto Parser::ParseLongOption(llvm::StringRef unparsed_arg) -> ErrorOr<Success> {
  907. CARBON_CHECK(unparsed_arg.starts_with("--") && unparsed_arg.size() > 2,
  908. "Must only be called on a potential long option.");
  909. // Walk past the double dash.
  910. unparsed_arg = unparsed_arg.drop_front(2);
  911. bool negated_name = unparsed_arg.consume_front("no-");
  912. std::optional<llvm::StringRef> value = SplitValue(unparsed_arg);
  913. auto option_it = option_map_.find(unparsed_arg);
  914. if (option_it == option_map_.end()) {
  915. // TODO: Improve error.
  916. return Error(llvm::formatv("unknown option `--{0}{1}`",
  917. negated_name ? "no-" : "", unparsed_arg));
  918. }
  919. // Mark this option as parsed.
  920. option_it->second.setInt(true);
  921. // Parse this specific option and any value.
  922. const Arg& option = *option_it->second.getPointer();
  923. return ParseArg(option, /*short_spelling=*/false, value, negated_name);
  924. }
  925. auto Parser::ParseShortOptionSeq(llvm::StringRef unparsed_arg)
  926. -> ErrorOr<Success> {
  927. CARBON_CHECK(unparsed_arg.starts_with("-") && unparsed_arg.size() > 1,
  928. "Must only be called on a potential short option sequence.");
  929. unparsed_arg = unparsed_arg.drop_front();
  930. std::optional<llvm::StringRef> value = SplitValue(unparsed_arg);
  931. if (value && unparsed_arg.size() != 1) {
  932. return Error(llvm::formatv(
  933. "cannot provide a value to the group of multiple short options "
  934. "`-{0}=...`; values must be provided to a single option, using "
  935. "either the short or long spelling",
  936. unparsed_arg));
  937. }
  938. for (unsigned char c : unparsed_arg) {
  939. auto* arg_entry =
  940. (c < short_option_table_.size()) ? short_option_table_[c] : nullptr;
  941. if (!arg_entry) {
  942. return Error(
  943. llvm::formatv("unknown short option `-{0}`", static_cast<char>(c)));
  944. }
  945. // Mark this argument as parsed.
  946. arg_entry->setInt(true);
  947. // Parse the argument, including the value if this is the last.
  948. const Arg& arg = *arg_entry->getPointer();
  949. CARBON_RETURN_IF_ERROR(ParseArg(arg, /*short_spelling=*/true, value));
  950. }
  951. return Success();
  952. }
  953. auto Parser::FinalizeParsedOptions() -> ErrorOr<Success> {
  954. llvm::SmallVector<const Arg*> missing_options;
  955. for (const auto& option_entry : option_map_) {
  956. const Arg* option = option_entry.second.getPointer();
  957. if (!option_entry.second.getInt()) {
  958. // If the argument has a default value and isn't a meta-action, we need to
  959. // act on that when it isn't passed.
  960. if (option->has_default && !option->meta_action) {
  961. SetOptionDefault(*option);
  962. }
  963. // Remember any missing required arguments, we'll diagnose those.
  964. if (option->is_required) {
  965. missing_options.push_back(option);
  966. }
  967. }
  968. }
  969. if (missing_options.empty()) {
  970. return Success();
  971. }
  972. // Sort the missing arguments by name to provide a stable and deterministic
  973. // error message. We know there can't be duplicate names because these came
  974. // from a may keyed on the name, so this provides a total ordering.
  975. llvm::sort(missing_options, [](const Arg* lhs, const Arg* rhs) {
  976. return lhs->info.name < rhs->info.name;
  977. });
  978. RawStringOstream error;
  979. error << "required options not provided: ";
  980. llvm::ListSeparator sep;
  981. for (const Arg* option : missing_options) {
  982. error << sep << "--" << option->info.name;
  983. }
  984. return Error(error.TakeStr());
  985. }
  986. auto Parser::ParsePositionalArg(llvm::StringRef unparsed_arg)
  987. -> ErrorOr<Success> {
  988. if (static_cast<size_t>(positional_arg_index_) >=
  989. command_->positional_args.size()) {
  990. return Error(llvm::formatv(
  991. "completed parsing all {0} configured positional arguments, and found "
  992. "an additional positional argument: `{1}`",
  993. command_->positional_args.size(), unparsed_arg));
  994. }
  995. const Arg& arg = *command_->positional_args[positional_arg_index_];
  996. // Mark that we'll keep appending here until a `--` marker. When already
  997. // appending this is redundant but harmless.
  998. appending_to_positional_arg_ = arg.is_append;
  999. if (!appending_to_positional_arg_) {
  1000. // If we're not continuing to append to a current positional arg,
  1001. // increment the positional arg index to find the next argument we
  1002. // should use here.
  1003. ++positional_arg_index_;
  1004. }
  1005. return ParseArg(arg, /*short_spelling=*/false, unparsed_arg);
  1006. }
  1007. auto Parser::ParseSubcommand(llvm::StringRef unparsed_arg) -> ErrorOr<Success> {
  1008. auto subcommand_it = subcommand_map_.find(unparsed_arg);
  1009. if (subcommand_it == subcommand_map_.end()) {
  1010. RawStringOstream error;
  1011. error << "invalid subcommand `" << unparsed_arg
  1012. << "`; available subcommands: ";
  1013. MetaPrinter(&error).PrintSubcommands(*command_);
  1014. return Error(error.TakeStr());
  1015. }
  1016. // Before we recurse into the subcommand, verify that all the required
  1017. // arguments for this command were in fact parsed.
  1018. CARBON_RETURN_IF_ERROR(FinalizeParsedOptions());
  1019. // Recurse into the subcommand, tracking the active command.
  1020. command_ = subcommand_it->second;
  1021. PopulateMaps(*command_);
  1022. return Success();
  1023. }
  1024. auto Parser::FinalizeParse() -> ErrorOr<ParseResult> {
  1025. // If an argument action is provided, we run that and consider the parse
  1026. // meta-successful rather than verifying required arguments were provided and
  1027. // the (sub)command action.
  1028. if (arg_meta_action_) {
  1029. arg_meta_action_();
  1030. return ParseResult::MetaSuccess;
  1031. }
  1032. // Verify we're not missing any arguments.
  1033. CARBON_RETURN_IF_ERROR(FinalizeParsedOptions());
  1034. // If we were appending to a positional argument, mark that as complete.
  1035. llvm::ArrayRef positional_args = command_->positional_args;
  1036. if (appending_to_positional_arg_) {
  1037. CARBON_CHECK(
  1038. static_cast<size_t>(positional_arg_index_) < positional_args.size(),
  1039. "Appending to a positional argument with an invalid index: {0}",
  1040. positional_arg_index_);
  1041. ++positional_arg_index_;
  1042. }
  1043. // See if any positional args are required and unparsed.
  1044. auto unparsed_positional_args = positional_args.slice(positional_arg_index_);
  1045. if (!unparsed_positional_args.empty()) {
  1046. // There are un-parsed positional arguments, make sure they aren't required.
  1047. const Arg& missing_arg = *unparsed_positional_args.front();
  1048. if (missing_arg.is_required) {
  1049. return Error(
  1050. llvm::formatv("not all required positional arguments were provided; "
  1051. "first missing and required positional argument: `{0}`",
  1052. missing_arg.info.name));
  1053. }
  1054. for (const auto& arg_ptr : unparsed_positional_args) {
  1055. CARBON_CHECK(
  1056. !arg_ptr->is_required,
  1057. "Cannot have required positional parameters after an optional one.");
  1058. }
  1059. }
  1060. switch (command_->kind) {
  1061. case Command::Kind::Invalid:
  1062. CARBON_FATAL("Should never have a parser with an invalid command!");
  1063. case Command::Kind::RequiresSubcommand: {
  1064. RawStringOstream error;
  1065. error << "no subcommand specified; available subcommands: ";
  1066. MetaPrinter(&error).PrintSubcommands(*command_);
  1067. return Error(error.TakeStr());
  1068. }
  1069. case Command::Kind::Action:
  1070. // All arguments have been successfully parsed, run any action for the
  1071. // most specific selected command. Only the leaf command's action is run.
  1072. command_->action();
  1073. return ParseResult::Success;
  1074. case Command::Kind::MetaAction:
  1075. command_->action();
  1076. return ParseResult::MetaSuccess;
  1077. }
  1078. }
  1079. auto Parser::ParsePositionalSuffix(
  1080. llvm::ArrayRef<llvm::StringRef> unparsed_args) -> ErrorOr<Success> {
  1081. CARBON_CHECK(
  1082. !command_->positional_args.empty(),
  1083. "Cannot do positional suffix parsing without positional arguments!");
  1084. CARBON_CHECK(
  1085. !unparsed_args.empty() && unparsed_args.front() == "--",
  1086. "Must be called with a suffix of arguments starting with a `--` that "
  1087. "switches to positional suffix parsing.");
  1088. // Once we're in the positional suffix, we can track empty positional
  1089. // arguments.
  1090. bool empty_positional = false;
  1091. while (!unparsed_args.empty()) {
  1092. llvm::StringRef unparsed_arg = unparsed_args.front();
  1093. unparsed_args = unparsed_args.drop_front();
  1094. if (unparsed_arg != "--") {
  1095. CARBON_RETURN_IF_ERROR(ParsePositionalArg(unparsed_arg));
  1096. empty_positional = false;
  1097. continue;
  1098. }
  1099. if (appending_to_positional_arg_ || empty_positional) {
  1100. ++positional_arg_index_;
  1101. if (static_cast<size_t>(positional_arg_index_) >=
  1102. command_->positional_args.size()) {
  1103. return Error(
  1104. llvm::formatv("completed parsing all {0} configured positional "
  1105. "arguments, but found a subsequent `--` and have no "
  1106. "further positional arguments to parse beyond it",
  1107. command_->positional_args.size()));
  1108. }
  1109. }
  1110. appending_to_positional_arg_ = false;
  1111. empty_positional = true;
  1112. }
  1113. return Success();
  1114. }
  1115. Parser::Parser(llvm::raw_ostream* out, CommandInfo command_info,
  1116. llvm::function_ref<auto(CommandBuilder&)->void> build)
  1117. : meta_printer_(out), root_command_(command_info) {
  1118. // Run the command building lambda on a builder for the root command.
  1119. CommandBuilder builder(&root_command_, &meta_printer_);
  1120. build(builder);
  1121. builder.Finalize();
  1122. command_ = &root_command_;
  1123. }
  1124. auto Parser::Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args)
  1125. -> ErrorOr<ParseResult> {
  1126. PopulateMaps(*command_);
  1127. while (!unparsed_args.empty()) {
  1128. llvm::StringRef unparsed_arg = unparsed_args.front();
  1129. // Peak at the front for an exact `--` argument that switches to a
  1130. // positional suffix parsing without dropping this argument.
  1131. if (unparsed_arg == "--") {
  1132. if (command_->positional_args.empty()) {
  1133. return Error(
  1134. "cannot meaningfully end option and subcommand arguments with a "
  1135. "`--` argument when there are no positional arguments to parse");
  1136. }
  1137. if (static_cast<size_t>(positional_arg_index_) >=
  1138. command_->positional_args.size()) {
  1139. return Error(
  1140. "switched to purely positional arguments with a `--` argument "
  1141. "despite already having parsed all positional arguments for this "
  1142. "command");
  1143. }
  1144. CARBON_RETURN_IF_ERROR(ParsePositionalSuffix(unparsed_args));
  1145. // No more unparsed arguments to handle.
  1146. break;
  1147. }
  1148. // Now that we're not switching parse modes, drop the current unparsed
  1149. // argument and parse it.
  1150. unparsed_args = unparsed_args.drop_front();
  1151. if (unparsed_arg.starts_with("--")) {
  1152. // Note that the exact argument "--" has been handled above already.
  1153. CARBON_RETURN_IF_ERROR(ParseLongOption(unparsed_arg));
  1154. continue;
  1155. }
  1156. if (unparsed_arg.starts_with("-") && unparsed_arg.size() > 1) {
  1157. CARBON_RETURN_IF_ERROR(ParseShortOptionSeq(unparsed_arg));
  1158. continue;
  1159. }
  1160. CARBON_CHECK(
  1161. command_->positional_args.empty() || command_->subcommands.empty(),
  1162. "Cannot have both positional arguments and subcommands!");
  1163. if (command_->positional_args.empty() && command_->subcommands.empty()) {
  1164. return Error(llvm::formatv(
  1165. "found unexpected positional argument or subcommand: `{0}`",
  1166. unparsed_arg));
  1167. }
  1168. if (!command_->positional_args.empty()) {
  1169. CARBON_RETURN_IF_ERROR(ParsePositionalArg(unparsed_arg));
  1170. continue;
  1171. }
  1172. CARBON_RETURN_IF_ERROR(ParseSubcommand(unparsed_arg));
  1173. }
  1174. return FinalizeParse();
  1175. }
  1176. auto ArgBuilder::Required(bool is_required) -> void {
  1177. arg_->is_required = is_required;
  1178. }
  1179. auto ArgBuilder::HelpHidden(bool is_help_hidden) -> void {
  1180. arg_->is_help_hidden = is_help_hidden;
  1181. }
  1182. ArgBuilder::ArgBuilder(Arg* arg) : arg_(arg) {}
  1183. auto FlagBuilder::Default(bool flag_value) -> void {
  1184. arg()->has_default = true;
  1185. arg()->default_flag = flag_value;
  1186. }
  1187. auto FlagBuilder::Set(bool* flag) -> void { arg()->flag_storage = flag; }
  1188. auto IntegerArgBuilder::Default(int integer_value) -> void {
  1189. arg()->has_default = true;
  1190. arg()->default_integer = integer_value;
  1191. }
  1192. auto IntegerArgBuilder::Set(int* integer) -> void {
  1193. arg()->is_append = false;
  1194. arg()->integer_storage = integer;
  1195. }
  1196. auto IntegerArgBuilder::Append(llvm::SmallVectorImpl<int>* sequence) -> void {
  1197. arg()->is_append = true;
  1198. arg()->integer_sequence = sequence;
  1199. }
  1200. auto StringArgBuilder::Default(llvm::StringRef string_value) -> void {
  1201. arg()->has_default = true;
  1202. arg()->default_string = string_value;
  1203. }
  1204. auto StringArgBuilder::Set(llvm::StringRef* string) -> void {
  1205. arg()->is_append = false;
  1206. arg()->string_storage = string;
  1207. }
  1208. auto StringArgBuilder::Append(llvm::SmallVectorImpl<llvm::StringRef>* sequence)
  1209. -> void {
  1210. arg()->is_append = true;
  1211. arg()->string_sequence = sequence;
  1212. }
  1213. static auto IsValidName(llvm::StringRef name) -> bool {
  1214. if (name.size() <= 1) {
  1215. return false;
  1216. }
  1217. if (!llvm::isAlnum(name.front())) {
  1218. return false;
  1219. }
  1220. if (!llvm::isAlnum(name.back())) {
  1221. return false;
  1222. }
  1223. for (char c : name.drop_front().drop_back()) {
  1224. if (c != '-' && c != '_' && !llvm::isAlnum(c)) {
  1225. return false;
  1226. }
  1227. }
  1228. // We disallow names starting with "no-" as we will parse those for boolean
  1229. // flags.
  1230. return !name.starts_with("no-");
  1231. }
  1232. auto CommandBuilder::AddFlag(const ArgInfo& info,
  1233. llvm::function_ref<auto(FlagBuilder&)->void> build)
  1234. -> void {
  1235. FlagBuilder builder(AddArgImpl(info, Arg::Kind::Flag));
  1236. // All boolean flags have an implicit default of `false`, although it can be
  1237. // overridden in the build callback.
  1238. builder.Default(false);
  1239. build(builder);
  1240. }
  1241. auto CommandBuilder::AddIntegerOption(
  1242. const ArgInfo& info,
  1243. llvm::function_ref<auto(IntegerArgBuilder&)->void> build) -> void {
  1244. IntegerArgBuilder builder(AddArgImpl(info, Arg::Kind::Integer));
  1245. build(builder);
  1246. }
  1247. auto CommandBuilder::AddStringOption(
  1248. const ArgInfo& info,
  1249. llvm::function_ref<auto(StringArgBuilder&)->void> build) -> void {
  1250. StringArgBuilder builder(AddArgImpl(info, Arg::Kind::String));
  1251. build(builder);
  1252. }
  1253. auto CommandBuilder::AddOneOfOption(
  1254. const ArgInfo& info, llvm::function_ref<auto(OneOfArgBuilder&)->void> build)
  1255. -> void {
  1256. OneOfArgBuilder builder(AddArgImpl(info, Arg::Kind::OneOf));
  1257. build(builder);
  1258. }
  1259. auto CommandBuilder::AddMetaActionOption(
  1260. const ArgInfo& info, llvm::function_ref<auto(ArgBuilder&)->void> build)
  1261. -> void {
  1262. ArgBuilder builder(AddArgImpl(info, Arg::Kind::MetaActionOnly));
  1263. build(builder);
  1264. }
  1265. auto CommandBuilder::AddIntegerPositionalArg(
  1266. const ArgInfo& info,
  1267. llvm::function_ref<auto(IntegerArgBuilder&)->void> build) -> void {
  1268. AddPositionalArgImpl(info, Arg::Kind::Integer, [build](Arg& arg) {
  1269. IntegerArgBuilder builder(&arg);
  1270. build(builder);
  1271. });
  1272. }
  1273. auto CommandBuilder::AddStringPositionalArg(
  1274. const ArgInfo& info,
  1275. llvm::function_ref<auto(StringArgBuilder&)->void> build) -> void {
  1276. AddPositionalArgImpl(info, Arg::Kind::String, [build](Arg& arg) {
  1277. StringArgBuilder builder(&arg);
  1278. build(builder);
  1279. });
  1280. }
  1281. auto CommandBuilder::AddOneOfPositionalArg(
  1282. const ArgInfo& info, llvm::function_ref<auto(OneOfArgBuilder&)->void> build)
  1283. -> void {
  1284. AddPositionalArgImpl(info, Arg::Kind::OneOf, [build](Arg& arg) {
  1285. OneOfArgBuilder builder(&arg);
  1286. build(builder);
  1287. });
  1288. }
  1289. auto CommandBuilder::AddSubcommand(
  1290. const CommandInfo& info,
  1291. llvm::function_ref<auto(CommandBuilder&)->void> build) -> void {
  1292. CARBON_CHECK(IsValidName(info.name), "Invalid subcommand name: {0}",
  1293. info.name);
  1294. CARBON_CHECK(subcommand_names_.insert(info.name).second,
  1295. "Added a duplicate subcommand: {0}", info.name);
  1296. CARBON_CHECK(
  1297. command_->positional_args.empty(),
  1298. "Cannot add subcommands to a command with a positional argument.");
  1299. command_->subcommands.emplace_back(new Command(info, command_));
  1300. CommandBuilder builder(command_->subcommands.back().get(), meta_printer_);
  1301. build(builder);
  1302. builder.Finalize();
  1303. }
  1304. auto CommandBuilder::HelpHidden(bool is_help_hidden) -> void {
  1305. command_->is_help_hidden = is_help_hidden;
  1306. }
  1307. auto CommandBuilder::RequiresSubcommand() -> void {
  1308. CARBON_CHECK(!command_->subcommands.empty(),
  1309. "Cannot require subcommands unless there are subcommands.");
  1310. CARBON_CHECK(command_->positional_args.empty(),
  1311. "Cannot require subcommands and have a positional argument.");
  1312. CARBON_CHECK(command_->kind == Kind::Invalid,
  1313. "Already established the kind of this command as: {0}",
  1314. command_->kind);
  1315. command_->kind = Kind::RequiresSubcommand;
  1316. }
  1317. auto CommandBuilder::Do(ActionT action) -> void {
  1318. CARBON_CHECK(command_->kind == Kind::Invalid,
  1319. "Already established the kind of this command as: {0}",
  1320. command_->kind);
  1321. command_->kind = Kind::Action;
  1322. command_->action = std::move(action);
  1323. }
  1324. auto CommandBuilder::Meta(ActionT action) -> void {
  1325. CARBON_CHECK(command_->kind == Kind::Invalid,
  1326. "Already established the kind of this command as: {0}",
  1327. command_->kind);
  1328. command_->kind = Kind::MetaAction;
  1329. command_->action = std::move(action);
  1330. }
  1331. CommandBuilder::CommandBuilder(Command* command, MetaPrinter* meta_printer)
  1332. : command_(command), meta_printer_(meta_printer) {}
  1333. auto CommandBuilder::AddArgImpl(const ArgInfo& info, Arg::Kind kind) -> Arg* {
  1334. CARBON_CHECK(IsValidName(info.name), "Invalid argument name: {0}", info.name);
  1335. CARBON_CHECK(arg_names_.insert(info.name).second,
  1336. "Added a duplicate argument name: {0}", info.name);
  1337. command_->options.emplace_back(new Arg(info));
  1338. Arg* arg = command_->options.back().get();
  1339. arg->kind = kind;
  1340. return arg;
  1341. }
  1342. auto CommandBuilder::AddPositionalArgImpl(
  1343. const ArgInfo& info, Arg::Kind kind,
  1344. llvm::function_ref<auto(Arg&)->void> build) -> void {
  1345. CARBON_CHECK(IsValidName(info.name), "Invalid argument name: {0}", info.name);
  1346. CARBON_CHECK(
  1347. command_->subcommands.empty(),
  1348. "Cannot add a positional argument to a command with subcommands.");
  1349. command_->positional_args.emplace_back(new Arg(info));
  1350. Arg& arg = *command_->positional_args.back();
  1351. arg.kind = kind;
  1352. build(arg);
  1353. CARBON_CHECK(!arg.is_help_hidden,
  1354. "Cannot have a help-hidden positional argument.");
  1355. if (arg.is_required && command_->positional_args.size() > 1) {
  1356. CARBON_CHECK((*std::prev(command_->positional_args.end(), 2))->is_required,
  1357. "A required positional argument cannot be added after an "
  1358. "optional one.");
  1359. }
  1360. }
  1361. auto CommandBuilder::Finalize() -> void {
  1362. meta_printer_->RegisterWithCommand(*command_, *this);
  1363. }
  1364. auto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args,
  1365. llvm::raw_ostream& out, CommandInfo command_info,
  1366. llvm::function_ref<auto(CommandBuilder&)->void> build)
  1367. -> ErrorOr<ParseResult> {
  1368. // Build a parser, which includes building the command description provided by
  1369. // the user.
  1370. Parser parser(&out, command_info, build);
  1371. // Now parse the arguments provided using that parser.
  1372. return parser.Parse(unparsed_args);
  1373. }
  1374. } // namespace Carbon::CommandLine
  1375. // NOLINTEND(misc-no-recursion)