class Toys::ToolDefinition::DefaultCompletion

A Completion that implements the default algorithm for a tool.

Attributes

delegation_target[RW]

Delegation target, or nil for none. @return [Array<String>] if there is a delegation target @return [nil] if there is no delegation target

Public Class Methods

new(complete_subtools: true, include_hidden_subtools: false, complete_args: true, complete_flags: true, complete_flag_values: true, delegation_target: nil) click to toggle source

Create a completion given configuration options.

@param complete_subtools [Boolean] Whether to complete subtool names @param include_hidden_subtools [Boolean] Whether to include hidden

subtools (i.e. those beginning with an underscore)

@param complete_args [Boolean] Whether to complete positional args @param complete_flags [Boolean] Whether to complete flag names @param complete_flag_values [Boolean] Whether to complete flag values @param delegation_target [Array<String>,nil] Delegation target, or

`nil` if none.
Calls superclass method
# File lib/toys/tool_definition.rb, line 1162
def initialize(complete_subtools: true, include_hidden_subtools: false,
               complete_args: true, complete_flags: true, complete_flag_values: true,
               delegation_target: nil)
  super()
  @complete_subtools = complete_subtools
  @include_hidden_subtools = include_hidden_subtools
  @complete_flags = complete_flags
  @complete_args = complete_args
  @complete_flag_values = complete_flag_values
  @delegation_target = delegation_target
end

Public Instance Methods

call(context) click to toggle source

Returns candidates for the current completion.

@param context [Toys::Completion::Context] the current completion

context including the string fragment.

@return [Array<Toys::Completion::Candidate>] an array of candidates

# File lib/toys/tool_definition.rb, line 1228
def call(context)
  candidates = valued_flag_candidates(context)
  return candidates if candidates
  candidates = subtool_or_arg_candidates(context)
  candidates += plain_flag_candidates(context)
  candidates += flag_value_candidates(context)
  if delegation_target
    delegate_tool = context.cli.loader.lookup_specific(delegation_target)
    if delegate_tool
      context = context.with(previous_words: delegation_target)
      candidates += delegate_tool.completion.call(context)
    end
  end
  candidates
end
complete_args?() click to toggle source

Whether to complete positional args @return [Boolean]

# File lib/toys/tool_definition.rb, line 1202
def complete_args?
  @complete_args
end
complete_flag_values?() click to toggle source

Whether to complete flag values @return [Boolean]

# File lib/toys/tool_definition.rb, line 1210
def complete_flag_values?
  @complete_flag_values
end
complete_flags?() click to toggle source

Whether to complete flags @return [Boolean]

# File lib/toys/tool_definition.rb, line 1194
def complete_flags?
  @complete_flags
end
complete_subtools?() click to toggle source

Whether to complete subtool names @return [Boolean]

# File lib/toys/tool_definition.rb, line 1178
def complete_subtools?
  @complete_subtools
end
include_hidden_subtools?() click to toggle source

Whether to include hidden subtools @return [Boolean]

# File lib/toys/tool_definition.rb, line 1186
def include_hidden_subtools?
  @include_hidden_subtools
end

Private Instance Methods

analyze_subtool_fragment(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1281
def analyze_subtool_fragment(context)
  tool_name = context.tool.full_name
  prefix = ""
  fragment = context.fragment
  delims = context.cli.extra_delimiters
  unless context.fragment_prefix.empty?
    if !context.fragment_prefix.end_with?(":") || !delims.include?(":")
      return [nil, nil, nil]
    end
    tool_name += context.fragment_prefix.split(":")
  end
  unless delims.empty?
    delims_regex = ::Regexp.escape(delims)
    if (match = /\A((.+)[#{delims_regex}])(.*)\z/.match(fragment))
      fragment = match[3]
      tool_name += match[2].split(/[#{delims_regex}]/)
      prefix = match[1]
    end
  end
  [tool_name, prefix, fragment]
end
arg_candidates(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1303
def arg_candidates(context)
  return unless @complete_args
  arg_def = context.arg_parser.next_arg_def
  return [] unless arg_def
  arg_def.completion.call(context)
end
flag_value_candidates(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1322
def flag_value_candidates(context)
  return unless @complete_flag_values
  arg_parser = context.arg_parser
  flag_def = arg_parser.active_flag_def
  return [] unless flag_def
  return [] if @complete_flags && arg_parser.flags_allowed? &&
               flag_def.value_type == :optional && context.fragment.start_with?("-")
  flag_def.value_completion.call(context)
end
plain_flag_candidates(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1310
def plain_flag_candidates(context)
  return [] if !@complete_flags || context[:disable_flags]
  arg_parser = context.arg_parser
  return [] unless arg_parser.flags_allowed?
  flag_def = arg_parser.active_flag_def
  return [] if flag_def && flag_def.value_type == :required
  return [] if context.fragment =~ /\A[^-]/ || !context.fragment_prefix.empty?
  context.tool.flags.flat_map do |flag|
    flag.flag_completion.call(context)
  end
end
subtool_candidates(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1266
def subtool_candidates(context)
  return if !@complete_subtools || !context.args.empty?
  tool_name, prefix, fragment = analyze_subtool_fragment(context)
  return unless tool_name
  subtools = context.cli.loader.list_subtools(tool_name,
                                              include_hidden: @include_hidden_subtools)
  return if subtools.empty?
  candidates = []
  subtools.each do |subtool|
    name = subtool.simple_name
    candidates << Completion::Candidate.new("#{prefix}#{name}") if name.start_with?(fragment)
  end
  candidates
end
subtool_or_arg_candidates(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1260
def subtool_or_arg_candidates(context)
  return [] if context.arg_parser.active_flag_def
  return [] if context.arg_parser.flags_allowed? && context.fragment.start_with?("-")
  subtool_candidates(context) || arg_candidates(context)
end
valued_flag_candidates(context) click to toggle source
# File lib/toys/tool_definition.rb, line 1246
def valued_flag_candidates(context)
  return unless @complete_flag_values
  arg_parser = context.arg_parser
  return unless arg_parser.flags_allowed?
  active_flag_def = arg_parser.active_flag_def
  return if active_flag_def && active_flag_def.value_type == :required
  match = /\A(--\w[?\w-]*)=(.*)\z/.match(context.fragment_prefix)
  return unless match
  flag_value_context = context.with(fragment_prefix: match[2])
  flag_def = flag_value_context.tool.resolve_flag(match[1]).unique_flag
  return [] unless flag_def
  flag_def.value_completion.call(flag_value_context)
end