lib/nanoc3/cli.rb in nanoc3-3.2.0b1 vs lib/nanoc3/cli.rb in nanoc3-3.2.0b2

- old
+ new

@@ -5,10 +5,14 @@ module Nanoc3::CLI module Commands end + autoload 'Logger', 'nanoc3/cli/logger' + autoload 'Command', 'nanoc3/cli/command' + autoload 'ErrorHandler', 'nanoc3/cli/error_handler' + # @return [Boolean] true if debug output is enabled, false if not # # @since 3.2.0 def self.debug? @debug || false @@ -22,22 +26,21 @@ # @since 3.2.0 def self.debug=(boolean) @debug = boolean end - autoload 'Logger', 'nanoc3/cli/logger' - autoload 'Command', 'nanoc3/cli/command' - # Invokes the nanoc commandline tool with the given arguments. # # @param [Array<String>] args An array of commandline arguments # # @return [void] def self.run(args) - self.setup - self.load_custom_commands - self.root_command.run(args) + Nanoc3::CLI::ErrorHandler.handle_while do + self.setup + self.load_custom_commands + self.root_command.run(args) + end end # Adds the given command to the collection of available commands. # # @param [Cri::Command] cmd The command to add @@ -51,12 +54,12 @@ # Makes the commandline interface ready for using by loading the commands. # # @return [void] def self.setup - # Don’t set up twice - return if @setup + # Reinit + @root_command = nil # Add help command help_cmd = Cri::Command.new_basic_help self.add_command(help_cmd) @@ -65,40 +68,66 @@ cmd_filenames.each do |filename| next if File.basename(filename, '.rb') == 'nanoc' cmd = self.load_command_at(filename) self.add_command(cmd) end - - @setup = true end # Loads the commands in `commands/`. # # @return [void] def self.load_custom_commands - Dir['commands/*.rb'].each do |filename| - cmd = Nanoc3::CLI.load_command_at(filename) - Nanoc3::CLI.root_command.add_command(cmd) + self.recursive_contents_of('commands').each do |filename| + # Create command + command = Nanoc3::CLI.load_command_at(filename) + + # Get supercommand + pieces = filename.gsub(/^commands\/|\.rb$/, '').split('/') + pieces = pieces[0, pieces.size-1] || [] + root = Nanoc3::CLI.root_command + supercommand = pieces.inject(root) do |cmd, piece| + cmd.nil? ? nil : cmd.command_named(piece) + end + + # Add to supercommand + if supercommand.nil? + raise "Cannot load command at #{filename} because its supercommand cannot be found" + end + supercommand.add_command(command) end end # Loads the command in the file with the given filename. # # @param [String] filename The name of the file that contains the command # # @return [Cri::Command] The loaded command - def self.load_command_at(filename) + def self.load_command_at(filename, command_name=nil) + # Load code = File.read(filename) cmd = Cri::Command.define(code) - cmd.modify { name File.basename(filename, '.rb') } + + # Set name + command_name ||= File.basename(filename, '.rb') + cmd.modify { name command_name } + + # Done cmd end # @return [Cri::Command] The root command, i.e. the commandline tool itself def self.root_command @root_command ||= begin filename = File.dirname(__FILE__) + "/cli/commands/nanoc.rb" self.load_command_at(filename) end + end + + # @return [Array] The directory contents + def self.recursive_contents_of(path) + return [] unless File.directory?(path) + files, dirs = *Dir[path + '/*'].sort.partition { |e| File.file?(e) } + dirs.each { |d| files.concat self.recursive_contents_of(d) } + files end end