atli 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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