class Pakyow::Task

Base task class that extends rake with additional functionality.

Constants

UNAVAILABLE_SHORT_NAMES

Attributes

description[R]

Public Class Methods

new(namespace: [], description: nil, arguments: {}, options: {}, flags: {}, task_args: [], global: false, &block) click to toggle source
# File lib/pakyow/task.rb, line 26
def initialize(namespace: [], description: nil, arguments: {}, options: {}, flags: {}, task_args: [], global: false, &block)
  @description, @arguments, @options, @flags, @global = description, arguments, options, flags, global
  @short_names = determine_short_names

  if namespace.any?
    send(:namespace, namespace.join(":")) do
      define_task(task_args, block)
    end
  else
    define_task(task_args, block)
  end
end

Public Instance Methods

app?() click to toggle source
# File lib/pakyow/task.rb, line 121
def app?
  args.include?(:app)
end
call(options = {}, argv = []) click to toggle source
# File lib/pakyow/task.rb, line 39
def call(options = {}, argv = [])
  parse_options(argv, options)
  parse_arguments(argv, options)
  check_options(options)

  @rake.invoke(*args.map { |arg|
    options[arg]
  })
end
global?() click to toggle source
# File lib/pakyow/task.rb, line 125
def global?
  @global == true
end
help(describe: true) click to toggle source
# File lib/pakyow/task.rb, line 49
    def help(describe: true)
      required_arguments = sorted_arguments.select { |_, argument|
        argument[:required]
      }.map { |key, _|
        "[#{key.to_s.upcase}]"
      }.join(" ")

      required_options = sorted_options.select { |_, option|
        option[:required]
      }.map { |key, _|
        "--#{key}=#{key}"
      }.join(" ")

      text = String.new

      if describe
        text << Support::CLI.style.blue.bold(@description) + "\n"
      end

      text += <<~HELP

        #{Support::CLI.style.bold("USAGE")}
          $ pakyow #{[name, required_arguments, required_options].reject(&:empty?).join(" ")}
      HELP

      if @arguments.any?
        text += <<~HELP

          #{Support::CLI.style.bold("ARGUMENTS")}
        HELP

        longest_length = @arguments.keys.map(&:to_s).max_by(&:length).length
        sorted_arguments.each do |key, argument|
          description = Support::CLI.style.yellow(argument[:description])
          if argument[:required]
            description += Support::CLI.style.red(" (required)")
          end
          text += "  #{key.upcase}".ljust(longest_length + 4) + description + "\n"
        end
      end

      if @options.any?
        text += <<~HELP

          #{Support::CLI.style.bold("OPTIONS")}
        HELP

        longest_length = (@options.keys + @flags.keys).map(&:to_s).max_by(&:length).length
        sorted_options_and_flags.each do |key, option|
          description = Support::CLI.style.yellow(option[:description])

          if option[:required]
            description += Support::CLI.style.red(" (required)")
          end

          prefix = if @flags.key?(key)
            "      --#{key}"
          else
            if @short_names.key?(key)
              "  -#{key.to_s[0]}, --#{key}=#{key}"
            else
              "      --#{key}=#{key}"
            end
          end

          text += prefix.ljust(longest_length * 2 + 11) + description + "\n"
        end
      end

      text
    end

Private Instance Methods

args() click to toggle source
# File lib/pakyow/task.rb, line 149
def args
  @args ||= @rake.arg_names.map(&:to_sym)
end
check_options(options) click to toggle source
# File lib/pakyow/task.rb, line 195
def check_options(options)
  @options.each do |key, option|
    if option[:required] && !options.key?(key)
      raise CLI::InvalidInput, "`#{key}' is a required option"
    end
  end

  options.keys.each do |key|
    unless global_options.key?(key) || args.include?(key)
      raise CLI::InvalidInput, "`#{key}' is not a supported option"
    end
  end
end
define_task(task_args, task_block) click to toggle source
# File lib/pakyow/task.rb, line 143
def define_task(task_args, task_block)
  @rake = task(*task_args) { |task, args|
    instance_exec(task, args, &task_block)
  }
end
determine_short_names() click to toggle source
# File lib/pakyow/task.rb, line 216
def determine_short_names
  short_names = {
    env: "e"
  }

  @options.each do |name, opts|
    if short = opts[:short]
      short = name[0] if short == :default
      unless short_names.value?(short) || UNAVAILABLE_SHORT_NAMES.include?(short)
        short_names[name] = short
      end
    end
  end

  @flags.each do |name, opts|
    if short = opts[:short]
      unless short_names.value?(short) || UNAVAILABLE_SHORT_NAMES.include?(short)
        short_names[name] = short
      end
    end
  end

  short_names
end
global_options() click to toggle source
# File lib/pakyow/task.rb, line 209
def global_options
  Hash[@options.select { |_, option|
    option[:global]
  }]
end
parse_arguments(argv, options) click to toggle source
# File lib/pakyow/task.rb, line 181
def parse_arguments(argv, options)
  sorted_arguments.each do |key, argument|
    if argv.any?
      options[key] = argv.shift
    elsif argument[:required]
      raise CLI::InvalidInput, "`#{key}' is a required argument"
    end
  end

  if argv.any?
    raise CLI::InvalidInput, "`#{argv.shift}' is not a supported argument"
  end
end
parse_options(argv, options) click to toggle source
# File lib/pakyow/task.rb, line 153
def parse_options(argv, options)
  unparsed = Array.new
  OptionParser.new { |opts|
    @flags.keys.each do |flag|
      opts.on("--#{flag}") do |v|
        options[flag] = v
      end
    end

    @options.keys.each do |option|
      match = ["--#{option}=VAL"]
      if @short_names.key?(option)
        match.unshift("-#{@short_names[option]}VAL")
      end

      opts.on(*match) do |v|
        options[option] = v
      end
    end
  }.order!(argv) do |arg|
    unparsed << arg
  end

  argv.concat(unparsed)
rescue OptionParser::InvalidOption => error
  raise CLI::InvalidInput, "`#{error.args.first}' is not a supported option"
end
sorted_arguments() click to toggle source
# File lib/pakyow/task.rb, line 131
def sorted_arguments
  @arguments.sort_by { |key, _| args.index(key) }
end
sorted_options() click to toggle source
# File lib/pakyow/task.rb, line 135
def sorted_options
  @options.sort
end
sorted_options_and_flags() click to toggle source
# File lib/pakyow/task.rb, line 139
def sorted_options_and_flags
  @options.merge(@flags).sort
end