aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt
diff options
context:
space:
mode:
authoramatanhead <amatanhead@yandex-team.ru>2022-02-10 16:50:04 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:50:04 +0300
commitb6f3a80f7c2c8b7dbb0c01b056fdc1fd8cd820e9 (patch)
tree5d5cb817648f650d76cf1076100726fd9b8448e8 /library/cpp/getopt
parent8879605a63ac17539be5b3bd41b529791f4d4b02 (diff)
downloadydb-b6f3a80f7c2c8b7dbb0c01b056fdc1fd8cd820e9.tar.gz
Restoring authorship annotation for <amatanhead@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/getopt')
-rw-r--r--library/cpp/getopt/last_getopt_demo/demo.cpp456
-rw-r--r--library/cpp/getopt/last_getopt_demo/ya.make2
-rw-r--r--library/cpp/getopt/small/completer.cpp724
-rw-r--r--library/cpp/getopt/small/completer.h612
-rw-r--r--library/cpp/getopt/small/completer_command.cpp324
-rw-r--r--library/cpp/getopt/small/completer_command.h22
-rw-r--r--library/cpp/getopt/small/completion_generator.cpp1554
-rw-r--r--library/cpp/getopt/small/completion_generator.h136
-rw-r--r--library/cpp/getopt/small/formatted_output.cpp72
-rw-r--r--library/cpp/getopt/small/formatted_output.h64
-rw-r--r--library/cpp/getopt/small/last_getopt.h10
-rw-r--r--library/cpp/getopt/small/last_getopt_opt.cpp20
-rw-r--r--library/cpp/getopt/small/last_getopt_opt.h604
-rw-r--r--library/cpp/getopt/small/last_getopt_opts.cpp258
-rw-r--r--library/cpp/getopt/small/last_getopt_opts.h774
-rw-r--r--library/cpp/getopt/small/last_getopt_parse_result.cpp12
-rw-r--r--library/cpp/getopt/small/last_getopt_parse_result.h288
-rw-r--r--library/cpp/getopt/small/last_getopt_parser.cpp16
-rw-r--r--library/cpp/getopt/small/last_getopt_parser.h40
-rw-r--r--library/cpp/getopt/small/last_getopt_support.h10
-rw-r--r--library/cpp/getopt/small/modchooser.cpp298
-rw-r--r--library/cpp/getopt/small/modchooser.h142
-rw-r--r--library/cpp/getopt/small/wrap.cpp196
-rw-r--r--library/cpp/getopt/small/wrap.h32
-rw-r--r--library/cpp/getopt/small/ya.make10
-rw-r--r--library/cpp/getopt/ut/last_getopt_ut.cpp18
-rw-r--r--library/cpp/getopt/ut/wrap.cpp188
-rw-r--r--library/cpp/getopt/ut/ya.make2
28 files changed, 3442 insertions, 3442 deletions
diff --git a/library/cpp/getopt/last_getopt_demo/demo.cpp b/library/cpp/getopt/last_getopt_demo/demo.cpp
index 9dc8ceae85..79426a9cc9 100644
--- a/library/cpp/getopt/last_getopt_demo/demo.cpp
+++ b/library/cpp/getopt/last_getopt_demo/demo.cpp
@@ -2,241 +2,241 @@
#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) {
+// 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;
+ 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");
- }
+ 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 {
+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());
-
+ 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",
-
+
+ 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());
+ "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 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);
+int main(int argc, const char** argv) {
+ NLastGetopt::NComp::TCustomCompleter::FireCustomCompleter(argc, argv);
+ TMain().Run(argc, argv);
}
diff --git a/library/cpp/getopt/last_getopt_demo/ya.make b/library/cpp/getopt/last_getopt_demo/ya.make
index b9fd815bdc..53f1cfc122 100644
--- a/library/cpp/getopt/last_getopt_demo/ya.make
+++ b/library/cpp/getopt/last_getopt_demo/ya.make
@@ -1,6 +1,6 @@
PROGRAM(last_getopt_demo)
-OWNER(amatanhead)
+OWNER(amatanhead)
PEERDIR(
library/cpp/getopt
diff --git a/library/cpp/getopt/small/completer.cpp b/library/cpp/getopt/small/completer.cpp
index 0536e4cccf..3fff684adb 100644
--- a/library/cpp/getopt/small/completer.cpp
+++ b/library/cpp/getopt/small/completer.cpp
@@ -1,367 +1,367 @@
-#include "completer.h"
-
-#include "completion_generator.h"
-
-#include <util/string/cast.h>
-#include <util/generic/fwd.h>
-
-using NLastGetopt::NEscaping::Q;
-using NLastGetopt::NEscaping::QQ;
-using NLastGetopt::NEscaping::C;
-using NLastGetopt::NEscaping::CC;
-using NLastGetopt::NEscaping::S;
-using NLastGetopt::NEscaping::SS;
-using NLastGetopt::NEscaping::B;
-using NLastGetopt::NEscaping::BB;
-
-namespace NLastGetopt::NComp {
-#define L out.Line()
-#define I auto Y_GENERATE_UNIQUE_ID(indent) = out.Indent()
-
- TCompleterManager::TCompleterManager(TStringBuf command)
- : Command_(command)
- , Id_(0)
- {
- }
-
- TStringBuf TCompleterManager::GetCompleterID(const ICompleter* completer) {
- return Queue_.emplace_back(TStringBuilder() << "_" << Command_ << "__completer_" << ++Id_, completer).first;
- }
-
- void TCompleterManager::GenerateZsh(TFormattedOutput& out) {
- while (!Queue_.empty()) {
- auto[name, completer] = Queue_.back();
- Queue_.pop_back();
-
- L << "(( $+functions[" << name << "] )) ||";
- L << name << "() {";
- {
- I;
- completer->GenerateZsh(out, *this);
- }
- L << "}";
- L;
- }
- }
-
- class TAlternativeCompleter: public ICompleter {
- public:
- TAlternativeCompleter(TVector<TAlternative> alternatives)
- : Alternatives_(std::move(alternatives))
- {
- }
-
- void GenerateBash(TFormattedOutput& out) const override {
- for (auto& alternative: Alternatives_) {
- if (alternative.Completer != nullptr) {
- alternative.Completer->GenerateBash(out);
- }
- }
- }
-
- TStringBuf GenerateZshAction(TCompleterManager& manager) const override {
- return manager.GetCompleterID(this);
- }
-
- void GenerateZsh(TFormattedOutput& out, TCompleterManager& manager) const override {
- // We should use '_alternative' here, but it doesn't process escape codes in group descriptions,
- // so we dispatch alternatives ourselves.
-
- L << "local expl action";
-
- size_t i = 0;
- for (auto& alternative: Alternatives_) {
- auto tag = "alt-" + ToString(++i);
- auto action = alternative.Completer ? alternative.Completer->GenerateZshAction(manager) : TStringBuf();
-
- L;
-
- if (action.empty()) {
- L << "_message -e " << SS(tag) << " " << SS(alternative.Description);
- } else if (action.StartsWith("((") && action.EndsWith("))")) {
- L << "action=" << action.substr(1, action.size() - 2);
- L << "_describe -t " << SS(tag) << " " << SS(alternative.Description) << " action -M 'r:|[_-]=* r:|=*'";
- } else if (action.StartsWith("(") && action.EndsWith(")")) {
- L << "action=" << action << "";
- L << "_describe -t " << SS(tag) << " " << SS(alternative.Description) << " action -M 'r:|[_-]=* r:|=*'";
- } else if (action.StartsWith(' ')) {
- L << action.substr(1);
- } else {
- L << "_description " << SS(tag) << " expl " << SS(alternative.Description);
- TStringBuf word, args;
- action.Split(' ', word, args);
- L << word << " \"${expl[@]}\" " << args;
- }
- }
- }
-
- private:
- TVector<TAlternative> Alternatives_;
- };
-
- ICompleterPtr Alternative(TVector<TAlternative> alternatives) {
- return MakeSimpleShared<TAlternativeCompleter>(std::move(alternatives));
- }
-
- class TSimpleCompleter: public ICompleter {
- public:
- TSimpleCompleter(TString bashCode, TString action)
- : BashCode(std::move(bashCode))
- , Action(std::move(action))
- {
- }
-
- void GenerateBash(TFormattedOutput& out) const override {
- if (BashCode) {
- L << BashCode;
- }
- }
-
- TStringBuf GenerateZshAction(TCompleterManager&) const override {
- return Action;
- }
-
- void GenerateZsh(TFormattedOutput&, TCompleterManager&) const override {
- Y_FAIL("unreachable");
- }
-
- private:
- TString BashCode;
- TString Action;
- };
-
- ICompleterPtr Choice(TVector<TChoice> choices) {
- auto bash = TStringBuilder() << "COMPREPLY+=( $(compgen -W '";
- TStringBuf sep = "";
- for (auto& choice : choices) {
- bash << sep << B(choice.Choice);
- sep = " ";
- }
- bash << "' -- ${cur}) )";
-
- auto action = TStringBuilder();
- action << "((";
- for (auto& choice: choices) {
- action << " " << SS(choice.Choice);
- if (choice.Description) {{
- action << ":" << SS(choice.Description);
- }}
- }
- action << "))";
- return MakeSimpleShared<TSimpleCompleter>(bash, action);
- }
-
- TString Compgen(TStringBuf flags) {
- return TStringBuilder() << "COMPREPLY+=( $(compgen " << flags << " -- ${cur}) )";
- }
-
- ICompleterPtr Default() {
- return MakeSimpleShared<TSimpleCompleter>("", "_default");
- }
-
- ICompleterPtr File(TString pattern) {
- if (pattern) {
- pattern = " -g " + SS(pattern);
- }
- return MakeSimpleShared<TSimpleCompleter>("", "_files" + pattern);
- }
-
- ICompleterPtr Directory() {
- return MakeSimpleShared<TSimpleCompleter>("", "_files -/");
- }
-
- ICompleterPtr Host() {
- return MakeSimpleShared<TSimpleCompleter>(Compgen("-A hostname"), "_hosts");
- }
-
- ICompleterPtr Pid() {
- return MakeSimpleShared<TSimpleCompleter>("", "_pids");
- }
-
- ICompleterPtr User() {
- return MakeSimpleShared<TSimpleCompleter>(Compgen("-A user"), "_users");
- }
-
- ICompleterPtr Group() {
- // For some reason, OSX freezes when trying to perform completion for groups.
- // You can try removing this ifdef and debugging it, but be prepared to force-shutdown your machine
- // (and possibly reinstall OSX if force-shutdown breaks anything).
-#ifdef _darwin_
- return MakeSimpleShared<TSimpleCompleter>("", "");
-#else
- return MakeSimpleShared<TSimpleCompleter>(Compgen("-A group"), "_groups");
-#endif
- }
-
- ICompleterPtr Url() {
- return MakeSimpleShared<TSimpleCompleter>("", "_urls");
- }
-
- ICompleterPtr Tty() {
- return MakeSimpleShared<TSimpleCompleter>("", "_ttys");
- }
-
- ICompleterPtr NetInterface() {
- return MakeSimpleShared<TSimpleCompleter>("", "_net_interfaces");
- }
-
- ICompleterPtr TimeZone() {
- return MakeSimpleShared<TSimpleCompleter>("", "_time_zone");
- }
-
- ICompleterPtr Signal() {
- return MakeSimpleShared<TSimpleCompleter>(Compgen("-A signal"), "_signals");
- }
-
- ICompleterPtr Domain() {
- return MakeSimpleShared<TSimpleCompleter>("", "_domains");
- }
-
- namespace {
- TCustomCompleter* Head = nullptr;
+#include "completer.h"
+
+#include "completion_generator.h"
+
+#include <util/string/cast.h>
+#include <util/generic/fwd.h>
+
+using NLastGetopt::NEscaping::Q;
+using NLastGetopt::NEscaping::QQ;
+using NLastGetopt::NEscaping::C;
+using NLastGetopt::NEscaping::CC;
+using NLastGetopt::NEscaping::S;
+using NLastGetopt::NEscaping::SS;
+using NLastGetopt::NEscaping::B;
+using NLastGetopt::NEscaping::BB;
+
+namespace NLastGetopt::NComp {
+#define L out.Line()
+#define I auto Y_GENERATE_UNIQUE_ID(indent) = out.Indent()
+
+ TCompleterManager::TCompleterManager(TStringBuf command)
+ : Command_(command)
+ , Id_(0)
+ {
+ }
+
+ TStringBuf TCompleterManager::GetCompleterID(const ICompleter* completer) {
+ return Queue_.emplace_back(TStringBuilder() << "_" << Command_ << "__completer_" << ++Id_, completer).first;
+ }
+
+ void TCompleterManager::GenerateZsh(TFormattedOutput& out) {
+ while (!Queue_.empty()) {
+ auto[name, completer] = Queue_.back();
+ Queue_.pop_back();
+
+ L << "(( $+functions[" << name << "] )) ||";
+ L << name << "() {";
+ {
+ I;
+ completer->GenerateZsh(out, *this);
+ }
+ L << "}";
+ L;
+ }
+ }
+
+ class TAlternativeCompleter: public ICompleter {
+ public:
+ TAlternativeCompleter(TVector<TAlternative> alternatives)
+ : Alternatives_(std::move(alternatives))
+ {
+ }
+
+ void GenerateBash(TFormattedOutput& out) const override {
+ for (auto& alternative: Alternatives_) {
+ if (alternative.Completer != nullptr) {
+ alternative.Completer->GenerateBash(out);
+ }
+ }
+ }
+
+ TStringBuf GenerateZshAction(TCompleterManager& manager) const override {
+ return manager.GetCompleterID(this);
+ }
+
+ void GenerateZsh(TFormattedOutput& out, TCompleterManager& manager) const override {
+ // We should use '_alternative' here, but it doesn't process escape codes in group descriptions,
+ // so we dispatch alternatives ourselves.
+
+ L << "local expl action";
+
+ size_t i = 0;
+ for (auto& alternative: Alternatives_) {
+ auto tag = "alt-" + ToString(++i);
+ auto action = alternative.Completer ? alternative.Completer->GenerateZshAction(manager) : TStringBuf();
+
+ L;
+
+ if (action.empty()) {
+ L << "_message -e " << SS(tag) << " " << SS(alternative.Description);
+ } else if (action.StartsWith("((") && action.EndsWith("))")) {
+ L << "action=" << action.substr(1, action.size() - 2);
+ L << "_describe -t " << SS(tag) << " " << SS(alternative.Description) << " action -M 'r:|[_-]=* r:|=*'";
+ } else if (action.StartsWith("(") && action.EndsWith(")")) {
+ L << "action=" << action << "";
+ L << "_describe -t " << SS(tag) << " " << SS(alternative.Description) << " action -M 'r:|[_-]=* r:|=*'";
+ } else if (action.StartsWith(' ')) {
+ L << action.substr(1);
+ } else {
+ L << "_description " << SS(tag) << " expl " << SS(alternative.Description);
+ TStringBuf word, args;
+ action.Split(' ', word, args);
+ L << word << " \"${expl[@]}\" " << args;
+ }
+ }
+ }
+
+ private:
+ TVector<TAlternative> Alternatives_;
+ };
+
+ ICompleterPtr Alternative(TVector<TAlternative> alternatives) {
+ return MakeSimpleShared<TAlternativeCompleter>(std::move(alternatives));
+ }
+
+ class TSimpleCompleter: public ICompleter {
+ public:
+ TSimpleCompleter(TString bashCode, TString action)
+ : BashCode(std::move(bashCode))
+ , Action(std::move(action))
+ {
+ }
+
+ void GenerateBash(TFormattedOutput& out) const override {
+ if (BashCode) {
+ L << BashCode;
+ }
+ }
+
+ TStringBuf GenerateZshAction(TCompleterManager&) const override {
+ return Action;
+ }
+
+ void GenerateZsh(TFormattedOutput&, TCompleterManager&) const override {
+ Y_FAIL("unreachable");
+ }
+
+ private:
+ TString BashCode;
+ TString Action;
+ };
+
+ ICompleterPtr Choice(TVector<TChoice> choices) {
+ auto bash = TStringBuilder() << "COMPREPLY+=( $(compgen -W '";
+ TStringBuf sep = "";
+ for (auto& choice : choices) {
+ bash << sep << B(choice.Choice);
+ sep = " ";
+ }
+ bash << "' -- ${cur}) )";
+
+ auto action = TStringBuilder();
+ action << "((";
+ for (auto& choice: choices) {
+ action << " " << SS(choice.Choice);
+ if (choice.Description) {{
+ action << ":" << SS(choice.Description);
+ }}
+ }
+ action << "))";
+ return MakeSimpleShared<TSimpleCompleter>(bash, action);
+ }
+
+ TString Compgen(TStringBuf flags) {
+ return TStringBuilder() << "COMPREPLY+=( $(compgen " << flags << " -- ${cur}) )";
+ }
+
+ ICompleterPtr Default() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_default");
+ }
+
+ ICompleterPtr File(TString pattern) {
+ if (pattern) {
+ pattern = " -g " + SS(pattern);
+ }
+ return MakeSimpleShared<TSimpleCompleter>("", "_files" + pattern);
+ }
+
+ ICompleterPtr Directory() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_files -/");
+ }
+
+ ICompleterPtr Host() {
+ return MakeSimpleShared<TSimpleCompleter>(Compgen("-A hostname"), "_hosts");
+ }
+
+ ICompleterPtr Pid() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_pids");
+ }
+
+ ICompleterPtr User() {
+ return MakeSimpleShared<TSimpleCompleter>(Compgen("-A user"), "_users");
+ }
+
+ ICompleterPtr Group() {
+ // For some reason, OSX freezes when trying to perform completion for groups.
+ // You can try removing this ifdef and debugging it, but be prepared to force-shutdown your machine
+ // (and possibly reinstall OSX if force-shutdown breaks anything).
+#ifdef _darwin_
+ return MakeSimpleShared<TSimpleCompleter>("", "");
+#else
+ return MakeSimpleShared<TSimpleCompleter>(Compgen("-A group"), "_groups");
+#endif
+ }
+
+ ICompleterPtr Url() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_urls");
+ }
+
+ ICompleterPtr Tty() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_ttys");
+ }
+
+ ICompleterPtr NetInterface() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_net_interfaces");
+ }
+
+ ICompleterPtr TimeZone() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_time_zone");
+ }
+
+ ICompleterPtr Signal() {
+ return MakeSimpleShared<TSimpleCompleter>(Compgen("-A signal"), "_signals");
+ }
+
+ ICompleterPtr Domain() {
+ return MakeSimpleShared<TSimpleCompleter>("", "_domains");
+ }
+
+ namespace {
+ TCustomCompleter* Head = nullptr;
TStringBuf SpecialFlag = "---CUSTOM-COMPLETION---";
- }
-
- void TCustomCompleter::FireCustomCompleter(int argc, const char** argv) {
- if (!argc) {
- return;
- }
-
- for (int i = 1; i < argc - 4; ++i) {
- if (SpecialFlag == argv[i]) {
- auto name = TStringBuf(argv[i + 1]);
- auto curIdx = FromString<int>(argv[i + 2]);
- auto prefix = TStringBuf(argv[i + 3]);
- auto suffix = TStringBuf(argv[i + 4]);
-
- auto cur = TStringBuf();
- if (0 <= curIdx && curIdx < i) {
- cur = TStringBuf(argv[curIdx]);
- }
- if (cur && !prefix && !suffix) {
- prefix = cur; // bash does not send prefix and suffix
- }
-
- auto head = Head;
- while (head) {
- if (head->GetUniqueName() == name) {
- head->GenerateCompletions(i, argv, curIdx, cur, prefix, suffix);
- }
- head = head->Next_;
- }
-
- exit(0);
- }
- }
- }
-
- void TCustomCompleter::RegisterCustomCompleter(TCustomCompleter* completer) noexcept {
- Y_VERIFY(completer);
- completer->Next_ = Head;
- Head = completer;
- }
-
- void TCustomCompleter::AddCompletion(TStringBuf completion) {
- Cout << completion << Endl; // this was easy =)
- // TODO: support option descriptions and messages
- }
-
- void TMultipartCustomCompleter::GenerateCompletions(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix) {
- auto root = TStringBuf();
- if (prefix.Contains(Sep_)) {
- auto tmp = TStringBuf();
- prefix.RSplit(Sep_, root, tmp);
- }
-
- if (root) {
- Cout << root << Sep_ << Endl;
- } else {
- Cout << Endl;
- }
-
- Cout << Sep_ << Endl;
-
- GenerateCompletionParts(argc, argv, curIdx, cur, prefix, suffix, root);
- }
-
- class TLaunchSelf: public ICompleter {
- public:
- TLaunchSelf(TCustomCompleter* completer)
- : Completer_(completer)
- {
- }
-
- void GenerateBash(TFormattedOutput& out) const override {
- L << "IFS=$'\\n'";
+ }
+
+ void TCustomCompleter::FireCustomCompleter(int argc, const char** argv) {
+ if (!argc) {
+ return;
+ }
+
+ for (int i = 1; i < argc - 4; ++i) {
+ if (SpecialFlag == argv[i]) {
+ auto name = TStringBuf(argv[i + 1]);
+ auto curIdx = FromString<int>(argv[i + 2]);
+ auto prefix = TStringBuf(argv[i + 3]);
+ auto suffix = TStringBuf(argv[i + 4]);
+
+ auto cur = TStringBuf();
+ if (0 <= curIdx && curIdx < i) {
+ cur = TStringBuf(argv[curIdx]);
+ }
+ if (cur && !prefix && !suffix) {
+ prefix = cur; // bash does not send prefix and suffix
+ }
+
+ auto head = Head;
+ while (head) {
+ if (head->GetUniqueName() == name) {
+ head->GenerateCompletions(i, argv, curIdx, cur, prefix, suffix);
+ }
+ head = head->Next_;
+ }
+
+ exit(0);
+ }
+ }
+ }
+
+ void TCustomCompleter::RegisterCustomCompleter(TCustomCompleter* completer) noexcept {
+ Y_VERIFY(completer);
+ completer->Next_ = Head;
+ Head = completer;
+ }
+
+ void TCustomCompleter::AddCompletion(TStringBuf completion) {
+ Cout << completion << Endl; // this was easy =)
+ // TODO: support option descriptions and messages
+ }
+
+ void TMultipartCustomCompleter::GenerateCompletions(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix) {
+ auto root = TStringBuf();
+ if (prefix.Contains(Sep_)) {
+ auto tmp = TStringBuf();
+ prefix.RSplit(Sep_, root, tmp);
+ }
+
+ if (root) {
+ Cout << root << Sep_ << Endl;
+ } else {
+ Cout << Endl;
+ }
+
+ Cout << Sep_ << Endl;
+
+ GenerateCompletionParts(argc, argv, curIdx, cur, prefix, suffix, root);
+ }
+
+ class TLaunchSelf: public ICompleter {
+ public:
+ TLaunchSelf(TCustomCompleter* completer)
+ : Completer_(completer)
+ {
+ }
+
+ void GenerateBash(TFormattedOutput& out) const override {
+ L << "IFS=$'\\n'";
L << "COMPREPLY+=( $(compgen -W \"$(${words[@]} " << SpecialFlag << " " << Completer_->GetUniqueName() << " \"${cword}\" \"\" \"\" 2> /dev/null)\" -- ${cur}) )";
- L << "IFS=$' \\t\\n'";
- }
-
- TStringBuf GenerateZshAction(TCompleterManager& manager) const override {
- return manager.GetCompleterID(this);
- }
-
- void GenerateZsh(TFormattedOutput& out, TCompleterManager&) const override {
+ L << "IFS=$' \\t\\n'";
+ }
+
+ TStringBuf GenerateZshAction(TCompleterManager& manager) const override {
+ return manager.GetCompleterID(this);
+ }
+
+ void GenerateZsh(TFormattedOutput& out, TCompleterManager&) const override {
L << "compadd ${@} ${expl[@]} -- \"${(@f)$(${words_orig[@]} " << SpecialFlag << " " << Completer_->GetUniqueName() << " \"${current_orig}\" \"${prefix_orig}\" \"${suffix_orig}\" 2> /dev/null)}\"";
- }
-
- private:
- TCustomCompleter* Completer_;
- };
-
- ICompleterPtr LaunchSelf(TCustomCompleter& completer) {
- return MakeSimpleShared<TLaunchSelf>(&completer);
- }
-
- class TLaunchSelfMultiPart: public ICompleter {
- public:
- TLaunchSelfMultiPart(TCustomCompleter* completer)
- : Completer_(completer)
- {
- }
-
- void GenerateBash(TFormattedOutput& out) const override {
- L << "IFS=$'\\n'";
+ }
+
+ private:
+ TCustomCompleter* Completer_;
+ };
+
+ ICompleterPtr LaunchSelf(TCustomCompleter& completer) {
+ return MakeSimpleShared<TLaunchSelf>(&completer);
+ }
+
+ class TLaunchSelfMultiPart: public ICompleter {
+ public:
+ TLaunchSelfMultiPart(TCustomCompleter* completer)
+ : Completer_(completer)
+ {
+ }
+
+ void GenerateBash(TFormattedOutput& out) const override {
+ L << "IFS=$'\\n'";
L << "items=( $(${words[@]} " << SpecialFlag << " " << Completer_->GetUniqueName() << " \"${cword}\" \"\" \"\" 2> /dev/null) )";
- L << "candidates=$(compgen -W \"${items[*]:1}\" -- \"$cur\")";
- L << "COMPREPLY+=( $candidates )";
- L << "[[ $candidates == *\"${items[1]}\" ]] && need_space=\"\"";
- L << "IFS=$' \\t\\n'";
- }
-
- TStringBuf GenerateZshAction(TCompleterManager& manager) const override {
- return manager.GetCompleterID(this);
- }
-
- void GenerateZsh(TFormattedOutput& out, TCompleterManager&) const override {
+ L << "candidates=$(compgen -W \"${items[*]:1}\" -- \"$cur\")";
+ L << "COMPREPLY+=( $candidates )";
+ L << "[[ $candidates == *\"${items[1]}\" ]] && need_space=\"\"";
+ L << "IFS=$' \\t\\n'";
+ }
+
+ TStringBuf GenerateZshAction(TCompleterManager& manager) const override {
+ return manager.GetCompleterID(this);
+ }
+
+ void GenerateZsh(TFormattedOutput& out, TCompleterManager&) const override {
L << "local items=( \"${(@f)$(${words_orig[@]} " << SpecialFlag << " " << Completer_->GetUniqueName() << " \"${current_orig}\" \"${prefix_orig}\" \"${suffix_orig}\" 2> /dev/null)}\" )";
- L;
- L << "local rempat=${items[1]}";
- L << "shift items";
- L;
- L << "local sep=${items[1]}";
- L << "shift items";
- L;
- L << "local files=( ${items:#*\"${sep}\"} )";
- L << "local filenames=( ${files#\"${rempat}\"} )";
- L << "local dirs=( ${(M)items:#*\"${sep}\"} )";
- L << "local dirnames=( ${dirs#\"${rempat}\"} )";
- L;
- L << "local need_suf";
- L << "compset -S \"${sep}*\" || need_suf=\"1\"";
- L;
- L << "compadd ${@} ${expl[@]} -d filenames -- ${(q)files}";
- L << "compadd ${@} ${expl[@]} ${need_suf:+-S\"${sep}\"} -q -d dirnames -- ${(q)dirs%\"${sep}\"}";
- }
-
- private:
- TCustomCompleter* Completer_;
- };
-
- ICompleterPtr LaunchSelfMultiPart(TCustomCompleter& completer) {
- return MakeSimpleShared<TLaunchSelfMultiPart>(&completer);
- }
-
-#undef I
-#undef L
-}
+ L;
+ L << "local rempat=${items[1]}";
+ L << "shift items";
+ L;
+ L << "local sep=${items[1]}";
+ L << "shift items";
+ L;
+ L << "local files=( ${items:#*\"${sep}\"} )";
+ L << "local filenames=( ${files#\"${rempat}\"} )";
+ L << "local dirs=( ${(M)items:#*\"${sep}\"} )";
+ L << "local dirnames=( ${dirs#\"${rempat}\"} )";
+ L;
+ L << "local need_suf";
+ L << "compset -S \"${sep}*\" || need_suf=\"1\"";
+ L;
+ L << "compadd ${@} ${expl[@]} -d filenames -- ${(q)files}";
+ L << "compadd ${@} ${expl[@]} ${need_suf:+-S\"${sep}\"} -q -d dirnames -- ${(q)dirs%\"${sep}\"}";
+ }
+
+ private:
+ TCustomCompleter* Completer_;
+ };
+
+ ICompleterPtr LaunchSelfMultiPart(TCustomCompleter& completer) {
+ return MakeSimpleShared<TLaunchSelfMultiPart>(&completer);
+ }
+
+#undef I
+#undef L
+}
diff --git a/library/cpp/getopt/small/completer.h b/library/cpp/getopt/small/completer.h
index 6a2fdbbbf4..4136f13add 100644
--- a/library/cpp/getopt/small/completer.h
+++ b/library/cpp/getopt/small/completer.h
@@ -1,306 +1,306 @@
-#pragma once
-
-#include "formatted_output.h"
-
-#include <util/generic/strbuf.h>
-#include <util/generic/hash.h>
-
-#include <utility>
-#include <util/generic/fwd.h>
-
-namespace NLastGetopt::NComp {
- class ICompleter;
-
- class TCompleterManager {
- public:
- TCompleterManager(TStringBuf command);
-
- /// Register new completer and get its function name.
- TStringBuf GetCompleterID(const ICompleter* completer);
-
- /// Generate zsh code for all collected completers.
- void GenerateZsh(TFormattedOutput& out);
-
- private:
- TStringBuf Command_;
- size_t Id_;
- TVector<std::pair<TString, const ICompleter*>> Queue_;
- };
-
- class ICompleter {
- public:
- virtual ~ICompleter() = default;
-
- public:
- /// Generate arbitrary bash code that modifies `COMPREPLY`.
- virtual void GenerateBash(TFormattedOutput& out) const = 0;
-
- /// Generate action that will be used with `_arguments`. If this completer requires a separate function,
- /// register it in the given manager and return function name assigned by manager.
- /// Supported forms are '()', '(items...)', '((items...))', 'command ...' and ' command ...'.
- /// Other forms, such as '{eval-string}', '->state', '=action' are not supported.
- virtual TStringBuf GenerateZshAction(TCompleterManager& manager) const = 0;
-
- /// Generate body of a zsh function (if Action points to a custom function).
- virtual void GenerateZsh(TFormattedOutput& out, TCompleterManager& manager) const = 0;
- };
-
- using ICompleterPtr = TSimpleSharedPtr<ICompleter>;
-
- /// Generate default completions.
- /// Output of this completer depends on shell settings.
- /// Usually ut generates file paths.
- ICompleterPtr Default();
-
- struct TAlternative {
- /// Description for this group of completions. Leave empty to use completer's default description.
- TString Description;
-
- /// Completer that generates values
- ICompleterPtr Completer;
-
- TAlternative(ICompleterPtr completer)
- : Description("")
- , Completer(std::move(completer))
- {
- }
-
- TAlternative(TString description, ICompleterPtr completer)
- : Description(std::move(description))
- , Completer(std::move(completer))
- {
- }
- };
-
- /// Run multiple completers and unite their output.
- /// Each completer's output placed in a separate group with its own description.
- ICompleterPtr Alternative(TVector<TAlternative> alternatives);
-
- struct TChoice {
- /// Option value.
- TString Choice;
-
- /// Description for a value.
- TString Description = "";
-
- TChoice(TString choice)
- : Choice(std::move(choice))
- {
- }
-
- TChoice(TString choice, TString description)
- : Choice(std::move(choice))
- , Description(std::move(description))
- {
- }
- };
-
- /// Complete items from a predefined list of choices.
- ICompleterPtr Choice(TVector<TChoice> choices);
-
- /// Complete files and directories. May filter results by pattern, e.g. `*.txt`.
- ICompleterPtr File(TString pattern= "");
-
- /// Complete directories.
- ICompleterPtr Directory();
-
- /// Complete hosts.
- ICompleterPtr Host();
-
- /// Complete process IDs.
- ICompleterPtr Pid();
-
- /// Complete users that're found in the system.
- ICompleterPtr User();
-
- /// Complete user groups that're found in the system.
- /// N: for some reason,
- ICompleterPtr Group();
-
- /// Complete URLs.
- ICompleterPtr Url();
-
- /// Complete TTY interfaces.
- ICompleterPtr Tty();
-
- /// Complete network interfaces.
- ICompleterPtr NetInterface();
-
- /// Complete timezone identifiers.
- ICompleterPtr TimeZone();
-
- /// Complete unix signal identifiers, e.g. `ABRT` or `KILL`.
- ICompleterPtr Signal();
-
- /// Complete domains.
- ICompleterPtr Domain();
-
- /// Custom completer. See `LaunchSelf` below.
- class TCustomCompleter {
- public:
- static void FireCustomCompleter(int argc, const char** argv);
- static void RegisterCustomCompleter(TCustomCompleter* completer) noexcept;
-
- struct TReg {
- TReg(TCustomCompleter* completer) noexcept {
- TCustomCompleter::RegisterCustomCompleter(completer);
- }
- };
-
- public:
- virtual ~TCustomCompleter() = default;
-
- public:
- /// @param argc total number of command line arguments.
- /// @param argv array of command line arguments.
- /// @param curIdx index of the currently completed argument, may be equal to `argc` if cursor is at the end
- /// of line.
- /// @param cur currently completed argument.
- /// @param prefix part of the currently completed argument before the cursor.
- /// @param suffix part of the currently completed argument after the cursor.
- virtual void GenerateCompletions(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix) = 0;
- virtual TStringBuf GetUniqueName() const = 0;
-
- protected:
- void AddCompletion(TStringBuf completion);
-
- private:
- TCustomCompleter* Next_ = nullptr;
- };
-
- /// Custom completer for objects that consist of multiple parts split by a common separator, such as file paths.
- class TMultipartCustomCompleter: public TCustomCompleter {
- public:
- TMultipartCustomCompleter(TStringBuf sep)
- : Sep_(sep)
- {
- Y_VERIFY(!Sep_.empty());
- }
-
- public:
- void GenerateCompletions(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix) final;
-
- public:
- /// @param argc same as in `GenerateCompletions`.
- /// @param argv same as in `GenerateCompletions`.
- /// @param curIdx same as in `GenerateCompletions`.
- /// @param cur same as in `GenerateCompletions`.
- /// @param prefix same as in `GenerateCompletions`.
- /// @param suffix same as in `GenerateCompletions`.
- /// @param root part of the currently completed argument before the last separator.
- virtual void GenerateCompletionParts(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix, TStringBuf root) = 0;
-
- protected:
- TStringBuf Sep_;
- };
-
-#define Y_COMPLETER(N) \
-class T##N: public ::NLastGetopt::NComp::TCustomCompleter { \
- public: \
- void GenerateCompletions(int, const char**, int, TStringBuf, TStringBuf, TStringBuf) override; \
- TStringBuf GetUniqueName() const override { return #N; } \
- }; \
- T##N N = T##N(); \
- ::NLastGetopt::NComp::TCustomCompleter::TReg _Reg_##N = &N; \
- void T##N::GenerateCompletions( \
- Y_DECLARE_UNUSED int argc, \
- Y_DECLARE_UNUSED const char** argv, \
- Y_DECLARE_UNUSED int curIdx, \
- Y_DECLARE_UNUSED TStringBuf cur, \
- Y_DECLARE_UNUSED TStringBuf prefix, \
- Y_DECLARE_UNUSED TStringBuf suffix)
-
-#define Y_MULTIPART_COMPLETER(N, SEP) \
-class T##N: public ::NLastGetopt::NComp::TMultipartCustomCompleter { \
- public: \
- T##N() : ::NLastGetopt::NComp::TMultipartCustomCompleter(SEP) {} \
- void GenerateCompletionParts(int, const char**, int, TStringBuf, TStringBuf, TStringBuf, TStringBuf) override; \
- TStringBuf GetUniqueName() const override { return #N; } \
- }; \
- T##N N = T##N(); \
- ::NLastGetopt::NComp::TCustomCompleter::TReg _Reg_##N = &N; \
- void T##N::GenerateCompletionParts( \
- Y_DECLARE_UNUSED int argc, \
- Y_DECLARE_UNUSED const char** argv, \
- Y_DECLARE_UNUSED int curIdx, \
- Y_DECLARE_UNUSED TStringBuf cur, \
- Y_DECLARE_UNUSED TStringBuf prefix, \
- Y_DECLARE_UNUSED TStringBuf suffix, \
- Y_DECLARE_UNUSED TStringBuf root)
-
- /// Launches this binary with a specially formed flags and retrieves completions from stdout.
- ///
- /// Your application must be set up in a certain way for this to work.
- ///
- /// First, create a custom completer:
- ///
- /// ```
- /// Y_COMPLETER(SomeUniqueName) {
- /// AddCompletion("foo");
- /// AddCompletion("bar");
- /// AddCompletion("baz");
- /// }
- /// ```
- ///
- /// Then, use it with this function.
- ///
- /// On completion attempt, completer will call your binary with some special arguments.
- ///
- /// In your main, before any other logic, call `TCustomCompleter::FireCustomCompleter`. This function will
- /// check for said special arguments and invoke the right completer:
- ///
- /// ```
- /// int main(int argc, const char** argv) {
- /// TCustomCompleter::FireCustomCompleter(argc, argv);
- /// ...
- /// }
- /// ```
- ICompleterPtr LaunchSelf(TCustomCompleter& completer);
-
- /// Launches this binary with a specially formed flags and retrieves completions from stdout.
- ///
- /// Your application must be set up in a certain way for this to work. See `LaunchSelf` for more info.
- ///
- /// Multipart completion is designed for objects that consist of multiple parts split by a common separator.
- /// It is ideal for completing remote file paths, for example.
- ///
- /// Multipart completers format stdout in the following way.
- ///
- /// On the first line, they print a common prefix that should be stripped from all completions. For example,
- /// if you complete paths, this prefix would be a common directory.
- ///
- /// On the second line, they print a separator. If some completion ends with this separator, shell will not add
- /// a whitespace after the item is completed. For example, if you complete paths, the separator would be a slash.
- ///
- /// On the following lines, they print completions, as formed by the `AddCompletion` function.
- ///
- /// For example, if a user invokes completion like this:
- ///
- /// ```
- /// $ program //home/logs/<tab><tab>
- /// ```
- ///
- /// The stdout might look like this:
- ///
- /// ```
- /// //home/logs/
- /// /
- /// //home/logs/access-log
- /// //home/logs/redir-log
- /// //home/logs/blockstat-log
- /// ```
- ///
- /// Then autocompletion will look like this:
- ///
- /// ```
- /// $ program //home/logs/<tab><tab>
- /// -- yt path --
- /// access-log redir-log blockstat-log
- /// ```
- ///
- /// Note: stdout lines with completion suggestions *must* be formatted by the `AddCompletion` function
- /// because their format may change in the future.
- ///
- /// Note: we recommend using `Y_MULTIPART_COMPLETER` because it will handle all stdout printing for you.
- ICompleterPtr LaunchSelfMultiPart(TCustomCompleter& completer);
-}
+#pragma once
+
+#include "formatted_output.h"
+
+#include <util/generic/strbuf.h>
+#include <util/generic/hash.h>
+
+#include <utility>
+#include <util/generic/fwd.h>
+
+namespace NLastGetopt::NComp {
+ class ICompleter;
+
+ class TCompleterManager {
+ public:
+ TCompleterManager(TStringBuf command);
+
+ /// Register new completer and get its function name.
+ TStringBuf GetCompleterID(const ICompleter* completer);
+
+ /// Generate zsh code for all collected completers.
+ void GenerateZsh(TFormattedOutput& out);
+
+ private:
+ TStringBuf Command_;
+ size_t Id_;
+ TVector<std::pair<TString, const ICompleter*>> Queue_;
+ };
+
+ class ICompleter {
+ public:
+ virtual ~ICompleter() = default;
+
+ public:
+ /// Generate arbitrary bash code that modifies `COMPREPLY`.
+ virtual void GenerateBash(TFormattedOutput& out) const = 0;
+
+ /// Generate action that will be used with `_arguments`. If this completer requires a separate function,
+ /// register it in the given manager and return function name assigned by manager.
+ /// Supported forms are '()', '(items...)', '((items...))', 'command ...' and ' command ...'.
+ /// Other forms, such as '{eval-string}', '->state', '=action' are not supported.
+ virtual TStringBuf GenerateZshAction(TCompleterManager& manager) const = 0;
+
+ /// Generate body of a zsh function (if Action points to a custom function).
+ virtual void GenerateZsh(TFormattedOutput& out, TCompleterManager& manager) const = 0;
+ };
+
+ using ICompleterPtr = TSimpleSharedPtr<ICompleter>;
+
+ /// Generate default completions.
+ /// Output of this completer depends on shell settings.
+ /// Usually ut generates file paths.
+ ICompleterPtr Default();
+
+ struct TAlternative {
+ /// Description for this group of completions. Leave empty to use completer's default description.
+ TString Description;
+
+ /// Completer that generates values
+ ICompleterPtr Completer;
+
+ TAlternative(ICompleterPtr completer)
+ : Description("")
+ , Completer(std::move(completer))
+ {
+ }
+
+ TAlternative(TString description, ICompleterPtr completer)
+ : Description(std::move(description))
+ , Completer(std::move(completer))
+ {
+ }
+ };
+
+ /// Run multiple completers and unite their output.
+ /// Each completer's output placed in a separate group with its own description.
+ ICompleterPtr Alternative(TVector<TAlternative> alternatives);
+
+ struct TChoice {
+ /// Option value.
+ TString Choice;
+
+ /// Description for a value.
+ TString Description = "";
+
+ TChoice(TString choice)
+ : Choice(std::move(choice))
+ {
+ }
+
+ TChoice(TString choice, TString description)
+ : Choice(std::move(choice))
+ , Description(std::move(description))
+ {
+ }
+ };
+
+ /// Complete items from a predefined list of choices.
+ ICompleterPtr Choice(TVector<TChoice> choices);
+
+ /// Complete files and directories. May filter results by pattern, e.g. `*.txt`.
+ ICompleterPtr File(TString pattern= "");
+
+ /// Complete directories.
+ ICompleterPtr Directory();
+
+ /// Complete hosts.
+ ICompleterPtr Host();
+
+ /// Complete process IDs.
+ ICompleterPtr Pid();
+
+ /// Complete users that're found in the system.
+ ICompleterPtr User();
+
+ /// Complete user groups that're found in the system.
+ /// N: for some reason,
+ ICompleterPtr Group();
+
+ /// Complete URLs.
+ ICompleterPtr Url();
+
+ /// Complete TTY interfaces.
+ ICompleterPtr Tty();
+
+ /// Complete network interfaces.
+ ICompleterPtr NetInterface();
+
+ /// Complete timezone identifiers.
+ ICompleterPtr TimeZone();
+
+ /// Complete unix signal identifiers, e.g. `ABRT` or `KILL`.
+ ICompleterPtr Signal();
+
+ /// Complete domains.
+ ICompleterPtr Domain();
+
+ /// Custom completer. See `LaunchSelf` below.
+ class TCustomCompleter {
+ public:
+ static void FireCustomCompleter(int argc, const char** argv);
+ static void RegisterCustomCompleter(TCustomCompleter* completer) noexcept;
+
+ struct TReg {
+ TReg(TCustomCompleter* completer) noexcept {
+ TCustomCompleter::RegisterCustomCompleter(completer);
+ }
+ };
+
+ public:
+ virtual ~TCustomCompleter() = default;
+
+ public:
+ /// @param argc total number of command line arguments.
+ /// @param argv array of command line arguments.
+ /// @param curIdx index of the currently completed argument, may be equal to `argc` if cursor is at the end
+ /// of line.
+ /// @param cur currently completed argument.
+ /// @param prefix part of the currently completed argument before the cursor.
+ /// @param suffix part of the currently completed argument after the cursor.
+ virtual void GenerateCompletions(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix) = 0;
+ virtual TStringBuf GetUniqueName() const = 0;
+
+ protected:
+ void AddCompletion(TStringBuf completion);
+
+ private:
+ TCustomCompleter* Next_ = nullptr;
+ };
+
+ /// Custom completer for objects that consist of multiple parts split by a common separator, such as file paths.
+ class TMultipartCustomCompleter: public TCustomCompleter {
+ public:
+ TMultipartCustomCompleter(TStringBuf sep)
+ : Sep_(sep)
+ {
+ Y_VERIFY(!Sep_.empty());
+ }
+
+ public:
+ void GenerateCompletions(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix) final;
+
+ public:
+ /// @param argc same as in `GenerateCompletions`.
+ /// @param argv same as in `GenerateCompletions`.
+ /// @param curIdx same as in `GenerateCompletions`.
+ /// @param cur same as in `GenerateCompletions`.
+ /// @param prefix same as in `GenerateCompletions`.
+ /// @param suffix same as in `GenerateCompletions`.
+ /// @param root part of the currently completed argument before the last separator.
+ virtual void GenerateCompletionParts(int argc, const char** argv, int curIdx, TStringBuf cur, TStringBuf prefix, TStringBuf suffix, TStringBuf root) = 0;
+
+ protected:
+ TStringBuf Sep_;
+ };
+
+#define Y_COMPLETER(N) \
+class T##N: public ::NLastGetopt::NComp::TCustomCompleter { \
+ public: \
+ void GenerateCompletions(int, const char**, int, TStringBuf, TStringBuf, TStringBuf) override; \
+ TStringBuf GetUniqueName() const override { return #N; } \
+ }; \
+ T##N N = T##N(); \
+ ::NLastGetopt::NComp::TCustomCompleter::TReg _Reg_##N = &N; \
+ void T##N::GenerateCompletions( \
+ Y_DECLARE_UNUSED int argc, \
+ Y_DECLARE_UNUSED const char** argv, \
+ Y_DECLARE_UNUSED int curIdx, \
+ Y_DECLARE_UNUSED TStringBuf cur, \
+ Y_DECLARE_UNUSED TStringBuf prefix, \
+ Y_DECLARE_UNUSED TStringBuf suffix)
+
+#define Y_MULTIPART_COMPLETER(N, SEP) \
+class T##N: public ::NLastGetopt::NComp::TMultipartCustomCompleter { \
+ public: \
+ T##N() : ::NLastGetopt::NComp::TMultipartCustomCompleter(SEP) {} \
+ void GenerateCompletionParts(int, const char**, int, TStringBuf, TStringBuf, TStringBuf, TStringBuf) override; \
+ TStringBuf GetUniqueName() const override { return #N; } \
+ }; \
+ T##N N = T##N(); \
+ ::NLastGetopt::NComp::TCustomCompleter::TReg _Reg_##N = &N; \
+ void T##N::GenerateCompletionParts( \
+ Y_DECLARE_UNUSED int argc, \
+ Y_DECLARE_UNUSED const char** argv, \
+ Y_DECLARE_UNUSED int curIdx, \
+ Y_DECLARE_UNUSED TStringBuf cur, \
+ Y_DECLARE_UNUSED TStringBuf prefix, \
+ Y_DECLARE_UNUSED TStringBuf suffix, \
+ Y_DECLARE_UNUSED TStringBuf root)
+
+ /// Launches this binary with a specially formed flags and retrieves completions from stdout.
+ ///
+ /// Your application must be set up in a certain way for this to work.
+ ///
+ /// First, create a custom completer:
+ ///
+ /// ```
+ /// Y_COMPLETER(SomeUniqueName) {
+ /// AddCompletion("foo");
+ /// AddCompletion("bar");
+ /// AddCompletion("baz");
+ /// }
+ /// ```
+ ///
+ /// Then, use it with this function.
+ ///
+ /// On completion attempt, completer will call your binary with some special arguments.
+ ///
+ /// In your main, before any other logic, call `TCustomCompleter::FireCustomCompleter`. This function will
+ /// check for said special arguments and invoke the right completer:
+ ///
+ /// ```
+ /// int main(int argc, const char** argv) {
+ /// TCustomCompleter::FireCustomCompleter(argc, argv);
+ /// ...
+ /// }
+ /// ```
+ ICompleterPtr LaunchSelf(TCustomCompleter& completer);
+
+ /// Launches this binary with a specially formed flags and retrieves completions from stdout.
+ ///
+ /// Your application must be set up in a certain way for this to work. See `LaunchSelf` for more info.
+ ///
+ /// Multipart completion is designed for objects that consist of multiple parts split by a common separator.
+ /// It is ideal for completing remote file paths, for example.
+ ///
+ /// Multipart completers format stdout in the following way.
+ ///
+ /// On the first line, they print a common prefix that should be stripped from all completions. For example,
+ /// if you complete paths, this prefix would be a common directory.
+ ///
+ /// On the second line, they print a separator. If some completion ends with this separator, shell will not add
+ /// a whitespace after the item is completed. For example, if you complete paths, the separator would be a slash.
+ ///
+ /// On the following lines, they print completions, as formed by the `AddCompletion` function.
+ ///
+ /// For example, if a user invokes completion like this:
+ ///
+ /// ```
+ /// $ program //home/logs/<tab><tab>
+ /// ```
+ ///
+ /// The stdout might look like this:
+ ///
+ /// ```
+ /// //home/logs/
+ /// /
+ /// //home/logs/access-log
+ /// //home/logs/redir-log
+ /// //home/logs/blockstat-log
+ /// ```
+ ///
+ /// Then autocompletion will look like this:
+ ///
+ /// ```
+ /// $ program //home/logs/<tab><tab>
+ /// -- yt path --
+ /// access-log redir-log blockstat-log
+ /// ```
+ ///
+ /// Note: stdout lines with completion suggestions *must* be formatted by the `AddCompletion` function
+ /// because their format may change in the future.
+ ///
+ /// Note: we recommend using `Y_MULTIPART_COMPLETER` because it will handle all stdout printing for you.
+ ICompleterPtr LaunchSelfMultiPart(TCustomCompleter& completer);
+}
diff --git a/library/cpp/getopt/small/completer_command.cpp b/library/cpp/getopt/small/completer_command.cpp
index 1a0c793bd5..5e593eec7e 100644
--- a/library/cpp/getopt/small/completer_command.cpp
+++ b/library/cpp/getopt/small/completer_command.cpp
@@ -1,165 +1,165 @@
-#include "completer_command.h"
-
-#include "completion_generator.h"
-#include "last_getopt.h"
-#include "wrap.h"
-
+#include "completer_command.h"
+
+#include "completion_generator.h"
+#include "last_getopt.h"
+#include "wrap.h"
+
#include <library/cpp/colorizer/colors.h>
-
-#include <util/string/subst.h>
-
-namespace NLastGetopt {
- TString MakeInfo(TStringBuf command, TStringBuf flag) {
- TString info = (
- "This command generates shell script with completion function and prints it to `stdout`, "
- "allowing one to re-direct the output to the file of their choosing. "
- "Where you place the file will depend on which shell and operating system you are using."
- "\n"
- "\n"
- "\n"
- "{B}BASH (Linux){R}:"
- "\n"
- "\n"
- "For system-wide commands, completion files are stored in `/etc/bash_completion.d/`. "
- "For user commands, they are stored in `~/.local/share/bash-completion/completions`. "
- "So, pipe output of this script to a file in one of these directories:"
- "\n"
- "\n"
- " $ mkdir -p ~/.local/share/bash-completion/completions"
- "\n"
- " $ {command} {completion} bash >"
- "\n"
- " ~/.local/share/bash-completion/completions/{command}"
- "\n"
- "\n"
- "You'll need to restart your shell for changes to take effect."
- "\n"
- "\n"
- "\n"
- "{B}BASH (OSX){R}:"
- "\n"
- "\n"
- "You'll need `bash-completion` (or `bash-completion@2` if you're using non-default, newer bash) "
- "homebrew formula. Completion files are stored in `/usr/local/etc/bash_completion.d`:"
- "\n"
- "\n"
- " $ mkdir -p $(brew --prefix)/etc/bash_completion.d"
- "\n"
- " $ {command} {completion} bash >"
- "\n"
- " $(brew --prefix)/etc/bash_completion.d/{command}"
- "\n"
- "\n"
- "Alternatively, just source the script in your `~/.bash_profile`."
- "\n"
- "\n"
- "You'll need to restart your shell for changes to take effect."
- "\n"
- "\n"
- "\n"
- "{B}ZSH{R}:"
- "\n"
- "\n"
- "Zsh looks for completion scripts in any directory listed in `$fpath` variable. We recommend placing "
- "completions to `~/.zfunc`:"
- "\n"
- "\n"
- " $ mkdir -p ~/.zfunc"
- "\n"
- " $ {command} {completion} zsh > ~/.zfunc/_{command}"
- "\n"
- "\n"
- "Add the following lines to your `.zshrc` just before `compinit`:"
- "\n"
- "\n"
- " fpath+=~/.zfunc"
- "\n"
- "\n"
- "You'll need to restart your shell for changes to take effect.");
- SubstGlobal(info, "{command}", command);
- SubstGlobal(info, "{completion}", flag);
- SubstGlobal(info, "{B}", NColorizer::StdErr().LightDefault());
- SubstGlobal(info, "{R}", NColorizer::StdErr().Reset());
- return info;
- }
-
- NComp::ICompleterPtr ShellChoiceCompleter() {
- return NComp::Choice({{"zsh"}, {"bash"}});
- }
-
- TOpt MakeCompletionOpt(const TOpts* opts, TString command, TString name) {
- return TOpt()
- .AddLongName(name)
- .Help("generate tab completion script for zsh or bash")
- .CompletionHelp("generate tab completion script")
- .OptionalArgument("shell-syntax")
- .CompletionArgHelp("shell syntax for completion script")
- .IfPresentDisableCompletion()
- .Completer(ShellChoiceCompleter())
- .Handler1T<TString>([opts, command, name](TStringBuf shell) {
- if (shell.empty()) {
- Cerr << Wrap(80, MakeInfo(command, "--" + name)) << Endl;
- } else if (shell == "bash") {
- TBashCompletionGenerator(opts).Generate(command, Cout);
- } else if (shell == "zsh") {
- TZshCompletionGenerator(opts).Generate(command, Cout);
- } else {
+
+#include <util/string/subst.h>
+
+namespace NLastGetopt {
+ TString MakeInfo(TStringBuf command, TStringBuf flag) {
+ TString info = (
+ "This command generates shell script with completion function and prints it to `stdout`, "
+ "allowing one to re-direct the output to the file of their choosing. "
+ "Where you place the file will depend on which shell and operating system you are using."
+ "\n"
+ "\n"
+ "\n"
+ "{B}BASH (Linux){R}:"
+ "\n"
+ "\n"
+ "For system-wide commands, completion files are stored in `/etc/bash_completion.d/`. "
+ "For user commands, they are stored in `~/.local/share/bash-completion/completions`. "
+ "So, pipe output of this script to a file in one of these directories:"
+ "\n"
+ "\n"
+ " $ mkdir -p ~/.local/share/bash-completion/completions"
+ "\n"
+ " $ {command} {completion} bash >"
+ "\n"
+ " ~/.local/share/bash-completion/completions/{command}"
+ "\n"
+ "\n"
+ "You'll need to restart your shell for changes to take effect."
+ "\n"
+ "\n"
+ "\n"
+ "{B}BASH (OSX){R}:"
+ "\n"
+ "\n"
+ "You'll need `bash-completion` (or `bash-completion@2` if you're using non-default, newer bash) "
+ "homebrew formula. Completion files are stored in `/usr/local/etc/bash_completion.d`:"
+ "\n"
+ "\n"
+ " $ mkdir -p $(brew --prefix)/etc/bash_completion.d"
+ "\n"
+ " $ {command} {completion} bash >"
+ "\n"
+ " $(brew --prefix)/etc/bash_completion.d/{command}"
+ "\n"
+ "\n"
+ "Alternatively, just source the script in your `~/.bash_profile`."
+ "\n"
+ "\n"
+ "You'll need to restart your shell for changes to take effect."
+ "\n"
+ "\n"
+ "\n"
+ "{B}ZSH{R}:"
+ "\n"
+ "\n"
+ "Zsh looks for completion scripts in any directory listed in `$fpath` variable. We recommend placing "
+ "completions to `~/.zfunc`:"
+ "\n"
+ "\n"
+ " $ mkdir -p ~/.zfunc"
+ "\n"
+ " $ {command} {completion} zsh > ~/.zfunc/_{command}"
+ "\n"
+ "\n"
+ "Add the following lines to your `.zshrc` just before `compinit`:"
+ "\n"
+ "\n"
+ " fpath+=~/.zfunc"
+ "\n"
+ "\n"
+ "You'll need to restart your shell for changes to take effect.");
+ SubstGlobal(info, "{command}", command);
+ SubstGlobal(info, "{completion}", flag);
+ SubstGlobal(info, "{B}", NColorizer::StdErr().LightDefault());
+ SubstGlobal(info, "{R}", NColorizer::StdErr().Reset());
+ return info;
+ }
+
+ NComp::ICompleterPtr ShellChoiceCompleter() {
+ return NComp::Choice({{"zsh"}, {"bash"}});
+ }
+
+ TOpt MakeCompletionOpt(const TOpts* opts, TString command, TString name) {
+ return TOpt()
+ .AddLongName(name)
+ .Help("generate tab completion script for zsh or bash")
+ .CompletionHelp("generate tab completion script")
+ .OptionalArgument("shell-syntax")
+ .CompletionArgHelp("shell syntax for completion script")
+ .IfPresentDisableCompletion()
+ .Completer(ShellChoiceCompleter())
+ .Handler1T<TString>([opts, command, name](TStringBuf shell) {
+ if (shell.empty()) {
+ Cerr << Wrap(80, MakeInfo(command, "--" + name)) << Endl;
+ } else if (shell == "bash") {
+ TBashCompletionGenerator(opts).Generate(command, Cout);
+ } else if (shell == "zsh") {
+ TZshCompletionGenerator(opts).Generate(command, Cout);
+ } else {
Cerr << "Unknown shell name " << TString{shell}.Quote() << Endl;
- exit(1);
- }
- exit(0);
- });
- }
-
- class TCompleterMode: public TMainClassArgs {
- public:
- TCompleterMode(const TModChooser* modChooser, TString command, TString modName)
- : Command_(std::move(command))
- , Modes_(modChooser)
- , ModName_(std::move(modName))
- {
- }
-
- protected:
- void RegisterOptions(NLastGetopt::TOpts& opts) override {
- TMainClassArgs::RegisterOptions(opts);
-
- opts.SetTitle("Generate tab completion scripts for zsh or bash");
-
- opts.AddSection("Description", MakeInfo(Command_, ModName_));
-
- opts.SetFreeArgsNum(1);
- opts.GetFreeArgSpec(0)
- .Title("<shell-syntax>")
- .Help("shell syntax for completion script (bash or zsh)")
- .CompletionArgHelp("shell syntax for completion script")
- .Completer(ShellChoiceCompleter());
- }
-
- int DoRun(NLastGetopt::TOptsParseResult&& parsedOptions) override {
- auto arg = parsedOptions.GetFreeArgs()[0];
- arg.to_lower();
-
- if (arg == "bash") {
- TBashCompletionGenerator(Modes_).Generate(Command_, Cout);
- } else if (arg == "zsh") {
- TZshCompletionGenerator(Modes_).Generate(Command_, Cout);
- } else {
- Cerr << "Unknown shell name " << arg.Quote() << Endl;
- parsedOptions.PrintUsage();
- return 1;
- }
-
- return 0;
- }
-
- private:
- TString Command_;
- const TModChooser* Modes_;
- TString ModName_;
- };
-
- THolder<TMainClassArgs> MakeCompletionMod(const TModChooser* modChooser, TString command, TString modName) {
+ exit(1);
+ }
+ exit(0);
+ });
+ }
+
+ class TCompleterMode: public TMainClassArgs {
+ public:
+ TCompleterMode(const TModChooser* modChooser, TString command, TString modName)
+ : Command_(std::move(command))
+ , Modes_(modChooser)
+ , ModName_(std::move(modName))
+ {
+ }
+
+ protected:
+ void RegisterOptions(NLastGetopt::TOpts& opts) override {
+ TMainClassArgs::RegisterOptions(opts);
+
+ opts.SetTitle("Generate tab completion scripts for zsh or bash");
+
+ opts.AddSection("Description", MakeInfo(Command_, ModName_));
+
+ opts.SetFreeArgsNum(1);
+ opts.GetFreeArgSpec(0)
+ .Title("<shell-syntax>")
+ .Help("shell syntax for completion script (bash or zsh)")
+ .CompletionArgHelp("shell syntax for completion script")
+ .Completer(ShellChoiceCompleter());
+ }
+
+ int DoRun(NLastGetopt::TOptsParseResult&& parsedOptions) override {
+ auto arg = parsedOptions.GetFreeArgs()[0];
+ arg.to_lower();
+
+ if (arg == "bash") {
+ TBashCompletionGenerator(Modes_).Generate(Command_, Cout);
+ } else if (arg == "zsh") {
+ TZshCompletionGenerator(Modes_).Generate(Command_, Cout);
+ } else {
+ Cerr << "Unknown shell name " << arg.Quote() << Endl;
+ parsedOptions.PrintUsage();
+ return 1;
+ }
+
+ return 0;
+ }
+
+ private:
+ TString Command_;
+ const TModChooser* Modes_;
+ TString ModName_;
+ };
+
+ THolder<TMainClassArgs> MakeCompletionMod(const TModChooser* modChooser, TString command, TString modName) {
return MakeHolder<TCompleterMode>(modChooser, std::move(command), std::move(modName));
- }
-}
+ }
+}
diff --git a/library/cpp/getopt/small/completer_command.h b/library/cpp/getopt/small/completer_command.h
index 4aba6dbfde..974cc4617c 100644
--- a/library/cpp/getopt/small/completer_command.h
+++ b/library/cpp/getopt/small/completer_command.h
@@ -1,11 +1,11 @@
-#pragma once
-
-#include "modchooser.h"
-
-namespace NLastGetopt {
- /// Create an option that generates completion.
- TOpt MakeCompletionOpt(const TOpts* opts, TString command, TString optName = "completion");
-
- /// Create a mode that generates completion.
- THolder<TMainClassArgs> MakeCompletionMod(const TModChooser* modChooser, TString command, TString modName = "completion");
-}
+#pragma once
+
+#include "modchooser.h"
+
+namespace NLastGetopt {
+ /// Create an option that generates completion.
+ TOpt MakeCompletionOpt(const TOpts* opts, TString command, TString optName = "completion");
+
+ /// Create a mode that generates completion.
+ THolder<TMainClassArgs> MakeCompletionMod(const TModChooser* modChooser, TString command, TString modName = "completion");
+}
diff --git a/library/cpp/getopt/small/completion_generator.cpp b/library/cpp/getopt/small/completion_generator.cpp
index 0ff83e1c07..ac41988217 100644
--- a/library/cpp/getopt/small/completion_generator.cpp
+++ b/library/cpp/getopt/small/completion_generator.cpp
@@ -1,791 +1,791 @@
-#include "completion_generator.h"
-
+#include "completion_generator.h"
+
#include <util/generic/overloaded.h>
-
-#include <util/string/ascii.h>
-#include <util/generic/hash_set.h>
-
-#include "last_getopt_parse_result.h"
-
-using NLastGetopt::NEscaping::Q;
-using NLastGetopt::NEscaping::QQ;
-using NLastGetopt::NEscaping::C;
-using NLastGetopt::NEscaping::CC;
-using NLastGetopt::NEscaping::S;
-using NLastGetopt::NEscaping::SS;
-using NLastGetopt::NEscaping::B;
-using NLastGetopt::NEscaping::BB;
-
-namespace NLastGetopt {
-
-#define L out.Line()
-#define I auto Y_GENERATE_UNIQUE_ID(indent) = out.Indent()
-
- TCompletionGenerator::TCompletionGenerator(const TModChooser* modChooser)
- : Options_(modChooser)
- {
- Y_VERIFY(modChooser != nullptr);
- }
-
- TCompletionGenerator::TCompletionGenerator(const TOpts* opts)
- : Options_(opts)
- {
- Y_VERIFY(opts != nullptr);
- }
-
- void TZshCompletionGenerator::Generate(TStringBuf command, IOutputStream& stream) {
- TFormattedOutput out;
- NComp::TCompleterManager manager{command};
-
- L << "#compdef " << command;
- L;
- L << "_" << command << "() {";
- {
- I;
- L << "local state line desc modes context curcontext=\"$curcontext\" ret=1";
- L << "local words_orig=(\"${words[@]}\")";
- L << "local current_orig=\"$((CURRENT - 1))\"";
- L << "local prefix_orig=\"$PREFIX\"";
- L << "local suffix_orig=\"$SUFFIX\"";
- L;
+
+#include <util/string/ascii.h>
+#include <util/generic/hash_set.h>
+
+#include "last_getopt_parse_result.h"
+
+using NLastGetopt::NEscaping::Q;
+using NLastGetopt::NEscaping::QQ;
+using NLastGetopt::NEscaping::C;
+using NLastGetopt::NEscaping::CC;
+using NLastGetopt::NEscaping::S;
+using NLastGetopt::NEscaping::SS;
+using NLastGetopt::NEscaping::B;
+using NLastGetopt::NEscaping::BB;
+
+namespace NLastGetopt {
+
+#define L out.Line()
+#define I auto Y_GENERATE_UNIQUE_ID(indent) = out.Indent()
+
+ TCompletionGenerator::TCompletionGenerator(const TModChooser* modChooser)
+ : Options_(modChooser)
+ {
+ Y_VERIFY(modChooser != nullptr);
+ }
+
+ TCompletionGenerator::TCompletionGenerator(const TOpts* opts)
+ : Options_(opts)
+ {
+ Y_VERIFY(opts != nullptr);
+ }
+
+ void TZshCompletionGenerator::Generate(TStringBuf command, IOutputStream& stream) {
+ TFormattedOutput out;
+ NComp::TCompleterManager manager{command};
+
+ L << "#compdef " << command;
+ L;
+ L << "_" << command << "() {";
+ {
+ I;
+ L << "local state line desc modes context curcontext=\"$curcontext\" ret=1";
+ L << "local words_orig=(\"${words[@]}\")";
+ L << "local current_orig=\"$((CURRENT - 1))\"";
+ L << "local prefix_orig=\"$PREFIX\"";
+ L << "local suffix_orig=\"$SUFFIX\"";
+ L;
std::visit(TOverloaded{
- [&out, &manager](const TModChooser* modChooser) {
- GenerateModesCompletion(out, *modChooser, manager);
- },
- [&out, &manager](const TOpts* opts) {
- GenerateOptsCompletion(out, *opts, manager);
- }
- }, Options_);
- L;
- L << "return ret";
- }
- L << "}";
- L;
- manager.GenerateZsh(out);
-
- out.Print(stream);
- }
-
- void TZshCompletionGenerator::GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager) {
- auto modes = chooser.GetUnsortedModes();
-
- L << "_arguments -C \\";
- L << " '(- : *)'{-h,--help}'[show help information]' \\";
- if (chooser.GetVersionHandler() != nullptr) {
- L << " '(- : *)'{-v,--version}'[display version information]' \\";
- }
- if (!chooser.IsSvnRevisionOptionDisabled()) {
- L << " '(- : *)--svnrevision[show build information]' \\";
- }
- L << " '(-v --version -h --help --svnrevision)1: :->modes' \\";
- L << " '(-v --version -h --help --svnrevision)*:: :->args' \\";
- L << " && ret=0";
- L;
- L << "case $state in";
- {
- I;
-
- L << "modes)";
- {
- I;
-
- size_t tag = 0;
- bool empty = true;
-
- L << "desc='modes'";
- L << "modes=(";
- for (auto& mode : modes) {
- if (mode->Hidden) {
- continue;
- }
- if (!mode->Name.empty()) {
- I;
- if (!mode->Description.empty()) {
- L << QQ(mode->Name) << ":" << QQ(mode->Description);
- } else {
- L << QQ(mode->Name);
- }
- empty = false;
- } else {
- L << ")";
- if (!empty) {
- L << "_describe -t 'mode-group-" << tag << "' $desc modes";
- }
- L;
- if (mode->Description.empty()) {
- L << "desc='modes'";
- } else {
- L << "desc=" << SS(mode->Description);
- }
- L << "modes=(";
- empty = true;
- ++tag;
- }
- }
- L << ")";
- if (!empty) {
- L << "_describe -t 'mode-group-" << tag << "' $desc modes";
- }
- L;
-
- L << ";;";
- }
-
- L << "args)";
- {
- I;
-
- L << "case $line[1] in";
- {
- I;
-
- for (auto& mode : modes) {
- if (mode->Name.empty() || mode->Hidden) {
- continue;
- }
-
- auto& line = L << SS(mode->Name);
- for (auto& alias : mode->Aliases) {
- line << "|" << SS(alias);
- }
- line << ")";
-
- {
- I;
-
- if (auto mainArgs = dynamic_cast<TMainClassArgs*>(mode->Main)) {
- GenerateOptsCompletion(out, mainArgs->GetOptions(), manager);
- } else if (auto mainModes = dynamic_cast<TMainClassModes*>(mode->Main)) {
- GenerateModesCompletion(out, mainModes->GetSubModes(), manager);
- } else {
- GenerateDefaultOptsCompletion(out, manager);
- }
-
- L << ";;";
- }
- }
- }
- L << "esac";
- L << ";;";
- }
- }
- L << "esac";
- }
-
- void TZshCompletionGenerator::GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager& manager) {
- L << "_arguments -s \\";
- {
- I;
-
- if (opts.ArgPermutation_ == EArgPermutation::REQUIRE_ORDER) {
- L << "-S \\";
- }
-
- for (auto opt: opts.GetOpts()) {
- if (!opt->Hidden_) {
- GenerateOptCompletion(out, opts, *opt, manager);
- }
- }
-
- auto argSpecs = opts.GetFreeArgSpecs();
- size_t numFreeArgs = opts.GetFreeArgsMax();
- bool unlimitedArgs = false;
- if (numFreeArgs == TOpts::UNLIMITED_ARGS) {
- numFreeArgs = argSpecs.empty() ? 0 : (argSpecs.rbegin()->first + 1);
- unlimitedArgs = true;
- }
-
- for (size_t i = 0; i < numFreeArgs; ++i) {
- auto& spec = argSpecs[i];
- auto& line = L << "'" << (i + 1) << ":";
- if (spec.IsOptional()) {
- line << ":";
- }
- auto argHelp = spec.GetCompletionArgHelp(opts.GetDefaultFreeArgTitle());
- if (argHelp) {
- line << Q(argHelp);
- } else {
- line << " ";
- }
- line << ":";
- if (spec.Completer_) {
- line << spec.Completer_->GenerateZshAction(manager);
- } else {
- line << "_default";
- }
- line << "' \\";
- }
-
- if (unlimitedArgs) {
- auto& spec = opts.GetTrailingArgSpec();
- auto& line = L << "'*:";
- auto argHelp = spec.GetCompletionArgHelp(opts.GetDefaultFreeArgTitle());
- if (argHelp) {
- line << Q(argHelp);
- } else {
- line << " ";
- }
- line << ":";
- if (spec.Completer_) {
- line << spec.Completer_->GenerateZshAction(manager);
- } else {
- line << "_default";
- }
- line << "' \\";
- }
-
- L << "&& ret=0";
- }
- }
-
- void TZshCompletionGenerator::GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager&) {
- L << "_arguments \\";
- L << " '(- *)'{-h,--help}'[show help information]' \\";
- L << " '(- *)--svnrevision[show build information]' \\";
- L << " '(-h --help --svnrevision)*: :_files' \\";
- L << " && ret=0";
- }
-
- void TZshCompletionGenerator::GenerateOptCompletion(TFormattedOutput& out, const TOpts& opts, const TOpt& opt, NComp::TCompleterManager& manager) {
- auto& line = L;
-
- THashSet<TString> disableOptions;
- if (opt.DisableCompletionForOptions_) {
- disableOptions.insert("-");
- } else {
- if (!opt.AllowMultipleCompletion_) {
- for (auto shortName: opt.GetShortNames()) {
- disableOptions.insert(TString("-") + shortName);
- }
- for (auto& longName: opt.GetLongNames()) {
- disableOptions.insert("--" + longName);
- }
- }
- for (auto disabledShortName : opt.DisableCompletionForChar_) {
- auto disabledOpt = opts.FindCharOption(disabledShortName);
- if (disabledOpt) {
- for (auto shortName: disabledOpt->GetShortNames()) {
- disableOptions.insert(TString("-") + shortName);
- }
- for (auto& longName: disabledOpt->GetLongNames()) {
- disableOptions.insert("--" + longName);
- }
- } else {
- disableOptions.insert(TString("-") + disabledShortName);
- }
- }
- for (auto& disabledLongName : opt.DisableCompletionForLongName_) {
- auto disabledOpt = opts.FindLongOption(disabledLongName);
- if (disabledOpt) {
- for (auto shortName: disabledOpt->GetShortNames()) {
- disableOptions.insert(TString("-") + shortName);
- }
- for (auto& longName: disabledOpt->GetLongNames()) {
- disableOptions.insert("--" + longName);
- }
- } else {
- disableOptions.insert("--" + disabledLongName);
- }
- }
- }
- if (opt.DisableCompletionForFreeArgs_) {
- disableOptions.insert(":");
- disableOptions.insert("*");
- } else {
- for (auto i : opt.DisableCompletionForFreeArg_) {
- disableOptions.insert(ToString(i + 1));
- }
- }
-
- TStringBuf sep = "";
-
- if (!disableOptions.empty()) {
- line << "'(";
- for (auto& disableOption : disableOptions) {
- line << sep << disableOption;
- sep = " ";
- }
- line << ")";
- }
-
- sep = "";
- TStringBuf mul = "";
- TStringBuf quot = "";
-
- if (opt.GetShortNames().size() + opt.GetLongNames().size() > 1) {
- if (!disableOptions.empty()) {
- line << "'";
- }
- line << "{";
- quot = "'";
- } else {
- if (disableOptions.empty()) {
- line << "'";
- }
- }
-
- if (opt.AllowMultipleCompletion_) {
- mul = "*";
- }
-
- for (auto& flag : opt.GetShortNames()) {
- line << sep << quot << mul << "-" << Q(TStringBuf(&flag, 1)) << quot;
- sep = ",";
- }
-
- for (auto& flag : opt.GetLongNames()) {
- line << sep << quot << mul << "--" << Q(flag) << quot;
- sep = ",";
- }
-
- if (opt.GetShortNames().size() + opt.GetLongNames().size() > 1) {
- line << "}'";
- }
-
- if (opt.GetCompletionHelp()) {
- line << "[";
- line << Q(opt.GetCompletionHelp());
- line << "]";
- }
-
- if (opt.HasArg_ != EHasArg::NO_ARGUMENT) {
- if (opt.HasArg_ == EHasArg::OPTIONAL_ARGUMENT) {
- line << ":";
- }
-
- line << ":";
-
- if (opt.GetCompletionArgHelp()) {
- line << C(opt.GetCompletionArgHelp());
- } else {
- line << " ";
- }
-
- line << ":";
-
- if (opt.Completer_) {
- line << C(opt.Completer_->GenerateZshAction(manager));
- } else {
- line << "_default";
- }
- }
-
- line << "' \\";
- }
-
- void TBashCompletionGenerator::Generate(TStringBuf command, IOutputStream& stream) {
- TFormattedOutput out;
- NComp::TCompleterManager manager{command};
-
- L << "_" << command << "() {";
- {
- I;
- L << "COMPREPLY=()";
- L;
- L << "local i args opts items candidates";
- L;
- L << "local cur prev words cword";
- L << "_get_comp_words_by_ref -n \"\\\"'><=;|&(:\" cur prev words cword";
- L;
- L << "local need_space=\"1\"";
- L << "local IFS=$' \\t\\n'";
- L;
+ [&out, &manager](const TModChooser* modChooser) {
+ GenerateModesCompletion(out, *modChooser, manager);
+ },
+ [&out, &manager](const TOpts* opts) {
+ GenerateOptsCompletion(out, *opts, manager);
+ }
+ }, Options_);
+ L;
+ L << "return ret";
+ }
+ L << "}";
+ L;
+ manager.GenerateZsh(out);
+
+ out.Print(stream);
+ }
+
+ void TZshCompletionGenerator::GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager) {
+ auto modes = chooser.GetUnsortedModes();
+
+ L << "_arguments -C \\";
+ L << " '(- : *)'{-h,--help}'[show help information]' \\";
+ if (chooser.GetVersionHandler() != nullptr) {
+ L << " '(- : *)'{-v,--version}'[display version information]' \\";
+ }
+ if (!chooser.IsSvnRevisionOptionDisabled()) {
+ L << " '(- : *)--svnrevision[show build information]' \\";
+ }
+ L << " '(-v --version -h --help --svnrevision)1: :->modes' \\";
+ L << " '(-v --version -h --help --svnrevision)*:: :->args' \\";
+ L << " && ret=0";
+ L;
+ L << "case $state in";
+ {
+ I;
+
+ L << "modes)";
+ {
+ I;
+
+ size_t tag = 0;
+ bool empty = true;
+
+ L << "desc='modes'";
+ L << "modes=(";
+ for (auto& mode : modes) {
+ if (mode->Hidden) {
+ continue;
+ }
+ if (!mode->Name.empty()) {
+ I;
+ if (!mode->Description.empty()) {
+ L << QQ(mode->Name) << ":" << QQ(mode->Description);
+ } else {
+ L << QQ(mode->Name);
+ }
+ empty = false;
+ } else {
+ L << ")";
+ if (!empty) {
+ L << "_describe -t 'mode-group-" << tag << "' $desc modes";
+ }
+ L;
+ if (mode->Description.empty()) {
+ L << "desc='modes'";
+ } else {
+ L << "desc=" << SS(mode->Description);
+ }
+ L << "modes=(";
+ empty = true;
+ ++tag;
+ }
+ }
+ L << ")";
+ if (!empty) {
+ L << "_describe -t 'mode-group-" << tag << "' $desc modes";
+ }
+ L;
+
+ L << ";;";
+ }
+
+ L << "args)";
+ {
+ I;
+
+ L << "case $line[1] in";
+ {
+ I;
+
+ for (auto& mode : modes) {
+ if (mode->Name.empty() || mode->Hidden) {
+ continue;
+ }
+
+ auto& line = L << SS(mode->Name);
+ for (auto& alias : mode->Aliases) {
+ line << "|" << SS(alias);
+ }
+ line << ")";
+
+ {
+ I;
+
+ if (auto mainArgs = dynamic_cast<TMainClassArgs*>(mode->Main)) {
+ GenerateOptsCompletion(out, mainArgs->GetOptions(), manager);
+ } else if (auto mainModes = dynamic_cast<TMainClassModes*>(mode->Main)) {
+ GenerateModesCompletion(out, mainModes->GetSubModes(), manager);
+ } else {
+ GenerateDefaultOptsCompletion(out, manager);
+ }
+
+ L << ";;";
+ }
+ }
+ }
+ L << "esac";
+ L << ";;";
+ }
+ }
+ L << "esac";
+ }
+
+ void TZshCompletionGenerator::GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager& manager) {
+ L << "_arguments -s \\";
+ {
+ I;
+
+ if (opts.ArgPermutation_ == EArgPermutation::REQUIRE_ORDER) {
+ L << "-S \\";
+ }
+
+ for (auto opt: opts.GetOpts()) {
+ if (!opt->Hidden_) {
+ GenerateOptCompletion(out, opts, *opt, manager);
+ }
+ }
+
+ auto argSpecs = opts.GetFreeArgSpecs();
+ size_t numFreeArgs = opts.GetFreeArgsMax();
+ bool unlimitedArgs = false;
+ if (numFreeArgs == TOpts::UNLIMITED_ARGS) {
+ numFreeArgs = argSpecs.empty() ? 0 : (argSpecs.rbegin()->first + 1);
+ unlimitedArgs = true;
+ }
+
+ for (size_t i = 0; i < numFreeArgs; ++i) {
+ auto& spec = argSpecs[i];
+ auto& line = L << "'" << (i + 1) << ":";
+ if (spec.IsOptional()) {
+ line << ":";
+ }
+ auto argHelp = spec.GetCompletionArgHelp(opts.GetDefaultFreeArgTitle());
+ if (argHelp) {
+ line << Q(argHelp);
+ } else {
+ line << " ";
+ }
+ line << ":";
+ if (spec.Completer_) {
+ line << spec.Completer_->GenerateZshAction(manager);
+ } else {
+ line << "_default";
+ }
+ line << "' \\";
+ }
+
+ if (unlimitedArgs) {
+ auto& spec = opts.GetTrailingArgSpec();
+ auto& line = L << "'*:";
+ auto argHelp = spec.GetCompletionArgHelp(opts.GetDefaultFreeArgTitle());
+ if (argHelp) {
+ line << Q(argHelp);
+ } else {
+ line << " ";
+ }
+ line << ":";
+ if (spec.Completer_) {
+ line << spec.Completer_->GenerateZshAction(manager);
+ } else {
+ line << "_default";
+ }
+ line << "' \\";
+ }
+
+ L << "&& ret=0";
+ }
+ }
+
+ void TZshCompletionGenerator::GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager&) {
+ L << "_arguments \\";
+ L << " '(- *)'{-h,--help}'[show help information]' \\";
+ L << " '(- *)--svnrevision[show build information]' \\";
+ L << " '(-h --help --svnrevision)*: :_files' \\";
+ L << " && ret=0";
+ }
+
+ void TZshCompletionGenerator::GenerateOptCompletion(TFormattedOutput& out, const TOpts& opts, const TOpt& opt, NComp::TCompleterManager& manager) {
+ auto& line = L;
+
+ THashSet<TString> disableOptions;
+ if (opt.DisableCompletionForOptions_) {
+ disableOptions.insert("-");
+ } else {
+ if (!opt.AllowMultipleCompletion_) {
+ for (auto shortName: opt.GetShortNames()) {
+ disableOptions.insert(TString("-") + shortName);
+ }
+ for (auto& longName: opt.GetLongNames()) {
+ disableOptions.insert("--" + longName);
+ }
+ }
+ for (auto disabledShortName : opt.DisableCompletionForChar_) {
+ auto disabledOpt = opts.FindCharOption(disabledShortName);
+ if (disabledOpt) {
+ for (auto shortName: disabledOpt->GetShortNames()) {
+ disableOptions.insert(TString("-") + shortName);
+ }
+ for (auto& longName: disabledOpt->GetLongNames()) {
+ disableOptions.insert("--" + longName);
+ }
+ } else {
+ disableOptions.insert(TString("-") + disabledShortName);
+ }
+ }
+ for (auto& disabledLongName : opt.DisableCompletionForLongName_) {
+ auto disabledOpt = opts.FindLongOption(disabledLongName);
+ if (disabledOpt) {
+ for (auto shortName: disabledOpt->GetShortNames()) {
+ disableOptions.insert(TString("-") + shortName);
+ }
+ for (auto& longName: disabledOpt->GetLongNames()) {
+ disableOptions.insert("--" + longName);
+ }
+ } else {
+ disableOptions.insert("--" + disabledLongName);
+ }
+ }
+ }
+ if (opt.DisableCompletionForFreeArgs_) {
+ disableOptions.insert(":");
+ disableOptions.insert("*");
+ } else {
+ for (auto i : opt.DisableCompletionForFreeArg_) {
+ disableOptions.insert(ToString(i + 1));
+ }
+ }
+
+ TStringBuf sep = "";
+
+ if (!disableOptions.empty()) {
+ line << "'(";
+ for (auto& disableOption : disableOptions) {
+ line << sep << disableOption;
+ sep = " ";
+ }
+ line << ")";
+ }
+
+ sep = "";
+ TStringBuf mul = "";
+ TStringBuf quot = "";
+
+ if (opt.GetShortNames().size() + opt.GetLongNames().size() > 1) {
+ if (!disableOptions.empty()) {
+ line << "'";
+ }
+ line << "{";
+ quot = "'";
+ } else {
+ if (disableOptions.empty()) {
+ line << "'";
+ }
+ }
+
+ if (opt.AllowMultipleCompletion_) {
+ mul = "*";
+ }
+
+ for (auto& flag : opt.GetShortNames()) {
+ line << sep << quot << mul << "-" << Q(TStringBuf(&flag, 1)) << quot;
+ sep = ",";
+ }
+
+ for (auto& flag : opt.GetLongNames()) {
+ line << sep << quot << mul << "--" << Q(flag) << quot;
+ sep = ",";
+ }
+
+ if (opt.GetShortNames().size() + opt.GetLongNames().size() > 1) {
+ line << "}'";
+ }
+
+ if (opt.GetCompletionHelp()) {
+ line << "[";
+ line << Q(opt.GetCompletionHelp());
+ line << "]";
+ }
+
+ if (opt.HasArg_ != EHasArg::NO_ARGUMENT) {
+ if (opt.HasArg_ == EHasArg::OPTIONAL_ARGUMENT) {
+ line << ":";
+ }
+
+ line << ":";
+
+ if (opt.GetCompletionArgHelp()) {
+ line << C(opt.GetCompletionArgHelp());
+ } else {
+ line << " ";
+ }
+
+ line << ":";
+
+ if (opt.Completer_) {
+ line << C(opt.Completer_->GenerateZshAction(manager));
+ } else {
+ line << "_default";
+ }
+ }
+
+ line << "' \\";
+ }
+
+ void TBashCompletionGenerator::Generate(TStringBuf command, IOutputStream& stream) {
+ TFormattedOutput out;
+ NComp::TCompleterManager manager{command};
+
+ L << "_" << command << "() {";
+ {
+ I;
+ L << "COMPREPLY=()";
+ L;
+ L << "local i args opts items candidates";
+ L;
+ L << "local cur prev words cword";
+ L << "_get_comp_words_by_ref -n \"\\\"'><=;|&(:\" cur prev words cword";
+ L;
+ L << "local need_space=\"1\"";
+ L << "local IFS=$' \\t\\n'";
+ L;
std::visit(TOverloaded{
- [&out, &manager](const TModChooser* modChooser) {
- GenerateModesCompletion(out, *modChooser, manager, 1);
- },
- [&out, &manager](const TOpts* opts) {
- GenerateOptsCompletion(out, *opts, manager, 1);
- }
- }, Options_);
- L;
- L;
- L << "__ltrim_colon_completions \"$cur\"";
- L;
- L << "IFS=$'\\n'";
- L << "if [ ${#COMPREPLY[@]} -ne 0 ]; then";
- {
- I;
- L << "if [[ -z $need_space ]]; then";
- {
- I;
- L << "COMPREPLY=( $(printf \"%q\\n\" \"${COMPREPLY[@]}\") )";
- }
- L << "else";
- {
- I;
- L << "COMPREPLY=( $(printf \"%q \\n\" \"${COMPREPLY[@]}\") )";
- }
- L << "fi";
- }
- L << "fi";
- L;
- L << "return 0";
- }
- L << "}";
- L;
- L << "complete -o nospace -o default -F _" << command << " " << command;
-
- out.Print(stream);
- }
-
- void TBashCompletionGenerator::GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager, size_t level) {
- auto modes = chooser.GetUnsortedModes();
-
- L << "if [[ ${cword} == " << level << " ]] ; then";
- {
- I;
- L << "if [[ ${cur} == -* ]] ; then";
- {
- I;
- auto& line = L << "COMPREPLY+=( $(compgen -W '-h --help";
- if (chooser.GetVersionHandler() != nullptr) {
- line << " -v --version";
- }
- if (!chooser.IsSvnRevisionOptionDisabled()) {
- line << " --svnrevision";
- }
- line << "' -- ${cur}) )";
- }
- L << "else";
- {
- I;
- auto& line = L << "COMPREPLY+=( $(compgen -W '";
- TStringBuf sep = "";
- for (auto& mode : modes) {
+ [&out, &manager](const TModChooser* modChooser) {
+ GenerateModesCompletion(out, *modChooser, manager, 1);
+ },
+ [&out, &manager](const TOpts* opts) {
+ GenerateOptsCompletion(out, *opts, manager, 1);
+ }
+ }, Options_);
+ L;
+ L;
+ L << "__ltrim_colon_completions \"$cur\"";
+ L;
+ L << "IFS=$'\\n'";
+ L << "if [ ${#COMPREPLY[@]} -ne 0 ]; then";
+ {
+ I;
+ L << "if [[ -z $need_space ]]; then";
+ {
+ I;
+ L << "COMPREPLY=( $(printf \"%q\\n\" \"${COMPREPLY[@]}\") )";
+ }
+ L << "else";
+ {
+ I;
+ L << "COMPREPLY=( $(printf \"%q \\n\" \"${COMPREPLY[@]}\") )";
+ }
+ L << "fi";
+ }
+ L << "fi";
+ L;
+ L << "return 0";
+ }
+ L << "}";
+ L;
+ L << "complete -o nospace -o default -F _" << command << " " << command;
+
+ out.Print(stream);
+ }
+
+ void TBashCompletionGenerator::GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager, size_t level) {
+ auto modes = chooser.GetUnsortedModes();
+
+ L << "if [[ ${cword} == " << level << " ]] ; then";
+ {
+ I;
+ L << "if [[ ${cur} == -* ]] ; then";
+ {
+ I;
+ auto& line = L << "COMPREPLY+=( $(compgen -W '-h --help";
+ if (chooser.GetVersionHandler() != nullptr) {
+ line << " -v --version";
+ }
+ if (!chooser.IsSvnRevisionOptionDisabled()) {
+ line << " --svnrevision";
+ }
+ line << "' -- ${cur}) )";
+ }
+ L << "else";
+ {
+ I;
+ auto& line = L << "COMPREPLY+=( $(compgen -W '";
+ TStringBuf sep = "";
+ for (auto& mode : modes) {
if (!mode->Hidden && !mode->NoCompletion) {
line << sep << B(mode->Name);
sep = " ";
}
- }
- line << "' -- ${cur}) )";
- }
- L << "fi";
- }
- L << "else";
- {
- I;
- L << "case \"${words[" << level << "]}\" in";
- {
- I;
-
- for (auto& mode : modes) {
+ }
+ line << "' -- ${cur}) )";
+ }
+ L << "fi";
+ }
+ L << "else";
+ {
+ I;
+ L << "case \"${words[" << level << "]}\" in";
+ {
+ I;
+
+ for (auto& mode : modes) {
if (mode->Name.empty() || mode->Hidden || mode->NoCompletion) {
- continue;
- }
-
- auto& line = L << BB(mode->Name);
- for (auto& alias : mode->Aliases) {
- line << "|" << BB(alias);
- }
- line << ")";
-
- {
- I;
-
- if (auto mainArgs = dynamic_cast<TMainClassArgs*>(mode->Main)) {
- GenerateOptsCompletion(out, mainArgs->GetOptions(), manager, level + 1);
- } else if (auto mainModes = dynamic_cast<TMainClassModes*>(mode->Main)) {
- GenerateModesCompletion(out, mainModes->GetSubModes(), manager, level + 1);
- } else {
- GenerateDefaultOptsCompletion(out, manager);
- }
-
- L << ";;";
- }
- }
- }
- L << "esac";
- }
- L << "fi";
- }
-
- void TBashCompletionGenerator::GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager&, size_t level) {
- auto unorderedOpts = opts.GetOpts();
-
- L << "if [[ ${cur} == -* ]] ; then";
- {
- I;
- auto& line = L << "COMPREPLY+=( $(compgen -W '";
- TStringBuf sep = "";
- for (auto& opt : unorderedOpts) {
+ continue;
+ }
+
+ auto& line = L << BB(mode->Name);
+ for (auto& alias : mode->Aliases) {
+ line << "|" << BB(alias);
+ }
+ line << ")";
+
+ {
+ I;
+
+ if (auto mainArgs = dynamic_cast<TMainClassArgs*>(mode->Main)) {
+ GenerateOptsCompletion(out, mainArgs->GetOptions(), manager, level + 1);
+ } else if (auto mainModes = dynamic_cast<TMainClassModes*>(mode->Main)) {
+ GenerateModesCompletion(out, mainModes->GetSubModes(), manager, level + 1);
+ } else {
+ GenerateDefaultOptsCompletion(out, manager);
+ }
+
+ L << ";;";
+ }
+ }
+ }
+ L << "esac";
+ }
+ L << "fi";
+ }
+
+ void TBashCompletionGenerator::GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager&, size_t level) {
+ auto unorderedOpts = opts.GetOpts();
+
+ L << "if [[ ${cur} == -* ]] ; then";
+ {
+ I;
+ auto& line = L << "COMPREPLY+=( $(compgen -W '";
+ TStringBuf sep = "";
+ for (auto& opt : unorderedOpts) {
if (opt->IsHidden()) {
continue;
}
- for (auto& shortName : opt->GetShortNames()) {
- line << sep << "-" << B(TStringBuf(&shortName, 1));
- sep = " ";
- }
- for (auto& longName: opt->GetLongNames()) {
- line << sep << "--" << B(longName);
- sep = " ";
- }
- }
- line << "' -- ${cur}) )";
- }
- L << "else";
- {
- I;
- L << "case ${prev} in";
- {
- I;
- for (auto& opt : unorderedOpts) {
+ for (auto& shortName : opt->GetShortNames()) {
+ line << sep << "-" << B(TStringBuf(&shortName, 1));
+ sep = " ";
+ }
+ for (auto& longName: opt->GetLongNames()) {
+ line << sep << "--" << B(longName);
+ sep = " ";
+ }
+ }
+ line << "' -- ${cur}) )";
+ }
+ L << "else";
+ {
+ I;
+ L << "case ${prev} in";
+ {
+ I;
+ for (auto& opt : unorderedOpts) {
if (opt->HasArg_ == EHasArg::NO_ARGUMENT || opt->IsHidden()) {
- continue;
- }
-
- auto& line = L;
- TStringBuf sep = "";
- for (auto& shortName : opt->GetShortNames()) {
- line << sep << "'-" << B(TStringBuf(&shortName, 1)) << "'";
- sep = "|";
- }
- for (auto& longName: opt->GetLongNames()) {
- line << sep << "'--" << B(longName) << "'";
- sep = "|";
- }
- line << ")";
- {
- I;
- if (opt->Completer_ != nullptr) {
- opt->Completer_->GenerateBash(out);
- }
- L << ";;";
- }
- }
-
- L << "*)";
- {
- I;
-
- L << "args=0";
- auto& line = L << "opts='@(";
- TStringBuf sep = "";
- for (auto& opt : unorderedOpts) {
+ continue;
+ }
+
+ auto& line = L;
+ TStringBuf sep = "";
+ for (auto& shortName : opt->GetShortNames()) {
+ line << sep << "'-" << B(TStringBuf(&shortName, 1)) << "'";
+ sep = "|";
+ }
+ for (auto& longName: opt->GetLongNames()) {
+ line << sep << "'--" << B(longName) << "'";
+ sep = "|";
+ }
+ line << ")";
+ {
+ I;
+ if (opt->Completer_ != nullptr) {
+ opt->Completer_->GenerateBash(out);
+ }
+ L << ";;";
+ }
+ }
+
+ L << "*)";
+ {
+ I;
+
+ L << "args=0";
+ auto& line = L << "opts='@(";
+ TStringBuf sep = "";
+ for (auto& opt : unorderedOpts) {
if (opt->HasArg_ == EHasArg::NO_ARGUMENT || opt->IsHidden()) {
- continue;
- }
- for (auto& shortName : opt->GetShortNames()) {
- line << sep << "-" << B(TStringBuf(&shortName, 1));
- sep = "|";
- }
- for (auto& longName: opt->GetLongNames()) {
- line << sep << "--" << B(longName);
- sep = "|";
- }
- }
- line << ")'";
- L << "for (( i=" << level << "; i < cword; i++ )); do";
- {
- I;
- L << "if [[ ${words[i]} != -* && ${words[i-1]} != $opts ]]; then";
- {
- I;
- L << "(( args++ ))";
- }
- L << "fi";
- }
- L << "done";
- L;
-
- auto argSpecs = opts.GetFreeArgSpecs();
- size_t numFreeArgs = opts.GetFreeArgsMax();
- bool unlimitedArgs = false;
- if (numFreeArgs == TOpts::UNLIMITED_ARGS) {
- numFreeArgs = argSpecs.empty() ? 0 : (argSpecs.rbegin()->first + 1);
- unlimitedArgs = true;
- }
-
- L << "case ${args} in";
- {
- I;
-
- for (size_t i = 0; i < numFreeArgs; ++i) {
- L << i << ")";
- {
- I;
- auto& spec = argSpecs[i];
- if (spec.Completer_ != nullptr) {
- spec.Completer_->GenerateBash(out);
- }
- L << ";;";
- }
- }
- if (unlimitedArgs) {
- L << "*)";
- {
- I;
- auto& spec = opts.GetTrailingArgSpec();
- if (spec.Completer_ != nullptr) {
- spec.Completer_->GenerateBash(out);
- }
- L << ";;";
- }
- }
- }
- L << "esac";
- L << ";;";
- }
- }
- L << "esac";
- }
- L << "fi";
- }
-
- void TBashCompletionGenerator::GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager&) {
- L << "if [[ ${cur} == -* ]] ; then";
- {
- I;
- L << "COMPREPLY+=( $(compgen -W '-h --help --svnrevision' -- ${cur}) )";
- }
- L << "fi";
- }
-
-#undef I
-#undef L
-
- TString NEscaping::Q(TStringBuf string) {
- TStringBuilder out;
- out.reserve(string.size());
- for (auto c: string) {
- switch (c) {
- case '\a':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- out << " ";
- break;
- case '\\':
- out << "\\\\";
- break;
- case '\'':
- out << "''";
- break;
- case '\"':
- out << "\\\"";
- break;
- case '[':
- out << "\\[";
- break;
- case ']':
- out << "\\]";
- break;
- case ':':
- out << "\\:";
- break;
- case '+':
- out << "\\+";
- break;
- case '=':
- out << "\\=";
- break;
- default:
- out << c;
- break;
- }
- }
- return out;
- }
-
- TString NEscaping::QQ(TStringBuf string) {
- auto q = Q(string);
- return "'" + q + "'";
- }
-
- TString NEscaping::C(TStringBuf string) {
- TStringBuilder out;
- out.reserve(string.size() + 1);
- for (auto c: string) {
- switch (c) {
- case '\a':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- out << " ";
- break;
- case '\'':
- out << "''";
- break;
- case ':':
- out << "\\:";
- break;
- default:
- out << c;
- break;
- }
- }
- return out;
- }
-
- TString NEscaping::CC(TStringBuf string) {
- auto c = C(string);
- return "'" + c + "'";
- }
-
- TString NEscaping::S(TStringBuf string) {
- TStringBuilder out;
- out.reserve(string.size() + 1);
- for (auto c: string) {
- switch (c) {
- case '\a':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- out << " ";
- break;
- case '\'':
- out << "''";
- break;
- default:
- out << c;
- break;
- }
- }
- return out;
- }
-
- TString NEscaping::SS(TStringBuf string) {
- auto s = S(string);
- return "'" + s + "'";
- }
-
- TString NEscaping::B(TStringBuf string) {
- TStringBuilder out;
- out.reserve(string.size() + 1);
- for (auto c: string) {
- switch (c) {
- case '\a':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- out << " ";
- break;
- case '\'':
- out << "'\"'\"'";
- break;
- default:
- out << c;
- break;
- }
- }
- return out;
- }
-
- TString NEscaping::BB(TStringBuf string) {
- auto b = B(string);
- return "'" + b + "'";
- }
-}
+ continue;
+ }
+ for (auto& shortName : opt->GetShortNames()) {
+ line << sep << "-" << B(TStringBuf(&shortName, 1));
+ sep = "|";
+ }
+ for (auto& longName: opt->GetLongNames()) {
+ line << sep << "--" << B(longName);
+ sep = "|";
+ }
+ }
+ line << ")'";
+ L << "for (( i=" << level << "; i < cword; i++ )); do";
+ {
+ I;
+ L << "if [[ ${words[i]} != -* && ${words[i-1]} != $opts ]]; then";
+ {
+ I;
+ L << "(( args++ ))";
+ }
+ L << "fi";
+ }
+ L << "done";
+ L;
+
+ auto argSpecs = opts.GetFreeArgSpecs();
+ size_t numFreeArgs = opts.GetFreeArgsMax();
+ bool unlimitedArgs = false;
+ if (numFreeArgs == TOpts::UNLIMITED_ARGS) {
+ numFreeArgs = argSpecs.empty() ? 0 : (argSpecs.rbegin()->first + 1);
+ unlimitedArgs = true;
+ }
+
+ L << "case ${args} in";
+ {
+ I;
+
+ for (size_t i = 0; i < numFreeArgs; ++i) {
+ L << i << ")";
+ {
+ I;
+ auto& spec = argSpecs[i];
+ if (spec.Completer_ != nullptr) {
+ spec.Completer_->GenerateBash(out);
+ }
+ L << ";;";
+ }
+ }
+ if (unlimitedArgs) {
+ L << "*)";
+ {
+ I;
+ auto& spec = opts.GetTrailingArgSpec();
+ if (spec.Completer_ != nullptr) {
+ spec.Completer_->GenerateBash(out);
+ }
+ L << ";;";
+ }
+ }
+ }
+ L << "esac";
+ L << ";;";
+ }
+ }
+ L << "esac";
+ }
+ L << "fi";
+ }
+
+ void TBashCompletionGenerator::GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager&) {
+ L << "if [[ ${cur} == -* ]] ; then";
+ {
+ I;
+ L << "COMPREPLY+=( $(compgen -W '-h --help --svnrevision' -- ${cur}) )";
+ }
+ L << "fi";
+ }
+
+#undef I
+#undef L
+
+ TString NEscaping::Q(TStringBuf string) {
+ TStringBuilder out;
+ out.reserve(string.size());
+ for (auto c: string) {
+ switch (c) {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ out << " ";
+ break;
+ case '\\':
+ out << "\\\\";
+ break;
+ case '\'':
+ out << "''";
+ break;
+ case '\"':
+ out << "\\\"";
+ break;
+ case '[':
+ out << "\\[";
+ break;
+ case ']':
+ out << "\\]";
+ break;
+ case ':':
+ out << "\\:";
+ break;
+ case '+':
+ out << "\\+";
+ break;
+ case '=':
+ out << "\\=";
+ break;
+ default:
+ out << c;
+ break;
+ }
+ }
+ return out;
+ }
+
+ TString NEscaping::QQ(TStringBuf string) {
+ auto q = Q(string);
+ return "'" + q + "'";
+ }
+
+ TString NEscaping::C(TStringBuf string) {
+ TStringBuilder out;
+ out.reserve(string.size() + 1);
+ for (auto c: string) {
+ switch (c) {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ out << " ";
+ break;
+ case '\'':
+ out << "''";
+ break;
+ case ':':
+ out << "\\:";
+ break;
+ default:
+ out << c;
+ break;
+ }
+ }
+ return out;
+ }
+
+ TString NEscaping::CC(TStringBuf string) {
+ auto c = C(string);
+ return "'" + c + "'";
+ }
+
+ TString NEscaping::S(TStringBuf string) {
+ TStringBuilder out;
+ out.reserve(string.size() + 1);
+ for (auto c: string) {
+ switch (c) {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ out << " ";
+ break;
+ case '\'':
+ out << "''";
+ break;
+ default:
+ out << c;
+ break;
+ }
+ }
+ return out;
+ }
+
+ TString NEscaping::SS(TStringBuf string) {
+ auto s = S(string);
+ return "'" + s + "'";
+ }
+
+ TString NEscaping::B(TStringBuf string) {
+ TStringBuilder out;
+ out.reserve(string.size() + 1);
+ for (auto c: string) {
+ switch (c) {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ out << " ";
+ break;
+ case '\'':
+ out << "'\"'\"'";
+ break;
+ default:
+ out << c;
+ break;
+ }
+ }
+ return out;
+ }
+
+ TString NEscaping::BB(TStringBuf string) {
+ auto b = B(string);
+ return "'" + b + "'";
+ }
+}
diff --git a/library/cpp/getopt/small/completion_generator.h b/library/cpp/getopt/small/completion_generator.h
index ac076e4d90..4241bb7d6c 100644
--- a/library/cpp/getopt/small/completion_generator.h
+++ b/library/cpp/getopt/small/completion_generator.h
@@ -1,69 +1,69 @@
-#pragma once
-
-#include "completer.h"
-#include "formatted_output.h"
-#include "last_getopt_opts.h"
-#include "modchooser.h"
-
-#include <util/generic/variant.h>
-#include <util/string/builder.h>
-
-namespace NLastGetopt {
- class TCompletionGenerator {
- public:
- explicit TCompletionGenerator(const TModChooser* modChooser);
- explicit TCompletionGenerator(const TOpts* opts);
- virtual ~TCompletionGenerator() = default;
-
- public:
- virtual void Generate(TStringBuf command, IOutputStream& stream) = 0;
-
- protected:
+#pragma once
+
+#include "completer.h"
+#include "formatted_output.h"
+#include "last_getopt_opts.h"
+#include "modchooser.h"
+
+#include <util/generic/variant.h>
+#include <util/string/builder.h>
+
+namespace NLastGetopt {
+ class TCompletionGenerator {
+ public:
+ explicit TCompletionGenerator(const TModChooser* modChooser);
+ explicit TCompletionGenerator(const TOpts* opts);
+ virtual ~TCompletionGenerator() = default;
+
+ public:
+ virtual void Generate(TStringBuf command, IOutputStream& stream) = 0;
+
+ protected:
std::variant<const TModChooser*, const TOpts*> Options_;
- };
-
- class TZshCompletionGenerator: public TCompletionGenerator {
- public:
- using TCompletionGenerator::TCompletionGenerator;
-
- public:
- void Generate(TStringBuf command, IOutputStream& stream) override;
-
- private:
- static void GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager);
- static void GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager& manager);
- static void GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager& manager);
- static void GenerateOptCompletion(TFormattedOutput& out, const TOpts& opts, const TOpt& opt, NComp::TCompleterManager& manager);
- };
-
- class TBashCompletionGenerator: public TCompletionGenerator {
- public:
- using TCompletionGenerator::TCompletionGenerator;
-
- public:
- void Generate(TStringBuf command, IOutputStream& stream) override;
-
- private:
- static void GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager, size_t level);
- static void GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager& manager, size_t level);
- static void GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager& manager);
- };
-
- namespace NEscaping {
- /// Escape ':', '-', '=', '[', ']' for use in zsh _arguments
- TString Q(TStringBuf string);
- TString QQ(TStringBuf string);
-
- /// Escape colons for use in zsh _alternative and _arguments
- TString C(TStringBuf string);
- TString CC(TStringBuf string);
-
- /// Simple escape for use in zsh single-quoted strings
- TString S(TStringBuf string);
- TString SS(TStringBuf string);
-
- /// Simple escape for use in bash single-quoted strings
- TString B(TStringBuf string);
- TString BB(TStringBuf string);
- }
-}
+ };
+
+ class TZshCompletionGenerator: public TCompletionGenerator {
+ public:
+ using TCompletionGenerator::TCompletionGenerator;
+
+ public:
+ void Generate(TStringBuf command, IOutputStream& stream) override;
+
+ private:
+ static void GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager);
+ static void GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager& manager);
+ static void GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager& manager);
+ static void GenerateOptCompletion(TFormattedOutput& out, const TOpts& opts, const TOpt& opt, NComp::TCompleterManager& manager);
+ };
+
+ class TBashCompletionGenerator: public TCompletionGenerator {
+ public:
+ using TCompletionGenerator::TCompletionGenerator;
+
+ public:
+ void Generate(TStringBuf command, IOutputStream& stream) override;
+
+ private:
+ static void GenerateModesCompletion(TFormattedOutput& out, const TModChooser& chooser, NComp::TCompleterManager& manager, size_t level);
+ static void GenerateOptsCompletion(TFormattedOutput& out, const TOpts& opts, NComp::TCompleterManager& manager, size_t level);
+ static void GenerateDefaultOptsCompletion(TFormattedOutput& out, NComp::TCompleterManager& manager);
+ };
+
+ namespace NEscaping {
+ /// Escape ':', '-', '=', '[', ']' for use in zsh _arguments
+ TString Q(TStringBuf string);
+ TString QQ(TStringBuf string);
+
+ /// Escape colons for use in zsh _alternative and _arguments
+ TString C(TStringBuf string);
+ TString CC(TStringBuf string);
+
+ /// Simple escape for use in zsh single-quoted strings
+ TString S(TStringBuf string);
+ TString SS(TStringBuf string);
+
+ /// Simple escape for use in bash single-quoted strings
+ TString B(TStringBuf string);
+ TString BB(TStringBuf string);
+ }
+}
diff --git a/library/cpp/getopt/small/formatted_output.cpp b/library/cpp/getopt/small/formatted_output.cpp
index fe355c2723..bf1b366f25 100644
--- a/library/cpp/getopt/small/formatted_output.cpp
+++ b/library/cpp/getopt/small/formatted_output.cpp
@@ -1,36 +1,36 @@
-#include "formatted_output.h"
-
-namespace NLastGetopt {
-
- TFormattedOutput::IndentGuard::IndentGuard(TFormattedOutput* output)
- : Output(output)
- {
- Output->IndentLevel_ += 2;
- }
-
- TFormattedOutput::IndentGuard::~IndentGuard() {
- Output->IndentLevel_ -= 2;
- }
-
- TFormattedOutput::IndentGuard TFormattedOutput::Indent() {
- return IndentGuard(this);
- }
-
- TStringBuilder& TFormattedOutput::Line() {
- return Lines_.emplace_back(IndentLevel_, TStringBuilder()).second;
- }
-
- void TFormattedOutput::Print(IOutputStream& out) {
- for (auto&[indent, line] : Lines_) {
- if (indent && !line.empty()) {
- TTempBuf buf(indent);
- Fill(buf.Data(), buf.Data() + indent, ' ');
- out.Write(buf.Data(), indent);
- }
- out << line;
- if (!line.EndsWith('\n')) {
- out << Endl;
- }
- }
- }
-}
+#include "formatted_output.h"
+
+namespace NLastGetopt {
+
+ TFormattedOutput::IndentGuard::IndentGuard(TFormattedOutput* output)
+ : Output(output)
+ {
+ Output->IndentLevel_ += 2;
+ }
+
+ TFormattedOutput::IndentGuard::~IndentGuard() {
+ Output->IndentLevel_ -= 2;
+ }
+
+ TFormattedOutput::IndentGuard TFormattedOutput::Indent() {
+ return IndentGuard(this);
+ }
+
+ TStringBuilder& TFormattedOutput::Line() {
+ return Lines_.emplace_back(IndentLevel_, TStringBuilder()).second;
+ }
+
+ void TFormattedOutput::Print(IOutputStream& out) {
+ for (auto&[indent, line] : Lines_) {
+ if (indent && !line.empty()) {
+ TTempBuf buf(indent);
+ Fill(buf.Data(), buf.Data() + indent, ' ');
+ out.Write(buf.Data(), indent);
+ }
+ out << line;
+ if (!line.EndsWith('\n')) {
+ out << Endl;
+ }
+ }
+ }
+}
diff --git a/library/cpp/getopt/small/formatted_output.h b/library/cpp/getopt/small/formatted_output.h
index f239dd7fdb..6fd16b73f9 100644
--- a/library/cpp/getopt/small/formatted_output.h
+++ b/library/cpp/getopt/small/formatted_output.h
@@ -1,32 +1,32 @@
-#pragma once
-
-#include <util/generic/algorithm.h>
-#include <util/generic/vector.h>
-#include <util/string/builder.h>
-#include <util/memory/tempbuf.h>
-
-namespace NLastGetopt {
- /// Utility for printing indented lines. Used by completion generators.
- class TFormattedOutput {
- public:
- struct IndentGuard {
- explicit IndentGuard(TFormattedOutput* output);
- virtual ~IndentGuard();
- TFormattedOutput* Output;
- };
-
- public:
- /// Increase indentation and return a RAII object that'll decrease it back automatically.
- IndentGuard Indent();
-
- /// Append a new indented line to the stream.
- TStringBuilder& Line();
-
- /// Collect all lines into a stream.
- void Print(IOutputStream& out);
-
- private:
- int IndentLevel_ = 0;
- TVector<std::pair<int, TStringBuilder>> Lines_;
- };
-}
+#pragma once
+
+#include <util/generic/algorithm.h>
+#include <util/generic/vector.h>
+#include <util/string/builder.h>
+#include <util/memory/tempbuf.h>
+
+namespace NLastGetopt {
+ /// Utility for printing indented lines. Used by completion generators.
+ class TFormattedOutput {
+ public:
+ struct IndentGuard {
+ explicit IndentGuard(TFormattedOutput* output);
+ virtual ~IndentGuard();
+ TFormattedOutput* Output;
+ };
+
+ public:
+ /// Increase indentation and return a RAII object that'll decrease it back automatically.
+ IndentGuard Indent();
+
+ /// Append a new indented line to the stream.
+ TStringBuilder& Line();
+
+ /// Collect all lines into a stream.
+ void Print(IOutputStream& out);
+
+ private:
+ int IndentLevel_ = 0;
+ TVector<std::pair<int, TStringBuilder>> Lines_;
+ };
+}
diff --git a/library/cpp/getopt/small/last_getopt.h b/library/cpp/getopt/small/last_getopt.h
index 0540f69313..07687bc914 100644
--- a/library/cpp/getopt/small/last_getopt.h
+++ b/library/cpp/getopt/small/last_getopt.h
@@ -40,7 +40,7 @@ namespace NLastGetopt {
TValue last = mutableValue ? NPrivate::OptFromString<TValue>(mutableValue, parser->CurOpt()) : first;
if (last < first) {
- throw TUsageException() << "failed to parse opt " << NPrivate::OptToString(parser->CurOpt()) << " value " << TString(val).Quote() << ": the second argument is less than the first one";
+ throw TUsageException() << "failed to parse opt " << NPrivate::OptToString(parser->CurOpt()) << " value " << TString(val).Quote() << ": the second argument is less than the first one";
}
for (++last; first < last; ++first) {
@@ -100,7 +100,7 @@ namespace NLastGetopt {
if (curval.IsInited()) {
TStringBuf key, value;
if (!curval.TrySplit(KVDelim, key, value)) {
- throw TUsageException() << "failed to parse opt " << NPrivate::OptToString(curOpt)
+ throw TUsageException() << "failed to parse opt " << NPrivate::OptToString(curOpt)
<< " value " << TString(curval).Quote() << ": expected key" << KVDelim << "value format";
}
Func(NPrivate::OptFromString<TKey>(key, curOpt), NPrivate::OptFromString<TValue>(value, curOpt));
@@ -119,10 +119,10 @@ namespace NLastGetopt {
const TpArg& arg = curval.IsInited() ? OptFromString<TpArg>(curval, parser->CurOpt()) : Def_;
try {
Func_(arg);
- } catch (const TUsageException&) {
- throw;
+ } catch (const TUsageException&) {
+ throw;
} catch (...) {
- throw TUsageException() << "failed to handle opt " << OptToString(parser->CurOpt())
+ throw TUsageException() << "failed to handle opt " << OptToString(parser->CurOpt())
<< " value " << TString(curval).Quote() << ": " << CurrentExceptionMessage();
}
}
diff --git a/library/cpp/getopt/small/last_getopt_opt.cpp b/library/cpp/getopt/small/last_getopt_opt.cpp
index 2839cca53f..9a99437f4b 100644
--- a/library/cpp/getopt/small/last_getopt_opt.cpp
+++ b/library/cpp/getopt/small/last_getopt_opt.cpp
@@ -54,7 +54,7 @@ namespace NLastGetopt {
TOpt& TOpt::AddShortName(unsigned char c) {
;
if (!IsAllowedShortName(c))
- throw TUsageException() << "option char '" << c << "' is not allowed";
+ throw TUsageException() << "option char '" << c << "' is not allowed";
Chars_.push_back(c);
return *this;
}
@@ -75,7 +75,7 @@ namespace NLastGetopt {
;
unsigned char c = 0;
if (!IsAllowedLongName(name, &c))
- throw TUsageException() << "option char '" << c
+ throw TUsageException() << "option char '" << c
<< "' in long '" << name << "' is not allowed";
LongNames_.push_back(name);
return *this;
@@ -102,12 +102,12 @@ namespace NLastGetopt {
}
}
- TOpt& TOpt::IfPresentDisableCompletionFor(const TOpt& opt) {
- if (opt.GetLongNames()) {
- IfPresentDisableCompletionFor(opt.GetName());
- } else {
- IfPresentDisableCompletionFor(opt.GetChar());
- }
- return *this;
- }
+ TOpt& TOpt::IfPresentDisableCompletionFor(const TOpt& opt) {
+ if (opt.GetLongNames()) {
+ IfPresentDisableCompletionFor(opt.GetName());
+ } else {
+ IfPresentDisableCompletionFor(opt.GetChar());
+ }
+ return *this;
+ }
}
diff --git a/library/cpp/getopt/small/last_getopt_opt.h b/library/cpp/getopt/small/last_getopt_opt.h
index a4e97e6a0a..a8dd5adca9 100644
--- a/library/cpp/getopt/small/last_getopt_opt.h
+++ b/library/cpp/getopt/small/last_getopt_opt.h
@@ -1,6 +1,6 @@
#pragma once
-#include "completer.h"
+#include "completer.h"
#include "last_getopt_handlers.h"
#include <util/string/split.h>
@@ -54,24 +54,24 @@ namespace NLastGetopt {
typedef TVector<TSimpleSharedPtr<IOptHandler>> TOptHandlers;
public:
- bool Hidden_ = false; // is visible in help
- TString ArgTitle_; // the name of argument in help output
- TString Help_; // the help string
- TString CompletionHelp_; // the help string that's used in completion script, a shorter version of Help_
- TString CompletionArgHelp_; // the description of argument in completion script
+ bool Hidden_ = false; // is visible in help
+ TString ArgTitle_; // the name of argument in help output
+ TString Help_; // the help string
+ TString CompletionHelp_; // the help string that's used in completion script, a shorter version of Help_
+ TString CompletionArgHelp_; // the description of argument in completion script
EHasArg HasArg_ = DEFAULT_HAS_ARG; // the argument parsing politics
bool Required_ = false; // option existence politics
- bool AllowMultipleCompletion_ = false; // let the completer know that this option can occur more than once
-
- bool DisableCompletionForOptions_ = false;
- bool DisableCompletionForFreeArgs_ = false;
- TShortNames DisableCompletionForChar_;
- TLongNames DisableCompletionForLongName_;
- TVector<size_t> DisableCompletionForFreeArg_;
- NComp::ICompleterPtr Completer_;
-
+ bool AllowMultipleCompletion_ = false; // let the completer know that this option can occur more than once
+
+ bool DisableCompletionForOptions_ = false;
+ bool DisableCompletionForFreeArgs_ = false;
+ TShortNames DisableCompletionForChar_;
+ TLongNames DisableCompletionForLongName_;
+ TVector<size_t> DisableCompletionForFreeArg_;
+ NComp::ICompleterPtr Completer_;
+
private:
//Handlers information
const void* UserValue_ = nullptr;
@@ -335,37 +335,37 @@ namespace NLastGetopt {
}
/**
- * Set help string that appears with `--help`. Unless `CompletionHelp` is given, this message will also be used
- * in completion script. In this case, don't make it too long, don't start it with a capital letter and don't
- * end it with a full stop.
- *
- * Note that `Help`, `CompletionHelp` and `CompletionArgHelp` are not the same. `Help` is printed in program
- * usage (when you call `program --help`), `CompletionHelp` is printed when completer lists available
- * options, and `CompletionArgHelp` is printed when completer shows available values for the option.
- *
- * Example of good help message:
- *
- * ```
- * opts.AddLongOption('t', "timeout")
- * .Help("specify query timeout in milliseconds")
- * .CompletionHelp("specify query timeout")
- * .CompletionArgHelp("query timeout (ms) [default=500]");
- * ```
- *
- * Notice how `Help` and `CompletionArgHelp` have units in them, but `CompletionHelp` don't.
- *
- * Another good example is the help option:
- *
- * ```
- * opts.AddLongOption('h', "help")
- * .Help("print this message and exit")
- * .CompletionHelp("print help message and exit");
- * ```
- *
- * Notice how `Help` mentions 'this message', but `CompletionHelp` mentions just 'help message'.
- *
- * See more on completion descriptions codestyle:
- * https://github.com/zsh-users/zsh/blob/master/Etc/completion-style-guide#L43
+ * Set help string that appears with `--help`. Unless `CompletionHelp` is given, this message will also be used
+ * in completion script. In this case, don't make it too long, don't start it with a capital letter and don't
+ * end it with a full stop.
+ *
+ * Note that `Help`, `CompletionHelp` and `CompletionArgHelp` are not the same. `Help` is printed in program
+ * usage (when you call `program --help`), `CompletionHelp` is printed when completer lists available
+ * options, and `CompletionArgHelp` is printed when completer shows available values for the option.
+ *
+ * Example of good help message:
+ *
+ * ```
+ * opts.AddLongOption('t', "timeout")
+ * .Help("specify query timeout in milliseconds")
+ * .CompletionHelp("specify query timeout")
+ * .CompletionArgHelp("query timeout (ms) [default=500]");
+ * ```
+ *
+ * Notice how `Help` and `CompletionArgHelp` have units in them, but `CompletionHelp` don't.
+ *
+ * Another good example is the help option:
+ *
+ * ```
+ * opts.AddLongOption('h', "help")
+ * .Help("print this message and exit")
+ * .CompletionHelp("print help message and exit");
+ * ```
+ *
+ * Notice how `Help` mentions 'this message', but `CompletionHelp` mentions just 'help message'.
+ *
+ * See more on completion descriptions codestyle:
+ * https://github.com/zsh-users/zsh/blob/master/Etc/completion-style-guide#L43
*/
TOpt& Help(const TString& help) {
Help_ = help;
@@ -373,178 +373,178 @@ namespace NLastGetopt {
}
/**
- * Get help string.
+ * Get help string.
*/
- const TString& GetHelp() const {
+ const TString& GetHelp() const {
return Help_;
}
/**
- * Set help string that appears when argument completer lists available options.
- *
- * See `Help` function for info on how this is different from setting `Help` and `CompletionArgHelp`.
- *
- * Use shorter messages for this message. Don't start them with a capital letter and don't end them
- * with a full stop. De aware that argument name and default value will not be printed by completer.
- *
- * In zsh, these messages will look like this:
- *
- * ```
- * $ program -<tab><tab>
- * -- option --
- * --help -h -- print help message and exit
- * --timeout -t -- specify query timeout
- * ```
- */
- TOpt& CompletionHelp(const TString& help) {
- CompletionHelp_ = help;
- return *this;
- }
-
- /**
- * Get help string that appears when argument completer lists available options.
- */
- const TString& GetCompletionHelp() const {
- return CompletionHelp_ ? CompletionHelp_ : Help_;
- }
-
- /**
- * Set help string that appears when completer suggests available values.
- *
- * See `Help` function for info on how this is different from setting `Help` and `CompletionHelp`.
- *
- * In zsh, these messages will look like this:
- *
- * ```
- * $ program --timeout <tab><tab>
- * -- query timeout (ms) [default=500] --
- * 50 100 250 500 1000
- * ```
- */
- TOpt& CompletionArgHelp(const TString& help) {
- CompletionArgHelp_ = help;
- return *this;
- }
-
- /**
- * @return argument help string for use in completion script.
- */
- const TString& GetCompletionArgHelp() const {
- return CompletionArgHelp_ ? CompletionArgHelp_ : ArgTitle_;
- }
-
- /**
- * Let the completer know that this option can occur more than once.
- */
- TOpt& AllowMultipleCompletion(bool allowMultipleCompletion = true) {
- AllowMultipleCompletion_ = allowMultipleCompletion;
- return *this;
- }
-
- /**
- * @return true if completer will offer completion for this option multiple times.
- */
- bool MultipleCompletionAllowed() const {
- return AllowMultipleCompletion_;
- }
-
- /**
- * Tell the completer to disable further completion if this option is present.
- * This is useful for options like `--help`.
- *
- * Note: this only works in zsh.
- *
- * @return self
- */
- TOpt& IfPresentDisableCompletion(bool value = true) {
- IfPresentDisableCompletionForOptions(value);
- IfPresentDisableCompletionForFreeArgs(value);
- return *this;
- }
-
- /**
- * Tell the completer to disable completion for all options if this option is already present in the input.
- * Free arguments will still be completed.
- *
- * Note: this only works in zsh.
- *
- * @return self
- */
- TOpt& IfPresentDisableCompletionForOptions(bool value = true) {
- DisableCompletionForOptions_ = value;
- return *this;
- }
-
- /**
- * Tell the completer to disable option `c` if this option is already present in the input.
- * For example, if you have two options `-a` and `-r` that are mutually exclusive, disable `-r` for `-a` and
- * disable `-a` for `-r`, like this:
- *
- * ```
- * opts.AddLongOption('a', "acquire").IfPresentDisableCompletionFor('r');
- * opts.AddLongOption('r', "release").IfPresentDisableCompletionFor('a');
- * ```
- *
- * This way, if user enabled option `-a`, completer will not suggest option `-r`.
- *
- * Note that we don't have to disable all flags for a single option. That is, disabling `-r` in the above
- * example disables `--release` automatically.
- *
- * Note: this only works in zsh.
- *
- * @param c char option that should be disabled when completer hits this option.
- */
- TOpt& IfPresentDisableCompletionFor(char c) {
- DisableCompletionForChar_.push_back(c);
- return *this;
- }
-
- /**
- * Like `IfPresentDisableCompletionFor(char c)`, but for long options.
- */
- TOpt& IfPresentDisableCompletionFor(const TString& name) {
- DisableCompletionForLongName_.push_back(name);
- return *this;
- }
-
- /**
- * Like `IfPresentDisableCompletionFor(char c)`, but for long options.
- */
- TOpt& IfPresentDisableCompletionFor(const TOpt& opt);
-
- /**
- * Tell the completer to disable completion for the given free argument if this option is present.
- *
- * Note: this only works in zsh.
- *
- * @param arg index of free arg
- */
- TOpt& IfPresentDisableCompletionForFreeArg(size_t index) {
- DisableCompletionForFreeArg_.push_back(index);
- return *this;
- }
-
- /**
- * Assign a completer for this option.
- */
- TOpt& Completer(NComp::ICompleterPtr completer) {
- Completer_ = std::move(completer);
- return *this;
- }
-
- /**
- * Tell the completer to disable completion for the all free arguments if this option is present.
- *
- * Note: this only works in zsh.
- */
- TOpt& IfPresentDisableCompletionForFreeArgs(bool value = true) {
- DisableCompletionForFreeArgs_ = value;
- return *this;
- }
-
- /**
- * Run handlers for this option.
- */
+ * Set help string that appears when argument completer lists available options.
+ *
+ * See `Help` function for info on how this is different from setting `Help` and `CompletionArgHelp`.
+ *
+ * Use shorter messages for this message. Don't start them with a capital letter and don't end them
+ * with a full stop. De aware that argument name and default value will not be printed by completer.
+ *
+ * In zsh, these messages will look like this:
+ *
+ * ```
+ * $ program -<tab><tab>
+ * -- option --
+ * --help -h -- print help message and exit
+ * --timeout -t -- specify query timeout
+ * ```
+ */
+ TOpt& CompletionHelp(const TString& help) {
+ CompletionHelp_ = help;
+ return *this;
+ }
+
+ /**
+ * Get help string that appears when argument completer lists available options.
+ */
+ const TString& GetCompletionHelp() const {
+ return CompletionHelp_ ? CompletionHelp_ : Help_;
+ }
+
+ /**
+ * Set help string that appears when completer suggests available values.
+ *
+ * See `Help` function for info on how this is different from setting `Help` and `CompletionHelp`.
+ *
+ * In zsh, these messages will look like this:
+ *
+ * ```
+ * $ program --timeout <tab><tab>
+ * -- query timeout (ms) [default=500] --
+ * 50 100 250 500 1000
+ * ```
+ */
+ TOpt& CompletionArgHelp(const TString& help) {
+ CompletionArgHelp_ = help;
+ return *this;
+ }
+
+ /**
+ * @return argument help string for use in completion script.
+ */
+ const TString& GetCompletionArgHelp() const {
+ return CompletionArgHelp_ ? CompletionArgHelp_ : ArgTitle_;
+ }
+
+ /**
+ * Let the completer know that this option can occur more than once.
+ */
+ TOpt& AllowMultipleCompletion(bool allowMultipleCompletion = true) {
+ AllowMultipleCompletion_ = allowMultipleCompletion;
+ return *this;
+ }
+
+ /**
+ * @return true if completer will offer completion for this option multiple times.
+ */
+ bool MultipleCompletionAllowed() const {
+ return AllowMultipleCompletion_;
+ }
+
+ /**
+ * Tell the completer to disable further completion if this option is present.
+ * This is useful for options like `--help`.
+ *
+ * Note: this only works in zsh.
+ *
+ * @return self
+ */
+ TOpt& IfPresentDisableCompletion(bool value = true) {
+ IfPresentDisableCompletionForOptions(value);
+ IfPresentDisableCompletionForFreeArgs(value);
+ return *this;
+ }
+
+ /**
+ * Tell the completer to disable completion for all options if this option is already present in the input.
+ * Free arguments will still be completed.
+ *
+ * Note: this only works in zsh.
+ *
+ * @return self
+ */
+ TOpt& IfPresentDisableCompletionForOptions(bool value = true) {
+ DisableCompletionForOptions_ = value;
+ return *this;
+ }
+
+ /**
+ * Tell the completer to disable option `c` if this option is already present in the input.
+ * For example, if you have two options `-a` and `-r` that are mutually exclusive, disable `-r` for `-a` and
+ * disable `-a` for `-r`, like this:
+ *
+ * ```
+ * opts.AddLongOption('a', "acquire").IfPresentDisableCompletionFor('r');
+ * opts.AddLongOption('r', "release").IfPresentDisableCompletionFor('a');
+ * ```
+ *
+ * This way, if user enabled option `-a`, completer will not suggest option `-r`.
+ *
+ * Note that we don't have to disable all flags for a single option. That is, disabling `-r` in the above
+ * example disables `--release` automatically.
+ *
+ * Note: this only works in zsh.
+ *
+ * @param c char option that should be disabled when completer hits this option.
+ */
+ TOpt& IfPresentDisableCompletionFor(char c) {
+ DisableCompletionForChar_.push_back(c);
+ return *this;
+ }
+
+ /**
+ * Like `IfPresentDisableCompletionFor(char c)`, but for long options.
+ */
+ TOpt& IfPresentDisableCompletionFor(const TString& name) {
+ DisableCompletionForLongName_.push_back(name);
+ return *this;
+ }
+
+ /**
+ * Like `IfPresentDisableCompletionFor(char c)`, but for long options.
+ */
+ TOpt& IfPresentDisableCompletionFor(const TOpt& opt);
+
+ /**
+ * Tell the completer to disable completion for the given free argument if this option is present.
+ *
+ * Note: this only works in zsh.
+ *
+ * @param arg index of free arg
+ */
+ TOpt& IfPresentDisableCompletionForFreeArg(size_t index) {
+ DisableCompletionForFreeArg_.push_back(index);
+ return *this;
+ }
+
+ /**
+ * Assign a completer for this option.
+ */
+ TOpt& Completer(NComp::ICompleterPtr completer) {
+ Completer_ = std::move(completer);
+ return *this;
+ }
+
+ /**
+ * Tell the completer to disable completion for the all free arguments if this option is present.
+ *
+ * Note: this only works in zsh.
+ */
+ TOpt& IfPresentDisableCompletionForFreeArgs(bool value = true) {
+ DisableCompletionForFreeArgs_ = value;
+ return *this;
+ }
+
+ /**
+ * Run handlers for this option.
+ */
void FireHandlers(const TOptsParser* parser) const;
private:
@@ -716,97 +716,97 @@ namespace NLastGetopt {
*/
struct TFreeArgSpec {
TFreeArgSpec() = default;
- TFreeArgSpec(const TString& title, const TString& help = TString(), bool optional = false)
- : Title_(title)
- , Help_(help)
- , Optional_(optional)
+ TFreeArgSpec(const TString& title, const TString& help = TString(), bool optional = false)
+ : Title_(title)
+ , Help_(help)
+ , Optional_(optional)
{
}
- TString Title_;
- TString Help_;
- TString CompletionArgHelp_;
-
- bool Optional_ = false;
- NComp::ICompleterPtr Completer_ = nullptr;
-
- /**
- * Check if this argument have default values for its title and help.
- */
- bool IsDefault() const {
- return Title_.empty() && Help_.empty();
- }
-
- /**
- * Set argument title.
- */
- TFreeArgSpec& Title(TString title) {
- Title_ = std::move(title);
- return *this;
- }
-
- /**
- * Get argument title. If title is empty, returns a default one.
- */
- TStringBuf GetTitle(TStringBuf defaultTitle) const {
- return Title_ ? TStringBuf(Title_) : defaultTitle;
- }
-
- /**
- * Set help string that appears with `--help`. Unless `CompletionHelp` is given, this message will also be used
- * in completion script. In this case, don't make it too long, don't start it with a capital letter and don't
- * end it with a full stop.
- *
- * See `TOpt::Help` function for more on how `Help` and `CompletionArgHelp` differ one from another.
- */
- TFreeArgSpec& Help(TString help) {
- Help_ = std::move(help);
- return *this;
- }
-
- /**
- * Get help string that appears with `--help`.
- */
- TStringBuf GetHelp() const {
- return Help_;
- }
-
- /**
- * Set help string that appears when completer suggests values fot this argument.
- */
- TFreeArgSpec& CompletionArgHelp(TString completionArgHelp) {
- CompletionArgHelp_ = std::move(completionArgHelp);
- return *this;
- }
-
- /**
- * Get help string that appears when completer suggests values fot this argument.
- */
- TStringBuf GetCompletionArgHelp(TStringBuf defaultTitle) const {
- return CompletionArgHelp_ ? TStringBuf(CompletionArgHelp_) : GetTitle(defaultTitle);
- }
-
- /**
- * Mark this argument as optional. This setting only affects help printing, it doesn't affect parsing.
- */
- TFreeArgSpec& Optional(bool optional = true) {
- Optional_ = optional;
- return *this;
- }
-
- /**
- * Check if this argument is optional.
- */
- bool IsOptional() const {
- return Optional_;
- }
-
- /**
- * Set completer for this argument.
- */
- TFreeArgSpec& Completer(NComp::ICompleterPtr completer) {
- Completer_ = std::move(completer);
- return *this;
- }
+ TString Title_;
+ TString Help_;
+ TString CompletionArgHelp_;
+
+ bool Optional_ = false;
+ NComp::ICompleterPtr Completer_ = nullptr;
+
+ /**
+ * Check if this argument have default values for its title and help.
+ */
+ bool IsDefault() const {
+ return Title_.empty() && Help_.empty();
+ }
+
+ /**
+ * Set argument title.
+ */
+ TFreeArgSpec& Title(TString title) {
+ Title_ = std::move(title);
+ return *this;
+ }
+
+ /**
+ * Get argument title. If title is empty, returns a default one.
+ */
+ TStringBuf GetTitle(TStringBuf defaultTitle) const {
+ return Title_ ? TStringBuf(Title_) : defaultTitle;
+ }
+
+ /**
+ * Set help string that appears with `--help`. Unless `CompletionHelp` is given, this message will also be used
+ * in completion script. In this case, don't make it too long, don't start it with a capital letter and don't
+ * end it with a full stop.
+ *
+ * See `TOpt::Help` function for more on how `Help` and `CompletionArgHelp` differ one from another.
+ */
+ TFreeArgSpec& Help(TString help) {
+ Help_ = std::move(help);
+ return *this;
+ }
+
+ /**
+ * Get help string that appears with `--help`.
+ */
+ TStringBuf GetHelp() const {
+ return Help_;
+ }
+
+ /**
+ * Set help string that appears when completer suggests values fot this argument.
+ */
+ TFreeArgSpec& CompletionArgHelp(TString completionArgHelp) {
+ CompletionArgHelp_ = std::move(completionArgHelp);
+ return *this;
+ }
+
+ /**
+ * Get help string that appears when completer suggests values fot this argument.
+ */
+ TStringBuf GetCompletionArgHelp(TStringBuf defaultTitle) const {
+ return CompletionArgHelp_ ? TStringBuf(CompletionArgHelp_) : GetTitle(defaultTitle);
+ }
+
+ /**
+ * Mark this argument as optional. This setting only affects help printing, it doesn't affect parsing.
+ */
+ TFreeArgSpec& Optional(bool optional = true) {
+ Optional_ = optional;
+ return *this;
+ }
+
+ /**
+ * Check if this argument is optional.
+ */
+ bool IsOptional() const {
+ return Optional_;
+ }
+
+ /**
+ * Set completer for this argument.
+ */
+ TFreeArgSpec& Completer(NComp::ICompleterPtr completer) {
+ Completer_ = std::move(completer);
+ return *this;
+ }
};
}
diff --git a/library/cpp/getopt/small/last_getopt_opts.cpp b/library/cpp/getopt/small/last_getopt_opts.cpp
index 936489c200..03c432849f 100644
--- a/library/cpp/getopt/small/last_getopt_opts.cpp
+++ b/library/cpp/getopt/small/last_getopt_opts.cpp
@@ -1,12 +1,12 @@
-#include "completer_command.h"
+#include "completer_command.h"
#include "last_getopt_opts.h"
-#include "wrap.h"
-#include "last_getopt_parser.h"
+#include "wrap.h"
+#include "last_getopt_parser.h"
#include <library/cpp/colorizer/colors.h>
#include <util/stream/format.h>
-#include <util/charset/utf8.h>
+#include <util/charset/utf8.h>
#include <stdlib.h>
@@ -70,7 +70,7 @@ namespace NLastGetopt {
, AllowUnknownCharOptions_(false)
, AllowUnknownLongOptions_(false)
, FreeArgsMin_(0)
- , FreeArgsMax_(UNLIMITED_ARGS)
+ , FreeArgsMax_(UNLIMITED_ARGS)
{
if (!optstring.empty()) {
AddCharOptions(optstring);
@@ -225,33 +225,33 @@ namespace NLastGetopt {
return *Opts_.back();
}
- TOpt& TOpts::AddCompletionOption(TString command, TString longName) {
- if (TOpt* o = FindLongOption(longName)) {
- return *o;
- }
-
- return AddOption(MakeCompletionOpt(this, std::move(command), std::move(longName)));
- }
-
- namespace {
- auto MutuallyExclusiveHandler(const TOpt* cur, const TOpt* other) {
- return [cur, other](const TOptsParser* p) {
- if (p->Seen(other)) {
- throw TUsageException()
- << "option " << cur->ToShortString()
- << " can't appear together with option " << other->ToShortString();
- }
- };
- }
- }
-
- void TOpts::MutuallyExclusiveOpt(TOpt& opt1, TOpt& opt2) {
- opt1.Handler1(MutuallyExclusiveHandler(&opt1, &opt2))
- .IfPresentDisableCompletionFor(opt2);
- opt2.Handler1(MutuallyExclusiveHandler(&opt2, &opt1))
- .IfPresentDisableCompletionFor(opt1);
- }
-
+ TOpt& TOpts::AddCompletionOption(TString command, TString longName) {
+ if (TOpt* o = FindLongOption(longName)) {
+ return *o;
+ }
+
+ return AddOption(MakeCompletionOpt(this, std::move(command), std::move(longName)));
+ }
+
+ namespace {
+ auto MutuallyExclusiveHandler(const TOpt* cur, const TOpt* other) {
+ return [cur, other](const TOptsParser* p) {
+ if (p->Seen(other)) {
+ throw TUsageException()
+ << "option " << cur->ToShortString()
+ << " can't appear together with option " << other->ToShortString();
+ }
+ };
+ }
+ }
+
+ void TOpts::MutuallyExclusiveOpt(TOpt& opt1, TOpt& opt2) {
+ opt1.Handler1(MutuallyExclusiveHandler(&opt1, &opt2))
+ .IfPresentDisableCompletionFor(opt2);
+ opt2.Handler1(MutuallyExclusiveHandler(&opt2, &opt1))
+ .IfPresentDisableCompletionFor(opt1);
+ }
+
size_t TOpts::IndexOf(const TOpt* opt) const {
TOptsVector::const_iterator it = std::find(Opts_.begin(), Opts_.end(), opt);
if (it == Opts_.end())
@@ -259,19 +259,19 @@ namespace NLastGetopt {
return it - Opts_.begin();
}
- TStringBuf TOpts::GetFreeArgTitle(size_t pos) const {
+ TStringBuf TOpts::GetFreeArgTitle(size_t pos) const {
if (FreeArgSpecs_.contains(pos)) {
- return FreeArgSpecs_.at(pos).GetTitle(DefaultFreeArgTitle_);
+ return FreeArgSpecs_.at(pos).GetTitle(DefaultFreeArgTitle_);
}
- return DefaultFreeArgTitle_;
+ return DefaultFreeArgTitle_;
}
- void TOpts::SetFreeArgTitle(size_t pos, const TString& title, const TString& help, bool optional) {
- FreeArgSpecs_[pos] = TFreeArgSpec(title, help, optional);
+ void TOpts::SetFreeArgTitle(size_t pos, const TString& title, const TString& help, bool optional) {
+ FreeArgSpecs_[pos] = TFreeArgSpec(title, help, optional);
}
- TFreeArgSpec& TOpts::GetFreeArgSpec(size_t pos) {
- return FreeArgSpecs_[pos];
+ TFreeArgSpec& TOpts::GetFreeArgSpec(size_t pos) {
+ return FreeArgSpecs_[pos];
}
static TString FormatOption(const TOpt* option, const NColorizer::TColors& colors) {
@@ -325,29 +325,29 @@ namespace NLastGetopt {
}
os << "[OPTIONS]";
- ui32 numDescribedFlags = FreeArgSpecs_.empty() ? 0 : FreeArgSpecs_.rbegin()->first + 1;
- ui32 numArgsToShow = Max(FreeArgsMin_, FreeArgsMax_ == UNLIMITED_ARGS ? numDescribedFlags : FreeArgsMax_);
-
- for (ui32 i = 0, nonOptionalFlagsPrinted = 0; i < numArgsToShow; ++i) {
- bool isOptional = nonOptionalFlagsPrinted >= FreeArgsMin_ || FreeArgSpecs_.Value(i, TFreeArgSpec()).Optional_;
-
- nonOptionalFlagsPrinted += !isOptional;
-
- os << " ";
-
- if (isOptional)
- os << "[";
-
- os << GetFreeArgTitle(i);
-
- if (isOptional)
- os << "]";
- }
-
- if (FreeArgsMax_ == UNLIMITED_ARGS) {
- os << " [" << TrailingArgSpec_.GetTitle(DefaultFreeArgTitle_) << "]...";
- }
-
+ ui32 numDescribedFlags = FreeArgSpecs_.empty() ? 0 : FreeArgSpecs_.rbegin()->first + 1;
+ ui32 numArgsToShow = Max(FreeArgsMin_, FreeArgsMax_ == UNLIMITED_ARGS ? numDescribedFlags : FreeArgsMax_);
+
+ for (ui32 i = 0, nonOptionalFlagsPrinted = 0; i < numArgsToShow; ++i) {
+ bool isOptional = nonOptionalFlagsPrinted >= FreeArgsMin_ || FreeArgSpecs_.Value(i, TFreeArgSpec()).Optional_;
+
+ nonOptionalFlagsPrinted += !isOptional;
+
+ os << " ";
+
+ if (isOptional)
+ os << "[";
+
+ os << GetFreeArgTitle(i);
+
+ if (isOptional)
+ os << "]";
+ }
+
+ if (FreeArgsMax_ == UNLIMITED_ARGS) {
+ os << " [" << TrailingArgSpec_.GetTitle(DefaultFreeArgTitle_) << "]...";
+ }
+
os << Endl;
}
@@ -361,7 +361,7 @@ namespace NLastGetopt {
TVector<TString> leftColumn(Opts_.size());
TVector<size_t> leftColumnSizes(leftColumn.size());
- const size_t kMaxLeftWidth = 25;
+ const size_t kMaxLeftWidth = 25;
size_t leftWidth = 0;
size_t requiredOptionsCount = 0;
NColorizer::TColors disabledColors(false);
@@ -371,14 +371,14 @@ namespace NLastGetopt {
if (opt->IsHidden())
continue;
leftColumn[i] = FormatOption(opt, colors);
- size_t leftColumnSize = leftColumn[i].size();
- if (colors.IsTTY()) {
- leftColumnSize -= NColorizer::TotalAnsiEscapeCodeLen(leftColumn[i]);
- }
+ size_t leftColumnSize = leftColumn[i].size();
+ if (colors.IsTTY()) {
+ leftColumnSize -= NColorizer::TotalAnsiEscapeCodeLen(leftColumn[i]);
+ }
leftColumnSizes[i] = leftColumnSize;
- if (leftColumnSize <= kMaxLeftWidth) {
- leftWidth = Max(leftWidth, leftColumnSize);
- }
+ if (leftColumnSize <= kMaxLeftWidth) {
+ leftWidth = Max(leftWidth, leftColumnSize);
+ }
if (opt->IsRequired())
requiredOptionsCount++;
}
@@ -410,59 +410,59 @@ namespace NLastGetopt {
continue;
if (leftColumnSizes[i] > leftWidth && !opt->GetHelp().empty()) {
- os << SPad << leftColumn[i] << Endl << SPad << leftPadding << ' ';
+ os << SPad << leftColumn[i] << Endl << SPad << leftPadding << ' ';
} else {
os << SPad << leftColumn[i] << ' ';
if (leftColumnSizes[i] < leftWidth)
os << TStringBuf(leftPadding.data(), leftWidth - leftColumnSizes[i]);
}
- TStringBuf help = opt->GetHelp();
- while (help && isspace(help.back())) {
- help.Chop(1);
+ TStringBuf help = opt->GetHelp();
+ while (help && isspace(help.back())) {
+ help.Chop(1);
+ }
+ size_t lastLineLength = 0;
+ bool helpHasParagraphs = false;
+ if (help) {
+ os << Wrap(Wrap_, help, SPad + leftPadding + " ", &lastLineLength, &helpHasParagraphs);
}
- size_t lastLineLength = 0;
- bool helpHasParagraphs = false;
- if (help) {
- os << Wrap(Wrap_, help, SPad + leftPadding + " ", &lastLineLength, &helpHasParagraphs);
- }
if (opt->HasDefaultValue()) {
- auto quotedDef = QuoteForHelp(opt->GetDefaultValue());
- if (helpHasParagraphs) {
- os << Endl << Endl << SPad << leftPadding << " ";
- os << "Default: " << colors.CyanColor() << quotedDef << colors.OldColor() << ".";
- } else if (help.EndsWith('.')) {
- os << Endl << SPad << leftPadding << " ";
- os << "Default: " << colors.CyanColor() << quotedDef << colors.OldColor() << ".";
- } else if (help) {
- if (SPad.size() + leftWidth + 1 + lastLineLength + 12 + quotedDef.size() > Wrap_) {
- os << Endl << SPad << leftPadding << " ";
- } else {
- os << " ";
- }
- os << "(default: " << colors.CyanColor() << quotedDef << colors.OldColor() << ")";
- } else {
- os << "default: " << colors.CyanColor() << quotedDef << colors.OldColor();
- }
+ auto quotedDef = QuoteForHelp(opt->GetDefaultValue());
+ if (helpHasParagraphs) {
+ os << Endl << Endl << SPad << leftPadding << " ";
+ os << "Default: " << colors.CyanColor() << quotedDef << colors.OldColor() << ".";
+ } else if (help.EndsWith('.')) {
+ os << Endl << SPad << leftPadding << " ";
+ os << "Default: " << colors.CyanColor() << quotedDef << colors.OldColor() << ".";
+ } else if (help) {
+ if (SPad.size() + leftWidth + 1 + lastLineLength + 12 + quotedDef.size() > Wrap_) {
+ os << Endl << SPad << leftPadding << " ";
+ } else {
+ os << " ";
+ }
+ os << "(default: " << colors.CyanColor() << quotedDef << colors.OldColor() << ")";
+ } else {
+ os << "default: " << colors.CyanColor() << quotedDef << colors.OldColor();
+ }
}
os << Endl;
-
- if (helpHasParagraphs) {
- os << Endl;
- }
+
+ if (helpHasParagraphs) {
+ os << Endl;
+ }
}
}
-
+
PrintFreeArgsDesc(os, colors);
-
- for (auto& [heading, text] : Sections) {
- os << Endl << colors.BoldColor() << heading << colors.OldColor() << ":" << Endl;
-
- os << SPad << Wrap(Wrap_, text, SPad) << Endl;
- }
-
+
+ for (auto& [heading, text] : Sections) {
+ os << Endl << colors.BoldColor() << heading << colors.OldColor() << ":" << Endl;
+
+ os << SPad << Wrap(Wrap_, text, SPad) << Endl;
+ }
+
osIn << os.Str();
}
@@ -479,8 +479,8 @@ namespace NLastGetopt {
leftFreeWidth = Max(leftFreeWidth, GetFreeArgTitle(i).size());
}
- if (!TrailingArgSpec_.IsDefault()) {
- leftFreeWidth = Max(leftFreeWidth, TrailingArgSpec_.GetTitle(DefaultFreeArgTitle_).size());
+ if (!TrailingArgSpec_.IsDefault()) {
+ leftFreeWidth = Max(leftFreeWidth, TrailingArgSpec_.GetTitle(DefaultFreeArgTitle_).size());
}
leftFreeWidth = Min(leftFreeWidth, size_t(30));
@@ -488,32 +488,32 @@ namespace NLastGetopt {
os << " min: " << colors.GreenColor() << FreeArgsMin_ << colors.OldColor() << ",";
os << " max: " << colors.GreenColor();
- if (FreeArgsMax_ != UNLIMITED_ARGS) {
+ if (FreeArgsMax_ != UNLIMITED_ARGS) {
os << FreeArgsMax_;
} else {
os << "unlimited";
}
- os << colors.OldColor() << Endl;
+ os << colors.OldColor() << Endl;
const size_t limit = FreeArgSpecs_.empty() ? 0 : FreeArgSpecs_.rbegin()->first;
for (size_t i = 0; i <= limit; ++i) {
- if (!FreeArgSpecs_.contains(i)) {
- continue;
- }
-
- if (auto help = FreeArgSpecs_.at(i).GetHelp()) {
- auto title = GetFreeArgTitle(i);
- os << SPad << colors.GreenColor() << RightPad(title, leftFreeWidth, ' ') << colors.OldColor()
- << SPad << help << Endl;
- }
- }
-
- if (FreeArgsMax_ == UNLIMITED_ARGS) {
- auto title = TrailingArgSpec_.GetTitle(DefaultFreeArgTitle_);
- if (auto help = TrailingArgSpec_.GetHelp()) {
- os << SPad << colors.GreenColor() << RightPad(title, leftFreeWidth, ' ') << colors.OldColor()
- << SPad << help << Endl;
- }
+ if (!FreeArgSpecs_.contains(i)) {
+ continue;
+ }
+
+ if (auto help = FreeArgSpecs_.at(i).GetHelp()) {
+ auto title = GetFreeArgTitle(i);
+ os << SPad << colors.GreenColor() << RightPad(title, leftFreeWidth, ' ') << colors.OldColor()
+ << SPad << help << Endl;
+ }
+ }
+
+ if (FreeArgsMax_ == UNLIMITED_ARGS) {
+ auto title = TrailingArgSpec_.GetTitle(DefaultFreeArgTitle_);
+ if (auto help = TrailingArgSpec_.GetHelp()) {
+ os << SPad << colors.GreenColor() << RightPad(title, leftFreeWidth, ' ') << colors.OldColor()
+ << SPad << help << Endl;
+ }
}
}
}
diff --git a/library/cpp/getopt/small/last_getopt_opts.h b/library/cpp/getopt/small/last_getopt_opts.h
index fe4f3b9a7d..825b99c871 100644
--- a/library/cpp/getopt/small/last_getopt_opts.h
+++ b/library/cpp/getopt/small/last_getopt_opts.h
@@ -15,32 +15,32 @@ namespace NLastGetopt {
};
/**
- * NLastGetopt::TOpts is a storage of program options' parse rules.
- * It contains information about all options, free args, some parsing options
- * and rules about interaction between options.
- *
- * The main point for defining program options.
- *
- * The parsing rules determined by the following parts:
- * - Arguments permutation. It is expected free args be after named args.
- * This point adjusts how to treat breaking this expectation.
- * if REQUIRE_ORDER is choosen, the exception during parsing will be raised,
- * the special string " -- " will be treated as end of named
- * options: all options after it will be parsed as free args
- * if PERMUTE is choosen, arguments will be rearranged in correct order,
- * if RETURN_IN_ORDER is choosen, all free args will be ommited (TODO: looks very strange)
- * - Using '+' as a prefix instead '--' for long names
- * - Using "-" as a prefix for both short and long names
- * - Allowing unknown options
- *
- */
+ * NLastGetopt::TOpts is a storage of program options' parse rules.
+ * It contains information about all options, free args, some parsing options
+ * and rules about interaction between options.
+ *
+ * The main point for defining program options.
+ *
+ * The parsing rules determined by the following parts:
+ * - Arguments permutation. It is expected free args be after named args.
+ * This point adjusts how to treat breaking this expectation.
+ * if REQUIRE_ORDER is choosen, the exception during parsing will be raised,
+ * the special string " -- " will be treated as end of named
+ * options: all options after it will be parsed as free args
+ * if PERMUTE is choosen, arguments will be rearranged in correct order,
+ * if RETURN_IN_ORDER is choosen, all free args will be ommited (TODO: looks very strange)
+ * - Using '+' as a prefix instead '--' for long names
+ * - Using "-" as a prefix for both short and long names
+ * - Allowing unknown options
+ *
+ */
class TOpts {
friend class TOptsParseResult;
friend class TOptsParser;
public:
- static constexpr const ui32 UNLIMITED_ARGS = Max<ui32>();
-
+ static constexpr const ui32 UNLIMITED_ARGS = Max<ui32>();
+
typedef TVector<TSimpleSharedPtr<TOpt>> TOptsVector;
TOptsVector Opts_; // infomation about named (short and long) options
TVector<std::function<void(TStringBuf)>> ArgBindings_;
@@ -53,32 +53,32 @@ namespace NLastGetopt {
bool AllowUnknownCharOptions_ = false;
bool AllowUnknownLongOptions_ = false;
- ui32 Wrap_ = 80;
-
+ ui32 Wrap_ = 80;
+
private:
ui32 FreeArgsMin_; // minimal number of free args
ui32 FreeArgsMax_; // maximal number of free args
- TMap<ui32, TFreeArgSpec> FreeArgSpecs_; // mapping [free arg position] -> [free arg specification]
- TFreeArgSpec TrailingArgSpec_; // spec for the trailing argument (when arguments are unlimited)
- TString DefaultFreeArgTitle_ = "ARG"; // title that's used for free args without a title
+ TMap<ui32, TFreeArgSpec> FreeArgSpecs_; // mapping [free arg position] -> [free arg specification]
+ TFreeArgSpec TrailingArgSpec_; // spec for the trailing argument (when arguments are unlimited)
+ TString DefaultFreeArgTitle_ = "ARG"; // title that's used for free args without a title
TString Title; // title of the help string
TString CustomCmdLineDescr; // user defined help string
TString CustomUsage; // user defined usage string
- TVector<std::pair<TString, TString>> Sections; // additional help entries to print after usage
-
+ TVector<std::pair<TString, TString>> Sections; // additional help entries to print after usage
+
public:
/**
- * Constructs TOpts from string as in getopt(3)
- */
+ * Constructs TOpts from string as in getopt(3)
+ */
TOpts(const TStringBuf& optstring = TStringBuf());
/**
- * Constructs TOpts from string as in getopt(3) and
- * additionally adds help option (for '?') and svn-verstion option (for 'V')
- */
+ * Constructs TOpts from string as in getopt(3) and
+ * additionally adds help option (for '?') and svn-verstion option (for 'V')
+ */
static TOpts Default(const TStringBuf& optstring = TStringBuf()) {
TOpts opts(optstring);
opts.AddHelpOption();
@@ -87,161 +87,161 @@ namespace NLastGetopt {
}
/**
- * Checks correctness of options' descriptions.
- * Throws TConfException if validation failed.
- * Check consist of:
- * -not intersecting of names
- * -compability of settings, that responsable for freeArgs parsing
- */
+ * Checks correctness of options' descriptions.
+ * Throws TConfException if validation failed.
+ * Check consist of:
+ * -not intersecting of names
+ * -compability of settings, that responsable for freeArgs parsing
+ */
void Validate() const;
/**
- * Search for the option with given long name
- * @param name long name for search
- * @return ptr on result (nullptr if not found)
- */
+ * Search for the option with given long name
+ * @param name long name for search
+ * @return ptr on result (nullptr if not found)
+ */
const TOpt* FindLongOption(const TStringBuf& name) const;
/**
- * Search for the option with given short name
- * @param c short name for search
- * @return ptr on result (nullptr if not found)
- */
+ * Search for the option with given short name
+ * @param c short name for search
+ * @return ptr on result (nullptr if not found)
+ */
const TOpt* FindCharOption(char c) const;
/**
- * Search for the option with given long name
- * @param name long name for search
- * @return ptr on result (nullptr if not found)
- */
+ * Search for the option with given long name
+ * @param name long name for search
+ * @return ptr on result (nullptr if not found)
+ */
TOpt* FindLongOption(const TStringBuf& name);
/**
- * Search for the option with given short name
- * @param c short name for search
- * @return ptr on result (nullptr if not found)
- */
+ * Search for the option with given short name
+ * @param c short name for search
+ * @return ptr on result (nullptr if not found)
+ */
TOpt* FindCharOption(char c);
/**
- * Search for the option with given name
- * @param name name for search
- * @return ptr on result (nullptr if not found)
- */
- /// @{
-
- const TOpt* FindOption(const TStringBuf& name) const {
- return FindLongOption(name);
- }
-
- TOpt* FindOption(const TStringBuf& name) {
- return FindLongOption(name);
- }
-
- const TOpt* FindOption(char c) const {
- return FindCharOption(c);
- }
-
- TOpt* FindOption(char c) {
- return FindCharOption(c);
- }
-
- /// @}
-
- /**
- * Sets title of the help string
- * @param title title to set
- */
+ * Search for the option with given name
+ * @param name name for search
+ * @return ptr on result (nullptr if not found)
+ */
+ /// @{
+
+ const TOpt* FindOption(const TStringBuf& name) const {
+ return FindLongOption(name);
+ }
+
+ TOpt* FindOption(const TStringBuf& name) {
+ return FindLongOption(name);
+ }
+
+ const TOpt* FindOption(char c) const {
+ return FindCharOption(c);
+ }
+
+ TOpt* FindOption(char c) {
+ return FindCharOption(c);
+ }
+
+ /// @}
+
+ /**
+ * Sets title of the help string
+ * @param title title to set
+ */
void SetTitle(const TString& title) {
Title = title;
}
/**
- * @return true if there is an option with given long name
- *
- * @param name long name for search
- */
+ * @return true if there is an option with given long name
+ *
+ * @param name long name for search
+ */
bool HasLongOption(const TString& name) const {
return FindLongOption(name) != nullptr;
}
/**
- * @return true if there is an option with given short name
- *
- * @param char short name for search
- */
+ * @return true if there is an option with given short name
+ *
+ * @param char short name for search
+ */
bool HasCharOption(char c) const {
return FindCharOption(c) != nullptr;
}
/**
- * Search for the option with given long name
- * @param name long name for search
- * @return ref on result (throw exception if not found)
- */
+ * Search for the option with given long name
+ * @param name long name for search
+ * @return ref on result (throw exception if not found)
+ */
const TOpt& GetLongOption(const TStringBuf& name) const;
/**
- * Search for the option with given long name
- * @param name long name for search
- * @return ref on result (throw exception if not found)
- */
+ * Search for the option with given long name
+ * @param name long name for search
+ * @return ref on result (throw exception if not found)
+ */
TOpt& GetLongOption(const TStringBuf& name);
/**
- * Search for the option with given short name
- * @param c short name for search
- * @return ref on result (throw exception if not found)
- */
+ * Search for the option with given short name
+ * @param c short name for search
+ * @return ref on result (throw exception if not found)
+ */
const TOpt& GetCharOption(char c) const;
/**
- * Search for the option with given short name
- * @param c short name for search
- * @return ref on result (throw exception if not found)
- */
+ * Search for the option with given short name
+ * @param c short name for search
+ * @return ref on result (throw exception if not found)
+ */
TOpt& GetCharOption(char c);
/**
- * Search for the option with given name
- * @param name name for search
- * @return ref on result (throw exception if not found)
- */
- /// @{
-
- const TOpt& GetOption(const TStringBuf& name) const {
- return GetLongOption(name);
- }
-
- TOpt& GetOption(const TStringBuf& name) {
- return GetLongOption(name);
- }
-
- const TOpt& GetOption(char c) const {
- return GetCharOption(c);
- }
-
- TOpt& GetOption(char c) {
- return GetCharOption(c);
- }
-
- /// @}
-
- /**
- * @return true if short options exist
- */
+ * Search for the option with given name
+ * @param name name for search
+ * @return ref on result (throw exception if not found)
+ */
+ /// @{
+
+ const TOpt& GetOption(const TStringBuf& name) const {
+ return GetLongOption(name);
+ }
+
+ TOpt& GetOption(const TStringBuf& name) {
+ return GetLongOption(name);
+ }
+
+ const TOpt& GetOption(char c) const {
+ return GetCharOption(c);
+ }
+
+ TOpt& GetOption(char c) {
+ return GetCharOption(c);
+ }
+
+ /// @}
+
+ /**
+ * @return true if short options exist
+ */
bool HasAnyShortOption() const;
/**
- * @return true if long options exist
- */
+ * @return true if long options exist
+ */
bool HasAnyLongOption() const;
/**
- * Creates new [option description (TOpt)] as a copy of given one
- * @param option source
- * @return reference for created option
- */
+ * Creates new [option description (TOpt)] as a copy of given one
+ * @param option source
+ * @return reference for created option
+ */
TOpt& AddOption(const TOpt& option);
/**
@@ -261,30 +261,30 @@ namespace NLastGetopt {
}
/**
- * Creates options list from string as in getopt(3)
- *
- * @param optstring source
- */
+ * Creates options list from string as in getopt(3)
+ *
+ * @param optstring source
+ */
void AddCharOptions(const TStringBuf& optstring);
/**
- * Creates new [option description (TOpt)] with given short name and given help string
- *
- * @param c short name
- * @param help help string
- * @return reference for created option
- */
+ * Creates new [option description (TOpt)] with given short name and given help string
+ *
+ * @param c short name
+ * @param help help string
+ * @return reference for created option
+ */
TOpt& AddCharOption(char c, const TString& help = "") {
return AddCharOption(c, DEFAULT_HAS_ARG, help);
}
/**
- * Creates new [option description (TOpt)] with given short name and given help string
- *
- * @param c short name
- * @param help help string
- * @return reference for created option
- */
+ * Creates new [option description (TOpt)] with given short name and given help string
+ *
+ * @param c short name
+ * @param help help string
+ * @return reference for created option
+ */
TOpt& AddCharOption(char c, EHasArg hasArg, const TString& help = "") {
TOpt option;
option.AddShortName(c);
@@ -294,24 +294,24 @@ namespace NLastGetopt {
}
/**
- * Creates new [option description (TOpt)] with given long name and given help string
- *
- * @param name long name
- * @param help help string
- * @return reference for created option
- */
+ * Creates new [option description (TOpt)] with given long name and given help string
+ *
+ * @param name long name
+ * @param help help string
+ * @return reference for created option
+ */
TOpt& AddLongOption(const TString& name, const TString& help = "") {
return AddLongOption(0, name, help);
}
/**
- * Creates new [option description (TOpt)] with given long and short names and given help string
- *
- * @param c short name
- * @param name long name
- * @param help help string
- * @return reference for created option
- */
+ * Creates new [option description (TOpt)] with given long and short names and given help string
+ *
+ * @param c short name
+ * @param name long name
+ * @param help help string
+ * @return reference for created option
+ */
TOpt& AddLongOption(char c, const TString& name, const TString& help = "") {
TOpt option;
if (c != 0)
@@ -322,12 +322,12 @@ namespace NLastGetopt {
}
/**
- * Creates new [option description (TOpt)] for help printing,
- * adds appropriate handler for it
- * If "help" option already exist, will add given short name to it.
- *
- * @param c new short name for help option
- */
+ * Creates new [option description (TOpt)] for help printing,
+ * adds appropriate handler for it
+ * If "help" option already exist, will add given short name to it.
+ *
+ * @param c new short name for help option
+ */
TOpt& AddHelpOption(char c = '?') {
if (TOpt* o = FindLongOption("help")) {
if (!o->CharIs(c))
@@ -336,17 +336,17 @@ namespace NLastGetopt {
}
return AddLongOption(c, "help", "print usage")
.HasArg(NO_ARGUMENT)
- .IfPresentDisableCompletion()
+ .IfPresentDisableCompletion()
.Handler(&PrintUsageAndExit);
}
/**
- * Creates new [option description (TOpt)] for svn-revision printing,
- * adds appropriate handler for it.
- * If "svnversion" option already exist, will add given short name to it.
- *
- * @param c new short name for "svnversion" option
- */
+ * Creates new [option description (TOpt)] for svn-revision printing,
+ * adds appropriate handler for it.
+ * If "svnversion" option already exist, will add given short name to it.
+ *
+ * @param c new short name for "svnversion" option
+ */
TOpt& AddVersionOption(char c = 'V') {
if (TOpt* o = FindLongOption("svnrevision")) {
if (!o->CharIs(c))
@@ -355,22 +355,22 @@ namespace NLastGetopt {
}
return AddLongOption(c, "svnrevision", "print svn version")
.HasArg(NO_ARGUMENT)
- .IfPresentDisableCompletion()
+ .IfPresentDisableCompletion()
.Handler(&PrintVersionAndExit);
}
/**
- * Creates new option for generating completion shell scripts.
- *
- * @param command name of command that should be completed (typically corresponds to the executable name).
- */
- TOpt& AddCompletionOption(TString command, TString longName = "completion");
-
- /**
- * Creates or finds option with given short name
- *
- * @param c new short name for search/create
- */
+ * Creates new option for generating completion shell scripts.
+ *
+ * @param command name of command that should be completed (typically corresponds to the executable name).
+ */
+ TOpt& AddCompletionOption(TString command, TString longName = "completion");
+
+ /**
+ * Creates or finds option with given short name
+ *
+ * @param c new short name for search/create
+ */
TOpt& CharOption(char c) {
const TOpt* opt = FindCharOption(c);
if (opt != nullptr) {
@@ -382,99 +382,99 @@ namespace NLastGetopt {
}
/**
- * Indicate that some options can't appear together.
- *
- * Note: this is not transitive.
- *
- * Note: don't use this on options with default values. If option with default value wasn't specified,
- * parser will run handlers for default value, thus triggering a false-positive exclusivity check.
- */
- template <typename T1, typename T2>
- void MutuallyExclusive(T1&& opt1, T2&& opt2) {
- MutuallyExclusiveOpt(GetOption(std::forward<T1>(opt1)), GetOption(std::forward<T2>(opt2)));
- }
-
- /**
- * Like `MutuallyExclusive`, but accepts `TOpt`s instead of option names.
- */
- void MutuallyExclusiveOpt(TOpt& opt1, TOpt& opt2);
-
- /**
- * @return index of option
- *
- * @param opt pointer of option to search
- */
+ * Indicate that some options can't appear together.
+ *
+ * Note: this is not transitive.
+ *
+ * Note: don't use this on options with default values. If option with default value wasn't specified,
+ * parser will run handlers for default value, thus triggering a false-positive exclusivity check.
+ */
+ template <typename T1, typename T2>
+ void MutuallyExclusive(T1&& opt1, T2&& opt2) {
+ MutuallyExclusiveOpt(GetOption(std::forward<T1>(opt1)), GetOption(std::forward<T2>(opt2)));
+ }
+
+ /**
+ * Like `MutuallyExclusive`, but accepts `TOpt`s instead of option names.
+ */
+ void MutuallyExclusiveOpt(TOpt& opt1, TOpt& opt2);
+
+ /**
+ * @return index of option
+ *
+ * @param opt pointer of option to search
+ */
size_t IndexOf(const TOpt* opt) const;
/**
- * Replace help string with given
- *
- * @param decr new help string
- */
+ * Replace help string with given
+ *
+ * @param decr new help string
+ */
void SetCmdLineDescr(const TString& descr) {
CustomCmdLineDescr = descr;
}
/**
- * Replace usage string with given
- *
- * @param usage new usage string
- */
+ * Replace usage string with given
+ *
+ * @param usage new usage string
+ */
void SetCustomUsage(const TString& usage) {
CustomUsage = usage;
}
/**
- * Add a section to print after the main usage spec.
- */
- void AddSection(TString title, TString text) {
- Sections.emplace_back(std::move(title), std::move(text));
- }
-
- /**
- * Add section with examples.
- *
- * @param examples text of this section
- */
- void SetExamples(TString examples) {
- AddSection("Examples", std::move(examples));
- }
-
- /**
- * Set minimal number of free args
- *
- * @param min new value
- */
+ * Add a section to print after the main usage spec.
+ */
+ void AddSection(TString title, TString text) {
+ Sections.emplace_back(std::move(title), std::move(text));
+ }
+
+ /**
+ * Add section with examples.
+ *
+ * @param examples text of this section
+ */
+ void SetExamples(TString examples) {
+ AddSection("Examples", std::move(examples));
+ }
+
+ /**
+ * Set minimal number of free args
+ *
+ * @param min new value
+ */
void SetFreeArgsMin(size_t min) {
FreeArgsMin_ = ui32(min);
}
-
+
+ /**
+ * Get current minimal number of free args
+ */
+ ui32 GetFreeArgsMin() const {
+ return FreeArgsMin_;
+ }
+
/**
- * Get current minimal number of free args
- */
- ui32 GetFreeArgsMin() const {
- return FreeArgsMin_;
- }
-
- /**
- * Set maximal number of free args
- *
+ * Set maximal number of free args
+ *
* @param max new value
- */
+ */
void SetFreeArgsMax(size_t max) {
FreeArgsMax_ = ui32(max);
FreeArgsMax_ = Max<ui32>(FreeArgsMax_, ArgBindings_.size());
}
/**
- * Get current maximal number of free args
- */
- ui32 GetFreeArgsMax() const {
- return FreeArgsMax_;
- }
-
- /**
+ * Get current maximal number of free args
+ */
+ ui32 GetFreeArgsMax() const {
+ return FreeArgsMax_;
+ }
+
+ /**
* Get mapping for free args
*/
const TMap<ui32, TFreeArgSpec>& GetFreeArgSpecs() const {
@@ -482,161 +482,161 @@ namespace NLastGetopt {
}
/**
- * Set exact expected number of free args
- *
- * @param count new value
- */
+ * Set exact expected number of free args
+ *
+ * @param count new value
+ */
void SetFreeArgsNum(size_t count) {
FreeArgsMin_ = ui32(count);
FreeArgsMax_ = ui32(count);
}
/**
- * Set minimal and maximal number of free args
- *
- * @param min new value for minimal
- * @param max new value for maximal
- */
+ * Set minimal and maximal number of free args
+ *
+ * @param min new value for minimal
+ * @param max new value for maximal
+ */
void SetFreeArgsNum(size_t min, size_t max) {
FreeArgsMin_ = ui32(min);
FreeArgsMax_ = ui32(max);
}
/**
- * Set title and help string of free argument
- *
- * @param pos index of argument
- * @param title new value for argument title
- * @param help new value for help string
- * @param optional indicates that the flag's help string should be rendered as for optional flag;
- * does not affect actual flags parsing
- */
- void SetFreeArgTitle(size_t pos, const TString& title, const TString& help = TString(), bool optional = false);
-
- /**
- * Get free argument's spec for further modification.
- */
- TFreeArgSpec& GetFreeArgSpec(size_t pos);
-
- /**
- * Legacy, don't use. Same as `SetTrailingArgTitle`.
- * Older versions of lastgetopt didn't have destinction between default title and title
- * for the trailing argument.
- */
- void SetFreeArgDefaultTitle(const TString& title, const TString& help = TString()) {
- SetTrailingArgTitle(title, help);
- }
-
- /**
- * Set default title that will be used for all arguments that have no title.
- */
- void SetDefaultFreeArgTitle(TString title) {
- DefaultFreeArgTitle_ = std::move(title);
- }
-
- /**
- * Set default title that will be used for all arguments that have no title.
- */
- const TString& GetDefaultFreeArgTitle() const {
- return DefaultFreeArgTitle_;
- }
-
- /**
- * Set title and help for the trailing argument.
- *
- * This title and help are used to render the last repeated argument when max number of arguments is unlimited.
- */
- /// @{
- void SetTrailingArgTitle(TString title) {
- TrailingArgSpec_.Title(std::move(title));
- }
- void SetTrailingArgTitle(TString title, TString help) {
- TrailingArgSpec_.Title(std::move(title));
- TrailingArgSpec_.Help(std::move(help));
- }
- /// @}
-
- /**
- * Get spec for the trailing argument.
- *
- * This spec is used to render the last repeated argument when max number of arguments is unlimited.
- */
- /// @{
- TFreeArgSpec& GetTrailingArgSpec() {
- return TrailingArgSpec_;
- }
- const TFreeArgSpec& GetTrailingArgSpec() const {
- return TrailingArgSpec_;
- }
- /// @}
-
- /**
- * Set the rule of parsing single dash as prefix of long names
- *
- * @param value new value of the option
- */
+ * Set title and help string of free argument
+ *
+ * @param pos index of argument
+ * @param title new value for argument title
+ * @param help new value for help string
+ * @param optional indicates that the flag's help string should be rendered as for optional flag;
+ * does not affect actual flags parsing
+ */
+ void SetFreeArgTitle(size_t pos, const TString& title, const TString& help = TString(), bool optional = false);
+
+ /**
+ * Get free argument's spec for further modification.
+ */
+ TFreeArgSpec& GetFreeArgSpec(size_t pos);
+
+ /**
+ * Legacy, don't use. Same as `SetTrailingArgTitle`.
+ * Older versions of lastgetopt didn't have destinction between default title and title
+ * for the trailing argument.
+ */
+ void SetFreeArgDefaultTitle(const TString& title, const TString& help = TString()) {
+ SetTrailingArgTitle(title, help);
+ }
+
+ /**
+ * Set default title that will be used for all arguments that have no title.
+ */
+ void SetDefaultFreeArgTitle(TString title) {
+ DefaultFreeArgTitle_ = std::move(title);
+ }
+
+ /**
+ * Set default title that will be used for all arguments that have no title.
+ */
+ const TString& GetDefaultFreeArgTitle() const {
+ return DefaultFreeArgTitle_;
+ }
+
+ /**
+ * Set title and help for the trailing argument.
+ *
+ * This title and help are used to render the last repeated argument when max number of arguments is unlimited.
+ */
+ /// @{
+ void SetTrailingArgTitle(TString title) {
+ TrailingArgSpec_.Title(std::move(title));
+ }
+ void SetTrailingArgTitle(TString title, TString help) {
+ TrailingArgSpec_.Title(std::move(title));
+ TrailingArgSpec_.Help(std::move(help));
+ }
+ /// @}
+
+ /**
+ * Get spec for the trailing argument.
+ *
+ * This spec is used to render the last repeated argument when max number of arguments is unlimited.
+ */
+ /// @{
+ TFreeArgSpec& GetTrailingArgSpec() {
+ return TrailingArgSpec_;
+ }
+ const TFreeArgSpec& GetTrailingArgSpec() const {
+ return TrailingArgSpec_;
+ }
+ /// @}
+
+ /**
+ * Set the rule of parsing single dash as prefix of long names
+ *
+ * @param value new value of the option
+ */
void SetAllowSingleDashForLong(bool value) {
AllowSingleDashForLong_ = value;
}
/**
- * Wrap help text at this number of characters. 0 to disable wrapping.
- */
- void SetWrap(ui32 wrap = 80) {
- Wrap_ = wrap;
- }
-
- /**
- * Print usage string
- *
- * @param program prefix of result (path to the program)
- * @param os destination stream
- * @param colors colorizer
- */
+ * Wrap help text at this number of characters. 0 to disable wrapping.
+ */
+ void SetWrap(ui32 wrap = 80) {
+ Wrap_ = wrap;
+ }
+
+ /**
+ * Print usage string
+ *
+ * @param program prefix of result (path to the program)
+ * @param os destination stream
+ * @param colors colorizer
+ */
void PrintUsage(const TStringBuf& program, IOutputStream& os, const NColorizer::TColors& colors) const;
/**
- * Print usage string
- *
- * @param program prefix of result (path to the program)
- * @param os destination stream
- */
+ * Print usage string
+ *
+ * @param program prefix of result (path to the program)
+ * @param os destination stream
+ */
void PrintUsage(const TStringBuf& program, IOutputStream& os = Cout) const;
/**
- * Get list of options in order of definition.
- */
- TVector<const TOpt*> GetOpts() const {
- auto ret = TVector<const TOpt*>(Reserve(Opts_.size()));
- for (auto& opt : Opts_) {
- ret.push_back(opt.Get());
- }
- return ret;
- }
+ * Get list of options in order of definition.
+ */
+ TVector<const TOpt*> GetOpts() const {
+ auto ret = TVector<const TOpt*>(Reserve(Opts_.size()));
+ for (auto& opt : Opts_) {
+ ret.push_back(opt.Get());
+ }
+ return ret;
+ }
- private:
+ private:
/**
- * @return argument title of a free argument
- *
- * @param pos position of the argument
- */
- TStringBuf GetFreeArgTitle(size_t pos) const;
+ * @return argument title of a free argument
+ *
+ * @param pos position of the argument
+ */
+ TStringBuf GetFreeArgTitle(size_t pos) const;
/**
- * Print usage helper
- *
- * @param program prefix of result (path to the program)
- * @param os destination stream
- * @param colors colorizer
- */
+ * Print usage helper
+ *
+ * @param program prefix of result (path to the program)
+ * @param os destination stream
+ * @param colors colorizer
+ */
void PrintCmdLine(const TStringBuf& program, IOutputStream& os, const NColorizer::TColors& colors) const;
/**
- * Print usage helper
- *
- * @param os destination stream
- * @param colors colorizer
- */
+ * Print usage helper
+ *
+ * @param os destination stream
+ * @param colors colorizer
+ */
void PrintFreeArgsDesc(IOutputStream& os, const NColorizer::TColors& colors) const;
};
diff --git a/library/cpp/getopt/small/last_getopt_parse_result.cpp b/library/cpp/getopt/small/last_getopt_parse_result.cpp
index ac27736a14..f4b5607a90 100644
--- a/library/cpp/getopt/small/last_getopt_parse_result.cpp
+++ b/library/cpp/getopt/small/last_getopt_parse_result.cpp
@@ -42,7 +42,7 @@ namespace NLastGetopt {
const TOptParseResult* r = FindOptParseResult(opt, includeDefault);
if (!r || r->Empty()) {
try {
- throw TUsageException() << "option " << opt->ToShortString() << " is unspecified";
+ throw TUsageException() << "option " << opt->ToShortString() << " is unspecified";
} catch (...) {
HandleError();
// unreachable
@@ -99,10 +99,10 @@ namespace NLastGetopt {
return Parser_->ProgramName_;
}
- void TOptsParseResult::PrintUsage(IOutputStream& os) const {
- Parser_->Opts_->PrintUsage(Parser_->ProgramName_, os);
- }
-
+ void TOptsParseResult::PrintUsage(IOutputStream& os) const {
+ Parser_->Opts_->PrintUsage(Parser_->ProgramName_, os);
+ }
+
size_t TOptsParseResult::GetFreeArgsPos() const {
return Parser_->Pos_;
}
@@ -147,7 +147,7 @@ namespace NLastGetopt {
if (Parser_->Opts_->FindLongOption("help") != nullptr) {
Cerr << "Try '" << Parser_->ProgramName_ << " --help' for more information." << Endl;
} else {
- PrintUsage();
+ PrintUsage();
}
}
exit(1);
diff --git a/library/cpp/getopt/small/last_getopt_parse_result.h b/library/cpp/getopt/small/last_getopt_parse_result.h
index a4baf8ca6b..1ab6f598c9 100644
--- a/library/cpp/getopt/small/last_getopt_parse_result.h
+++ b/library/cpp/getopt/small/last_getopt_parse_result.h
@@ -1,15 +1,15 @@
#pragma once
#include "last_getopt_opts.h"
-#include "last_getopt_parser.h"
+#include "last_getopt_parser.h"
namespace NLastGetopt {
/**
- * NLastGetopt::TOptParseResult contains all arguments for exactly one TOpt,
- * that have been fetched during parsing
- *
- * The class is a wraper over a vector of nil-terminated strings.
- */
+ * NLastGetopt::TOptParseResult contains all arguments for exactly one TOpt,
+ * that have been fetched during parsing
+ *
+ * The class is a wraper over a vector of nil-terminated strings.
+ */
class TOptParseResult {
public:
typedef TVector<const char*> TValues;
@@ -56,14 +56,14 @@ namespace NLastGetopt {
};
/**
- * NLastGetopt::TOptsParseResult contains result of parsing argc,argv be parser.
- *
- * In most common case constructed by argc,argv pair and rules (TOpts).
- * The instance being constructed validates rules and performs parsing, stores result for futher access.
- *
- * If error during parsing occures, the program aborts with exit code 1.
- * Note, that if PERMUTE mode is on, then data, pointed by argv can be changed.
- */
+ * NLastGetopt::TOptsParseResult contains result of parsing argc,argv be parser.
+ *
+ * In most common case constructed by argc,argv pair and rules (TOpts).
+ * The instance being constructed validates rules and performs parsing, stores result for futher access.
+ *
+ * If error during parsing occures, the program aborts with exit code 1.
+ * Note, that if PERMUTE mode is on, then data, pointed by argv can be changed.
+ */
class TOptsParseResult {
private:
THolder<TOptsParser> Parser_; //The instance of parser.
@@ -78,49 +78,49 @@ namespace NLastGetopt {
TOptParseResult& OptParseResult();
/**
- * Searchs for object in given container
- *
- * @param vec container
- * @param opt ptr for required object
- *
- * @retunr ptr on corresponding TOptParseResult
- */
+ * Searchs for object in given container
+ *
+ * @param vec container
+ * @param opt ptr for required object
+ *
+ * @retunr ptr on corresponding TOptParseResult
+ */
static const TOptParseResult* FindParseResult(const TdVec& vec, const TOpt* opt);
protected:
/**
- * Performs parsing of comand line arguments.
- */
+ * Performs parsing of comand line arguments.
+ */
void Init(const TOpts* options, int argc, const char** argv);
TOptsParseResult() = default;
public:
/**
- * The action in case of parser failure.
- * Allows to asjust behavior in derived classes.
- * By default prints error string and aborts the program
- */
+ * The action in case of parser failure.
+ * Allows to asjust behavior in derived classes.
+ * By default prints error string and aborts the program
+ */
virtual void HandleError() const;
/**
- * Constructs object by parsing arguments with given rules
- *
- * @param options ptr on parsing rules
- * @param argc
- * @param argv
- */
+ * Constructs object by parsing arguments with given rules
+ *
+ * @param options ptr on parsing rules
+ * @param argc
+ * @param argv
+ */
TOptsParseResult(const TOpts* options, int argc, const char* argv[]) {
Init(options, argc, argv);
}
/**
- * Constructs object by parsing arguments with given rules
- *
- * @param options ptr on parsing rules
- * @param argc
- * @param argv
- */
+ * Constructs object by parsing arguments with given rules
+ *
+ * @param options ptr on parsing rules
+ * @param argc
+ * @param argv
+ */
TOptsParseResult(const TOpts* options, int argc, char* argv[]) {
Init(options, argc, const_cast<const char**>(argv));
}
@@ -128,146 +128,146 @@ namespace NLastGetopt {
virtual ~TOptsParseResult() = default;
/**
- * Search for TOptParseResult that corresponds to given option (TOpt)
- *
- * @param opt ptr on required object
- * @param includeDefault search in results obtained from default values
- *
- * @return ptr on result
- */
+ * Search for TOptParseResult that corresponds to given option (TOpt)
+ *
+ * @param opt ptr on required object
+ * @param includeDefault search in results obtained from default values
+ *
+ * @return ptr on result
+ */
const TOptParseResult* FindOptParseResult(const TOpt* opt, bool includeDefault = false) const;
/**
- * Search for TOptParseResult that corresponds to given long name
- *
- * @param name long name of required object
- * @param includeDefault search in results obtained from default values
- *
- * @return ptr on result
- */
+ * Search for TOptParseResult that corresponds to given long name
+ *
+ * @param name long name of required object
+ * @param includeDefault search in results obtained from default values
+ *
+ * @return ptr on result
+ */
const TOptParseResult* FindLongOptParseResult(const TString& name, bool includeDefault = false) const;
/**
- * Search for TOptParseResult that corresponds to given short name
- *
- * @param c short name of required object
- * @param includeDefault search in results obtained from default values
- *
- * @return ptr on result
- */
+ * Search for TOptParseResult that corresponds to given short name
+ *
+ * @param c short name of required object
+ * @param includeDefault search in results obtained from default values
+ *
+ * @return ptr on result
+ */
const TOptParseResult* FindCharOptParseResult(char c, bool includeDefault = false) const;
/**
- * @return argv[0]
- */
+ * @return argv[0]
+ */
TString GetProgramName() const;
/**
- * Print usage string.
- */
- void PrintUsage(IOutputStream& os = Cout) const;
-
- /**
- * @return position in [premuted argv] of the first free argument
- */
+ * Print usage string.
+ */
+ void PrintUsage(IOutputStream& os = Cout) const;
+
+ /**
+ * @return position in [premuted argv] of the first free argument
+ */
size_t GetFreeArgsPos() const;
/**
- * @return number of fetched free arguments
- */
+ * @return number of fetched free arguments
+ */
size_t GetFreeArgCount() const;
/**
- * @return all fetched free arguments
- */
+ * @return all fetched free arguments
+ */
TVector<TString> GetFreeArgs() const;
/**
- * @return true if given option exist in results of parsing
- *
- * @param opt ptr on required object
- * @param includeDefault search in results obtained from default values
- *
- */
+ * @return true if given option exist in results of parsing
+ *
+ * @param opt ptr on required object
+ * @param includeDefault search in results obtained from default values
+ *
+ */
bool Has(const TOpt* opt, bool includeDefault = false) const;
/**
- * @return nil terminated string on the last fetched argument of givne option
- *
- * @param opt ptr on required object
- * @param includeDefault search in results obtained from default values
- */
+ * @return nil terminated string on the last fetched argument of givne option
+ *
+ * @param opt ptr on required object
+ * @param includeDefault search in results obtained from default values
+ */
const char* Get(const TOpt* opt, bool includeDefault = true) const;
/**
- * @return nil terminated string on the last fetched argument of givne option
- * if option haven't been fetched, given defaultValue will be returned
- *
- * @param opt ptr on required object
- * @param defaultValue
- */
+ * @return nil terminated string on the last fetched argument of givne option
+ * if option haven't been fetched, given defaultValue will be returned
+ *
+ * @param opt ptr on required object
+ * @param defaultValue
+ */
const char* GetOrElse(const TOpt* opt, const char* defaultValue) const;
/**
- * @return true if given option exist in results of parsing
- *
- * @param name long name of required object
- * @param includeDefault search in results obtained from default values
- *
- */
+ * @return true if given option exist in results of parsing
+ *
+ * @param name long name of required object
+ * @param includeDefault search in results obtained from default values
+ *
+ */
bool Has(const TString& name, bool includeDefault = false) const;
/**
- * @return nil terminated string on the last fetched argument of givne option
- *
- * @param name long name of required object
- * @param includeDefault search in results obtained from default values
- */
+ * @return nil terminated string on the last fetched argument of givne option
+ *
+ * @param name long name of required object
+ * @param includeDefault search in results obtained from default values
+ */
const char* Get(const TString& name, bool includeDefault = true) const;
/**
- * @return nil terminated string on the last fetched argument of givne option
- * if option haven't been fetched, given defaultValue will be returned
- *
- * @param name long name of required object
- * @param defaultValue
- */
+ * @return nil terminated string on the last fetched argument of givne option
+ * if option haven't been fetched, given defaultValue will be returned
+ *
+ * @param name long name of required object
+ * @param defaultValue
+ */
const char* GetOrElse(const TString& name, const char* defaultValue) const;
/**
- * @return true if given option exist in results of parsing
- *
- * @param c short name of required object
- * @param includeDefault search in results obtained from default values
- *
- */
+ * @return true if given option exist in results of parsing
+ *
+ * @param c short name of required object
+ * @param includeDefault search in results obtained from default values
+ *
+ */
bool Has(char name, bool includeDefault = false) const;
/**
- * @return nil terminated string on the last fetched argument of givne option
- *
- * @param c short name of required object
- * @param includeDefault search in results obtained from default values
- */
+ * @return nil terminated string on the last fetched argument of givne option
+ *
+ * @param c short name of required object
+ * @param includeDefault search in results obtained from default values
+ */
const char* Get(char name, bool includeDefault = true) const;
/**
- * @return nil terminated string on the last fetched argument of givne option
- * if option haven't been fetched, given defaultValue will be returned
- *
- * @param c short name of required object
- * @param defaultValue
- */
+ * @return nil terminated string on the last fetched argument of givne option
+ * if option haven't been fetched, given defaultValue will be returned
+ *
+ * @param c short name of required object
+ * @param defaultValue
+ */
const char* GetOrElse(char name, const char* defaultValue) const;
/**
- * for givne option return parsed value of the last fetched argument
- * if option haven't been fetched, HandleError action is called
- *
- * @param opt required option (one of: ptr, short name, long name).
- *
- * @return FromString<T>(last feteched argument)
- */
+ * for givne option return parsed value of the last fetched argument
+ * if option haven't been fetched, HandleError action is called
+ *
+ * @param opt required option (one of: ptr, short name, long name).
+ *
+ * @return FromString<T>(last feteched argument)
+ */
template <typename T, typename TKey>
T Get(const TKey opt) const {
const char* value = Get(opt);
@@ -280,14 +280,14 @@ namespace NLastGetopt {
}
/**
- * for givne option return parsed value of the last fetched argument
- * if option haven't been fetched, given defaultValue will be returned
- *
- * @param opt required option (one of: ptr, short name, long name).
- * @param defaultValue
- *
- * @return FromString<T>(last feteched argument)
- */
+ * for givne option return parsed value of the last fetched argument
+ * if option haven't been fetched, given defaultValue will be returned
+ *
+ * @param opt required option (one of: ptr, short name, long name).
+ * @param defaultValue
+ *
+ * @return FromString<T>(last feteched argument)
+ */
template <typename T, typename TKey>
T GetOrElse(const TKey opt, const T& defaultValue) const {
if (Has(opt))
@@ -298,11 +298,11 @@ namespace NLastGetopt {
};
/**
- * NLastGetopt::TOptsParseResultException contains result of parsing argc,argv be parser.
- *
- * Unlike TOptsParseResult, if error during parsing occures, an exception is thrown.
- *
- */
+ * NLastGetopt::TOptsParseResultException contains result of parsing argc,argv be parser.
+ *
+ * Unlike TOptsParseResult, if error during parsing occures, an exception is thrown.
+ *
+ */
class TOptsParseResultException: public TOptsParseResult {
public:
TOptsParseResultException(const TOpts* options, int argc, const char* argv[]) {
diff --git a/library/cpp/getopt/small/last_getopt_parser.cpp b/library/cpp/getopt/small/last_getopt_parser.cpp
index 10eebc3c45..7668b12a03 100644
--- a/library/cpp/getopt/small/last_getopt_parser.cpp
+++ b/library/cpp/getopt/small/last_getopt_parser.cpp
@@ -11,7 +11,7 @@ namespace NLastGetopt {
Opts_ = opts;
if (argc < 1)
- throw TUsageException() << "argv must have at least one argument";
+ throw TUsageException() << "argv must have at least one argument";
Argc_ = argc;
Argv_ = argv;
@@ -66,11 +66,11 @@ namespace NLastGetopt {
Y_ASSERT(!Stopped_);
if (Opts_->FreeArgsMin_ == Opts_->FreeArgsMax_ && Argc_ - Pos_ != Opts_->FreeArgsMin_)
- throw TUsageException() << "required exactly " << Opts_->FreeArgsMin_ << " free args";
+ throw TUsageException() << "required exactly " << Opts_->FreeArgsMin_ << " free args";
else if (Argc_ - Pos_ < Opts_->FreeArgsMin_)
- throw TUsageException() << "required at least " << Opts_->FreeArgsMin_ << " free args";
+ throw TUsageException() << "required at least " << Opts_->FreeArgsMin_ << " free args";
else if (Argc_ - Pos_ > Opts_->FreeArgsMax_)
- throw TUsageException() << "required at most " << Opts_->FreeArgsMax_ << " free args";
+ throw TUsageException() << "required at most " << Opts_->FreeArgsMax_ << " free args";
return false;
}
@@ -83,7 +83,7 @@ namespace NLastGetopt {
Y_ASSERT(EIO_NONE != IsOpt(arg));
if (!Opts_->AllowUnknownCharOptions_)
- throw TUsageException() << "unknown option '" << EscapeC(arg[sop])
+ throw TUsageException() << "unknown option '" << EscapeC(arg[sop])
<< "' in '" << arg << "'";
TempCurrentOpt_.Reset(new TOpt);
@@ -152,13 +152,13 @@ namespace NLastGetopt {
} else if (Opts_->AllowUnknownLongOptions_) {
return false;
} else {
- throw TUsageException() << "unknown option '" << optionName
+ throw TUsageException() << "unknown option '" << optionName
<< "' in '" << Argv_[pos] << "'";
}
}
if (arg.IsInited()) {
if (option->GetHasArg() == NO_ARGUMENT)
- throw TUsageException() << "option " << optionName << " must have no arg";
+ throw TUsageException() << "option " << optionName << " must have no arg";
return Commit(option, arg, pos + 1, 0);
}
++pos;
@@ -175,7 +175,7 @@ namespace NLastGetopt {
}
if (pos == Argc_) {
if (opt->GetHasArg() == REQUIRED_ARGUMENT)
- throw TUsageException() << "option " << opt->ToShortString() << " must have arg";
+ throw TUsageException() << "option " << opt->ToShortString() << " must have arg";
return Commit(opt, nullptr, pos, 0);
}
const TStringBuf arg(Argv_[pos]);
diff --git a/library/cpp/getopt/small/last_getopt_parser.h b/library/cpp/getopt/small/last_getopt_parser.h
index 19c34dce51..2cf8a6c308 100644
--- a/library/cpp/getopt/small/last_getopt_parser.h
+++ b/library/cpp/getopt/small/last_getopt_parser.h
@@ -88,26 +88,26 @@ namespace NLastGetopt {
/// fetch next argument, false if no more arguments left
bool Next();
- bool Seen(const TOpt* opt) const {
- return OptsSeen_.contains(opt);
- }
-
- bool Seen(TStringBuf name) const {
- if (auto opt = Opts_->FindLongOption(name)) {
- return Seen(opt);
- } else {
- return false;
- }
- }
-
- bool Seen(char name) const {
- if (auto opt = Opts_->FindCharOption(name)) {
- return Seen(opt);
- } else {
- return false;
- }
- }
-
+ bool Seen(const TOpt* opt) const {
+ return OptsSeen_.contains(opt);
+ }
+
+ bool Seen(TStringBuf name) const {
+ if (auto opt = Opts_->FindLongOption(name)) {
+ return Seen(opt);
+ } else {
+ return false;
+ }
+ }
+
+ bool Seen(char name) const {
+ if (auto opt = Opts_->FindCharOption(name)) {
+ return Seen(opt);
+ } else {
+ return false;
+ }
+ }
+
const TOpt* CurOpt() const {
return CurrentOpt_;
}
diff --git a/library/cpp/getopt/small/last_getopt_support.h b/library/cpp/getopt/small/last_getopt_support.h
index d0e0baf77a..17bed3e614 100644
--- a/library/cpp/getopt/small/last_getopt_support.h
+++ b/library/cpp/getopt/small/last_getopt_support.h
@@ -16,13 +16,13 @@ namespace NLastGetopt {
class TException: public yexception {
};
- /// TOpts configuration is incorrect
+ /// TOpts configuration is incorrect
class TConfException: public TException {
};
- /// User passed incorrect arguments, parsing failed
- /// Note: use `throw TUsageException()` instead of `ythrow TUsageException()` to prevent appearence of stacktrace
- /// and location of the `ythrow` statment in error messages.
+ /// User passed incorrect arguments, parsing failed
+ /// Note: use `throw TUsageException()` instead of `ythrow TUsageException()` to prevent appearence of stacktrace
+ /// and location of the `ythrow` statment in error messages.
class TUsageException: public TException {
};
@@ -166,7 +166,7 @@ namespace NLastGetopt {
try {
return OptFromStringImpl<T>(value);
} catch (...) {
- throw TUsageException() << "failed to parse opt " << OptToString(opt) << " value " << TString(value).Quote() << ": " << CurrentExceptionMessage();
+ throw TUsageException() << "failed to parse opt " << OptToString(opt) << " value " << TString(value).Quote() << ": " << CurrentExceptionMessage();
}
}
diff --git a/library/cpp/getopt/small/modchooser.cpp b/library/cpp/getopt/small/modchooser.cpp
index 64d18862be..2fa5cfd070 100644
--- a/library/cpp/getopt/small/modchooser.cpp
+++ b/library/cpp/getopt/small/modchooser.cpp
@@ -1,7 +1,7 @@
-#include "completer.h"
-#include "completer_command.h"
-#include "completion_generator.h"
-#include "last_getopt.h"
+#include "completer.h"
+#include "completer_command.h"
+#include "completion_generator.h"
+#include "last_getopt.h"
#include "modchooser.h"
#include <library/cpp/colorizer/colors.h>
@@ -10,54 +10,54 @@
#include <util/stream/format.h>
#include <util/generic/yexception.h>
#include <util/generic/ptr.h>
-#include <util/string/builder.h>
-#include <util/string/join.h>
+#include <util/string/builder.h>
+#include <util/string/join.h>
-class PtrWrapper: public TMainClass {
+class PtrWrapper: public TMainClass {
public:
explicit PtrWrapper(const TMainFunctionPtr main)
: Main(main)
{
}
- int operator()(const int argc, const char** argv) override {
- return Main(argc, argv);
+ int operator()(const int argc, const char** argv) override {
+ return Main(argc, argv);
}
private:
TMainFunctionPtr Main;
};
-class PtrvWrapper: public TMainClass {
+class PtrvWrapper: public TMainClass {
public:
explicit PtrvWrapper(const TMainFunctionPtrV main)
: Main(main)
{
}
- int operator()(const int argc, const char** argv) override {
- TVector<TString> nargv(argv, argv + argc);
- return Main(nargv);
+ int operator()(const int argc, const char** argv) override {
+ TVector<TString> nargv(argv, argv + argc);
+ return Main(nargv);
}
private:
TMainFunctionPtrV Main;
};
-class ClassWrapper: public TMainClass {
+class ClassWrapper: public TMainClass {
public:
- explicit ClassWrapper(TMainClassV* main)
+ explicit ClassWrapper(TMainClassV* main)
: Main(main)
{
}
- int operator()(const int argc, const char** argv) override {
- TVector<TString> nargv(argv, argv + argc);
- return (*Main)(nargv);
+ int operator()(const int argc, const char** argv) override {
+ TVector<TString> nargv(argv, argv + argc);
+ return (*Main)(nargv);
}
private:
- TMainClassV* Main;
+ TMainClassV* Main;
};
TModChooser::TMode::TMode(const TString& name, TMainClass* main, const TString& descr, bool hidden, bool noCompletion)
@@ -83,7 +83,7 @@ TModChooser::~TModChooser() = default;
void TModChooser::AddMode(const TString& mode, const TMainFunctionRawPtr func, const TString& description, bool hidden, bool noCompletion) {
AddMode(mode, TMainFunctionPtr(func), description, hidden, noCompletion);
}
-
+
void TModChooser::AddMode(const TString& mode, const TMainFunctionRawPtrV func, const TString& description, bool hidden, bool noCompletion) {
AddMode(mode, TMainFunctionPtrV(func), description, hidden, noCompletion);
}
@@ -109,8 +109,8 @@ void TModChooser::AddMode(const TString& mode, TMainClass* func, const TString&
void TModChooser::AddMode(const TString& mode, TMainClassV* func, const TString& description, bool hidden, bool noCompletion) {
Wrappers.push_back(MakeHolder<ClassWrapper>(func));
AddMode(mode, Wrappers.back().Get(), description, hidden, noCompletion);
-}
-
+}
+
void TModChooser::AddGroupModeDescription(const TString& description, bool hidden, bool noCompletion) {
UnsortedModes.push_back(MakeHolder<TMode>(TString(), nullptr, description.data(), hidden, noCompletion));
}
@@ -119,15 +119,15 @@ void TModChooser::SetDefaultMode(const TString& mode) {
DefaultMode = mode;
}
-void TModChooser::AddAlias(const TString& alias, const TString& mode) {
- if (!Modes.FindPtr(mode)) {
- ythrow yexception() << "TMode '" << mode << "' not found in TModChooser.";
- }
-
- Modes[mode]->Aliases.push_back(alias);
- Modes[alias] = Modes[mode];
-}
-
+void TModChooser::AddAlias(const TString& alias, const TString& mode) {
+ if (!Modes.FindPtr(mode)) {
+ ythrow yexception() << "TMode '" << mode << "' not found in TModChooser.";
+ }
+
+ Modes[mode]->Aliases.push_back(alias);
+ Modes[alias] = Modes[mode];
+}
+
void TModChooser::SetDescription(const TString& descr) {
Description = descr;
}
@@ -157,18 +157,18 @@ void TModChooser::DisableSvnRevisionOption() {
}
void TModChooser::AddCompletions(TString progName, const TString& name, bool hidden, bool noCompletion) {
- if (CompletionsGenerator == nullptr) {
- CompletionsGenerator = NLastGetopt::MakeCompletionMod(this, std::move(progName), name);
+ if (CompletionsGenerator == nullptr) {
+ CompletionsGenerator = NLastGetopt::MakeCompletionMod(this, std::move(progName), name);
AddMode(name, CompletionsGenerator.Get(), "generate autocompletion files", hidden, noCompletion);
- }
+ }
}
-int TModChooser::Run(const int argc, const char** argv) const {
- Y_ENSURE(argc, "Can't run TModChooser with empty list of arguments.");
+int TModChooser::Run(const int argc, const char** argv) const {
+ Y_ENSURE(argc, "Can't run TModChooser with empty list of arguments.");
bool shiftArgs = true;
TString modeName;
- if (argc == 1) {
+ if (argc == 1) {
if (DefaultMode.empty()) {
PrintHelp(argv[0]);
return 0;
@@ -205,89 +205,89 @@ int TModChooser::Run(const int argc, const char** argv) const {
}
if (shiftArgs) {
- TString firstArg;
+ TString firstArg;
TVector<const char*> nargv(Reserve(argc));
-
+
if (PrintShortCommandInUsage) {
- firstArg = modeIter->second->Name;
+ firstArg = modeIter->second->Name;
} else {
- firstArg = argv[0] + TString(" ") + modeIter->second->Name;
+ firstArg = argv[0] + TString(" ") + modeIter->second->Name;
}
- nargv.push_back(firstArg.data());
-
- for (int i = 2; i < argc; ++i) {
+ nargv.push_back(firstArg.data());
+
+ for (int i = 2; i < argc; ++i) {
nargv.push_back(argv[i]);
}
// According to the standard, "argv[argc] shall be a null pointer" (5.1.2.2.1).
// http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1336
nargv.push_back(nullptr);
-
+
return (*modeIter->second->Main)(nargv.size() - 1, nargv.data());
} else {
- return (*modeIter->second->Main)(argc, argv);
+ return (*modeIter->second->Main)(argc, argv);
}
}
-int TModChooser::Run(const TVector<TString>& argv) const {
+int TModChooser::Run(const TVector<TString>& argv) const {
TVector<const char*> nargv(Reserve(argv.size() + 1));
- for (auto& arg : argv) {
- nargv.push_back(arg.c_str());
- }
+ for (auto& arg : argv) {
+ nargv.push_back(arg.c_str());
+ }
// According to the standard, "argv[argc] shall be a null pointer" (5.1.2.2.1).
// http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1336
nargv.push_back(nullptr);
return Run(nargv.size() - 1, nargv.data());
-}
-
-size_t TModChooser::TMode::CalculateFullNameLen() const {
- size_t len = Name.size();
- if (Aliases) {
- len += 2;
- for (auto& alias : Aliases) {
- len += alias.size() + 1;
- }
- }
- return len;
-}
-
-TString TModChooser::TMode::FormatFullName(size_t pad) const {
- TStringBuilder name;
- if (Aliases) {
- name << "{";
- }
-
- name << NColorizer::StdErr().GreenColor();
- name << Name;
- name << NColorizer::StdErr().OldColor();
-
- if (Aliases) {
- for (const auto& alias : Aliases) {
- name << "|" << NColorizer::StdErr().GreenColor() << alias << NColorizer::StdErr().OldColor();
- }
- name << "}";
- }
-
- auto len = CalculateFullNameLen();
- if (pad > len) {
- name << TString(" ") * (pad - len);
- }
-
- return name;
-}
-
+}
+
+size_t TModChooser::TMode::CalculateFullNameLen() const {
+ size_t len = Name.size();
+ if (Aliases) {
+ len += 2;
+ for (auto& alias : Aliases) {
+ len += alias.size() + 1;
+ }
+ }
+ return len;
+}
+
+TString TModChooser::TMode::FormatFullName(size_t pad) const {
+ TStringBuilder name;
+ if (Aliases) {
+ name << "{";
+ }
+
+ name << NColorizer::StdErr().GreenColor();
+ name << Name;
+ name << NColorizer::StdErr().OldColor();
+
+ if (Aliases) {
+ for (const auto& alias : Aliases) {
+ name << "|" << NColorizer::StdErr().GreenColor() << alias << NColorizer::StdErr().OldColor();
+ }
+ name << "}";
+ }
+
+ auto len = CalculateFullNameLen();
+ if (pad > len) {
+ name << TString(" ") * (pad - len);
+ }
+
+ return name;
+}
+
void TModChooser::PrintHelp(const TString& progName) const {
- Cerr << Description << Endl << Endl;
+ Cerr << Description << Endl << Endl;
Cerr << NColorizer::StdErr().BoldColor() << "Usage" << NColorizer::StdErr().OldColor() << ": " << progName << " MODE [MODE_OPTIONS]" << Endl;
Cerr << Endl;
Cerr << NColorizer::StdErr().BoldColor() << "Modes" << NColorizer::StdErr().OldColor() << ":" << Endl;
size_t maxModeLen = 0;
- for (const auto& [name, mode] : Modes) {
- if (name != mode->Name)
- continue; // this is an alias
- maxModeLen = Max(maxModeLen, mode->CalculateFullNameLen());
- }
+ for (const auto& [name, mode] : Modes) {
+ if (name != mode->Name)
+ continue; // this is an alias
+ maxModeLen = Max(maxModeLen, mode->CalculateFullNameLen());
+ }
if (ShowSeparated) {
for (const auto& unsortedMode : UnsortedModes)
@@ -300,14 +300,14 @@ void TModChooser::PrintHelp(const TString& progName) const {
}
}
} else {
- for (const auto& mode : Modes) {
- if (mode.first != mode.second->Name)
- continue; // this is an alias
+ for (const auto& mode : Modes) {
+ if (mode.first != mode.second->Name)
+ continue; // this is an alias
if (!mode.second->Hidden) {
Cerr << " " << mode.second->FormatFullName(maxModeLen + 4) << mode.second->Description << Endl;
}
- }
+ }
}
Cerr << Endl;
@@ -319,54 +319,54 @@ void TModChooser::PrintHelp(const TString& progName) const {
}
return;
}
-
-TVersionHandlerPtr TModChooser::GetVersionHandler() const {
- return VersionHandler;
-}
-
-bool TModChooser::IsSvnRevisionOptionDisabled() const {
- return SvnRevisionOptionDisabled;
-}
-
-int TMainClassArgs::Run(int argc, const char** argv) {
- return DoRun(NLastGetopt::TOptsParseResult(&GetOptions(), argc, argv));
-}
-
-const NLastGetopt::TOpts& TMainClassArgs::GetOptions() {
- if (Opts_.Empty()) {
- Opts_ = NLastGetopt::TOpts();
- RegisterOptions(Opts_.GetRef());
- }
-
- return Opts_.GetRef();
-}
-
-void TMainClassArgs::RegisterOptions(NLastGetopt::TOpts& opts) {
- opts.AddHelpOption('h');
-}
-
-int TMainClassArgs::operator()(const int argc, const char** argv) {
- return Run(argc, argv);
-}
-
-int TMainClassModes::operator()(const int argc, const char** argv) {
- return Run(argc, argv);
-}
-
-int TMainClassModes::Run(int argc, const char** argv) {
- auto& chooser = GetSubModes();
- return chooser.Run(argc, argv);
-}
-
-const TModChooser& TMainClassModes::GetSubModes() {
- if (Modes_.Empty()) {
- Modes_.ConstructInPlace();
- RegisterModes(Modes_.GetRef());
- }
-
- return Modes_.GetRef();
-}
-
-void TMainClassModes::RegisterModes(TModChooser& modes) {
- modes.SetModesHelpOption("-h");
-}
+
+TVersionHandlerPtr TModChooser::GetVersionHandler() const {
+ return VersionHandler;
+}
+
+bool TModChooser::IsSvnRevisionOptionDisabled() const {
+ return SvnRevisionOptionDisabled;
+}
+
+int TMainClassArgs::Run(int argc, const char** argv) {
+ return DoRun(NLastGetopt::TOptsParseResult(&GetOptions(), argc, argv));
+}
+
+const NLastGetopt::TOpts& TMainClassArgs::GetOptions() {
+ if (Opts_.Empty()) {
+ Opts_ = NLastGetopt::TOpts();
+ RegisterOptions(Opts_.GetRef());
+ }
+
+ return Opts_.GetRef();
+}
+
+void TMainClassArgs::RegisterOptions(NLastGetopt::TOpts& opts) {
+ opts.AddHelpOption('h');
+}
+
+int TMainClassArgs::operator()(const int argc, const char** argv) {
+ return Run(argc, argv);
+}
+
+int TMainClassModes::operator()(const int argc, const char** argv) {
+ return Run(argc, argv);
+}
+
+int TMainClassModes::Run(int argc, const char** argv) {
+ auto& chooser = GetSubModes();
+ return chooser.Run(argc, argv);
+}
+
+const TModChooser& TMainClassModes::GetSubModes() {
+ if (Modes_.Empty()) {
+ Modes_.ConstructInPlace();
+ RegisterModes(Modes_.GetRef());
+ }
+
+ return Modes_.GetRef();
+}
+
+void TMainClassModes::RegisterModes(TModChooser& modes) {
+ modes.SetModesHelpOption("-h");
+}
diff --git a/library/cpp/getopt/small/modchooser.h b/library/cpp/getopt/small/modchooser.h
index 95f5a5944e..0a8de6d50b 100644
--- a/library/cpp/getopt/small/modchooser.h
+++ b/library/cpp/getopt/small/modchooser.h
@@ -1,7 +1,7 @@
#pragma once
-#include "last_getopt_opts.h"
-
+#include "last_getopt_opts.h"
+
#include <util/generic/map.h>
#include <util/generic/string.h>
#include <util/generic/vector.h>
@@ -60,12 +60,12 @@ public:
//! Set default mode (if not specified explicitly)
void SetDefaultMode(const TString& mode);
- void AddAlias(const TString& alias, const TString& mode);
-
+ void AddAlias(const TString& alias, const TString& mode);
+
//! Set main program description.
void SetDescription(const TString& descr);
- //! Set modes help option name (-? is by default)
+ //! Set modes help option name (-? is by default)
void SetModesHelpOption(const TString& helpOption);
//! Specify handler for '--version' parameter
@@ -83,7 +83,7 @@ public:
void DisableSvnRevisionOption();
void AddCompletions(TString progName, const TString& name = "completion", bool hidden = false, bool noCompletion = false);
-
+
/*! Run appropriate mode.
*
* In this method following things happen:
@@ -104,11 +104,11 @@ public:
struct TMode {
TString Name;
- TMainClass* Main;
+ TMainClass* Main;
TString Description;
bool Hidden;
bool NoCompletion;
- TVector<TString> Aliases;
+ TVector<TString> Aliases;
TMode()
: Main(nullptr)
@@ -116,24 +116,24 @@ public:
}
TMode(const TString& name, TMainClass* main, const TString& descr, bool hidden, bool noCompletion);
-
- // Full name includes primary name and aliases. Also, will add ANSI colors.
- size_t CalculateFullNameLen() const;
- TString FormatFullName(size_t pad) const;
+
+ // Full name includes primary name and aliases. Also, will add ANSI colors.
+ size_t CalculateFullNameLen() const;
+ TString FormatFullName(size_t pad) const;
};
- TVector<const TMode*> GetUnsortedModes() const {
- auto ret = TVector<const TMode*>(Reserve(UnsortedModes.size()));
- for (auto& mode : UnsortedModes) {
- ret.push_back(mode.Get());
- }
- return ret;
- }
-
- TVersionHandlerPtr GetVersionHandler() const;
-
- bool IsSvnRevisionOptionDisabled() const;
-
+ TVector<const TMode*> GetUnsortedModes() const {
+ auto ret = TVector<const TMode*>(Reserve(UnsortedModes.size()));
+ for (auto& mode : UnsortedModes) {
+ ret.push_back(mode.Get());
+ }
+ return ret;
+ }
+
+ TVersionHandlerPtr GetVersionHandler() const;
+
+ bool IsSvnRevisionOptionDisabled() const;
+
private:
//! Main program description.
TString Description;
@@ -142,10 +142,10 @@ private:
TString ModesHelpOption;
//! Wrappers around all modes.
- TVector<THolder<TMainClass>> Wrappers;
+ TVector<THolder<TMainClass>> Wrappers;
//! Modes
- TMap<TString, TMode*> Modes;
+ TMap<TString, TMode*> Modes;
TString DefaultMode;
@@ -165,51 +165,51 @@ private:
TString SeparationString;
//! Unsorted list of options
- TVector<THolder<TMode>> UnsortedModes;
-
- //! Mode that generates completions
- THolder<TMainClass> CompletionsGenerator;
+ TVector<THolder<TMode>> UnsortedModes;
+
+ //! Mode that generates completions
+ THolder<TMainClass> CompletionsGenerator;
};
-
-//! Mode class that allows introspecting its console arguments.
-class TMainClassArgs: public TMainClass {
-public:
+
+//! Mode class that allows introspecting its console arguments.
+class TMainClassArgs: public TMainClass {
+public:
int operator()(int argc, const char** argv) final;
-
-public:
- //! Run this mode.
- int Run(int argc, const char** argv);
-
- //! Get console arguments for this mode.
- const NLastGetopt::TOpts& GetOptions();
-
-protected:
- //! Fill given empty `TOpts` with options.
- virtual void RegisterOptions(NLastGetopt::TOpts& opts);
-
- //! Actual mode logic. Takes parsed options and returns exit code.
- virtual int DoRun(NLastGetopt::TOptsParseResult&& parsedOptions) = 0;
-
-private:
- TMaybe<NLastGetopt::TOpts> Opts_;
-};
-
-//! Mode class that uses sub-modes to dispatch commands further.
-class TMainClassModes: public TMainClass {
-public:
+
+public:
+ //! Run this mode.
+ int Run(int argc, const char** argv);
+
+ //! Get console arguments for this mode.
+ const NLastGetopt::TOpts& GetOptions();
+
+protected:
+ //! Fill given empty `TOpts` with options.
+ virtual void RegisterOptions(NLastGetopt::TOpts& opts);
+
+ //! Actual mode logic. Takes parsed options and returns exit code.
+ virtual int DoRun(NLastGetopt::TOptsParseResult&& parsedOptions) = 0;
+
+private:
+ TMaybe<NLastGetopt::TOpts> Opts_;
+};
+
+//! Mode class that uses sub-modes to dispatch commands further.
+class TMainClassModes: public TMainClass {
+public:
int operator()(int argc, const char** argv) final;
-
-public:
- //! Run this mode.
- int Run(int argc, const char** argv);
-
- //! Get sub-modes for this mode.
- const TModChooser& GetSubModes();
-
-protected:
- //! Fill given modchooser with sub-modes.
- virtual void RegisterModes(TModChooser& modes);
-
-private:
- TMaybe<TModChooser> Modes_;
-};
+
+public:
+ //! Run this mode.
+ int Run(int argc, const char** argv);
+
+ //! Get sub-modes for this mode.
+ const TModChooser& GetSubModes();
+
+protected:
+ //! Fill given modchooser with sub-modes.
+ virtual void RegisterModes(TModChooser& modes);
+
+private:
+ TMaybe<TModChooser> Modes_;
+};
diff --git a/library/cpp/getopt/small/wrap.cpp b/library/cpp/getopt/small/wrap.cpp
index 8002028a2a..9fbd38842a 100644
--- a/library/cpp/getopt/small/wrap.cpp
+++ b/library/cpp/getopt/small/wrap.cpp
@@ -1,99 +1,99 @@
-#include "wrap.h"
-
+#include "wrap.h"
+
#include <library/cpp/colorizer/colors.h>
-
-#include <util/generic/string.h>
-#include <util/stream/str.h>
-#include <util/charset/utf8.h>
-
-#include <cctype>
-
-namespace NLastGetopt {
- TString Wrap(ui32 width, TStringBuf text, TStringBuf indent, size_t* lastLineLen, bool* hasParagraphs) {
- if (width == 0) {
- return TString(text);
- }
-
- if (width >= indent.size()) {
- width -= indent.size();
- }
-
- if (hasParagraphs) {
- *hasParagraphs = false;
- }
-
- TString res;
- auto os = TStringOutput(res);
-
- const char* spaceBegin = text.begin();
- const char* wordBegin = text.begin();
- const char* wordEnd = text.begin();
- const char* end = text.end();
-
- size_t lenSoFar = 0;
-
- bool isPreParagraph = false;
-
- do {
- spaceBegin = wordBegin = wordEnd;
-
- while (wordBegin < end && *wordBegin == ' ') {
- wordBegin++;
- }
-
- if (wordBegin == end) {
- break;
- }
-
- wordEnd = wordBegin;
-
- while (wordEnd < end && *wordEnd != ' ' && *wordEnd != '\n') {
- wordEnd++;
- }
-
- auto spaces = TStringBuf(spaceBegin, wordBegin);
- auto word = TStringBuf(wordBegin, wordEnd);
-
- size_t spaceLen = spaces.size();
-
- size_t wordLen = 0;
- if (!GetNumberOfUTF8Chars(word.data(), word.size(), wordLen)) {
- wordLen = word.size(); // not a utf8 string -- just use its binary size
- }
- wordLen -= NColorizer::TotalAnsiEscapeCodeLen(word);
-
- // Empty word means we've found a bunch of whitespaces followed by newline.
- // We don't want to print trailing whitespaces.
- if (word) {
- // We can't fit this word into the line -- insert additional line break.
- // We shouldn't insert line breaks if we're at the beginning of a line, hence `lenSoFar` check.
- if (lenSoFar && lenSoFar + spaceLen + wordLen > width) {
- os << Endl << indent << word;
- lenSoFar = wordLen;
- } else {
- os << spaces << word;
- lenSoFar += spaceLen + wordLen;
- }
- isPreParagraph = false;
- }
-
- if (wordEnd != end && *wordEnd == '\n') {
- os << Endl << indent;
- lenSoFar = 0;
- wordEnd++;
- if (hasParagraphs && isPreParagraph) {
- *hasParagraphs = true;
- } else {
- isPreParagraph = true;
- }
- continue;
- }
- } while (wordEnd < end);
-
- if (lastLineLen) {
- *lastLineLen = lenSoFar;
- }
-
- return res;
- }
-}
+
+#include <util/generic/string.h>
+#include <util/stream/str.h>
+#include <util/charset/utf8.h>
+
+#include <cctype>
+
+namespace NLastGetopt {
+ TString Wrap(ui32 width, TStringBuf text, TStringBuf indent, size_t* lastLineLen, bool* hasParagraphs) {
+ if (width == 0) {
+ return TString(text);
+ }
+
+ if (width >= indent.size()) {
+ width -= indent.size();
+ }
+
+ if (hasParagraphs) {
+ *hasParagraphs = false;
+ }
+
+ TString res;
+ auto os = TStringOutput(res);
+
+ const char* spaceBegin = text.begin();
+ const char* wordBegin = text.begin();
+ const char* wordEnd = text.begin();
+ const char* end = text.end();
+
+ size_t lenSoFar = 0;
+
+ bool isPreParagraph = false;
+
+ do {
+ spaceBegin = wordBegin = wordEnd;
+
+ while (wordBegin < end && *wordBegin == ' ') {
+ wordBegin++;
+ }
+
+ if (wordBegin == end) {
+ break;
+ }
+
+ wordEnd = wordBegin;
+
+ while (wordEnd < end && *wordEnd != ' ' && *wordEnd != '\n') {
+ wordEnd++;
+ }
+
+ auto spaces = TStringBuf(spaceBegin, wordBegin);
+ auto word = TStringBuf(wordBegin, wordEnd);
+
+ size_t spaceLen = spaces.size();
+
+ size_t wordLen = 0;
+ if (!GetNumberOfUTF8Chars(word.data(), word.size(), wordLen)) {
+ wordLen = word.size(); // not a utf8 string -- just use its binary size
+ }
+ wordLen -= NColorizer::TotalAnsiEscapeCodeLen(word);
+
+ // Empty word means we've found a bunch of whitespaces followed by newline.
+ // We don't want to print trailing whitespaces.
+ if (word) {
+ // We can't fit this word into the line -- insert additional line break.
+ // We shouldn't insert line breaks if we're at the beginning of a line, hence `lenSoFar` check.
+ if (lenSoFar && lenSoFar + spaceLen + wordLen > width) {
+ os << Endl << indent << word;
+ lenSoFar = wordLen;
+ } else {
+ os << spaces << word;
+ lenSoFar += spaceLen + wordLen;
+ }
+ isPreParagraph = false;
+ }
+
+ if (wordEnd != end && *wordEnd == '\n') {
+ os << Endl << indent;
+ lenSoFar = 0;
+ wordEnd++;
+ if (hasParagraphs && isPreParagraph) {
+ *hasParagraphs = true;
+ } else {
+ isPreParagraph = true;
+ }
+ continue;
+ }
+ } while (wordEnd < end);
+
+ if (lastLineLen) {
+ *lastLineLen = lenSoFar;
+ }
+
+ return res;
+ }
+}
diff --git a/library/cpp/getopt/small/wrap.h b/library/cpp/getopt/small/wrap.h
index 223c21e720..e98028688d 100644
--- a/library/cpp/getopt/small/wrap.h
+++ b/library/cpp/getopt/small/wrap.h
@@ -1,16 +1,16 @@
-#pragma once
-
-#include <util/generic/fwd.h>
-#include <util/generic/strbuf.h>
-
-namespace NLastGetopt {
- /**
- * Split text to multiple lines so that each line fits the given width.
- * Can work with UTF8, understands ANSI escape codes.
- *
- * @param indent will print this string after each newline.
- * @param lastLineLen output: will set to number of unicode codepoints in the last printed line.
- * @param hasParagraphs output: will set to true if there are two consecutive newlines in the text.
- */
- TString Wrap(ui32 width, TStringBuf text, TStringBuf indent = "", size_t* lastLineLen = nullptr, bool* hasParagraphs = nullptr);
-}
+#pragma once
+
+#include <util/generic/fwd.h>
+#include <util/generic/strbuf.h>
+
+namespace NLastGetopt {
+ /**
+ * Split text to multiple lines so that each line fits the given width.
+ * Can work with UTF8, understands ANSI escape codes.
+ *
+ * @param indent will print this string after each newline.
+ * @param lastLineLen output: will set to number of unicode codepoints in the last printed line.
+ * @param hasParagraphs output: will set to true if there are two consecutive newlines in the text.
+ */
+ TString Wrap(ui32 width, TStringBuf text, TStringBuf indent = "", size_t* lastLineLen = nullptr, bool* hasParagraphs = nullptr);
+}
diff --git a/library/cpp/getopt/small/ya.make b/library/cpp/getopt/small/ya.make
index 90bc114f0a..96de0f04b1 100644
--- a/library/cpp/getopt/small/ya.make
+++ b/library/cpp/getopt/small/ya.make
@@ -7,10 +7,10 @@ PEERDIR(
)
SRCS(
- completer.cpp
- completer_command.cpp
- completion_generator.cpp
- formatted_output.cpp
+ completer.cpp
+ completer_command.cpp
+ completion_generator.cpp
+ formatted_output.cpp
last_getopt.cpp
last_getopt_easy_setup.cpp
last_getopt_opt.cpp
@@ -21,7 +21,7 @@ SRCS(
opt.cpp
opt2.cpp
posix_getopt.cpp
- wrap.cpp
+ wrap.cpp
ygetopt.cpp
)
diff --git a/library/cpp/getopt/ut/last_getopt_ut.cpp b/library/cpp/getopt/ut/last_getopt_ut.cpp
index 9d2a46a51d..c99a1d053d 100644
--- a/library/cpp/getopt/ut/last_getopt_ut.cpp
+++ b/library/cpp/getopt/ut/last_getopt_ut.cpp
@@ -612,9 +612,9 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) {
opts.AddCharOption('d').DefaultValue("42");
opts.AddCharOption('s').DefaultValue("str_default");
opts.SetFreeArgsNum(123, 456);
- opts.SetFreeArgTitle(0, "first_free_arg", "help");
- opts.SetFreeArgTitle(2, "second_free_arg");
- opts.AddSection("Section", "Section\n text");
+ opts.SetFreeArgTitle(0, "first_free_arg", "help");
+ opts.SetFreeArgTitle(2, "second_free_arg");
+ opts.AddSection("Section", "Section\n text");
const char* cmd[] = {prog};
TOptsParser parser(&opts, Y_ARRAY_SIZE(cmd), cmd);
TStringStream out;
@@ -636,8 +636,8 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) {
UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.GreenColor() << "123" << colors.OldColor()) != TString::npos);
UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.GreenColor() << "456" << colors.OldColor()) != TString::npos);
UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.GreenColor() << "first_free_arg" << colors.OldColor()) != TString::npos);
- // free args without help not rendered even if they have custom title
- UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.GreenColor() << "second_free_arg" << colors.OldColor()) == TString::npos);
+ // free args without help not rendered even if they have custom title
+ UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.GreenColor() << "second_free_arg" << colors.OldColor()) == TString::npos);
// find signatures
UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.BoldColor() << "Usage" << colors.OldColor()) != TString::npos);
@@ -645,10 +645,10 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) {
UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.BoldColor() << "Optional parameters" << colors.OldColor()) != TString::npos);
UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.BoldColor() << "Free args" << colors.OldColor()) != TString::npos);
- // find sections
- UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.BoldColor() << "Section" << colors.OldColor() << ":") != TString::npos);
- UNIT_ASSERT(out.Str().find(TStringBuilder() << " Section\n text") != TString::npos);
-
+ // find sections
+ UNIT_ASSERT(out.Str().find(TStringBuilder() << colors.BoldColor() << "Section" << colors.OldColor() << ":") != TString::npos);
+ UNIT_ASSERT(out.Str().find(TStringBuilder() << " Section\n text") != TString::npos);
+
// print without colors
TStringStream out2;
opts.PrintUsage(prog, out2);
diff --git a/library/cpp/getopt/ut/wrap.cpp b/library/cpp/getopt/ut/wrap.cpp
index 2d78a8ba4d..3444eea102 100644
--- a/library/cpp/getopt/ut/wrap.cpp
+++ b/library/cpp/getopt/ut/wrap.cpp
@@ -1,96 +1,96 @@
#include <library/cpp/testing/unittest/registar.h>
-
+
#include <library/cpp/getopt/small/wrap.h>
-
-Y_UNIT_TEST_SUITE(Wrap) {
- Y_UNIT_TEST(TestWrapping) {
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b c d eeffeff").Quote(),
- TString("a b c\nd\neeffeff").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b\nc d\neeffeff").Quote(),
- TString("a b\nc d\neeffeff").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b\n c d\neeffeff").Quote(),
- TString("a b\n c\nd\neeffeff").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b\nx c d\neeffeff").Quote(),
- TString("a b\nx\nc d\neeffeff").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b\nx \n c d\neeffeff").Quote(),
- TString("a b\nx\n c\nd\neeffeff").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b\nx \n c d\neeffeff").Quote(),
- TString("a b\nx\n c\nd\neeffeff").Quote()
- );
- }
-
- Y_UNIT_TEST(TestWrappingIndent) {
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b c d", "|>").Quote(),
- TString("a b\n|>c d").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b\n\nc d", "|>").Quote(),
- TString("a b\n|>\n|>c d").Quote()
- );
- }
-
- Y_UNIT_TEST(TestWrappingAnsi) {
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5m").Quote(),
- TString("\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5m").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a \033[1;2;3;4;5mb c\033[1;2;3;4;5m \033[1;2;3;4;5md e f").Quote(),
- TString("a \033[1;2;3;4;5mb c\033[1;2;3;4;5m\n\033[1;2;3;4;5md e f").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b \033[1;2;3;4;5m c d").Quote(),
- TString("a b \033[1;2;3;4;5m\nc d").Quote()
- );
-
- UNIT_ASSERT_STRINGS_EQUAL(
- NLastGetopt::Wrap(5, "a b \033[1;2;3;4;5m c d").Quote(),
- TString("a b\n\033[1;2;3;4;5m c d").Quote()
- );
- }
-
- Y_UNIT_TEST(TestTextInfo) {
- size_t lastLineLen;
- bool hasParagraphs;
-
- NLastGetopt::Wrap(5, "a b c d e", "", &lastLineLen, &hasParagraphs);
- UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 3);
- UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, false);
-
- NLastGetopt::Wrap(5, "a b c\n\nd e f h", "", &lastLineLen, &hasParagraphs);
- UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 1);
- UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, true);
-
- NLastGetopt::Wrap(5, "a b c\n\n", "", &lastLineLen, &hasParagraphs);
- UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 0);
- UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, true);
-
- NLastGetopt::Wrap(5, "\n \na b c", "", &lastLineLen, &hasParagraphs);
- UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 5);
- UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, true);
-
- NLastGetopt::Wrap(5, "\nx\na b c", "", &lastLineLen, &hasParagraphs);
- UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 5);
- UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, false);
- }
-}
+
+Y_UNIT_TEST_SUITE(Wrap) {
+ Y_UNIT_TEST(TestWrapping) {
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b c d eeffeff").Quote(),
+ TString("a b c\nd\neeffeff").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b\nc d\neeffeff").Quote(),
+ TString("a b\nc d\neeffeff").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b\n c d\neeffeff").Quote(),
+ TString("a b\n c\nd\neeffeff").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b\nx c d\neeffeff").Quote(),
+ TString("a b\nx\nc d\neeffeff").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b\nx \n c d\neeffeff").Quote(),
+ TString("a b\nx\n c\nd\neeffeff").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b\nx \n c d\neeffeff").Quote(),
+ TString("a b\nx\n c\nd\neeffeff").Quote()
+ );
+ }
+
+ Y_UNIT_TEST(TestWrappingIndent) {
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b c d", "|>").Quote(),
+ TString("a b\n|>c d").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b\n\nc d", "|>").Quote(),
+ TString("a b\n|>\n|>c d").Quote()
+ );
+ }
+
+ Y_UNIT_TEST(TestWrappingAnsi) {
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5m").Quote(),
+ TString("\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5mx\033[1;2;3;4;5m").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a \033[1;2;3;4;5mb c\033[1;2;3;4;5m \033[1;2;3;4;5md e f").Quote(),
+ TString("a \033[1;2;3;4;5mb c\033[1;2;3;4;5m\n\033[1;2;3;4;5md e f").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b \033[1;2;3;4;5m c d").Quote(),
+ TString("a b \033[1;2;3;4;5m\nc d").Quote()
+ );
+
+ UNIT_ASSERT_STRINGS_EQUAL(
+ NLastGetopt::Wrap(5, "a b \033[1;2;3;4;5m c d").Quote(),
+ TString("a b\n\033[1;2;3;4;5m c d").Quote()
+ );
+ }
+
+ Y_UNIT_TEST(TestTextInfo) {
+ size_t lastLineLen;
+ bool hasParagraphs;
+
+ NLastGetopt::Wrap(5, "a b c d e", "", &lastLineLen, &hasParagraphs);
+ UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 3);
+ UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, false);
+
+ NLastGetopt::Wrap(5, "a b c\n\nd e f h", "", &lastLineLen, &hasParagraphs);
+ UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 1);
+ UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, true);
+
+ NLastGetopt::Wrap(5, "a b c\n\n", "", &lastLineLen, &hasParagraphs);
+ UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 0);
+ UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, true);
+
+ NLastGetopt::Wrap(5, "\n \na b c", "", &lastLineLen, &hasParagraphs);
+ UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 5);
+ UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, true);
+
+ NLastGetopt::Wrap(5, "\nx\na b c", "", &lastLineLen, &hasParagraphs);
+ UNIT_ASSERT_VALUES_EQUAL(lastLineLen, 5);
+ UNIT_ASSERT_VALUES_EQUAL(hasParagraphs, false);
+ }
+}
diff --git a/library/cpp/getopt/ut/ya.make b/library/cpp/getopt/ut/ya.make
index c2e928b6f0..8d00669efb 100644
--- a/library/cpp/getopt/ut/ya.make
+++ b/library/cpp/getopt/ut/ya.make
@@ -8,7 +8,7 @@ SRCS(
opt2_ut.cpp
opt_ut.cpp
posix_getopt_ut.cpp
- wrap.cpp
+ wrap.cpp
ygetopt_ut.cpp
)