atli 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|