diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/small/completer_command.cpp | |
download | ydb-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.cpp | 165 |
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)); + } +} |