aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt/last_getopt_demo/demo.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/last_getopt_demo/demo.cpp
downloadydb-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.cpp242
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);
+}