class Runfile::Userfile

Represents a single runfile.

Attributes

context[RW]
host[R]
path[R]

Public Class Methods

new(path, context: nil, host: nil) click to toggle source
# File lib/runfile/userfile.rb, line 13
def initialize(path, context: nil, host: nil)
  @path = path
  @host = host
  @context = context || {}
end

Public Instance Methods

basename() click to toggle source
# File lib/runfile/userfile.rb, line 19
def basename
  @basename ||= File.basename(path, '.runfile')
end
code() click to toggle source
# File lib/runfile/userfile.rb, line 23
def code
  @code ||= File.read(path)
end
commands() click to toggle source
# File lib/runfile/userfile.rb, line 27
def commands
  actions.values.select(&:help)
end
eval_code() click to toggle source
# File lib/runfile/userfile.rb, line 31
def eval_code
  return if evaluated?

  @evaluated = true
  instance_eval code, path
end
evaluated?() click to toggle source
# File lib/runfile/userfile.rb, line 38
def evaluated?
  @evaluated
end
full_name() click to toggle source
# File lib/runfile/userfile.rb, line 42
def full_name
  @full_name ||= id.join ' '
end
guests() click to toggle source
# File lib/runfile/userfile.rb, line 46
def guests
  @guests ||= begin
    result = imports.map do |glob, context|
      Dir.glob("#{glob}.runfile").map do |guest_path|
        Userfile.new guest_path, context: context, host: self
      end
    end

    result.flatten
  end
end
id() click to toggle source
# File lib/runfile/userfile.rb, line 58
def id
  @id ||= if host
    (host.id + [name]).compact
  else
    [name].compact
  end
end
inspectable() click to toggle source
# File lib/runfile/userfile.rb, line 66
def inspectable
  { name: name, path: path }
end
name() click to toggle source
# File lib/runfile/userfile.rb, line 70
def name
  @name ||= (rootfile? ? nil : basename.downcase)
end
rootfile?() click to toggle source
# File lib/runfile/userfile.rb, line 74
def rootfile?
  @rootfile ||= basename.casecmp? 'runfile'
end
run(argv = []) click to toggle source
# File lib/runfile/userfile.rb, line 78
def run(argv = [])
  eval_code

  if argv.any?
    argv = expand_shortcuts argv
    found_guest = find_guest argv
  end

  if found_guest
    found_guest.run argv
  else
    run_local argv
  end
end

Private Instance Methods

docopt() click to toggle source
# File lib/runfile/userfile.rb, line 95
def docopt
  @docopt ||= render 'userfile', context: self
end
expand_shortcuts(argv) click to toggle source

Shortcuts will always appear after the name, so we split argv to name (array), shortcut wannabe (string), rest of the args (array). Then, if the shortcut wannabe is a match, we stitch the new argv back together, with its expansion.

# File lib/runfile/userfile.rb, line 137
def expand_shortcuts(argv)
  size = id.size

  p1 = argv[0...size]
  p2 = argv[size]
  p3 = argv[(size + 1)..]

  shortcuts.each do |from, to|
    return p1 + Shellwords.split(to) + p3 if from == p2
  end

  argv
end
find_action(args) click to toggle source
# File lib/runfile/userfile.rb, line 99
def find_action(args)
  acts = actions.values
  acts.find { |a| args[a.name] } ||
    acts.find { |a| args[a.shortcut] } ||
    acts.find { |a| args[a.prefix] } ||
    actions[:default]
end
find_guest(argv) click to toggle source
# File lib/runfile/userfile.rb, line 107
def find_guest(argv)
  guests.find do |guest|
    guest_id_size = guest.id.size
    next if guest_id_size.zero?

    argv.first(guest_id_size) == guest.id
  end
end
run_local(argv) click to toggle source
# File lib/runfile/userfile.rb, line 116
def run_local(argv)
  exit_code = nil
  # This is here to allow guests to provide their own title/summary as
  # the help message for the Commands block.
  # TODO: Relatively costly. Consider alternatives.
  guests.each(&:eval_code)

  Runner.run docopt, argv: argv, version: version do |args|
    action = find_action(args)
    raise ActionNotFound, 'Cannot find action. Is it properly defined?' unless action

    exit_code = action.run args
  end

  exit_code if exit_code.is_a? Integer
end