atli 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,15 @@
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Stdlib
5
+ # -----------------------------------------------------------------------
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+ require 'nrser'
10
+
11
+ # Project / Package
12
+ # -----------------------------------------------------------------------
1
13
  require "thor/command"
2
14
  require "thor/core_ext/hash_with_indifferent_access"
3
15
  require "thor/core_ext/ordered_hash"
@@ -7,6 +19,16 @@ require "thor/parser"
7
19
  require "thor/shell"
8
20
  require "thor/line_editor"
9
21
  require "thor/util"
22
+ require 'thor/execution'
23
+ require 'thor/base/common_class_options'
24
+
25
+
26
+ # Refinements
27
+ # =======================================================================
28
+
29
+ using NRSER
30
+ using NRSER::Types
31
+
10
32
 
11
33
  class Thor
12
34
  autoload :Actions, "thor/actions"
@@ -148,47 +170,69 @@ class Thor
148
170
 
149
171
  # end protected
150
172
 
173
+
174
+ # Module Methods
175
+ # ============================================================================
176
+
177
+ # Hook called when {Thor::Base} is mixed in ({Thor} and {Thor::Group}).
178
+ #
179
+ # Extends `base` with {Thor::Base::ClassMethods}, and includes
180
+ # {Thor::Invocation} and {Thor::Shell} in `base` as well.
181
+ #
182
+ # @param [Module] base
183
+ # Module (or Class) that included {Thor::Base}.
184
+ #
185
+ # @return [void]
186
+ #
187
+ def self.included base
188
+ base.extend ClassMethods
189
+ base.send :include, Invocation
190
+ base.send :include, Shell
191
+
192
+ base.no_commands {
193
+ base.send :include, SemanticLogger::Loggable
194
+ }
195
+
196
+ end
151
197
 
152
- class << self
153
- def included(base) #:nodoc:
154
- base.extend ClassMethods
155
- base.send :include, Invocation
156
- base.send :include, Shell
157
- end
198
+ # Returns the classes that inherits from Thor or Thor::Group.
199
+ #
200
+ # ==== Returns
201
+ # Array[Class]
202
+ #
203
+ def self.subclasses
204
+ @subclasses ||= []
205
+ end
158
206
 
159
- # Returns the classes that inherits from Thor or Thor::Group.
160
- #
161
- # ==== Returns
162
- # Array[Class]
163
- #
164
- def subclasses
165
- @subclasses ||= []
166
- end
207
+ # Returns the files where the subclasses are kept.
208
+ #
209
+ # ==== Returns
210
+ # Hash[path<String> => Class]
211
+ #
212
+ def self.subclass_files
213
+ @subclass_files ||= Hash.new { |h, k| h[k] = [] }
214
+ end
167
215
 
168
- # Returns the files where the subclasses are kept.
169
- #
170
- # ==== Returns
171
- # Hash[path<String> => Class]
172
- #
173
- def subclass_files
174
- @subclass_files ||= Hash.new { |h, k| h[k] = [] }
216
+ # Whenever a class inherits from Thor or Thor::Group, we should track the
217
+ # class and the file on Thor::Base. This is the method responsible for it.
218
+ #
219
+ def self.register_klass_file(klass) #:nodoc:
220
+ file = caller[1].match(/(.*):\d+/)[1]
221
+ unless Thor::Base.subclasses.include?(klass)
222
+ Thor::Base.subclasses << klass
175
223
  end
176
224
 
177
- # Whenever a class inherits from Thor or Thor::Group, we should track the
178
- # class and the file on Thor::Base. This is the method responsible for it.
179
- #
180
- def register_klass_file(klass) #:nodoc:
181
- file = caller[1].match(/(.*):\d+/)[1]
182
- unless Thor::Base.subclasses.include?(klass)
183
- Thor::Base.subclasses << klass
184
- end
185
-
186
- file_subclasses = Thor::Base.subclass_files[File.expand_path(file)]
187
- file_subclasses << klass unless file_subclasses.include?(klass)
188
- end
225
+ file_subclasses = Thor::Base.subclass_files[File.expand_path(file)]
226
+ file_subclasses << klass unless file_subclasses.include?(klass)
189
227
  end
190
-
228
+
229
+
230
+ # Methods that are mixed in as module/class/singleton methods to modules
231
+ # that include {Thor::Base}.
232
+ #
191
233
  module ClassMethods
234
+ include Thor::Base::CommonClassOptions
235
+
192
236
  def attr_reader(*) #:nodoc:
193
237
  no_commands { super }
194
238
  end
@@ -528,7 +572,7 @@ class Thor
528
572
  @namespace ||= Thor::Util.namespace_from_thor_class(self)
529
573
  end
530
574
  end
531
-
575
+
532
576
  # Parses the command and options from the given args, instantiate the class
533
577
  # and invoke the command. This method is used when the arguments must be parsed
534
578
  # from an array. If you are inside Ruby and want to use a Thor class, you
@@ -541,11 +585,11 @@ class Thor
541
585
  config[:shell] ||= Thor::Base.shell.new
542
586
  dispatch(nil, given_args.dup, nil, config)
543
587
  rescue Thor::Error => e
544
- config[:debug] || (
545
- ENV["THOR_DEBUG"] == "1" ?
546
- (raise e) :
547
- config[:shell].error(e.message)
548
- )
588
+ if config[:debug] || ENV["THOR_DEBUG"] == "1"
589
+ raise e
590
+ else
591
+ config[:shell].error(e.message)
592
+ end
549
593
  exit(1) if exit_on_failure?
550
594
  rescue Errno::EPIPE
551
595
  # This happens if a thor command is piped to something like `head`,
@@ -554,6 +598,22 @@ class Thor
554
598
  # computation will not occur.
555
599
  exit(0)
556
600
  end
601
+
602
+
603
+ # Like {#start}, but explicitly for handling over control in an
604
+ # executable.
605
+ #
606
+ # For details on why this is here see
607
+ # {file:doc/files/notes/too-broken-to-fail.md Too Broken to Fail}.
608
+ #
609
+ def exec!(given_args = ARGV, config = {})
610
+ execution = Thor::Execution.new thor_class: self,
611
+ given_args: given_args,
612
+ thor_config: config
613
+
614
+ execution.exec!
615
+ end # #start
616
+
557
617
 
558
618
  # Allows to use private methods from parent in child classes as commands.
559
619
  #
@@ -592,182 +652,184 @@ class Thor
592
652
  raise InvocationError, msg
593
653
  end
594
654
 
595
- protected
655
+ protected
656
+ # ============================================================================
596
657
 
597
- # Prints the class options per group. If an option does not belong to
598
- # any group, it's printed as Class option.
599
- #
600
- def class_options_help(shell, groups = {}) #:nodoc:
601
- # Group options by group
602
- class_options.each do |_, value|
603
- groups[value.group] ||= []
604
- groups[value.group] << value
605
- end
658
+ # Prints the class options per group. If an option does not belong to
659
+ # any group, it's printed as Class option.
660
+ #
661
+ def class_options_help(shell, groups = {}) #:nodoc:
662
+ # Group options by group
663
+ class_options.each do |_, value|
664
+ groups[value.group] ||= []
665
+ groups[value.group] << value
666
+ end
606
667
 
607
- # Deal with default group
608
- global_options = groups.delete(nil) || []
609
- print_options(shell, global_options)
668
+ # Deal with default group
669
+ global_options = groups.delete(nil) || []
670
+ print_options(shell, global_options)
610
671
 
611
- # Print all others
612
- groups.each do |group_name, options|
613
- print_options(shell, options, group_name)
672
+ # Print all others
673
+ groups.each do |group_name, options|
674
+ print_options(shell, options, group_name)
675
+ end
614
676
  end
615
- end
616
677
 
617
- # Receives a set of options and print them.
618
- def print_options(shell, options, group_name = nil)
619
- return if options.empty?
678
+ # Receives a set of options and print them.
679
+ def print_options(shell, options, group_name = nil)
680
+ return if options.empty?
620
681
 
621
- list = []
622
- padding = options.map { |o| o.aliases.size }.max.to_i * 4
682
+ list = []
683
+ padding = options.map { |o| o.aliases.size }.max.to_i * 4
623
684
 
624
- options.each do |option|
625
- next if option.hide
626
- item = [option.usage(padding)]
627
- item.push(option.description ? "# #{option.description}" : "")
685
+ options.each do |option|
686
+ next if option.hide
687
+ item = [option.usage(padding)]
688
+ item.push(option.description ? "# #{option.description}" : "")
628
689
 
629
- list << item
630
- list << ["", "# Default: #{option.default}"] if option.show_default?
631
- if option.enum
632
- list << ["", "# Possible values: #{option.enum.join(', ')}"]
690
+ list << item
691
+ list << ["", "# Default: #{option.default}"] if option.show_default?
692
+ if option.enum
693
+ list << ["", "# Possible values: #{option.enum.join(', ')}"]
694
+ end
633
695
  end
696
+
697
+ shell.say(group_name ? "#{group_name} options:" : "Options:")
698
+ shell.print_table(list, :indent => 2)
699
+ shell.say ""
634
700
  end
635
701
 
636
- shell.say(group_name ? "#{group_name} options:" : "Options:")
637
- shell.print_table(list, :indent => 2)
638
- shell.say ""
639
- end
702
+ # Raises an error if the word given is a Thor reserved word.
703
+ def is_thor_reserved_word?(word, type) #:nodoc:
704
+ return false unless THOR_RESERVED_WORDS.include?(word.to_s)
705
+ raise "#{word.inspect} is a Thor reserved word and cannot be " \
706
+ "defined as #{type}"
707
+ end
640
708
 
641
- # Raises an error if the word given is a Thor reserved word.
642
- def is_thor_reserved_word?(word, type) #:nodoc:
643
- return false unless THOR_RESERVED_WORDS.include?(word.to_s)
644
- raise "#{word.inspect} is a Thor reserved word and cannot be " \
645
- "defined as #{type}"
646
- end
709
+ # Build an option and adds it to the given scope.
710
+ #
711
+ # ==== Parameters
712
+ # name<Symbol>:: The name of the argument.
713
+ # options<Hash>:: Described in both class_option and method_option.
714
+ # scope<Hash>:: Options hash that is being built up
715
+ def build_option(name, options, scope) #:nodoc:
716
+ scope[name] = Thor::Option.new(
717
+ name,
718
+ options.merge(:check_default_type => check_default_type?)
719
+ )
720
+ end
647
721
 
648
- # Build an option and adds it to the given scope.
649
- #
650
- # ==== Parameters
651
- # name<Symbol>:: The name of the argument.
652
- # options<Hash>:: Described in both class_option and method_option.
653
- # scope<Hash>:: Options hash that is being built up
654
- def build_option(name, options, scope) #:nodoc:
655
- scope[name] = Thor::Option.new(
656
- name,
657
- options.merge(:check_default_type => check_default_type?)
658
- )
659
- end
722
+ # Receives a hash of options, parse them and add to the scope. This is a
723
+ # fast way to set a bunch of options:
724
+ #
725
+ # build_options :foo => true, :bar => :required, :baz => :string
726
+ #
727
+ # ==== Parameters
728
+ # Hash[Symbol => Object]
729
+ def build_options(options, scope) #:nodoc:
730
+ options.each do |key, value|
731
+ scope[key] = Thor::Option.parse(key, value)
732
+ end
733
+ end
660
734
 
661
- # Receives a hash of options, parse them and add to the scope. This is a
662
- # fast way to set a bunch of options:
663
- #
664
- # build_options :foo => true, :bar => :required, :baz => :string
665
- #
666
- # ==== Parameters
667
- # Hash[Symbol => Object]
668
- def build_options(options, scope) #:nodoc:
669
- options.each do |key, value|
670
- scope[key] = Thor::Option.parse(key, value)
735
+ # Finds a command with the given name. If the command belongs to the current
736
+ # class, just return it, otherwise dup it and add the fresh copy to the
737
+ # current command hash.
738
+ def find_and_refresh_command(name) #:nodoc:
739
+ if commands[name.to_s]
740
+ commands[name.to_s]
741
+ elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition
742
+ commands[name.to_s] = command.clone
743
+ else
744
+ raise ArgumentError,
745
+ "You supplied :for => #{name.inspect}, but the command " \
746
+ "#{name.inspect} could not be found."
747
+ end
671
748
  end
672
- end
749
+ alias_method :find_and_refresh_task, :find_and_refresh_command
673
750
 
674
- # Finds a command with the given name. If the command belongs to the current
675
- # class, just return it, otherwise dup it and add the fresh copy to the
676
- # current command hash.
677
- def find_and_refresh_command(name) #:nodoc:
678
- if commands[name.to_s]
679
- commands[name.to_s]
680
- elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition
681
- commands[name.to_s] = command.clone
682
- else
683
- raise ArgumentError,
684
- "You supplied :for => #{name.inspect}, but the command " \
685
- "#{name.inspect} could not be found."
751
+ # Everytime someone inherits from a Thor class, register the klass
752
+ # and file into baseclass.
753
+ def inherited(klass)
754
+ Thor::Base.register_klass_file(klass)
755
+ klass.instance_variable_set(:@no_commands, false)
686
756
  end
687
- end
688
- alias_method :find_and_refresh_task, :find_and_refresh_command
689
757
 
690
- # Everytime someone inherits from a Thor class, register the klass
691
- # and file into baseclass.
692
- def inherited(klass)
693
- Thor::Base.register_klass_file(klass)
694
- klass.instance_variable_set(:@no_commands, false)
695
- end
758
+ # Fire this callback whenever a method is added. Added methods are
759
+ # tracked as commands by invoking the create_command method.
760
+ def method_added(meth)
761
+ meth = meth.to_s
696
762
 
697
- # Fire this callback whenever a method is added. Added methods are
698
- # tracked as commands by invoking the create_command method.
699
- def method_added(meth)
700
- meth = meth.to_s
763
+ if meth == "initialize"
764
+ initialize_added
765
+ return
766
+ end
701
767
 
702
- if meth == "initialize"
703
- initialize_added
704
- return
705
- end
768
+ # Return if it's not a public instance method
769
+ return unless public_method_defined?(meth.to_sym)
706
770
 
707
- # Return if it's not a public instance method
708
- return unless public_method_defined?(meth.to_sym)
771
+ @no_commands ||= false
772
+ return if @no_commands || !create_command(meth)
709
773
 
710
- @no_commands ||= false
711
- return if @no_commands || !create_command(meth)
774
+ is_thor_reserved_word?(meth, :command)
775
+ Thor::Base.register_klass_file(self)
776
+ end
712
777
 
713
- is_thor_reserved_word?(meth, :command)
714
- Thor::Base.register_klass_file(self)
715
- end
778
+ # Retrieves a value from superclass. If it reaches the baseclass,
779
+ # returns default.
780
+ def from_superclass(method, default = nil)
781
+ if self == baseclass || !superclass.respond_to?(method, true)
782
+ default
783
+ else
784
+ value = superclass.send(method)
785
+
786
+ # Ruby implements `dup` on Object, but raises a `TypeError`
787
+ # if the method is called on immediates. As a result, we
788
+ # don't have a good way to check whether dup will succeed
789
+ # without calling it and rescuing the TypeError.
790
+ begin
791
+ value.dup
792
+ rescue TypeError
793
+ value
794
+ end
716
795
 
717
- # Retrieves a value from superclass. If it reaches the baseclass,
718
- # returns default.
719
- def from_superclass(method, default = nil)
720
- if self == baseclass || !superclass.respond_to?(method, true)
721
- default
722
- else
723
- value = superclass.send(method)
724
-
725
- # Ruby implements `dup` on Object, but raises a `TypeError`
726
- # if the method is called on immediates. As a result, we
727
- # don't have a good way to check whether dup will succeed
728
- # without calling it and rescuing the TypeError.
729
- begin
730
- value.dup
731
- rescue TypeError
732
- value
733
796
  end
734
-
735
797
  end
736
- end
737
798
 
738
- # A flag that makes the process exit with status 1 if any error happens.
739
- def exit_on_failure?
740
- false
741
- end
799
+ # A flag that makes the process exit with status 1 if any error happens.
800
+ def exit_on_failure?
801
+ false
802
+ end
742
803
 
743
- #
744
- # The basename of the program invoking the thor class.
745
- #
746
- def basename
747
- File.basename($PROGRAM_NAME).split(" ").first
748
- end
804
+ #
805
+ # The basename of the program invoking the thor class.
806
+ #
807
+ def basename
808
+ File.basename($PROGRAM_NAME).split(" ").first
809
+ end
749
810
 
750
- # SIGNATURE: Sets the baseclass. This is where the superclass lookup
751
- # finishes.
752
- def baseclass #:nodoc:
753
- end
811
+ # SIGNATURE: Sets the baseclass. This is where the superclass lookup
812
+ # finishes.
813
+ def baseclass #:nodoc:
814
+ end
754
815
 
755
- # SIGNATURE: Creates a new command if valid_command? is true. This method
756
- # is called when a new method is added to the class.
757
- def create_command(meth) #:nodoc:
758
- end
759
- alias_method :create_task, :create_command
816
+ # SIGNATURE: Creates a new command if valid_command? is true. This method
817
+ # is called when a new method is added to the class.
818
+ def create_command(meth) #:nodoc:
819
+ end
820
+ alias_method :create_task, :create_command
760
821
 
761
- # SIGNATURE: Defines behavior when the initialize method is added to the
762
- # class.
763
- def initialize_added #:nodoc:
764
- end
822
+ # SIGNATURE: Defines behavior when the initialize method is added to the
823
+ # class.
824
+ def initialize_added #:nodoc:
825
+ end
765
826
 
766
- # SIGNATURE: The hook invoked by start.
767
- def dispatch(command, given_args, given_opts, config) #:nodoc:
768
- raise NotImplementedError
769
- end
770
-
771
- end # self << class
827
+ # SIGNATURE: The hook invoked by start.
828
+ def dispatch(command, given_args, given_opts, config) #:nodoc:
829
+ raise NotImplementedError
830
+ end
831
+
832
+ # end protected
833
+ end # ClassMethods
772
834
  end # module Base
773
835
  end # class Thor