Refactor CLI to allow 3rd party commands
This commit is contained in:
parent
7e20616fe6
commit
20ae42dcc0
7 changed files with 173 additions and 181 deletions
|
@ -9,7 +9,7 @@ require 'rubygems'
|
|||
module Middleman
|
||||
module ProjectLocator
|
||||
class << self
|
||||
def locate_middleman_root!(args)
|
||||
def locate_middleman_root!
|
||||
cwd = Dir.pwd
|
||||
|
||||
if !in_middleman_project? && !in_middleman_project_subdirectory?
|
||||
|
@ -18,14 +18,14 @@ module Middleman
|
|||
end
|
||||
|
||||
if in_middleman_project?
|
||||
did_locate_middleman_project(cwd, args)
|
||||
did_locate_middleman_project(cwd)
|
||||
return
|
||||
end
|
||||
|
||||
Dir.chdir("..") do
|
||||
# Recurse in a chdir block: if the search fails we want to be sure
|
||||
# the application is generated in the original working directory.
|
||||
locate_middleman_root!(args) unless cwd == Dir.pwd
|
||||
locate_middleman_root! unless cwd == Dir.pwd
|
||||
end
|
||||
rescue SystemCallError
|
||||
# could not chdir, no problem just return
|
||||
|
@ -39,39 +39,25 @@ module Middleman
|
|||
File.exists?(File.join(path, 'config.rb')) || !path.root? && in_middleman_project_subdirectory?(path.parent)
|
||||
end
|
||||
|
||||
def did_locate_middleman_project(path, args)
|
||||
def did_locate_middleman_project(path)
|
||||
# Set up gems listed in the Gemfile.
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', path)
|
||||
|
||||
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
||||
|
||||
start_cli!(args)
|
||||
start_cli!
|
||||
end
|
||||
|
||||
def start_cli!(args)
|
||||
def start_cli!
|
||||
require 'middleman'
|
||||
Middleman::CLI.start(args)
|
||||
Middleman::CLI::Base.start
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
args = ARGV.dup
|
||||
|
||||
ARG_ALIASES = {
|
||||
"s" => "server",
|
||||
"b" => "build",
|
||||
"i" => "init",
|
||||
"new" => "init",
|
||||
"n" => "init"
|
||||
}
|
||||
|
||||
if ARG_ALIASES.has_key?(args[0])
|
||||
args[0] = ARG_ALIASES[args[0]]
|
||||
end
|
||||
|
||||
if args.length < 1 || %w(server build migrate).include?(args.first)
|
||||
Middleman::ProjectLocator.locate_middleman_root!(args)
|
||||
if ARGV.length < 1 || %w(server build migrate).include?(ARGV.first)
|
||||
Middleman::ProjectLocator.locate_middleman_root!
|
||||
else
|
||||
Middleman::ProjectLocator.start_cli!(args)
|
||||
Middleman::ProjectLocator.start_cli!
|
||||
end
|
|
@ -12,11 +12,16 @@ module Middleman
|
|||
# Auto-load modules on-demand
|
||||
autoload :Base, "middleman/base"
|
||||
autoload :Cache, "middleman/cache"
|
||||
autoload :Builder, "middleman/builder"
|
||||
autoload :CLI, "middleman/cli"
|
||||
autoload :Templates, "middleman/templates"
|
||||
autoload :Guard, "middleman/guard"
|
||||
|
||||
module CLI
|
||||
autoload :Base, "middleman/cli"
|
||||
autoload :Build, "middleman/cli/build"
|
||||
autoload :Templates, "middleman/cli/templates"
|
||||
autoload :Server, "middleman/cli/server"
|
||||
end
|
||||
|
||||
# Custom Renderers
|
||||
module Renderers
|
||||
autoload :Haml, "middleman/renderers/haml"
|
||||
|
@ -161,12 +166,6 @@ module Middleman
|
|||
|
||||
class << self
|
||||
|
||||
# Where to look for custom templates
|
||||
# @return [String]
|
||||
def templates_path
|
||||
File.join(File.expand_path("~/"), ".middleman")
|
||||
end
|
||||
|
||||
# Automatically load extensions from available RubyGems
|
||||
# which contain the EXTENSION_FILE
|
||||
#
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
require 'thor'
|
||||
require "thor/group"
|
||||
|
||||
module Middleman
|
||||
class CLI < Thor
|
||||
# CLI Module
|
||||
module Middleman::CLI
|
||||
|
||||
class Base < Thor
|
||||
include Thor::Actions
|
||||
check_unknown_options!
|
||||
default_task :server
|
||||
|
||||
class_option "help",
|
||||
:type => :boolean,
|
||||
|
@ -15,98 +16,6 @@ module Middleman
|
|||
help_check if options[:help]
|
||||
end
|
||||
|
||||
desc "init NAME [options]", "Create new project NAME"
|
||||
available_templates = Middleman::Templates.registered.keys.join(", ")
|
||||
method_option "template",
|
||||
:aliases => "-T",
|
||||
:default => "default",
|
||||
:desc => "Use a project template: #{available_templates}"
|
||||
method_option "css_dir",
|
||||
:default => "stylesheets",
|
||||
:desc => 'The path to the css files'
|
||||
method_option "js_dir",
|
||||
:default => "javascripts",
|
||||
:desc => 'The path to the javascript files'
|
||||
method_option "images_dir",
|
||||
:default => "images",
|
||||
:desc => 'The path to the image files'
|
||||
method_option "rack",
|
||||
:type => :boolean,
|
||||
:default => false,
|
||||
:desc => 'Include a config.ru file'
|
||||
method_option "bundler",
|
||||
:type => :boolean,
|
||||
:default => false,
|
||||
:desc => 'Create a Gemfile and use Bundler to manage gems'
|
||||
def init(name)
|
||||
key = options[:template].to_sym
|
||||
unless Middleman::Templates.registered.has_key?(key)
|
||||
raise Thor::Error.new "Unknown project template '#{key}'"
|
||||
end
|
||||
|
||||
thor_group = Middleman::Templates.registered[key]
|
||||
thor_group.new([name], options).invoke_all
|
||||
end
|
||||
|
||||
desc "server [options]", "Start the preview server"
|
||||
method_option "environment",
|
||||
:aliases => "-e",
|
||||
:default => ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development',
|
||||
:desc => "The environment Middleman will run under"
|
||||
method_option :host,
|
||||
:type => :string,
|
||||
:aliases => "-h",
|
||||
# :required => true,
|
||||
:default => "0.0.0.0",
|
||||
:desc => "Bind to HOST address"
|
||||
method_option "port",
|
||||
:aliases => "-p",
|
||||
:default => "4567",
|
||||
:desc => "The port Middleman will listen on"
|
||||
method_option "debug",
|
||||
:type => :boolean,
|
||||
:default => false,
|
||||
:desc => 'Print debug messages'
|
||||
def server
|
||||
params = {
|
||||
:port => options["port"],
|
||||
:host => options["host"],
|
||||
:environment => options["environment"],
|
||||
:debug => options["debug"]
|
||||
}
|
||||
|
||||
puts "== The Middleman is loading"
|
||||
Middleman::Guard.start(params)
|
||||
end
|
||||
|
||||
desc "build", "Builds the static site for deployment"
|
||||
method_option :relative,
|
||||
:type => :boolean,
|
||||
:aliases => "-r",
|
||||
:default => false,
|
||||
:desc => 'Force relative urls'
|
||||
method_option :clean,
|
||||
:type => :boolean,
|
||||
:aliases => "-c",
|
||||
:default => false,
|
||||
:desc => 'Removes orpahand files or directories from build'
|
||||
method_option :glob,
|
||||
:type => :string,
|
||||
:aliases => "-g",
|
||||
:default => nil,
|
||||
:desc => 'Build a subset of the project'
|
||||
def build
|
||||
thor_group = Middleman::Builder.new([], options).invoke_all
|
||||
end
|
||||
|
||||
desc "migrate", "Migrates an older project to the 2.0 structure"
|
||||
def migrate
|
||||
return if File.exists?("source")
|
||||
`mv public source`
|
||||
`cp -R views/* source/`
|
||||
`rm -rf views`
|
||||
end
|
||||
|
||||
desc "version", "Show version"
|
||||
def version
|
||||
require 'middleman/version'
|
||||
|
@ -121,3 +30,7 @@ module Middleman
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "middleman/cli/templates"
|
||||
require "middleman/cli/server"
|
||||
require "middleman/cli/build"
|
|
@ -1,11 +1,42 @@
|
|||
require "thor"
|
||||
require "thor/group"
|
||||
require "rack"
|
||||
require "rack/test"
|
||||
require "find"
|
||||
|
||||
module Middleman
|
||||
class Builder < Thor::Group
|
||||
module Middleman::CLI
|
||||
class Build < Thor::Group
|
||||
include Thor::Actions
|
||||
check_unknown_options!
|
||||
|
||||
desc "build [options]"
|
||||
class_option :relative,
|
||||
:type => :boolean,
|
||||
:aliases => "-r",
|
||||
:default => false,
|
||||
:desc => 'Force relative urls'
|
||||
class_option :clean,
|
||||
:type => :boolean,
|
||||
:aliases => "-c",
|
||||
:default => false,
|
||||
:desc => 'Removes orpahand files or directories from build'
|
||||
class_option :glob,
|
||||
:type => :string,
|
||||
:aliases => "-g",
|
||||
:default => nil,
|
||||
:desc => 'Build a subset of the project'
|
||||
def build
|
||||
if options.has_key?("relative") && options["relative"]
|
||||
self.class.shared_instance.activate :relative_assets
|
||||
end
|
||||
|
||||
self.class.shared_rack
|
||||
|
||||
opts = {}
|
||||
opts[:glob] = options["glob"] if options.has_key?("glob")
|
||||
opts[:clean] = options["clean"] if options.has_key?("clean")
|
||||
|
||||
action GlobAction.new(self, self.class.shared_instance, opts)
|
||||
|
||||
self.class.shared_instance.run_hook :after_build, self
|
||||
end
|
||||
|
||||
class << self
|
||||
def shared_instance
|
||||
|
@ -13,11 +44,11 @@ module Middleman
|
|||
set :environment, :build
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def shared_server
|
||||
@_shared_server ||= shared_instance.class
|
||||
end
|
||||
|
||||
|
||||
def shared_rack
|
||||
@_shared_rack ||= begin
|
||||
mock = ::Rack::MockSession.new(shared_server.to_rack_app)
|
||||
|
@ -28,6 +59,8 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
source_root(shared_instance.root)
|
||||
|
||||
# @private
|
||||
module ThorActions
|
||||
# Render a template to a file.
|
||||
|
@ -36,12 +69,12 @@ module Middleman
|
|||
config = args.last.is_a?(Hash) ? args.pop : {}
|
||||
destination = args.first || source
|
||||
|
||||
request_path = destination.sub(/^#{::Middleman::Builder.shared_instance.build_dir}/, "")
|
||||
request_path = destination.sub(/^#{self.class.shared_instance.build_dir}/, "")
|
||||
|
||||
begin
|
||||
destination, request_path = ::Middleman::Builder.shared_instance.reroute_builder(destination, request_path)
|
||||
destination, request_path = self.class.shared_instance.reroute_builder(destination, request_path)
|
||||
|
||||
response = ::Middleman::Builder.shared_rack.get(request_path.gsub(/\s/, "%20"))
|
||||
response = self.class.shared_rack.get(request_path.gsub(/\s/, "%20"))
|
||||
|
||||
create_file(destination, response.body, config)
|
||||
|
||||
|
@ -52,36 +85,8 @@ module Middleman
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
include ThorActions
|
||||
|
||||
class_option :relative, :type => :boolean, :aliases => "-r", :default => false, :desc => 'Override the config.rb file and force relative urls'
|
||||
class_option :glob, :type => :string, :aliases => "-g", :default => nil, :desc => 'Build a subset of the project'
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
|
||||
if options.has_key?("relative") && options["relative"]
|
||||
self.class.shared_instance.activate :relative_assets
|
||||
end
|
||||
end
|
||||
|
||||
def source_paths
|
||||
@source_paths ||= [
|
||||
self.class.shared_instance.root
|
||||
]
|
||||
end
|
||||
|
||||
def build_all_files
|
||||
self.class.shared_rack
|
||||
|
||||
opts = { }
|
||||
opts[:glob] = options["glob"] if options.has_key?("glob")
|
||||
opts[:clean] = options["clean"] if options.has_key?("clean")
|
||||
|
||||
action GlobAction.new(self, self.class.shared_instance, opts)
|
||||
|
||||
self.class.shared_instance.run_hook :after_build, self
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
|
@ -92,9 +97,9 @@ module Middleman
|
|||
@app = app
|
||||
source = @app.source
|
||||
@destination = @app.build_dir
|
||||
|
||||
|
||||
@source = File.expand_path(base.find_in_source_paths(source.to_s))
|
||||
|
||||
|
||||
super(base, destination, config)
|
||||
end
|
||||
|
||||
|
@ -109,7 +114,7 @@ module Middleman
|
|||
end
|
||||
|
||||
protected
|
||||
|
||||
|
||||
def clean!
|
||||
files = @cleaning_queue.select { |q| File.file? q }
|
||||
directories = @cleaning_queue.select { |q| File.directory? q }
|
||||
|
@ -124,7 +129,7 @@ module Middleman
|
|||
base.remove_file d, :force => true if directory_empty? d
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def cleaning?
|
||||
@config.has_key?(:clean) && @config[:clean]
|
||||
end
|
||||
|
@ -142,20 +147,20 @@ module Middleman
|
|||
end
|
||||
end if File.exist?(@destination)
|
||||
end
|
||||
|
||||
|
||||
def execute!
|
||||
sort_order = %w(.png .jpeg .jpg .gif .bmp .svg .svgz .ico .woff .otf .ttf .eot .js .css)
|
||||
|
||||
|
||||
paths = @app.sitemap.all_paths.sort do |a, b|
|
||||
a_ext = File.extname(a)
|
||||
b_ext = File.extname(b)
|
||||
|
||||
|
||||
a_idx = sort_order.index(a_ext) || 100
|
||||
b_idx = sort_order.index(b_ext) || 100
|
||||
|
||||
|
||||
a_idx <=> b_idx
|
||||
end
|
||||
|
||||
|
||||
paths.each do |path|
|
||||
file_source = path
|
||||
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
||||
|
@ -168,15 +173,18 @@ module Middleman
|
|||
elsif @app.sitemap.ignored?(file_source)
|
||||
next
|
||||
end
|
||||
|
||||
|
||||
if @config[:glob]
|
||||
next unless File.fnmatch(@config[:glob], file_source)
|
||||
end
|
||||
|
||||
|
||||
file_destination = base.tilt_template(file_source, file_destination, { :force => true })
|
||||
|
||||
@cleaning_queue.delete(file_destination) if cleaning?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Base.register(Build, :build, "build [options]", "Builds the static site for deployment")
|
||||
Base.map({ "b" => "build" })
|
||||
end
|
40
lib/middleman/cli/server.rb
Normal file
40
lib/middleman/cli/server.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
module Middleman::CLI
|
||||
class Server < Thor::Group
|
||||
check_unknown_options!
|
||||
|
||||
desc "server [options]"
|
||||
class_option "environment",
|
||||
:aliases => "-e",
|
||||
:default => ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development',
|
||||
:desc => "The environment Middleman will run under"
|
||||
class_option :host,
|
||||
:type => :string,
|
||||
:aliases => "-h",
|
||||
# :required => true,
|
||||
:default => "0.0.0.0",
|
||||
:desc => "Bind to HOST address"
|
||||
class_option "port",
|
||||
:aliases => "-p",
|
||||
:default => "4567",
|
||||
:desc => "The port Middleman will listen on"
|
||||
class_option "debug",
|
||||
:type => :boolean,
|
||||
:default => false,
|
||||
:desc => 'Print debug messages'
|
||||
def server
|
||||
params = {
|
||||
:port => options["port"],
|
||||
:host => options["host"],
|
||||
:environment => options["environment"],
|
||||
:debug => options["debug"]
|
||||
}
|
||||
|
||||
puts "== The Middleman is loading"
|
||||
Middleman::Guard.start(params)
|
||||
end
|
||||
end
|
||||
|
||||
Base.register(Server, :server, "server [options]", "Start the preview server")
|
||||
Base.map({ "s" => "server" })
|
||||
Base.default_task :server
|
||||
end
|
46
lib/middleman/cli/templates.rb
Normal file
46
lib/middleman/cli/templates.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
module Middleman::CLI
|
||||
class Templates < Thor::Group
|
||||
check_unknown_options!
|
||||
|
||||
desc "init NAME [options]"
|
||||
available_templates = ::Middleman::Templates.registered.keys.join(", ")
|
||||
argument :name
|
||||
class_option "template",
|
||||
:aliases => "-T",
|
||||
:default => "default",
|
||||
:desc => "Use a project template: #{available_templates}"
|
||||
class_option "css_dir",
|
||||
:default => "stylesheets",
|
||||
:desc => 'The path to the css files'
|
||||
class_option "js_dir",
|
||||
:default => "javascripts",
|
||||
:desc => 'The path to the javascript files'
|
||||
class_option "images_dir",
|
||||
:default => "images",
|
||||
:desc => 'The path to the image files'
|
||||
class_option "rack",
|
||||
:type => :boolean,
|
||||
:default => false,
|
||||
:desc => 'Include a config.ru file'
|
||||
class_option "bundler",
|
||||
:type => :boolean,
|
||||
:default => false,
|
||||
:desc => 'Create a Gemfile and use Bundler to manage gems'
|
||||
def init
|
||||
key = options[:template].to_sym
|
||||
unless ::Middleman::Templates.registered.has_key?(key)
|
||||
raise Thor::Error.new "Unknown project template '#{key}'"
|
||||
end
|
||||
|
||||
thor_group = ::Middleman::Templates.registered[key]
|
||||
thor_group.new([name], options).invoke_all
|
||||
end
|
||||
end
|
||||
|
||||
Base.register(Templates, :init, "init NAME [options]", "Create new project NAME")
|
||||
Base.map({
|
||||
"i" => "init",
|
||||
"new" => "init",
|
||||
"n" => "init"
|
||||
})
|
||||
end
|
|
@ -4,7 +4,7 @@ class Middleman::Templates::Local < Middleman::Templates::Base
|
|||
# Look for templates in ~/.middleman
|
||||
# @return [String]
|
||||
def self.source_root
|
||||
Middleman.templates_path
|
||||
File.join(File.expand_path("~/"), ".middleman")
|
||||
end
|
||||
|
||||
# Just copy from the template path
|
||||
|
@ -15,7 +15,7 @@ class Middleman::Templates::Local < Middleman::Templates::Base
|
|||
end
|
||||
|
||||
# Iterate over the directories in the templates path and register each one.
|
||||
Dir[File.join(Middleman.templates_path, "*")].each do |dir|
|
||||
Dir[File.join(Middleman::Templates::Local.source_root, "*")].each do |dir|
|
||||
next unless File.directory?(dir)
|
||||
Middleman::Templates.register(File.basename(dir).to_sym, Middleman::Templates::Local)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue