diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/last_getopt_demo/demo.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/getopt/last_getopt_demo/demo.cpp')
-rw-r--r-- | library/cpp/getopt/last_getopt_demo/demo.cpp | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/library/cpp/getopt/last_getopt_demo/demo.cpp b/library/cpp/getopt/last_getopt_demo/demo.cpp new file mode 100644 index 0000000000..79426a9cc9 --- /dev/null +++ b/library/cpp/getopt/last_getopt_demo/demo.cpp @@ -0,0 +1,242 @@ +#include <library/cpp/getopt/last_getopt.h> +#include <library/cpp/getopt/modchooser.h> +#include <library/cpp/colorizer/colors.h> + +// For the sake of this example, let's implement Wget + +Y_COMPLETER(HeaderCompleter) { + AddCompletion("Host"); + AddCompletion("Referer"); + + bool addPostHeaders = false; + + for (int i = 0; i < argc; ++i) { + if (argv[i] == TStringBuf("--method") && i + 1 < argc) { + auto method = TString(argv[i + 1]); + method.to_upper(); + addPostHeaders = method == "POST" || method == "PUT"; + break; + } else if (argv[i] == TStringBuf("--post-data") || argv[i] == TStringBuf("--post-file")) { + addPostHeaders = true; + break; + } + } + + if (addPostHeaders) { + AddCompletion("Content-Type"); + AddCompletion("Content-Encoding"); + AddCompletion("Content-Language"); + AddCompletion("Content-Length"); + AddCompletion("Content-Location"); + AddCompletion("Content-MD5"); + AddCompletion("Content-Range"); + } +} + +class TMain: public TMainClassArgs { + bool Background_; + size_t Timeout_; + TString ExplicitMethod_; + TString ImplicitMethod_ = "GET"; + TString UserAgent_; + TMaybe<TString> PostData_; + TMaybe<TString> PostFile_; + TVector<TString> Headers_; + +protected: + void RegisterOptions(NLastGetopt::TOpts& opts) override { + // Brief description for the whole program, will appear in the beginning of a help message. + opts.SetTitle("last_getopt_demo -- like wget, but doesn't actually do anything"); + + // Built-in options. + opts.AddHelpOption('h'); + opts.AddCompletionOption("last_getopt_demo"); + + // Custom options. + + opts.AddLongOption('V', "version") + .Help("print version and exit") + .IfPresentDisableCompletion() + .NoArgument() + .Handler([]() { + Cerr << "last_getopt_demo 1.0.0" << Endl; + exit(0); + }); + + opts.AddLongOption('b', "background") + .Help("go to background immediately after startup") + .StoreTrue(&Background_); + + opts.AddLongOption("timeout") + .RequiredArgument("timeout") + .DefaultValue("60000") + .Help("specify timeout in milliseconds for each request") + .CompletionHelp("specify timeout for each request") + .CompletionArgHelp("timeout (ms)") + .StoreResult(&Timeout_) + .Completer(NLastGetopt::NComp::Choice({{"1000"}, {"5000"}, {"10000"}, {"60000"}})); + + opts.AddLongOption("method") + .RequiredArgument("http-method") + .Help("specify HTTP method") + .CompletionArgHelp("http method") + .StoreResult(&ExplicitMethod_) + .Completer( + NLastGetopt::NComp::Choice( + {{"GET", "request representation of the specified resource"}, + {"HEAD", "request response identical to that of GET, but without response body"}, + {"POST", "submit an entry to the specified resource"}, + {"PUT", "replace representation of the specified resource with the request body"}, + {"DELETE", "delete the specified resource"}, + {"CONNECT", "establish a tunnel to the server identified by the target resource"}, + {"OPTIONS", "describe the communication options for the target resource"}, + {"TRACE", "perform a message loop-back test"}, + {"PATCH", "apply partial modifications to the specified resource"}})); + + opts.AddLongOption('U', "user-agent") + .RequiredArgument("agent-string") + .DefaultValue("LastGetoptDemo/1.0.0") + .Help("identify as `agent-string` to the HTTP server") + .CompletionHelp("set custom user agent for each HTTP request") + .CompletionArgHelp("user agent string") + .StoreResult(&UserAgent_); + + opts.AddLongOption("post-data") + .RequiredArgument("string") + .Help("use POST method and send the specified data in the request body (cannot be used with --post-file)") + .CompletionHelp("use POST method and send the specified data in the request body") + .CompletionArgHelp("POST data string") + .StoreResultT<TString>(&PostData_) + .Handler0([this]() { + ImplicitMethod_ = "POST"; + }); + + opts.AddLongOption("post-file") + .RequiredArgument("file") + .Help("use POST method and send contents of the specified file in the request body (cannot be used with --post-data)") + .CompletionHelp("use POST method and send contents of the specified file in the request body") + .CompletionArgHelp("POST file") + .StoreResultT<TString>(&PostFile_) + .Handler0([this]() { + ImplicitMethod_ = "POST"; + }) + .Completer(NLastGetopt::NComp::File()); + + // These two options can't be together. + opts.MutuallyExclusive("post-file", "post-data"); + + opts.AddLongOption("header") + .RequiredArgument("header-line") + .Help("send `header-line` along with the rest of the headers in each HTTP request") + .CompletionHelp("add header to each HTTP request") + .CompletionArgHelp("header string") + .AppendTo(&Headers_) + .AllowMultipleCompletion() + .Completer(NLastGetopt::NComp::LaunchSelf(HeaderCompleter)); + + // Setting up free arguments. + + // We are going to have one mandatory argument and unlimited number of optional arguments. + opts.SetFreeArgsMin(1); + opts.SetFreeArgsMax(NLastGetopt::TOpts::UNLIMITED_ARGS); + + // Configuration for the first argument. + opts.GetFreeArgSpec(0) + .Title("URL") + .Help("URL for download") + .CompletionArgHelp("URL for download") + .Completer(NLastGetopt::NComp::Url()); + + // Configuration for optional arguments. + opts.GetTrailingArgSpec() + .Title("URL") + .CompletionArgHelp("URL for download") + .Completer(NLastGetopt::NComp::Url()); + + // Let's add more text to our help. A nice description and examples. + + opts.AddSection( + "Description", + + "LastGetoptDemo is a showcase of library/cpp/getopt capabilities. It mimics interface of Wget " + "but doesn't actually do anything." + "\n\n" + "GNU Wget, on the other hand, is a free utility for non-interactive download of files from the Web." + "It supports HTTP, HTTPS, and FTP protocols, as well as retrieval through HTTP proxies." + "\n\n" + "Wget is non-interactive, meaning that it can work in the background, while the user is not logged on. " + "This allows you to start a retrieval and disconnect from the system, letting Wget finish the work. " + "By contrast, most of the Web browsers require constant user's presence, " + "which can be a great hindrance when transferring a lot of data." + "\n\n" + "Wget can follow links in HTML, XHTML, and CSS pages, to create local versions of remote web sites, " + "fully recreating the directory structure of the original site. " + "This is sometimes referred to as \"recursive downloading.\" " + "While doing that, Wget respects the Robot Exclusion Standard (/robots.txt). " + "Wget can be instructed to convert the links in downloaded files to point at the local files, " + "for offline viewing." + "\n\n" + "Wget has been designed for robustness over slow or unstable network connections; " + "if a download fails due to a network problem, " + "it will keep retrying until the whole file has been retrieved. " + "If the server supports regetting, " + "it will instruct the server to continue the download from where it left off." + "\n\n" + "Wget does not support Client Revocation Lists (CRLs) so the HTTPS certificate " + "you are connecting to might be revoked by the siteowner."); + + // We will use colors for this one. + auto& colors = NColorizer::StdErr(); + opts.AddSection( + "Examples", + + TStringBuilder() + << "Download a file:" + << "\n" + << colors.Cyan() + << " $ last_getopt_demo https://wordpress.org/latest.zip" + << colors.Reset() + << "\n" + << "Download a file in background, set custom user agent:" + << "\n" + << colors.Cyan() + << " $ last_getopt_demo -b -U 'Wget/1.0.0' https://wordpress.org/latest.zip" + << colors.Reset()); + } + + int DoRun(NLastGetopt::TOptsParseResult&& parsedOptions) override { + using namespace NColorizer; + + TString method = ExplicitMethod_ ? ExplicitMethod_ : ImplicitMethod_; + + Cerr << ST_LIGHT << "Settings:" << RESET << Endl; + Cerr << GREEN << " Background: " << RESET << Background_ << Endl; + Cerr << GREEN << " Timeout: " << RESET << Timeout_ << Endl; + Cerr << GREEN << " Method: " << RESET << method.Quote() << Endl; + Cerr << GREEN << " UserAgent: " << RESET << UserAgent_.Quote() << Endl; + Cerr << GREEN << " PostData: " << RESET << (PostData_ ? PostData_->Quote() : "Nothing") << Endl; + Cerr << GREEN << " PostFile: " << RESET << (PostFile_ ? PostFile_->Quote() : "Nothing") << Endl; + + Cerr << ST_LIGHT << "Headers:" << RESET << Endl; + for (auto& header : Headers_) { + Cerr << " " << header.Quote() << Endl; + } + if (!Headers_) { + Cerr << GREEN << " no headers" << RESET << Endl; + } + + Cerr << ST_LIGHT << "Will download the following URLs:" << RESET << Endl; + for (auto& arg : parsedOptions.GetFreeArgs()) { + Cerr << " " << arg.Quote() << Endl; + } + if (!parsedOptions.GetFreeArgs()) { + Cerr << " no urls" << Endl; + } + return 0; + } +}; + +int main(int argc, const char** argv) { + NLastGetopt::NComp::TCustomCompleter::FireCustomCompleter(argc, argv); + TMain().Run(argc, argv); +} |