atli 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/CHANGELOG.md +193 -0
  4. data/CONTRIBUTING.md +20 -0
  5. data/LICENSE.md +24 -0
  6. data/README.md +44 -0
  7. data/atli.gemspec +30 -0
  8. data/bin/thor +6 -0
  9. data/lib/thor.rb +868 -0
  10. data/lib/thor/actions.rb +322 -0
  11. data/lib/thor/actions/create_file.rb +104 -0
  12. data/lib/thor/actions/create_link.rb +60 -0
  13. data/lib/thor/actions/directory.rb +118 -0
  14. data/lib/thor/actions/empty_directory.rb +143 -0
  15. data/lib/thor/actions/file_manipulation.rb +364 -0
  16. data/lib/thor/actions/inject_into_file.rb +109 -0
  17. data/lib/thor/base.rb +773 -0
  18. data/lib/thor/command.rb +192 -0
  19. data/lib/thor/core_ext/hash_with_indifferent_access.rb +97 -0
  20. data/lib/thor/core_ext/io_binary_read.rb +12 -0
  21. data/lib/thor/core_ext/ordered_hash.rb +129 -0
  22. data/lib/thor/error.rb +32 -0
  23. data/lib/thor/group.rb +281 -0
  24. data/lib/thor/invocation.rb +182 -0
  25. data/lib/thor/line_editor.rb +17 -0
  26. data/lib/thor/line_editor/basic.rb +37 -0
  27. data/lib/thor/line_editor/readline.rb +88 -0
  28. data/lib/thor/parser.rb +5 -0
  29. data/lib/thor/parser/argument.rb +70 -0
  30. data/lib/thor/parser/arguments.rb +175 -0
  31. data/lib/thor/parser/option.rb +146 -0
  32. data/lib/thor/parser/options.rb +221 -0
  33. data/lib/thor/parser/shared_option.rb +23 -0
  34. data/lib/thor/rake_compat.rb +71 -0
  35. data/lib/thor/runner.rb +324 -0
  36. data/lib/thor/shell.rb +81 -0
  37. data/lib/thor/shell/basic.rb +439 -0
  38. data/lib/thor/shell/color.rb +149 -0
  39. data/lib/thor/shell/html.rb +126 -0
  40. data/lib/thor/util.rb +268 -0
  41. data/lib/thor/version.rb +22 -0
  42. metadata +114 -0
@@ -0,0 +1,192 @@
1
+ require 'semantic_logger'
2
+
3
+ class Thor
4
+ class Command < Struct.new( :name,
5
+ :description,
6
+ :long_description,
7
+ :usage,
8
+ :options,
9
+ :ancestor_name )
10
+ include SemanticLogger::Loggable
11
+
12
+ FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
13
+
14
+ def initialize(name, description, long_description, usage, options = nil)
15
+ super(name.to_s, description, long_description, usage, options || {})
16
+ end
17
+
18
+ def initialize_copy(other) #:nodoc:
19
+ super(other)
20
+ self.options = other.options.dup if other.options
21
+ end
22
+
23
+ def hidden?
24
+ false
25
+ end
26
+
27
+ # By default, a command invokes a method in the thor class. You can change
28
+ # this implementation to create custom commands.
29
+ def run(instance, args = [])
30
+ logger.trace "Command#run",
31
+ self: self,
32
+ instance: instance,
33
+ args: args
34
+
35
+ arity = nil
36
+
37
+ if private_method?(instance)
38
+ instance.class.handle_no_command_error(name)
39
+ elsif public_method?(instance)
40
+ arity = instance.method(name).arity
41
+ instance.__send__(name, *args)
42
+ elsif local_method?(instance, :method_missing)
43
+ instance.__send__(:method_missing, name.to_sym, *args)
44
+ else
45
+ instance.class.handle_no_command_error(name)
46
+ end
47
+ rescue ArgumentError => e
48
+ if handle_argument_error?(instance, e, caller)
49
+ instance.class.handle_argument_error(self, e, args, arity)
50
+ else
51
+ raise e
52
+ end
53
+ rescue NoMethodError => e
54
+ if handle_no_method_error?(instance, e, caller)
55
+ instance.class.handle_no_command_error(name)
56
+ else
57
+ raise e
58
+ end
59
+ rescue Exception => error
60
+ instance.send :on_run_error, error, self, args
61
+
62
+ # We should not get here!!!
63
+ # {Thor::Base#on_run_error} should exit or re-raise :(
64
+ logger.error "#on_run_error failed to exit or re-raise", error: error
65
+
66
+ # If you want something done right...
67
+ raise error
68
+ end
69
+
70
+ # Returns the formatted usage by injecting given required arguments
71
+ # and required options into the given usage.
72
+ def formatted_usage(klass, namespace = true, subcommand = false)
73
+ logger.trace "Formatting usage",
74
+ self: self,
75
+ klass: klass,
76
+ namespace: namespace,
77
+ subcommand: subcommand,
78
+ ancestor_name: ancestor_name
79
+
80
+ if ancestor_name
81
+ formatted = "#{ancestor_name} ".dup # add space
82
+ elsif namespace
83
+ namespace = klass.namespace
84
+ formatted = "#{namespace.gsub(/^(default)/, '')}:".dup
85
+ end
86
+ formatted ||= "#{klass.namespace.split(':').last} ".dup if subcommand
87
+
88
+ formatted ||= "".dup
89
+
90
+ # Add usage with required arguments
91
+ formatted << if klass && !klass.arguments.empty?
92
+ usage.to_s.gsub(/^#{name}/) do |match|
93
+ match << " " \
94
+ << klass.arguments.map(&:usage).compact.join(" ")
95
+ end
96
+ else
97
+ usage.to_s
98
+ end
99
+
100
+ # Add required options
101
+ formatted << " #{required_options}"
102
+
103
+ # Strip and go!
104
+ formatted.strip
105
+ end
106
+
107
+ protected
108
+
109
+ def not_debugging?(instance)
110
+ !(instance.class.respond_to?(:debugging) && instance.class.debugging)
111
+ end
112
+
113
+ def required_options
114
+ @required_options ||= options.
115
+ map { |_, o| o.usage if o.required? }.
116
+ compact.
117
+ sort.
118
+ join(" ")
119
+ end
120
+
121
+ # Given a target, checks if this class name is a public method.
122
+ def public_method?(instance) #:nodoc:
123
+ !(instance.public_methods & [name.to_s, name.to_sym]).empty?
124
+ end
125
+
126
+ def private_method?(instance)
127
+ !(instance.private_methods & [name.to_s, name.to_sym]).empty?
128
+ end
129
+
130
+ def local_method?(instance, name)
131
+ methods = instance.public_methods(false) +
132
+ instance.private_methods(false) +
133
+ instance.protected_methods(false)
134
+ !(methods & [name.to_s, name.to_sym]).empty?
135
+ end
136
+
137
+ def sans_backtrace(backtrace, caller) #:nodoc:
138
+ saned = backtrace.reject { |frame|
139
+ (frame =~ FILE_REGEXP) ||
140
+ (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) ||
141
+ (frame =~ %r{^kernel/} && RUBY_ENGINE =~ /rbx/)
142
+ }
143
+ saned - caller
144
+ end
145
+
146
+ def handle_argument_error?(instance, error, caller)
147
+ not_debugging?(instance) \
148
+ && ( error.message =~ /wrong number of arguments/ \
149
+ || error.message =~ /given \d*, expected \d*/ ) \
150
+ && begin
151
+ saned = sans_backtrace(error.backtrace, caller)
152
+ # Ruby 1.9 always include the called method in the backtrace
153
+ saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
154
+ end
155
+ end
156
+
157
+ def handle_no_method_error?(instance, error, caller)
158
+ not_debugging?(instance) &&
159
+ error.message =~ \
160
+ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
161
+ end
162
+ end
163
+ Task = Command
164
+
165
+ # A command that is hidden in help messages but still invocable.
166
+ class HiddenCommand < Command
167
+ def hidden?
168
+ true
169
+ end
170
+ end
171
+ HiddenTask = HiddenCommand
172
+
173
+ # A dynamic command that handles method missing scenarios.
174
+ class DynamicCommand < Command
175
+ def initialize(name, options = nil)
176
+ super( name.to_s,
177
+ "A dynamically-generated command",
178
+ name.to_s,
179
+ name.to_s,
180
+ options )
181
+ end
182
+
183
+ def run(instance, args = [])
184
+ if (instance.methods & [name.to_s, name.to_sym]).empty?
185
+ super
186
+ else
187
+ instance.class.handle_no_command_error(name)
188
+ end
189
+ end
190
+ end
191
+ DynamicTask = DynamicCommand
192
+ end
@@ -0,0 +1,97 @@
1
+ class Thor
2
+ module CoreExt #:nodoc:
3
+ # A hash with indifferent access and magic predicates.
4
+ #
5
+ # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true
6
+ #
7
+ # hash[:foo] #=> 'bar'
8
+ # hash['foo'] #=> 'bar'
9
+ # hash.foo? #=> true
10
+ #
11
+ class HashWithIndifferentAccess < ::Hash #:nodoc:
12
+ def initialize(hash = {})
13
+ super()
14
+ hash.each do |key, value|
15
+ self[convert_key(key)] = value
16
+ end
17
+ end
18
+
19
+ def [](key)
20
+ super(convert_key(key))
21
+ end
22
+
23
+ def []=(key, value)
24
+ super(convert_key(key), value)
25
+ end
26
+
27
+ def delete(key)
28
+ super(convert_key(key))
29
+ end
30
+
31
+ def fetch(key, *args)
32
+ super(convert_key(key), *args)
33
+ end
34
+
35
+ def key?(key)
36
+ super(convert_key(key))
37
+ end
38
+
39
+ def values_at(*indices)
40
+ indices.map { |key| self[convert_key(key)] }
41
+ end
42
+
43
+ def merge(other)
44
+ dup.merge!(other)
45
+ end
46
+
47
+ def merge!(other)
48
+ other.each do |key, value|
49
+ self[convert_key(key)] = value
50
+ end
51
+ self
52
+ end
53
+
54
+ def reverse_merge(other)
55
+ self.class.new(other).merge(self)
56
+ end
57
+
58
+ def reverse_merge!(other_hash)
59
+ replace(reverse_merge(other_hash))
60
+ end
61
+
62
+ def replace(other_hash)
63
+ super(other_hash)
64
+ end
65
+
66
+ # Convert to a Hash with String keys.
67
+ def to_hash
68
+ Hash.new(default).merge!(self)
69
+ end
70
+
71
+ protected
72
+
73
+ def convert_key(key)
74
+ key.is_a?(Symbol) ? key.to_s : key
75
+ end
76
+
77
+ # Magic predicates. For instance:
78
+ #
79
+ # options.force? # => !!options['force']
80
+ # options.shebang # => "/usr/lib/local/ruby"
81
+ # options.test_framework?(:rspec) # => options[:test_framework] == :rspec
82
+ #
83
+ def method_missing(method, *args)
84
+ method = method.to_s
85
+ if method =~ /^(\w+)\?$/
86
+ if args.empty?
87
+ !!self[$1]
88
+ else
89
+ self[$1] == args.first
90
+ end
91
+ else
92
+ self[method]
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,12 @@
1
+ class IO #:nodoc:
2
+ class << self
3
+ unless method_defined? :binread
4
+ def binread(file, *args)
5
+ raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
6
+ File.open(file, "rb") do |f|
7
+ f.read(*args)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,129 @@
1
+ class Thor
2
+ module CoreExt
3
+ class OrderedHash < ::Hash
4
+ if RUBY_VERSION < "1.9"
5
+ def initialize(*args, &block)
6
+ super
7
+ @keys = []
8
+ end
9
+
10
+ def initialize_copy(other)
11
+ super
12
+ # make a deep copy of keys
13
+ @keys = other.keys
14
+ end
15
+
16
+ def []=(key, value)
17
+ @keys << key unless key?(key)
18
+ super
19
+ end
20
+
21
+ def delete(key)
22
+ if key? key
23
+ index = @keys.index(key)
24
+ @keys.delete_at index
25
+ end
26
+ super
27
+ end
28
+
29
+ def delete_if
30
+ super
31
+ sync_keys!
32
+ self
33
+ end
34
+
35
+ alias_method :reject!, :delete_if
36
+
37
+ def reject(&block)
38
+ dup.reject!(&block)
39
+ end
40
+
41
+ def keys
42
+ @keys.dup
43
+ end
44
+
45
+ def values
46
+ @keys.map { |key| self[key] }
47
+ end
48
+
49
+ def to_hash
50
+ self
51
+ end
52
+
53
+ def to_a
54
+ @keys.map { |key| [key, self[key]] }
55
+ end
56
+
57
+ def each_key
58
+ return to_enum(:each_key) unless block_given?
59
+ @keys.each { |key| yield(key) }
60
+ self
61
+ end
62
+
63
+ def each_value
64
+ return to_enum(:each_value) unless block_given?
65
+ @keys.each { |key| yield(self[key]) }
66
+ self
67
+ end
68
+
69
+ def each
70
+ return to_enum(:each) unless block_given?
71
+ @keys.each { |key| yield([key, self[key]]) }
72
+ self
73
+ end
74
+
75
+ def each_pair
76
+ return to_enum(:each_pair) unless block_given?
77
+ @keys.each { |key| yield(key, self[key]) }
78
+ self
79
+ end
80
+
81
+ alias_method :select, :find_all
82
+
83
+ def clear
84
+ super
85
+ @keys.clear
86
+ self
87
+ end
88
+
89
+ def shift
90
+ k = @keys.first
91
+ v = delete(k)
92
+ [k, v]
93
+ end
94
+
95
+ def merge!(other_hash)
96
+ if block_given?
97
+ other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
98
+ else
99
+ other_hash.each { |k, v| self[k] = v }
100
+ end
101
+ self
102
+ end
103
+
104
+ alias_method :update, :merge!
105
+
106
+ def merge(other_hash, &block)
107
+ dup.merge!(other_hash, &block)
108
+ end
109
+
110
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
111
+ def replace(other)
112
+ super
113
+ @keys = other.keys
114
+ self
115
+ end
116
+
117
+ def inspect
118
+ "#<#{self.class} #{super}>"
119
+ end
120
+
121
+ private
122
+
123
+ def sync_keys!
124
+ @keys.delete_if { |k| !key?(k) }
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
data/lib/thor/error.rb ADDED
@@ -0,0 +1,32 @@
1
+ class Thor
2
+ # Thor::Error is raised when it's caused by wrong usage of thor classes. Those
3
+ # errors have their backtrace suppressed and are nicely shown to the user.
4
+ #
5
+ # Errors that are caused by the developer, like declaring a method which
6
+ # overwrites a thor keyword, SHOULD NOT raise a Thor::Error. This way, we
7
+ # ensure that developer errors are shown with full backtrace.
8
+ class Error < StandardError
9
+ end
10
+
11
+ # Raised when a command was not found.
12
+ class UndefinedCommandError < Error
13
+ end
14
+ UndefinedTaskError = UndefinedCommandError
15
+
16
+ class AmbiguousCommandError < Error
17
+ end
18
+ AmbiguousTaskError = AmbiguousCommandError
19
+
20
+ # Raised when a command was found, but not invoked properly.
21
+ class InvocationError < Error
22
+ end
23
+
24
+ class UnknownArgumentError < Error
25
+ end
26
+
27
+ class RequiredArgumentMissingError < InvocationError
28
+ end
29
+
30
+ class MalformattedArgumentError < InvocationError
31
+ end
32
+ end