aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt/small/completer_command.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/small/completer_command.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/getopt/small/completer_command.cpp')
-rw-r--r--library/cpp/getopt/small/completer_command.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/library/cpp/getopt/small/completer_command.cpp b/library/cpp/getopt/small/completer_command.cpp
new file mode 100644
index 0000000000..5e593eec7e
--- /dev/null
+++ b/library/cpp/getopt/small/completer_command.cpp
@@ -0,0 +1,165 @@
+#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 {
+ 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) {
+ return MakeHolder<TCompleterMode>(modChooser, std::move(command), std::move(modName));
+ }
+}