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, Wanted, ZshGenerator

Constant Summary collapse

GENERATORS =
{
  bash: Clamp::Completion::BashGenerator,
  fish: Clamp::Completion::FishGenerator,
  zsh: Clamp::Completion::ZshGenerator
}.freeze

Class Method Summary collapse

Class Method Details

.collect_subcommand_names(command_class) ⇒ Object

Collect all subcommand names across the command tree.



75
76
77
78
79
80
81
# File 'lib/clamp/completion.rb', line 75

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

.expanded_switches(option) ⇒ Object

Return switches with –[no-]foo expanded to –foo and –no-foo.



44
45
46
47
48
49
50
51
52
# File 'lib/clamp/completion.rb', line 44

def expanded_switches(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



36
37
38
39
40
41
# File 'lib/clamp/completion.rb', line 36

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

.visible_options(command_class) ⇒ Object

Options visible in completion (excludes hidden).



55
56
57
# File 'lib/clamp/completion.rb', line 55

def visible_options(command_class)
  command_class.recognised_options.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).

Yields:

  • (command_class, path, has_children)


62
63
64
65
66
67
68
69
70
71
72
# File 'lib/clamp/completion.rb', line 62

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