Class: Toys::Loader

Inherits:
Object
  • Object
show all
Defined in:
lib/toys/loader.rb

Overview

The Loader service loads tools from configuration files, and finds the appropriate tool given a set of command line arguments.

Instance Method Summary collapse

Constructor Details

#initialize(index_file_name: nil, middleware_stack: [], mixin_lookup: nil, middleware_lookup: nil, template_lookup: nil) ⇒ Loader

Create a Loader



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/toys/loader.rb', line 65

def initialize(index_file_name: nil, middleware_stack: [],
               mixin_lookup: nil, middleware_lookup: nil, template_lookup: nil)
  if index_file_name && ::File.extname(index_file_name) != ".rb"
    raise ::ArgumentError, "Illegal index file name #{index_file_name.inspect}"
  end
  @mixin_lookup = mixin_lookup || Utils::ModuleLookup.new
  @middleware_lookup = middleware_lookup || Utils::ModuleLookup.new
  @template_lookup = template_lookup || Utils::ModuleLookup.new
  @index_file_name = index_file_name
  @middleware_stack = middleware_stack
  @worklist = []
  @tool_data = {}
  @max_priority = @min_priority = 0
  get_tool_definition([], -999_999)
end

Instance Method Details

#add_block(high_priority: false, path: nil, &block) ⇒ Object

Add a configuration block to the loader.



108
109
110
111
112
113
# File 'lib/toys/loader.rb', line 108

def add_block(high_priority: false, path: nil, &block)
  path ||= "(Block #{block.object_id})"
  priority = high_priority ? (@max_priority += 1) : (@min_priority -= 1)
  @worklist << [block, path, [], priority]
  self
end

#add_path(path, high_priority: false) ⇒ Object

Add a configuration file/directory to the loader.



89
90
91
92
93
94
95
96
# File 'lib/toys/loader.rb', line 89

def add_path(path, high_priority: false)
  paths = Array(path)
  priority = high_priority ? (@max_priority += 1) : (@min_priority -= 1)
  paths.each do |p|
    @worklist << [:file, check_path(p), [], priority]
  end
  self
end

#has_subtools?(words) ⇒ Boolean

Returns true if the given path has at least one subtool. Loads from the configuration if necessary.



182
183
184
185
186
187
188
189
# File 'lib/toys/loader.rb', line 182

def has_subtools?(words)
  load_for_prefix(words)
  len = words.length
  @tool_data.each_key do |n|
    return true if !n.empty? && n.length > len && n.slice(0, len) == words
  end
  false
end

#list_subtools(words, recursive: false) ⇒ Array<Toys::Definition::Tool,Toys::Definition::Alias>

Returns a list of subtools for the given path, loading from the configuration if necessary.



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/toys/loader.rb', line 158

def list_subtools(words, recursive: false)
  load_for_prefix(words)
  found_tools = []
  len = words.length
  @tool_data.each do |n, td|
    next if n.empty?
    if recursive
      next if n.length <= len || n.slice(0, len) != words
    else
      next unless n.slice(0..-2) == words
    end
    tool = td.active_definition || td.top_definition
    found_tools << tool unless tool.nil?
  end
  sort_tools_by_name(found_tools)
end

#lookup(args) ⇒ Array(Toys::Definition::Tool,Array<String>)

Given a list of command line arguments, find the appropriate tool to handle the command, loading it from the configuration if necessary, and following aliases. This always returns a tool. If the specific tool path is not defined and cannot be found in any configuration, it finds the nearest namespace that would contain that tool, up to the root tool.

Returns a tuple of the found tool, and the array of remaining arguments that are not part of the tool name and should be passed as tool args.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/toys/loader.rb', line 129

def lookup(args)
  orig_prefix = args.take_while { |arg| !arg.start_with?("-") }
  cur_prefix = orig_prefix
  loop do
    load_for_prefix(cur_prefix)
    p = orig_prefix
    loop do
      tool_definition = get_active_tool(p, [])
      if tool_definition
        finish_definitions_in_tree(tool_definition.full_name)
        return [tool_definition, args.slice(p.length..-1)]
      end
      break if p.empty? || p.length <= cur_prefix.length
      p = p.slice(0..-2)
    end
    raise "Unexpected error" if cur_prefix.empty?
    cur_prefix = cur_prefix.slice(0..-2)
  end
end

#resolve_standard_mixin(name) ⇒ Module?

Attempt to get a well-known mixin module for the given symbolic name.



273
274
275
# File 'lib/toys/loader.rb', line 273

def resolve_standard_mixin(name)
  @mixin_lookup.lookup(name)
end

#resolve_standard_template(name) ⇒ Class?

Attempt to get a well-known template class for the given symbolic name.



283
284
285
# File 'lib/toys/loader.rb', line 283

def resolve_standard_template(name)
  @template_lookup.lookup(name)
end