From f16510d034ff5bf82d10b516b924baa2d32c719a Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 4 Jan 2015 14:23:35 -0600 Subject: [PATCH] Update CLI --- CHANGELOG.md | 1 + middleman-cli/bin/middleman | 7 +- middleman-cli/lib/middleman-cli.rb | 81 ++-------- middleman-cli/lib/middleman-cli/build.rb | 139 +++++++++--------- middleman-cli/lib/middleman-cli/console.rb | 30 ++-- middleman-cli/lib/middleman-cli/extension.rb | 20 +-- middleman-cli/lib/middleman-cli/init.rb | 69 +++++---- middleman-cli/lib/middleman-cli/server.rb | 92 ++++++------ .../templates/extension/lib/lib.rb | 2 +- middleman-cli/lib/middleman-core/cli.rb | 2 +- middleman-core/features/3rd_party_cli.feature | 15 -- .../lib/middleman-core/application.rb | 2 +- .../lib/middleman-core/step_definitions.rb | 2 +- 13 files changed, 193 insertions(+), 269 deletions(-) delete mode 100644 middleman-core/features/3rd_party_cli.feature diff --git a/CHANGELOG.md b/CHANGELOG.md index 70d2f7ca..b637acb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ master === +* Remove side-loading of CLI tasks from `tasks/` * Add the option of naming `config.rb` as `middleman.rb`. * Builder extracted from Thor. `after_build` hook now passes an instance of a Builder instead of the Thor CLI. * New FileWatcher API. diff --git a/middleman-cli/bin/middleman b/middleman-cli/bin/middleman index 924f905d..165b7bc9 100755 --- a/middleman-cli/bin/middleman +++ b/middleman-cli/bin/middleman @@ -14,5 +14,10 @@ require "middleman-cli" # Change directory to the root Dir.chdir(ENV["MM_ROOT"]) if ENV["MM_ROOT"] +# Default command is server +if ARGV[0] != 'help' && (ARGV.length < 1 || ARGV.first.include?('-')) + ARGV.unshift('server') +end + # Start the CLI -Middleman::Cli::Base.start +Middleman::Cli::Base.start(ARGV) diff --git a/middleman-cli/lib/middleman-cli.rb b/middleman-cli/lib/middleman-cli.rb index 73f59795..67565f3e 100644 --- a/middleman-cli/lib/middleman-cli.rb +++ b/middleman-cli/lib/middleman-cli.rb @@ -6,81 +6,18 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) # Require Thor since that's what the whole CLI is built around require 'thor' -require 'thor/group' # CLI Module -module Middleman - module Cli - # The base task from which everything else extends - class Base < Thor - class << self - def start(*args) - # Change flag to a module - ARGV.unshift('help') if ARGV.delete('--help') +module Middleman::Cli + # The base task from which everything else extends + class Base < ::Thor + desc 'version', 'Show version' + def version + say "Middleman #{Middleman::VERSION}" + end - # Default command is server - if ARGV[0] != 'help' && (ARGV.length < 1 || ARGV.first.include?('-')) - ARGV.unshift('server') - end - - super - end - end - - desc 'version', 'Show version' - def version - say "Middleman #{Middleman::VERSION}" - end - - desc 'help', 'Show help' - - # Override the Thor help method to find help for subtasks - # @param [Symbol, String, nil] meth - # @param [Boolean] subcommand - # @return [void] - # rubocop:disable UnusedMethodArgument - def help(meth=nil, subcommand=false) - if meth && !self.respond_to?(meth) - klass, task = Thor::Util.find_class_and_task_by_namespace("#{meth}:#{meth}") - klass.start(['-h', task].compact, shell: shell) - else - list = [] - Thor::Util.thor_classes_in(Middleman::Cli).each do |thor_class| - list += thor_class.printable_tasks(false) - end - list.sort! { |a, b| a[0] <=> b[0] } - - shell.say 'Tasks:' - shell.print_table(list, ident: 2, truncate: true) - shell.say %(\nSee 'middleman help ' for more information on specific command.) - shell.say - end - end - - # Intercept missing methods and search subtasks for them - # @param [Symbol] meth - def method_missing(meth, *args) - meth = meth.to_s - meth = self.class.map[meth] if self.class.map.key?(meth) - - klass, task = Thor::Util.find_class_and_task_by_namespace("#{meth}:#{meth}") - - if klass.nil? - tasks_dir = File.join(Dir.pwd, 'tasks') - - if File.exist?(tasks_dir) - Dir[File.join(tasks_dir, '**/*_task.rb')].each { |f| require f } - klass, task = Thor::Util.find_class_and_task_by_namespace("#{meth}:#{meth}") - end - end - - if klass.nil? - raise Thor::Error, "There's no '#{meth}' command for Middleman. Try 'middleman help' for a list of commands." - else - args.unshift(task) if task - klass.start(args, shell: shell) - end - end + def self.exit_on_failure? + true end end end diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index f69bd72e..42510819 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -1,39 +1,36 @@ # CLI Module module Middleman::Cli # The CLI Build class - class Build < Thor + class Build < Thor::Group include Thor::Actions check_unknown_options! - namespace :build - - desc 'build [options]', 'Builds the static site for deployment' - method_option :environment, - aliases: '-e', - default: ENV['MM_ENV'] || ENV['RACK_ENV'] || 'production', - desc: 'The environment Middleman will run under' - method_option :clean, - type: :boolean, - default: true, - desc: 'Remove orphaned files from build (--no-clean to disable)' - method_option :glob, - type: :string, - aliases: '-g', - default: nil, - desc: 'Build a subset of the project' - method_option :verbose, - type: :boolean, - default: false, - desc: 'Print debug messages' - method_option :instrument, - type: :string, - default: false, - desc: 'Print instrument messages' - method_option :profile, - type: :boolean, - default: false, - desc: 'Generate profiling report for the build' + class_option :environment, + aliases: '-e', + default: ENV['MM_ENV'] || ENV['RACK_ENV'] || 'production', + desc: 'The environment Middleman will run under' + class_option :clean, + type: :boolean, + default: true, + desc: 'Remove orphaned files from build (--no-clean to disable)' + class_option :glob, + type: :string, + aliases: '-g', + default: nil, + desc: 'Build a subset of the project' + class_option :verbose, + type: :boolean, + default: false, + desc: 'Print debug messages' + class_option :instrument, + type: :string, + default: false, + desc: 'Print instrument messages' + class_option :profile, + type: :boolean, + default: false, + desc: 'Generate profiling report for the build' # Core build Thor command # @return [void] @@ -78,51 +75,49 @@ module Middleman::Cli end end - # Tell Thor to send an exit status on a failure. - def self.exit_on_failure? - true - end + protected - no_tasks do - # Handles incoming events from the builder. - # @param [Symbol] event_type The type of event. - # @param [String] contents The event contents. - # @param [String] extra The extra information. - # @return [void] - def on_event(event_type, target, extra=nil) - case event_type - when :error - say_status :error, target, :red - shell.say extra, :red if options['verbose'] - when :deleted - say_status :remove, target, :green - when :created - say_status :create, target, :green - when :identical - say_status :identical, target, :blue - when :updated - say_status :updated, target, :yellow - else - say_status event_type, extra, :blue - end - end - - # Find empty directories in the build folder and remove them. - # @return [Boolean] - def clean_directories! - all_build_files = File.join(@app.config[:build_dir], '**', '*') - - empty_directories = Dir[all_build_files].select do |d| - File.directory?(d) - end - - empty_directories.each do |d| - remove_file d, force: true if Pathname(d).children.empty? - end + # Handles incoming events from the builder. + # @param [Symbol] event_type The type of event. + # @param [String] contents The event contents. + # @param [String] extra The extra information. + # @return [void] + def on_event(event_type, target, extra=nil) + case event_type + when :error + say_status :error, target, :red + shell.say extra, :red if options['verbose'] + when :deleted + say_status :remove, target, :green + when :created + say_status :create, target, :green + when :identical + say_status :identical, target, :blue + when :updated + say_status :updated, target, :yellow + else + say_status event_type, extra, :blue end end + + # Find empty directories in the build folder and remove them. + # @return [Boolean] + def clean_directories! + all_build_files = File.join(@app.config[:build_dir], '**', '*') + + empty_directories = Dir[all_build_files].select do |d| + File.directory?(d) + end + + empty_directories.each do |d| + remove_file d, force: true if Pathname(d).children.empty? + end + end + + # Add to CLI + Base.register(self, 'build', 'build [options]', 'Builds the static site for deployment') + + # Map "b" to "build" + Base.map('b' => 'build') end - - # Alias "b" to "build" - Base.map('b' => 'build') end diff --git a/middleman-cli/lib/middleman-cli/console.rb b/middleman-cli/lib/middleman-cli/console.rb index 3200cb6b..51ddb28e 100644 --- a/middleman-cli/lib/middleman-cli/console.rb +++ b/middleman-cli/lib/middleman-cli/console.rb @@ -1,25 +1,19 @@ # CLI Module module Middleman::Cli - # Alias "c" to "console" - Base.map(c: 'console') - # The CLI Console class - class Console < Thor + class Console < Thor::Group include Thor::Actions check_unknown_options! - namespace :console - - desc 'console [options]', 'Start an interactive console in the context of your Middleman application' - method_option :environment, - aliases: '-e', - default: ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development', - desc: 'The environment Middleman will run under' - method_option :verbose, - type: :boolean, - default: false, - desc: 'Print debug messages' + class_option :environment, + aliases: '-e', + default: ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development', + desc: 'The environment Middleman will run under' + class_option :verbose, + type: :boolean, + default: false, + desc: 'Print debug messages' def console require 'middleman-core' require 'irb' @@ -42,5 +36,11 @@ module Middleman::Cli require 'irb/ext/multi-irb' IRB.irb nil, @app end + + # Add to CLI + Base.register(self, 'console', 'console [options]', 'Start an interactive console in the context of your Middleman application') + + # Map "c" to "console" + Base.map('c' => 'console') end end diff --git a/middleman-cli/lib/middleman-cli/extension.rb b/middleman-cli/lib/middleman-cli/extension.rb index ff0eda28..1b079f4d 100644 --- a/middleman-cli/lib/middleman-cli/extension.rb +++ b/middleman-cli/lib/middleman-cli/extension.rb @@ -1,13 +1,11 @@ # CLI Module module Middleman::Cli # A thor task for creating new projects - class Extension < Thor + class Extension < Thor::Group include Thor::Actions check_unknown_options! - namespace :extension - # Required path for the new project to be generated argument :name, type: :string @@ -17,11 +15,13 @@ module Middleman::Cli File.join(File.dirname(__FILE__), 'templates') end - desc 'extension [options]', 'Create Middleman extension scaffold NAME' - method_option 'skip-git', - type: :boolean, - default: false, - desc: 'Skip Git ignores and keeps' + class_option 'skip-git', + type: :boolean, + default: false, + desc: 'Skip Git ignores and keeps' + + # Output a .gitignore file + class_option :git, type: :boolean, default: true # The extension task # @param [String] name @@ -36,7 +36,7 @@ module Middleman::Cli empty_directory File.join(name, 'fixtures') end - # Output a .gitignore file - class_option :git, type: :boolean, default: true + # Add to CLI + Base.register(self, 'extension', 'extension [options]', 'Create a new Middleman extension') end end diff --git a/middleman-cli/lib/middleman-cli/init.rb b/middleman-cli/lib/middleman-cli/init.rb index 0bae42de..2a11022b 100644 --- a/middleman-cli/lib/middleman-cli/init.rb +++ b/middleman-cli/lib/middleman-cli/init.rb @@ -1,28 +1,27 @@ # CLI Module module Middleman::Cli # A thor task for creating new projects - class Init < Thor + class Init < Thor::Group include Thor::Actions + check_unknown_options! - namespace :init + argument :target, type: :string, default: '.' - desc 'init TARGET [options]', 'Create new project at TARGET' - method_option 'template', - aliases: '-T', - default: 'middleman/middleman-templates-default', - desc: 'Use a project template' + class_option 'template', + aliases: '-T', + default: 'middleman/middleman-templates-default', + desc: 'Use a project template' # Do not run bundle install - method_option 'skip-bundle', - type: :boolean, - aliases: '-B', - default: false, - desc: 'Skip bundle install' + class_option 'skip-bundle', + type: :boolean, + aliases: '-B', + default: false, + desc: 'Skip bundle install' # The init task - # @param [String] name - def init(target='.') + def init require 'tmpdir' repo_path, repo_branch = if shortname?(options[:template]) @@ -37,8 +36,8 @@ module Middleman::Cli data['links']['github'] data['links']['github'].split('#') rescue ::OpenURI::HTTPError - puts "Template `#{options[:template]}` not found in Middleman Directory." - puts 'Did you mean to use a full `user/repo` path?' + say "Template `#{options[:template]}` not found in Middleman Directory." + say 'Did you mean to use a full `user/repo` path?' exit end else @@ -51,13 +50,20 @@ module Middleman::Cli run("git #{cmd} #{repo_path} #{dir}") - source_paths << dir - - directory dir, target, exclude_pattern: /\.git\/|\.gitignore$/ - inside(target) do - run('bundle install') - end unless ENV['TEST'] || options[:'skip-bundle'] + thorfile = File.join(dir, 'Thorfile') + + if File.exist?(thorfile) + ::Thor::Util.load_thorfile(thorfile) + + invoke 'middleman:generator' + else + source_paths << dir + directory dir, '.', exclude_pattern: /\.git\/|\.gitignore$/ + end + + run('bundle install') unless ENV['TEST'] || options[:'skip-bundle'] + end end end @@ -70,16 +76,15 @@ module Middleman::Cli def repository_path(repo) "git://github.com/#{repo}.git" end - end - def self.exit_on_failure? - true - end + # Add to CLI + Base.register(self, 'init', 'init TARGET [options]', 'Create new project at TARGET') - # Map "i", "new" and "n" to "init" - Base.map( - 'i' => 'init', - 'new' => 'init', - 'n' => 'init' - ) + # Map "i", "new" and "n" to "init" + Base.map( + 'i' => 'init', + 'new' => 'init', + 'n' => 'init' + ) + end end diff --git a/middleman-cli/lib/middleman-cli/server.rb b/middleman-cli/lib/middleman-cli/server.rb index 5c66e3b4..47ec23d5 100644 --- a/middleman-cli/lib/middleman-cli/server.rb +++ b/middleman-cli/lib/middleman-cli/server.rb @@ -1,50 +1,47 @@ # CLI Module module Middleman::Cli # Server thor task - class Server < Thor + class Server < Thor::Group check_unknown_options! - namespace :server - - 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', - 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 :verbose, - type: :boolean, - default: false, - desc: 'Print debug messages' - method_option :instrument, - type: :string, - default: false, - desc: 'Print instrument messages' - method_option :disable_watcher, - type: :boolean, - default: false, - desc: 'Disable the file change and delete watcher process' - method_option :profile, - type: :boolean, - default: false, - desc: 'Generate profiling report for server startup' - method_option :force_polling, - type: :boolean, - default: false, - desc: 'Force file watcher into polling mode' - method_option :latency, - type: :numeric, - aliases: '-l', - default: 0.25, - desc: 'Set file watcher latency, in seconds' + 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', + 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 :verbose, + type: :boolean, + default: false, + desc: 'Print debug messages' + class_option :instrument, + type: :string, + default: false, + desc: 'Print instrument messages' + class_option :disable_watcher, + type: :boolean, + default: false, + desc: 'Disable the file change and delete watcher process' + class_option :profile, + type: :boolean, + default: false, + desc: 'Generate profiling report for server startup' + class_option :force_polling, + type: :boolean, + default: false, + desc: 'Force file watcher into polling mode' + class_option :latency, + type: :numeric, + aliases: '-l', + default: 0.25, + desc: 'Set file watcher latency, in seconds' # Start the server def server @@ -71,12 +68,11 @@ module Middleman::Cli puts '== The Middleman is loading' ::Middleman::PreviewServer.start(params) end - end - def self.exit_on_failure? - true - end + # Add to CLI + Base.register(self, 'server', 'server [options]', 'Start the preview server') - # Map "s" to "server" - Base.map('s' => 'server') + # Map "s" to "server" + Base.map('s' => 'server') + end end diff --git a/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb b/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb index 8b98bf78..8a3c5dc6 100644 --- a/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb +++ b/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb @@ -24,7 +24,7 @@ class MyExtension < ::Middleman::Extension # def manipulate_resource_list(resources) # end - # module do + # helpers do # def a_helper # end # end diff --git a/middleman-cli/lib/middleman-core/cli.rb b/middleman-cli/lib/middleman-core/cli.rb index 6ae5fb51..19f65d52 100644 --- a/middleman-cli/lib/middleman-core/cli.rb +++ b/middleman-cli/lib/middleman-core/cli.rb @@ -1,2 +1,2 @@ # Backwards compat -require 'middleman-cli' \ No newline at end of file +require 'middleman-cli' diff --git a/middleman-core/features/3rd_party_cli.feature b/middleman-core/features/3rd_party_cli.feature deleted file mode 100644 index 71e6a009..00000000 --- a/middleman-core/features/3rd_party_cli.feature +++ /dev/null @@ -1,15 +0,0 @@ -Feature: Allow config.rb and extensions to add CLI commands - - Scenario: Command autoloaded from tasks/ directory - Given an empty app - And a file named "tasks/hello_task.rb" with: - """ - class Hello < Thor - desc "hello", "Say hello" - def hello - puts "Hello World" - end - end - """ - When I run `middleman hello` - Then the output should contain "Hello World" \ No newline at end of file diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 917da02a..059d7a43 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -255,7 +255,7 @@ module Middleman Tilt.mappings.delete(key) end end - + @extensions.activate_all run_hook :after_configuration diff --git a/middleman-core/lib/middleman-core/step_definitions.rb b/middleman-core/lib/middleman-core/step_definitions.rb index 083bca0a..e8134764 100644 --- a/middleman-core/lib/middleman-core/step_definitions.rb +++ b/middleman-core/lib/middleman-core/step_definitions.rb @@ -17,5 +17,5 @@ end World(ArubaMonkeypatch) Before do - @aruba_timeout_seconds = RUBY_PLATFORM == 'java' ? 120 : 60 + @aruba_timeout_seconds = RUBY_PLATFORM == 'java' ? 240 : 120 end