command_line.cpp 51 KB

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