You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					408 lines
				
				19 KiB
			
		
		
			
		
	
	
					408 lines
				
				19 KiB
			| 
								 
											8 years ago
										 
									 | 
							
								// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
							 | 
						||
| 
								 | 
							
								// Licensed under the MIT License:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Permission is hereby granted, free of charge, to any person obtaining a copy
							 | 
						||
| 
								 | 
							
								// of this software and associated documentation files (the "Software"), to deal
							 | 
						||
| 
								 | 
							
								// in the Software without restriction, including without limitation the rights
							 | 
						||
| 
								 | 
							
								// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
							 | 
						||
| 
								 | 
							
								// copies of the Software, and to permit persons to whom the Software is
							 | 
						||
| 
								 | 
							
								// furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								// all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
							 | 
						||
| 
								 | 
							
								// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef KJ_MAIN_H_
							 | 
						||
| 
								 | 
							
								#define KJ_MAIN_H_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
							 | 
						||
| 
								 | 
							
								#pragma GCC system_header
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "array.h"
							 | 
						||
| 
								 | 
							
								#include "string.h"
							 | 
						||
| 
								 | 
							
								#include "vector.h"
							 | 
						||
| 
								 | 
							
								#include "function.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace kj {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ProcessContext {
							 | 
						||
| 
								 | 
							
								  // Context for command-line programs.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  virtual StringPtr getProgramName() = 0;
							 | 
						||
| 
								 | 
							
								  // Get argv[0] as passed to main().
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  KJ_NORETURN(virtual void exit()) = 0;
							 | 
						||
| 
								 | 
							
								  // Indicates program completion.  The program is considered successful unless `error()` was
							 | 
						||
| 
								 | 
							
								  // called.  Typically this exits with _Exit(), meaning that the stack is not unwound, buffers
							 | 
						||
| 
								 | 
							
								  // are not flushed, etc. -- it is the responsibility of the caller to flush any buffers that
							 | 
						||
| 
								 | 
							
								  // matter.  However, an alternate context implementation e.g. for unit testing purposes could
							 | 
						||
| 
								 | 
							
								  // choose to throw an exception instead.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // At first this approach may sound crazy.  Isn't it much better to shut down cleanly?  What if
							 | 
						||
| 
								 | 
							
								  // you lose data?  However, it turns out that if you look at each common class of program, _Exit()
							 | 
						||
| 
								 | 
							
								  // is almost always preferable.  Let's break it down:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // * Commands:  A typical program you might run from the command line is single-threaded and
							 | 
						||
| 
								 | 
							
								  //   exits quickly and deterministically.  Commands often use buffered I/O and need to flush
							 | 
						||
| 
								 | 
							
								  //   those buffers before exit.  However, most of the work performed by destructors is not
							 | 
						||
| 
								 | 
							
								  //   flushing buffers, but rather freeing up memory, placing objects into freelists, and closing
							 | 
						||
| 
								 | 
							
								  //   file descriptors.  All of this is irrelevant if the process is about to exit anyway, and
							 | 
						||
| 
								 | 
							
								  //   for a command that runs quickly, time wasted freeing heap space may make a real difference
							 | 
						||
| 
								 | 
							
								  //   in the overall runtime of a script.  Meanwhile, it is usually easy to determine exactly what
							 | 
						||
| 
								 | 
							
								  //   resources need to be flushed before exit, and easy to tell if they are not being flushed
							 | 
						||
| 
								 | 
							
								  //   (because the command fails to produce the expected output).  Therefore, it is reasonably
							 | 
						||
| 
								 | 
							
								  //   easy for commands to explicitly ensure all output is flushed before exiting, and it is
							 | 
						||
| 
								 | 
							
								  //   probably a good idea for them to do so anyway, because write failures should be detected
							 | 
						||
| 
								 | 
							
								  //   and handled.  For commands, a good strategy is to allocate any objects that require clean
							 | 
						||
| 
								 | 
							
								  //   destruction on the stack, and allow them to go out of scope before the command exits.
							 | 
						||
| 
								 | 
							
								  //   Meanwhile, any resources which do not need to be cleaned up should be allocated as members
							 | 
						||
| 
								 | 
							
								  //   of the command's main class, whose destructor normally will not be called.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // * Interactive apps:  Programs that interact with the user (whether they be graphical apps
							 | 
						||
| 
								 | 
							
								  //   with windows or console-based apps like emacs) generally exit only when the user asks them
							 | 
						||
| 
								 | 
							
								  //   to.  Such applications may store large data structures in memory which need to be synced
							 | 
						||
| 
								 | 
							
								  //   to disk, such as documents or user preferences.  However, relying on stack unwind or global
							 | 
						||
| 
								 | 
							
								  //   destructors as the mechanism for ensuring such syncing occurs is probably wrong.  First of
							 | 
						||
| 
								 | 
							
								  //   all, it's 2013, and applications ought to be actively syncing changes to non-volatile
							 | 
						||
| 
								 | 
							
								  //   storage the moment those changes are made.  Applications can crash at any time and a crash
							 | 
						||
| 
								 | 
							
								  //   should never lose data that is more than half a second old.  Meanwhile, if a user actually
							 | 
						||
| 
								 | 
							
								  //   does try to close an application while unsaved changes exist, the application UI should
							 | 
						||
| 
								 | 
							
								  //   prompt the user to decide what to do.  Such a UI mechanism is obviously too high level to
							 | 
						||
| 
								 | 
							
								  //   be implemented via destructors, so KJ's use of _Exit() shouldn't make a difference here.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // * Servers:  A good server is fault-tolerant, prepared for the possibility that at any time
							 | 
						||
| 
								 | 
							
								  //   it could crash, the OS could decide to kill it off, or the machine it is running on could
							 | 
						||
| 
								 | 
							
								  //   just die.  So, using _Exit() should be no problem.  In fact, servers generally never even
							 | 
						||
| 
								 | 
							
								  //   call exit anyway; they are killed externally.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // * Batch jobs:  A long-running batch job is something between a command and a server.  It
							 | 
						||
| 
								 | 
							
								  //   probably knows exactly what needs to be flushed before exiting, and it probably should be
							 | 
						||
| 
								 | 
							
								  //   fault-tolerant.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Meanwhile, regardless of program type, if you are adhering to KJ style, then the use of
							 | 
						||
| 
								 | 
							
								  // _Exit() shouldn't be a problem anyway:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // * KJ style forbids global mutable state (singletons) in general and global constructors and
							 | 
						||
| 
								 | 
							
								  //   destructors in particular.  Therefore, everything that could possibly need cleanup either
							 | 
						||
| 
								 | 
							
								  //   lives on the stack or is transitively owned by something living on the stack.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // * Calling exit() simply means "Don't clean up anything older than this stack frame.".  If you
							 | 
						||
| 
								 | 
							
								  //   have resources that require cleanup before exit, make sure they are owned by stack frames
							 | 
						||
| 
								 | 
							
								  //   beyond the one that eventually calls exit().  To be as safe as possible, don't place any
							 | 
						||
| 
								 | 
							
								  //   state in your program's main class, and don't call exit() yourself.  Then, runMainAndExit()
							 | 
						||
| 
								 | 
							
								  //   will do it, and the only thing on the stack at that time will be your main class, which
							 | 
						||
| 
								 | 
							
								  //   has no state anyway.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // TODO(someday):  Perhaps we should use the new std::quick_exit(), so that at_quick_exit() is
							 | 
						||
| 
								 | 
							
								  //   available for those who really think they need it.  Unfortunately, it is not yet available
							 | 
						||
| 
								 | 
							
								  //   on many platforms.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void warning(StringPtr message) = 0;
							 | 
						||
| 
								 | 
							
								  // Print the given message to standard error.  A newline is printed after the message if it
							 | 
						||
| 
								 | 
							
								  // doesn't already have one.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void error(StringPtr message) = 0;
							 | 
						||
| 
								 | 
							
								  // Like `warning()`, but also sets a flag indicating that the process has failed, and that when
							 | 
						||
| 
								 | 
							
								  // it eventually exits it should indicate an error status.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  KJ_NORETURN(virtual void exitError(StringPtr message)) = 0;
							 | 
						||
| 
								 | 
							
								  // Equivalent to `error(message)` followed by `exit()`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  KJ_NORETURN(virtual void exitInfo(StringPtr message)) = 0;
							 | 
						||
| 
								 | 
							
								  // Displays the given non-error message to the user and then calls `exit()`.  This is used to
							 | 
						||
| 
								 | 
							
								  // implement things like --help.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void increaseLoggingVerbosity() = 0;
							 | 
						||
| 
								 | 
							
								  // Increase the level of detail produced by the debug logging system.  `MainBuilder` invokes
							 | 
						||
| 
								 | 
							
								  // this if the caller uses the -v flag.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // TODO(someday):  Add interfaces representing standard OS resources like the filesystem, so that
							 | 
						||
| 
								 | 
							
								  //   these things can be mocked out.
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class TopLevelProcessContext final: public ProcessContext {
							 | 
						||
| 
								 | 
							
								  // A ProcessContext implementation appropriate for use at the actual entry point of a process
							 | 
						||
| 
								 | 
							
								  // (as opposed to when you are trying to call a program's main function from within some other
							 | 
						||
| 
								 | 
							
								  // program).  This implementation writes errors to stderr, and its `exit()` method actually
							 | 
						||
| 
								 | 
							
								  // calls the C `quick_exit()` function.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  explicit TopLevelProcessContext(StringPtr programName);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  struct CleanShutdownException { int exitCode; };
							 | 
						||
| 
								 | 
							
								  // If the environment variable KJ_CLEAN_SHUTDOWN is set, then exit() will actually throw this
							 | 
						||
| 
								 | 
							
								  // exception rather than exiting.  `kj::runMain()` catches this exception and returns normally.
							 | 
						||
| 
								 | 
							
								  // This is useful primarily for testing purposes, to assist tools like memory leak checkers that
							 | 
						||
| 
								 | 
							
								  // are easily confused by quick_exit().
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  StringPtr getProgramName() override;
							 | 
						||
| 
								 | 
							
								  KJ_NORETURN(void exit() override);
							 | 
						||
| 
								 | 
							
								  void warning(StringPtr message) override;
							 | 
						||
| 
								 | 
							
								  void error(StringPtr message) override;
							 | 
						||
| 
								 | 
							
								  KJ_NORETURN(void exitError(StringPtr message) override);
							 | 
						||
| 
								 | 
							
								  KJ_NORETURN(void exitInfo(StringPtr message) override);
							 | 
						||
| 
								 | 
							
								  void increaseLoggingVerbosity() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  StringPtr programName;
							 | 
						||
| 
								 | 
							
								  bool cleanShutdown;
							 | 
						||
| 
								 | 
							
								  bool hadErrors = false;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef Function<void(StringPtr programName, ArrayPtr<const StringPtr> params)> MainFunc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int runMainAndExit(ProcessContext& context, MainFunc&& func, int argc, char* argv[]);
							 | 
						||
| 
								 | 
							
								// Runs the given main function and then exits using the given context.  If an exception is thrown,
							 | 
						||
| 
								 | 
							
								// this will catch it, report it via the context and exit with an error code.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Normally this function does not return, because returning would probably lead to wasting time
							 | 
						||
| 
								 | 
							
								// on cleanup when the process is just going to exit anyway.  However, to facilitate memory leak
							 | 
						||
| 
								 | 
							
								// checkers and other tools that require a clean shutdown to do their job, if the environment
							 | 
						||
| 
								 | 
							
								// variable KJ_CLEAN_SHUTDOWN is set, the function will in fact return an exit code, which should
							 | 
						||
| 
								 | 
							
								// then be returned from main().
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Most users will use the KJ_MAIN() macro rather than call this function directly.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KJ_MAIN(MainClass) \
							 | 
						||
| 
								 | 
							
								  int main(int argc, char* argv[]) { \
							 | 
						||
| 
								 | 
							
								    ::kj::TopLevelProcessContext context(argv[0]); \
							 | 
						||
| 
								 | 
							
								    MainClass mainObject(context); \
							 | 
						||
| 
								 | 
							
								    return ::kj::runMainAndExit(context, mainObject.getMain(), argc, argv); \
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								// Convenience macro for declaring a main function based on the given class.  The class must have
							 | 
						||
| 
								 | 
							
								// a constructor that accepts a ProcessContext& and a method getMain() which returns
							 | 
						||
| 
								 | 
							
								// kj::MainFunc (probably building it using a MainBuilder).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class MainBuilder {
							 | 
						||
| 
								 | 
							
								  // Builds a main() function with nice argument parsing.  As options and arguments are parsed,
							 | 
						||
| 
								 | 
							
								  // corresponding callbacks are called, so that you never have to write a massive switch()
							 | 
						||
| 
								 | 
							
								  // statement to interpret arguments.  Additionally, this approach encourages you to write
							 | 
						||
| 
								 | 
							
								  // main classes that have a reasonable API that can be used as an alternative to their
							 | 
						||
| 
								 | 
							
								  // command-line interface.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // All StringPtrs passed to MainBuilder must remain valid until option parsing completes.  The
							 | 
						||
| 
								 | 
							
								  // assumption is that these strings will all be literals, making this an easy requirement.  If
							 | 
						||
| 
								 | 
							
								  // not, consider allocating them in an Arena.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Some flags are automatically recognized by the main functions built by this class:
							 | 
						||
| 
								 | 
							
								  //     --help:  Prints help text and exits.  The help text is constructed based on the
							 | 
						||
| 
								 | 
							
								  //       information you provide to the builder as you define each flag.
							 | 
						||
| 
								 | 
							
								  //     --verbose:  Increase logging verbosity.
							 | 
						||
| 
								 | 
							
								  //     --version:  Print version information and exit.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Example usage:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     class FooMain {
							 | 
						||
| 
								 | 
							
								  //     public:
							 | 
						||
| 
								 | 
							
								  //       FooMain(kj::ProcessContext& context): context(context) {}
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //       bool setAll() { all = true; return true; }
							 | 
						||
| 
								 | 
							
								  //       // Enable the --all flag.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //       kj::MainBuilder::Validity setOutput(kj::StringPtr name) {
							 | 
						||
| 
								 | 
							
								  //         // Set the output file.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //         if (name.endsWith(".foo")) {
							 | 
						||
| 
								 | 
							
								  //           outputFile = name;
							 | 
						||
| 
								 | 
							
								  //           return true;
							 | 
						||
| 
								 | 
							
								  //         } else {
							 | 
						||
| 
								 | 
							
								  //           return "Output file must have extension .foo.";
							 | 
						||
| 
								 | 
							
								  //         }
							 | 
						||
| 
								 | 
							
								  //       }
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //       kj::MainBuilder::Validity processInput(kj::StringPtr name) {
							 | 
						||
| 
								 | 
							
								  //         // Process an input file.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //         if (!exists(name)) {
							 | 
						||
| 
								 | 
							
								  //           return kj::str(name, ": file not found");
							 | 
						||
| 
								 | 
							
								  //         }
							 | 
						||
| 
								 | 
							
								  //         // ... process the input file ...
							 | 
						||
| 
								 | 
							
								  //         return true;
							 | 
						||
| 
								 | 
							
								  //       }
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //       kj::MainFunc getMain() {
							 | 
						||
| 
								 | 
							
								  //         return MainBuilder(context, "Foo Builder v1.5", "Reads <source>s and builds a Foo.")
							 | 
						||
| 
								 | 
							
								  //             .addOption({'a', "all"}, KJ_BIND_METHOD(*this, setAll),
							 | 
						||
| 
								 | 
							
								  //                 "Frob all the widgets.  Otherwise, only some widgets are frobbed.")
							 | 
						||
| 
								 | 
							
								  //             .addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setOutput),
							 | 
						||
| 
								 | 
							
								  //                 "<filename>", "Output to <filename>.  Must be a .foo file.")
							 | 
						||
| 
								 | 
							
								  //             .expectOneOrMoreArgs("<source>", KJ_BIND_METHOD(*this, processInput))
							 | 
						||
| 
								 | 
							
								  //             .build();
							 | 
						||
| 
								 | 
							
								  //       }
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     private:
							 | 
						||
| 
								 | 
							
								  //       bool all = false;
							 | 
						||
| 
								 | 
							
								  //       kj::StringPtr outputFile;
							 | 
						||
| 
								 | 
							
								  //       kj::ProcessContext& context;
							 | 
						||
| 
								 | 
							
								  //     };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  MainBuilder(ProcessContext& context, StringPtr version,
							 | 
						||
| 
								 | 
							
								              StringPtr briefDescription, StringPtr extendedDescription = nullptr);
							 | 
						||
| 
								 | 
							
								  ~MainBuilder() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class OptionName {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    OptionName() = default;
							 | 
						||
| 
								 | 
							
								    inline OptionName(char shortName): isLong(false), shortName(shortName) {}
							 | 
						||
| 
								 | 
							
								    inline OptionName(const char* longName): isLong(true), longName(longName) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    bool isLong;
							 | 
						||
| 
								 | 
							
								    union {
							 | 
						||
| 
								 | 
							
								      char shortName;
							 | 
						||
| 
								 | 
							
								      const char* longName;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    friend class MainBuilder;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class Validity {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    inline Validity(bool valid) {
							 | 
						||
| 
								 | 
							
								      if (!valid) errorMessage = heapString("invalid argument");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    inline Validity(const char* errorMessage)
							 | 
						||
| 
								 | 
							
								        : errorMessage(heapString(errorMessage)) {}
							 | 
						||
| 
								 | 
							
								    inline Validity(String&& errorMessage)
							 | 
						||
| 
								 | 
							
								        : errorMessage(kj::mv(errorMessage)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    inline const Maybe<String>& getError() const { return errorMessage; }
							 | 
						||
| 
								 | 
							
								    inline Maybe<String> releaseError() { return kj::mv(errorMessage); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    Maybe<String> errorMessage;
							 | 
						||
| 
								 | 
							
								    friend class MainBuilder;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  MainBuilder& addOption(std::initializer_list<OptionName> names, Function<Validity()> callback,
							 | 
						||
| 
								 | 
							
								                         StringPtr helpText);
							 | 
						||
| 
								 | 
							
								  // Defines a new option (flag).  `names` is a list of characters and strings that can be used to
							 | 
						||
| 
								 | 
							
								  // specify the option on the command line.  Single-character names are used with "-" while string
							 | 
						||
| 
								 | 
							
								  // names are used with "--".  `helpText` is a natural-language description of the flag.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // `callback` is called when the option is seen.  Its return value indicates whether the option
							 | 
						||
| 
								 | 
							
								  // was accepted.  If not, further option processing stops, and error is written, and the process
							 | 
						||
| 
								 | 
							
								  // exits.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Example:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     builder.addOption({'a', "all"}, KJ_BIND_METHOD(*this, showAll), "Show all files.");
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // This option could be specified in the following ways:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     -a
							 | 
						||
| 
								 | 
							
								  //     --all
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Note that single-character option names can be combined into a single argument.  For example,
							 | 
						||
| 
								 | 
							
								  // `-abcd` is equivalent to `-a -b -c -d`.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // The help text for this option would look like:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     -a, --all
							 | 
						||
| 
								 | 
							
								  //         Show all files.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Note that help text is automatically word-wrapped.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  MainBuilder& addOptionWithArg(std::initializer_list<OptionName> names,
							 | 
						||
| 
								 | 
							
								                                Function<Validity(StringPtr)> callback,
							 | 
						||
| 
								 | 
							
								                                StringPtr argumentTitle, StringPtr helpText);
							 | 
						||
| 
								 | 
							
								  // Like `addOption()`, but adds an option which accepts an argument.  `argumentTitle` is used in
							 | 
						||
| 
								 | 
							
								  // the help text.  The argument text is passed to the callback.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Example:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     builder.addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setOutput),
							 | 
						||
| 
								 | 
							
								  //                              "<filename>", "Output to <filename>.");
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // This option could be specified with an argument of "foo" in the following ways:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     -ofoo
							 | 
						||
| 
								 | 
							
								  //     -o foo
							 | 
						||
| 
								 | 
							
								  //     --output=foo
							 | 
						||
| 
								 | 
							
								  //     --output foo
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Note that single-character option names can be combined, but only the last option can have an
							 | 
						||
| 
								 | 
							
								  // argument, since the characters after the option letter are interpreted as the argument.  E.g.
							 | 
						||
| 
								 | 
							
								  // `-abofoo` would be equivalent to `-a -b -o foo`.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // The help text for this option would look like:
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  //     -o FILENAME, --output=FILENAME
							 | 
						||
| 
								 | 
							
								  //         Output to FILENAME.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  MainBuilder& addSubCommand(StringPtr name, Function<MainFunc()> getSubParser,
							 | 
						||
| 
								 | 
							
								                             StringPtr briefHelpText);
							 | 
						||
| 
								 | 
							
								  // If exactly the given name is seen as an argument, invoke getSubParser() and then pass all
							 | 
						||
| 
								 | 
							
								  // remaining arguments to the parser it returns.  This is useful for implementing commands which
							 | 
						||
| 
								 | 
							
								  // have lots of sub-commands, like "git" (which has sub-commands "checkout", "branch", "pull",
							 | 
						||
| 
								 | 
							
								  // etc.).
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // `getSubParser` is only called if the command is seen.  This avoids building main functions
							 | 
						||
| 
								 | 
							
								  // for commands that aren't used.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // `briefHelpText` should be brief enough to show immediately after the command name on a single
							 | 
						||
| 
								 | 
							
								  // line.  It will not be wrapped.  Users can use the built-in "help" command to get extended
							 | 
						||
| 
								 | 
							
								  // help on a particular command.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  MainBuilder& expectArg(StringPtr title, Function<Validity(StringPtr)> callback);
							 | 
						||
| 
								 | 
							
								  MainBuilder& expectOptionalArg(StringPtr title, Function<Validity(StringPtr)> callback);
							 | 
						||
| 
								 | 
							
								  MainBuilder& expectZeroOrMoreArgs(StringPtr title, Function<Validity(StringPtr)> callback);
							 | 
						||
| 
								 | 
							
								  MainBuilder& expectOneOrMoreArgs(StringPtr title, Function<Validity(StringPtr)> callback);
							 | 
						||
| 
								 | 
							
								  // Set callbacks to handle arguments.  `expectArg()` and `expectOptionalArg()` specify positional
							 | 
						||
| 
								 | 
							
								  // arguments with special handling, while `expect{Zero,One}OrMoreArgs()` specifies a handler for
							 | 
						||
| 
								 | 
							
								  // an argument list (the handler is called once for each argument in the list).  `title`
							 | 
						||
| 
								 | 
							
								  // specifies how the argument should be represented in the usage text.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // All options callbacks are called before argument callbacks, regardless of their ordering on
							 | 
						||
| 
								 | 
							
								  // the command line.  This matches GNU getopt's behavior of permuting non-flag arguments to the
							 | 
						||
| 
								 | 
							
								  // end of the argument list.  Also matching getopt, the special option "--" indicates that the
							 | 
						||
| 
								 | 
							
								  // rest of the command line is all arguments, not options, even if they start with '-'.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // The interpretation of positional arguments is fairly flexible.  The non-optional arguments can
							 | 
						||
| 
								 | 
							
								  // be expected at the beginning, end, or in the middle.  If more arguments are specified than
							 | 
						||
| 
								 | 
							
								  // the number of non-optional args, they are assigned to the optional argument handlers in the
							 | 
						||
| 
								 | 
							
								  // order of registration.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // For example, say you called:
							 | 
						||
| 
								 | 
							
								  //     builder.expectArg("<foo>", ...);
							 | 
						||
| 
								 | 
							
								  //     builder.expectOptionalArg("<bar>", ...);
							 | 
						||
| 
								 | 
							
								  //     builder.expectArg("<baz>", ...);
							 | 
						||
| 
								 | 
							
								  //     builder.expectZeroOrMoreArgs("<qux>", ...);
							 | 
						||
| 
								 | 
							
								  //     builder.expectArg("<corge>", ...);
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // This command requires at least three arguments: foo, baz, and corge.  If four arguments are
							 | 
						||
| 
								 | 
							
								  // given, the second is assigned to bar.  If five or more arguments are specified, then the
							 | 
						||
| 
								 | 
							
								  // arguments between the third and last are assigned to qux.  Note that it never makes sense
							 | 
						||
| 
								 | 
							
								  // to call `expect*OrMoreArgs()` more than once since only the first call would ever be used.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // In practice, you probably shouldn't create such complicated commands as in the above example.
							 | 
						||
| 
								 | 
							
								  // But, this flexibility seems necessary to support commands where the first argument is special
							 | 
						||
| 
								 | 
							
								  // as well as commands (like `cp`) where the last argument is special.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  MainBuilder& callAfterParsing(Function<Validity()> callback);
							 | 
						||
| 
								 | 
							
								  // Call the given function after all arguments have been parsed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  MainFunc build();
							 | 
						||
| 
								 | 
							
								  // Build the "main" function, which simply parses the arguments.  Once this returns, the
							 | 
						||
| 
								 | 
							
								  // `MainBuilder` is no longer valid.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  struct Impl;
							 | 
						||
| 
								 | 
							
								  Own<Impl> impl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class MainImpl;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace kj
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // KJ_MAIN_H_
							 |