jekyll如何使用mercenary解析命令行选项
以下基于2.5.3
在bin/jekyll中,先将lib置顶于PATH,然后执行其中的jekyll.rb
$:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
require 'jekyll'
然后,在lib/jekyll.rb中有require command.rb 和 commands/*
def require_all(path)
glob = File.join(File.dirname(__FILE__), path, '*.rb')
Dir[glob].each do |f|
require f
end
end
module Jekyll
require 'jekyll/command'
end
require_all 'jekyll/commands'
而command.rb和commands/分别是这样:
在lib/jekyll/command.rb中,重写类方法、回调方法inherited,将子类塞到类的@subclass中
module Jekyll
class Command
class << self
def subclasses
@subclasses ||= []
end
def inherited(base)
subclasses << base
super(base)
end
#...
在lib/jekyll/commands/*中,定义鸭子方法init_with_program,该方法接受“Mercenary.program(:jekyll) do |p|”的“p” ,以build.rb为例
module Jekyll
module Commands
class Build < Command
class << self
# Create the Mercenary command for the Jekyll CLI for this Command
def init_with_program(prog)
prog.command(:build) do |c|
c.syntax 'build [options]'
c.description 'Build your site'
c.alias :b
add_build_options(c)
c.action do |args, options|
options["serving"] = false
Jekyll::Commands::Build.process(options)
end
end
end
最后,回到bin/jekyll,为@subclass中每个命令子类定义选项,实质上选项的具体已在init_with_program中写好
Mercenary.program(:jekyll) do |p|
#...
Jekyll::Command.subclasses.each { |c| c.init_with_program(p) }
这个框架使得想扩展命令时,只需扩展commands中的内容即可