Module: Clamp::Completion
- Defined in:
- lib/clamp/completion.rb,
lib/clamp/completion/zsh_generator.rb,
lib/clamp/completion/bash_generator.rb,
lib/clamp/completion/fish_generator.rb
Overview
Shell completion script generation.
Defined Under Namespace
Classes: BashGenerator, FishGenerator, ParamsSatisfiedHelper, Wanted, ZshGenerator
Constant Summary collapse
- GENERATORS =
{ bash: Clamp::Completion::BashGenerator, fish: Clamp::Completion::FishGenerator, zsh: Clamp::Completion::ZshGenerator }.freeze
Class Method Summary collapse
-
.argparse_specs_for(option) ⇒ Object
Return fish argparse optspecs for an option.
-
.collect_subcommand_names(command_class) ⇒ Object
Collect all subcommand names across the command tree.
-
.encode_name(name) ⇒ Object
Encode a name for use as a shell function identifier.
-
.expanded_switches(option) ⇒ Object
Return switches with --[no-]foo expanded to --foo and --no-foo.
- .generate(command_class, shell, executable_name) ⇒ Object
-
.required_parameter_count(command_class) ⇒ Object
Count required, non-multivalued parameters for a command.
-
.visible_options(command_class) ⇒ Object
Options visible in completion (excludes hidden).
-
.walk_command_tree(command_class, path = [], visited = Set.new) {|command_class, path, has_children| ... } ⇒ Object
Walk the command tree depth-first, yielding (command_class, path, has_children).
Class Method Details
.argparse_specs_for(option) ⇒ Object
Return fish argparse optspecs for an option.
86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/clamp/completion.rb', line 86 def argparse_specs_for(option) switches = (option) suffix = option.flag? ? "" : "=" short = switches.find { |s| s.match?(/^-[^-]$/) } longs = switches.select { |s| s.start_with?("--") } if short && longs.length == 1 ["#{short.delete_prefix('-')}/#{longs.first.delete_prefix('--')}#{suffix}"] else longs.map { |l| "#{l.delete_prefix('--')}#{suffix}" } end end |
.collect_subcommand_names(command_class) ⇒ Object
Collect all subcommand names across the command tree.
99 100 101 102 103 104 105 |
# File 'lib/clamp/completion.rb', line 99 def collect_subcommand_names(command_class) names = [] walk_command_tree(command_class) do |cmd, _path, has_children| cmd.recognised_subcommands.each { |sub| names.concat(sub.names) } if has_children end names.uniq end |
.encode_name(name) ⇒ Object
Encode a name for use as a shell function identifier. Special characters are replaced with _XX hex codes.
38 39 40 |
# File 'lib/clamp/completion.rb', line 38 def encode_name(name) name.gsub(/[^a-zA-Z0-9_]/) { |c| format("_%02x", c.ord) } end |
.expanded_switches(option) ⇒ Object
Return switches with --[no-]foo expanded to --foo and --no-foo.
50 51 52 53 54 55 56 57 58 |
# File 'lib/clamp/completion.rb', line 50 def (option) option.switches.flat_map do |switch| if switch =~ /^--\[no-\](.*)/ ["--#{Regexp.last_match(1)}", "--no-#{Regexp.last_match(1)}"] else switch end end end |
.generate(command_class, shell, executable_name) ⇒ Object
42 43 44 45 46 47 |
# File 'lib/clamp/completion.rb', line 42 def generate(command_class, shell, executable_name) generator_class = GENERATORS.fetch(shell) do raise ArgumentError, "unsupported shell: #{shell.inspect}" end generator_class.new(command_class, executable_name).generate end |
.required_parameter_count(command_class) ⇒ Object
Count required, non-multivalued parameters for a command.
81 82 83 |
# File 'lib/clamp/completion.rb', line 81 def required_parameter_count(command_class) command_class.parameters.count { |p| p.required? && !p.multivalued? } end |
.visible_options(command_class) ⇒ Object
Options visible in completion (excludes hidden).
61 62 63 |
# File 'lib/clamp/completion.rb', line 61 def (command_class) command_class..reject(&:hidden?) end |
.walk_command_tree(command_class, path = [], visited = Set.new) {|command_class, path, has_children| ... } ⇒ Object
Walk the command tree depth-first, yielding (command_class, path, has_children). Path is an array of Subcommand::Definition objects. Always yields, even for revisited classes (with has_children=false).
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/clamp/completion.rb', line 68 def walk_command_tree(command_class, path = [], visited = Set.new, &block) fresh = !visited.include?(command_class) visited |= [command_class] has_children = command_class.has_subcommands? && fresh yield command_class, path, has_children return unless has_children command_class.recognised_subcommands.each do |sub| walk_command_tree(sub.subcommand_class, path + [sub], visited, &block) end end |