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.
- checksums.yaml +4 -4
- data/.yardopts +1 -2
- data/atli.gemspec +34 -3
- data/lib/thor.rb +202 -204
- data/lib/thor/base.rb +247 -185
- data/lib/thor/base/common_class_options.rb +56 -0
- data/lib/thor/command.rb +9 -1
- data/lib/thor/error.rb +16 -0
- data/lib/thor/execution.rb +276 -0
- data/lib/thor/version.rb +11 -2
- metadata +35 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17320147d3f8b501e297a58c94b4c7d4eee07005
|
4
|
+
data.tar.gz: 1945e98ecebe7600c4e968a24f6676650cd22ce2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7092d41e483671cd9069517f316bb8349696bcc0b8fb9d0537e42dc4e356b44249db4755a41af76edbbc984cc82ca1a0d0ba244ee5972a9ab371ab5cfacd1b5a
|
7
|
+
data.tar.gz: f5ac08027334f1aa8864e869cb2a4aac8e009b6fb794dc35c872fcde18ebdfc1d01d5eac16ecaca464e942936a13e6dd972d758612ae5a88f487a667d9341779
|
data/.yardopts
CHANGED
data/atli.gemspec
CHANGED
@@ -21,10 +21,41 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
# Dependencies
|
23
23
|
# ============================================================================
|
24
|
+
|
25
|
+
# My guns
|
26
|
+
spec.add_dependency "nrser", '>= 0.2.0.pre.2'
|
27
|
+
|
28
|
+
|
29
|
+
# Development Dependencies
|
30
|
+
# ----------------------------------------------------------------------------
|
24
31
|
#
|
25
|
-
# NOTE Development dependencies are in `//Gemfile`
|
32
|
+
# NOTE Development dependencies that came from Thor are in `//Gemfile`
|
26
33
|
#
|
27
34
|
|
28
|
-
|
29
|
-
|
35
|
+
### Yard
|
36
|
+
#
|
37
|
+
# I'm not used to dealing with RDoc docstrings, and want to still write doc
|
38
|
+
# files in Markdown, but it's been funky to get them to work together...
|
39
|
+
#
|
40
|
+
# When things get funky:
|
41
|
+
#
|
42
|
+
# 1. `qb yard/clean`
|
43
|
+
# 2. `bundle exec yard doc`
|
44
|
+
# 3. `locd site restart yard.atli`
|
45
|
+
#
|
46
|
+
|
47
|
+
# Doc site generation with `yard`
|
48
|
+
spec.add_development_dependency 'yard', '~> 0.9.12'
|
49
|
+
|
50
|
+
# This being installed *seems* to help Yard do the right things with
|
51
|
+
# markdown files...
|
52
|
+
spec.add_development_dependency 'redcarpet', '~> 3.4'
|
53
|
+
|
54
|
+
# These... do not seem to work or help...
|
55
|
+
#
|
56
|
+
# GitHub-Flavored Markdown (GFM) for use with `yard`
|
57
|
+
# spec.add_development_dependency 'github-markup', '~> 1.6'
|
58
|
+
# Provider for `commonmarker`, the new GFM lib
|
59
|
+
# spec.add_development_dependency 'yard-commonmarker', '~> 0.3.0'
|
60
|
+
|
30
61
|
end
|
data/lib/thor.rb
CHANGED
@@ -6,8 +6,6 @@ require "thor/base"
|
|
6
6
|
using NRSER
|
7
7
|
|
8
8
|
class Thor
|
9
|
-
# Atli - add {.logger} and {#logger} methods
|
10
|
-
include SemanticLogger::Loggable
|
11
9
|
|
12
10
|
class << self
|
13
11
|
# Allows for custom "Command" package naming.
|
@@ -406,7 +404,7 @@ class Thor
|
|
406
404
|
|
407
405
|
# Find shared options given names and groups.
|
408
406
|
#
|
409
|
-
# @param [*<Symbol>]
|
407
|
+
# @param [*<Symbol>] names
|
410
408
|
# Individual shared option names to include.
|
411
409
|
#
|
412
410
|
# @param [nil | Symbol | Enumerable<Symbol>] groups:
|
@@ -545,229 +543,230 @@ class Thor
|
|
545
543
|
|
546
544
|
# END Atli Public Class Methods ******************************************
|
547
545
|
|
546
|
+
|
547
|
+
protected # Class Methods
|
548
|
+
# ============================================================================
|
548
549
|
|
549
|
-
|
550
|
-
|
551
|
-
def stop_on_unknown_option #:nodoc:
|
552
|
-
@stop_on_unknown_option ||= Set.new
|
553
|
-
end
|
554
|
-
|
555
|
-
# help command has the required check disabled by default.
|
556
|
-
def disable_required_check #:nodoc:
|
557
|
-
@disable_required_check ||= Set.new([:help])
|
558
|
-
end
|
559
|
-
|
560
|
-
# The method responsible for dispatching given the args.
|
561
|
-
def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength
|
562
|
-
meth ||= retrieve_command_name(given_args)
|
563
|
-
command = all_commands[normalize_command_name(meth)]
|
564
|
-
|
565
|
-
if !command && config[:invoked_via_subcommand]
|
566
|
-
# We're a subcommand and our first argument didn't match any of our
|
567
|
-
# commands. So we put it back and call our default command.
|
568
|
-
given_args.unshift(meth)
|
569
|
-
command = all_commands[normalize_command_name(default_command)]
|
550
|
+
def stop_on_unknown_option #:nodoc:
|
551
|
+
@stop_on_unknown_option ||= Set.new
|
570
552
|
end
|
571
553
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
# given_args starts with a non-option, so we treat everything as
|
576
|
-
# ordinary arguments
|
577
|
-
args.concat opts
|
578
|
-
opts.clear
|
579
|
-
end
|
580
|
-
else
|
581
|
-
args = given_args
|
582
|
-
opts = nil
|
583
|
-
command = dynamic_command_class.new(meth)
|
554
|
+
# help command has the required check disabled by default.
|
555
|
+
def disable_required_check #:nodoc:
|
556
|
+
@disable_required_check ||= Set.new([:help])
|
584
557
|
end
|
585
558
|
|
586
|
-
|
587
|
-
config
|
588
|
-
|
559
|
+
# The method responsible for dispatching given the args.
|
560
|
+
def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength
|
561
|
+
meth ||= retrieve_command_name(given_args)
|
562
|
+
command = all_commands[normalize_command_name(meth)]
|
589
563
|
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
# The banner for this class. You can customize it if you are invoking the
|
599
|
-
# thor class by another ways which is not the Thor::Runner. It receives
|
600
|
-
# the command that is going to be invoked and a boolean which indicates if
|
601
|
-
# the namespace should be displayed as arguments.
|
602
|
-
#
|
603
|
-
# @param [Thor::Command] command
|
604
|
-
# The command to render the banner for.
|
605
|
-
#
|
606
|
-
# @param [nil | ?] namespace
|
607
|
-
# *Atli*: this argument is _not_ _used_ _at_ _all_. I don't know what it
|
608
|
-
# could or should be, but it doesn't seem like it matters at all :/
|
609
|
-
#
|
610
|
-
# @param [Boolean] subcommand
|
611
|
-
# Should be +true+ if the command was invoked as a sub-command; passed
|
612
|
-
# on to {Command#formatted_usage} so it can render correctly.
|
613
|
-
#
|
614
|
-
# @return [String]
|
615
|
-
# The banner for the command.
|
616
|
-
#
|
617
|
-
def banner(command, namespace = nil, subcommand = false)
|
618
|
-
"#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
619
|
-
end
|
620
|
-
|
621
|
-
|
622
|
-
def baseclass #:nodoc:
|
623
|
-
Thor
|
624
|
-
end
|
564
|
+
if !command && config[:invoked_via_subcommand]
|
565
|
+
# We're a subcommand and our first argument didn't match any of our
|
566
|
+
# commands. So we put it back and call our default command.
|
567
|
+
given_args.unshift(meth)
|
568
|
+
command = all_commands[normalize_command_name(default_command)]
|
569
|
+
end
|
625
570
|
|
626
|
-
|
627
|
-
|
628
|
-
|
571
|
+
if command
|
572
|
+
args, opts = Thor::Options.split(given_args)
|
573
|
+
if stop_on_unknown_option?(command) && !args.empty?
|
574
|
+
# given_args starts with a non-option, so we treat everything as
|
575
|
+
# ordinary arguments
|
576
|
+
args.concat opts
|
577
|
+
opts.clear
|
578
|
+
end
|
579
|
+
else
|
580
|
+
args = given_args
|
581
|
+
opts = nil
|
582
|
+
command = dynamic_command_class.new(meth)
|
583
|
+
end
|
629
584
|
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
@long_desc ||= nil
|
634
|
-
@hide ||= nil
|
635
|
-
|
636
|
-
if @usage && @desc
|
637
|
-
base_class = @hide ? Thor::HiddenCommand : Thor::Command
|
638
|
-
commands[meth] = base_class.new(
|
639
|
-
meth,
|
640
|
-
@desc,
|
641
|
-
@long_desc,
|
642
|
-
@usage,
|
643
|
-
method_options
|
644
|
-
)
|
645
|
-
@usage, @desc, @long_desc, @method_options, @hide = nil
|
646
|
-
true
|
647
|
-
elsif all_commands[meth] || meth == "method_missing"
|
648
|
-
true
|
649
|
-
else
|
650
|
-
puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " \
|
651
|
-
"Call desc if you want this method to be available as command or declare it inside a " \
|
652
|
-
"no_commands{} block. Invoked from #{caller[1].inspect}."
|
653
|
-
false
|
654
|
-
end
|
655
|
-
end
|
656
|
-
alias_method :create_task, :create_command
|
585
|
+
opts = given_opts || opts || []
|
586
|
+
config[:current_command] = command
|
587
|
+
config[:command_options] = command.options
|
657
588
|
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
589
|
+
instance = new(args, opts, config)
|
590
|
+
yield instance if block_given?
|
591
|
+
args = instance.args
|
592
|
+
trailing = args[Range.new(arguments.size, -1)]
|
593
|
+
instance.invoke_command(command, trailing || [])
|
594
|
+
end
|
595
|
+
|
596
|
+
|
597
|
+
# The banner for this class. You can customize it if you are invoking the
|
598
|
+
# thor class by another ways which is not the Thor::Runner. It receives
|
599
|
+
# the command that is going to be invoked and a boolean which indicates if
|
600
|
+
# the namespace should be displayed as arguments.
|
601
|
+
#
|
602
|
+
# @param [Thor::Command] command
|
603
|
+
# The command to render the banner for.
|
604
|
+
#
|
605
|
+
# @param [nil | ?] namespace
|
606
|
+
# *Atli*: this argument is _not_ _used_ _at_ _all_. I don't know what it
|
607
|
+
# could or should be, but it doesn't seem like it matters at all :/
|
608
|
+
#
|
609
|
+
# @param [Boolean] subcommand
|
610
|
+
# Should be +true+ if the command was invoked as a sub-command; passed
|
611
|
+
# on to {Command#formatted_usage} so it can render correctly.
|
612
|
+
#
|
613
|
+
# @return [String]
|
614
|
+
# The banner for the command.
|
615
|
+
#
|
616
|
+
def banner(command, namespace = nil, subcommand = false)
|
617
|
+
"#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
618
|
+
end
|
619
|
+
|
620
|
+
|
621
|
+
def baseclass #:nodoc:
|
622
|
+
Thor
|
623
|
+
end
|
662
624
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
args.shift if meth && (map[meth] || meth !~ /^\-/)
|
667
|
-
end
|
668
|
-
alias_method :retrieve_task_name, :retrieve_command_name
|
625
|
+
def dynamic_command_class #:nodoc:
|
626
|
+
Thor::DynamicCommand
|
627
|
+
end
|
669
628
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
629
|
+
def create_command(meth) #:nodoc:
|
630
|
+
@usage ||= nil
|
631
|
+
@desc ||= nil
|
632
|
+
@long_desc ||= nil
|
633
|
+
@hide ||= nil
|
634
|
+
|
635
|
+
if @usage && @desc
|
636
|
+
base_class = @hide ? Thor::HiddenCommand : Thor::Command
|
637
|
+
commands[meth] = base_class.new(
|
638
|
+
meth,
|
639
|
+
@desc,
|
640
|
+
@long_desc,
|
641
|
+
@usage,
|
642
|
+
method_options
|
643
|
+
)
|
644
|
+
@usage, @desc, @long_desc, @method_options, @hide = nil
|
645
|
+
true
|
646
|
+
elsif all_commands[meth] || meth == "method_missing"
|
647
|
+
true
|
648
|
+
else
|
649
|
+
puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " \
|
650
|
+
"Call desc if you want this method to be available as command or declare it inside a " \
|
651
|
+
"no_commands{} block. Invoked from #{caller[1].inspect}."
|
652
|
+
false
|
653
|
+
end
|
654
|
+
end
|
655
|
+
alias_method :create_task, :create_command
|
679
656
|
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
raise AmbiguousTaskError,
|
684
|
-
"Ambiguous command #{meth} matches [#{possibilities.join(', ')}]"
|
657
|
+
def initialize_added #:nodoc:
|
658
|
+
class_options.merge!(method_options)
|
659
|
+
@method_options = nil
|
685
660
|
end
|
686
661
|
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
meth
|
691
|
-
else
|
692
|
-
meth = possibilities.first
|
662
|
+
# Retrieve the command name from given args.
|
663
|
+
def retrieve_command_name(args) #:nodoc:
|
664
|
+
meth = args.first.to_s unless args.empty?
|
665
|
+
args.shift if meth && (map[meth] || meth !~ /^\-/)
|
693
666
|
end
|
667
|
+
alias_method :retrieve_task_name, :retrieve_command_name
|
668
|
+
|
669
|
+
# receives a (possibly nil) command name and returns a name that is in
|
670
|
+
# the commands hash. In addition to normalizing aliases, this logic
|
671
|
+
# will determine if a shortened command is an unambiguous substring of
|
672
|
+
# a command or alias.
|
673
|
+
#
|
674
|
+
# +normalize_command_name+ also converts names like +animal-prison+
|
675
|
+
# into +animal_prison+.
|
676
|
+
def normalize_command_name(meth) #:nodoc:
|
677
|
+
return default_command.to_s.tr("-", "_") unless meth
|
678
|
+
|
679
|
+
possibilities = find_command_possibilities(meth)
|
680
|
+
|
681
|
+
if possibilities.size > 1
|
682
|
+
raise AmbiguousTaskError,
|
683
|
+
"Ambiguous command #{meth} matches [#{possibilities.join(', ')}]"
|
684
|
+
end
|
694
685
|
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
possibilities = all_commands.merge(map).keys.select { |n|
|
705
|
-
meth == n[0, len]
|
706
|
-
}.sort
|
707
|
-
unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
|
708
|
-
|
709
|
-
if possibilities.include?(meth)
|
710
|
-
[meth]
|
711
|
-
elsif unique_possibilities.size == 1
|
712
|
-
unique_possibilities
|
713
|
-
else
|
714
|
-
possibilities
|
686
|
+
if possibilities.empty?
|
687
|
+
meth ||= default_command
|
688
|
+
elsif map[meth]
|
689
|
+
meth = map[meth]
|
690
|
+
else
|
691
|
+
meth = possibilities.first
|
692
|
+
end
|
693
|
+
|
694
|
+
meth.to_s.tr("-", "_") # treat foo-bar as foo_bar
|
715
695
|
end
|
716
|
-
|
717
|
-
|
696
|
+
alias_method :normalize_task_name, :normalize_command_name
|
697
|
+
|
698
|
+
# this is the logic that takes the command name passed in by the user
|
699
|
+
# and determines whether it is an unambiguous substrings of a command or
|
700
|
+
# alias name.
|
701
|
+
def find_command_possibilities(meth)
|
702
|
+
len = meth.to_s.length
|
703
|
+
possibilities = all_commands.merge(map).keys.select { |n|
|
704
|
+
meth == n[0, len]
|
705
|
+
}.sort
|
706
|
+
unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
|
707
|
+
|
708
|
+
if possibilities.include?(meth)
|
709
|
+
[meth]
|
710
|
+
elsif unique_possibilities.size == 1
|
711
|
+
unique_possibilities
|
712
|
+
else
|
713
|
+
possibilities
|
714
|
+
end
|
715
|
+
end
|
716
|
+
alias_method :find_task_possibilities, :find_command_possibilities
|
718
717
|
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
|
725
|
-
|
726
|
-
# Atli - This used to be {#class_eval} (maybe to support really old
|
727
|
-
# Rubies? Who knows...) but that made it really hard to find in
|
728
|
-
# stack traces, so I switched it to {#define_method}.
|
729
|
-
#
|
730
|
-
define_method :help do |*args|
|
718
|
+
def subcommand_help(cmd)
|
719
|
+
logger.trace __method__.to_s,
|
720
|
+
cmd: cmd,
|
721
|
+
caller: caller
|
731
722
|
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
#
|
741
|
-
args
|
723
|
+
desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
|
724
|
+
|
725
|
+
# Atli - This used to be {#class_eval} (maybe to support really old
|
726
|
+
# Rubies? Who knows...) but that made it really hard to find in
|
727
|
+
# stack traces, so I switched it to {#define_method}.
|
728
|
+
#
|
729
|
+
define_method :help do |*args|
|
730
|
+
|
731
|
+
# Add the `is_subcommand = true` trailing arg
|
732
|
+
case args[-1]
|
733
|
+
when true
|
734
|
+
# pass
|
735
|
+
when false
|
736
|
+
# Weird, `false` was explicitly passed... whatever, set it to `true`
|
737
|
+
args[-1] = true
|
738
|
+
else
|
739
|
+
# "Normal" case, append it
|
740
|
+
args << true
|
741
|
+
end
|
742
|
+
|
743
|
+
super( *args )
|
742
744
|
end
|
743
745
|
|
744
|
-
super *args
|
745
746
|
end
|
747
|
+
alias_method :subtask_help, :subcommand_help
|
746
748
|
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
749
|
+
# Atli Protected Class Methods
|
750
|
+
# ======================================================================
|
751
|
+
|
752
|
+
# Build a Thor::SharedOption and add it to Thor.shared_method_options.
|
753
|
+
#
|
754
|
+
# The Thor::SharedOption is returned.
|
755
|
+
#
|
756
|
+
# ==== Parameters
|
757
|
+
# name<Symbol>:: The name of the argument.
|
758
|
+
# options<Hash>:: Described in both class_option and method_option,
|
759
|
+
# with the additional `:groups` shared option keyword.
|
760
|
+
def build_shared_option(name, options)
|
761
|
+
shared_method_options[name] = Thor::SharedOption.new(
|
762
|
+
name,
|
763
|
+
options.merge(:check_default_type => check_default_type?)
|
764
|
+
)
|
765
|
+
end # #build_shared_option
|
752
766
|
|
753
|
-
#
|
754
|
-
#
|
755
|
-
# The Thor::SharedOption is returned.
|
756
|
-
#
|
757
|
-
# ==== Parameters
|
758
|
-
# name<Symbol>:: The name of the argument.
|
759
|
-
# options<Hash>:: Described in both class_option and method_option,
|
760
|
-
# with the additional `:groups` shared option keyword.
|
761
|
-
def build_shared_option(name, options)
|
762
|
-
shared_method_options[name] = Thor::SharedOption.new(
|
763
|
-
name,
|
764
|
-
options.merge(:check_default_type => check_default_type?)
|
765
|
-
)
|
766
|
-
end # #build_shared_option
|
767
|
+
# END protected Class Methods ********************************************
|
767
768
|
|
768
|
-
#
|
769
|
-
|
770
|
-
end # class << self
|
769
|
+
end # class << self ********************************************************
|
771
770
|
|
772
771
|
|
773
772
|
protected # Instance Methods
|
@@ -796,8 +795,7 @@ class Thor
|
|
796
795
|
options.slice( *name_set ).sym_keys
|
797
796
|
end
|
798
797
|
|
799
|
-
# END protected Instance Methods
|
800
|
-
public
|
798
|
+
public # END protected Instance Methods ************************************
|
801
799
|
|
802
800
|
|
803
801
|
# After this, {.method_added} hook is installed and defined methods become
|
@@ -806,7 +804,7 @@ class Thor
|
|
806
804
|
|
807
805
|
|
808
806
|
# Commands
|
809
|
-
#
|
807
|
+
# ==========================================================================
|
810
808
|
|
811
809
|
map HELP_MAPPINGS => :help
|
812
810
|
|