colorcode_convert_rgb 0.1.0

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.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +7 -0
  3. data/Gemfile.lock +23 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +40 -0
  6. data/Rakefile +10 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/colorcode_convert_rgb.gemspec +30 -0
  10. data/exe/colorcode_convert_rgb +4 -0
  11. data/lib/colorcode_convert_rgb.rb +7 -0
  12. data/lib/colorcode_convert_rgb/cli.rb +13 -0
  13. data/lib/colorcode_convert_rgb/version.rb +3 -0
  14. data/vendor/bundle/ruby/2.5.0/bin/colorcode_convert_rgb +27 -0
  15. data/vendor/bundle/ruby/2.5.0/bin/rake +27 -0
  16. data/vendor/bundle/ruby/2.5.0/bin/thor +27 -0
  17. data/vendor/bundle/ruby/2.5.0/cache/minitest-5.14.2.gem +0 -0
  18. data/vendor/bundle/ruby/2.5.0/cache/rake-12.3.3.gem +0 -0
  19. data/vendor/bundle/ruby/2.5.0/cache/thor-1.0.1.gem +0 -0
  20. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/.autotest +34 -0
  21. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/History.rdoc +1397 -0
  22. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/Manifest.txt +27 -0
  23. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/README.rdoc +764 -0
  24. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/Rakefile +74 -0
  25. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/design_rationale.rb +52 -0
  26. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/hoe/minitest.rb +32 -0
  27. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest.rb +1056 -0
  28. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/assertions.rb +807 -0
  29. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/autorun.rb +13 -0
  30. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/benchmark.rb +455 -0
  31. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/expectations.rb +303 -0
  32. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/hell.rb +11 -0
  33. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/mock.rb +240 -0
  34. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/parallel.rb +70 -0
  35. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/pride.rb +4 -0
  36. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/pride_plugin.rb +142 -0
  37. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/spec.rb +342 -0
  38. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/test.rb +220 -0
  39. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/lib/minitest/unit.rb +45 -0
  40. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/metametameta.rb +136 -0
  41. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/test_minitest_assertions.rb +1575 -0
  42. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/test_minitest_benchmark.rb +137 -0
  43. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/test_minitest_mock.rb +872 -0
  44. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/test_minitest_reporter.rb +299 -0
  45. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/test_minitest_spec.rb +1061 -0
  46. data/vendor/bundle/ruby/2.5.0/gems/minitest-5.14.2/test/minitest/test_minitest_test.rb +1084 -0
  47. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/CONTRIBUTING.rdoc +43 -0
  48. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/Gemfile +3 -0
  49. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/History.rdoc +2344 -0
  50. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/MIT-LICENSE +21 -0
  51. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/README.rdoc +156 -0
  52. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/Rakefile +41 -0
  53. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/azure-pipelines.yml +11 -0
  54. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/bin/bundle +105 -0
  55. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/bin/console +7 -0
  56. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/bin/rake +29 -0
  57. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/bin/rdoc +29 -0
  58. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/bin/rubocop +29 -0
  59. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/bin/setup +6 -0
  60. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/command_line_usage.rdoc +158 -0
  61. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/example/Rakefile1 +38 -0
  62. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/example/Rakefile2 +35 -0
  63. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/example/a.c +6 -0
  64. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/example/b.c +6 -0
  65. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/example/main.c +11 -0
  66. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/glossary.rdoc +42 -0
  67. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/jamis.rb +592 -0
  68. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/proto_rake.rdoc +127 -0
  69. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/rake.1 +156 -0
  70. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/rakefile.rdoc +622 -0
  71. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/doc/rational.rdoc +151 -0
  72. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/exe/rake +27 -0
  73. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake.rb +71 -0
  74. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/application.rb +824 -0
  75. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/backtrace.rb +24 -0
  76. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/clean.rb +78 -0
  77. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/cloneable.rb +17 -0
  78. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/cpu_counter.rb +107 -0
  79. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/default_loader.rb +15 -0
  80. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/dsl_definition.rb +195 -0
  81. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/early_time.rb +22 -0
  82. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/ext/core.rb +26 -0
  83. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/ext/string.rb +176 -0
  84. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/file_creation_task.rb +25 -0
  85. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/file_list.rb +435 -0
  86. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/file_task.rb +54 -0
  87. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/file_utils.rb +137 -0
  88. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/file_utils_ext.rb +145 -0
  89. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/invocation_chain.rb +57 -0
  90. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/invocation_exception_mixin.rb +17 -0
  91. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/late_time.rb +18 -0
  92. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/linked_list.rb +112 -0
  93. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/loaders/makefile.rb +54 -0
  94. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/multi_task.rb +14 -0
  95. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/name_space.rb +38 -0
  96. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/packagetask.rb +207 -0
  97. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/phony.rb +16 -0
  98. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/private_reader.rb +21 -0
  99. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/promise.rb +100 -0
  100. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/pseudo_status.rb +30 -0
  101. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/rake_module.rb +67 -0
  102. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/rake_test_loader.rb +27 -0
  103. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/rule_recursion_overflow_error.rb +20 -0
  104. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/scope.rb +43 -0
  105. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/task.rb +413 -0
  106. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/task_argument_error.rb +8 -0
  107. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/task_arguments.rb +109 -0
  108. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/task_manager.rb +324 -0
  109. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/tasklib.rb +12 -0
  110. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/testtask.rb +224 -0
  111. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/thread_history_display.rb +49 -0
  112. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/thread_pool.rb +163 -0
  113. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/trace_output.rb +23 -0
  114. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/version.rb +10 -0
  115. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/lib/rake/win32.rb +51 -0
  116. data/vendor/bundle/ruby/2.5.0/gems/rake-12.3.3/rake.gemspec +42 -0
  117. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/.document +5 -0
  118. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/CHANGELOG.md +220 -0
  119. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/CONTRIBUTING.md +15 -0
  120. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/LICENSE.md +20 -0
  121. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/README.md +51 -0
  122. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/bin/thor +6 -0
  123. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor.rb +517 -0
  124. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions.rb +336 -0
  125. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions/create_file.rb +104 -0
  126. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions/create_link.rb +61 -0
  127. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions/directory.rb +108 -0
  128. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions/empty_directory.rb +143 -0
  129. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions/file_manipulation.rb +373 -0
  130. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/actions/inject_into_file.rb +120 -0
  131. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/base.rb +699 -0
  132. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/command.rb +142 -0
  133. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/core_ext/hash_with_indifferent_access.rb +97 -0
  134. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/error.rb +110 -0
  135. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/group.rb +281 -0
  136. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/invocation.rb +178 -0
  137. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/line_editor.rb +17 -0
  138. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/line_editor/basic.rb +37 -0
  139. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/line_editor/readline.rb +88 -0
  140. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/nested_context.rb +29 -0
  141. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/parser.rb +4 -0
  142. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/parser/argument.rb +70 -0
  143. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/parser/arguments.rb +175 -0
  144. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/parser/option.rb +159 -0
  145. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/parser/options.rb +236 -0
  146. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/rake_compat.rb +72 -0
  147. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/runner.rb +325 -0
  148. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/shell.rb +81 -0
  149. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/shell/basic.rb +491 -0
  150. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/shell/color.rb +153 -0
  151. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/shell/html.rb +126 -0
  152. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/util.rb +284 -0
  153. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/lib/thor/version.rb +3 -0
  154. data/vendor/bundle/ruby/2.5.0/gems/thor-1.0.1/thor.gemspec +28 -0
  155. data/vendor/bundle/ruby/2.5.0/specifications/minitest-5.14.2.gemspec +38 -0
  156. data/vendor/bundle/ruby/2.5.0/specifications/rake-12.3.3.gemspec +43 -0
  157. data/vendor/bundle/ruby/2.5.0/specifications/thor-1.0.1.gemspec +34 -0
  158. metadata +214 -0
@@ -0,0 +1,120 @@
1
+ require_relative "empty_directory"
2
+
3
+ class Thor
4
+ module Actions
5
+ # Injects the given content into a file. Different from gsub_file, this
6
+ # method is reversible.
7
+ #
8
+ # ==== Parameters
9
+ # destination<String>:: Relative path to the destination root
10
+ # data<String>:: Data to add to the file. Can be given as a block.
11
+ # config<Hash>:: give :verbose => false to not log the status and the flag
12
+ # for injection (:after or :before) or :force => true for
13
+ # insert two or more times the same content.
14
+ #
15
+ # ==== Examples
16
+ #
17
+ # insert_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n"
18
+ #
19
+ # insert_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do
20
+ # gems = ask "Which gems would you like to add?"
21
+ # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
22
+ # end
23
+ #
24
+ WARNINGS = { unchanged_no_flag: 'File unchanged! The supplied flag value not found!' }
25
+
26
+ def insert_into_file(destination, *args, &block)
27
+ data = block_given? ? block : args.shift
28
+
29
+ config = args.shift || {}
30
+ config[:after] = /\z/ unless config.key?(:before) || config.key?(:after)
31
+
32
+ action InjectIntoFile.new(self, destination, data, config)
33
+ end
34
+ alias_method :inject_into_file, :insert_into_file
35
+
36
+ class InjectIntoFile < EmptyDirectory #:nodoc:
37
+ attr_reader :replacement, :flag, :behavior
38
+
39
+ def initialize(base, destination, data, config)
40
+ super(base, destination, {:verbose => true}.merge(config))
41
+
42
+ @behavior, @flag = if @config.key?(:after)
43
+ [:after, @config.delete(:after)]
44
+ else
45
+ [:before, @config.delete(:before)]
46
+ end
47
+
48
+ @replacement = data.is_a?(Proc) ? data.call : data
49
+ @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp)
50
+ end
51
+
52
+ def invoke!
53
+ content = if @behavior == :after
54
+ '\0' + replacement
55
+ else
56
+ replacement + '\0'
57
+ end
58
+
59
+ if exists?
60
+ if replace!(/#{flag}/, content, config[:force])
61
+ say_status(:invoke)
62
+ else
63
+ say_status(:unchanged, warning: WARNINGS[:unchanged_no_flag], color: :red)
64
+ end
65
+ else
66
+ unless pretend?
67
+ raise Thor::Error, "The file #{ destination } does not appear to exist"
68
+ end
69
+ end
70
+ end
71
+
72
+ def revoke!
73
+ say_status :revoke
74
+
75
+ regexp = if @behavior == :after
76
+ content = '\1\2'
77
+ /(#{flag})(.*)(#{Regexp.escape(replacement)})/m
78
+ else
79
+ content = '\2\3'
80
+ /(#{Regexp.escape(replacement)})(.*)(#{flag})/m
81
+ end
82
+
83
+ replace!(regexp, content, true)
84
+ end
85
+
86
+ protected
87
+
88
+ def say_status(behavior, warning: nil, color: nil)
89
+ status = if behavior == :invoke
90
+ if flag == /\A/
91
+ :prepend
92
+ elsif flag == /\z/
93
+ :append
94
+ else
95
+ :insert
96
+ end
97
+ elsif warning
98
+ warning
99
+ else
100
+ :subtract
101
+ end
102
+
103
+ super(status, (color || config[:verbose]))
104
+ end
105
+
106
+ # Adds the content to the file.
107
+ #
108
+ def replace!(regexp, string, force)
109
+ return if pretend?
110
+ content = File.read(destination)
111
+ if force || !content.include?(replacement)
112
+ success = content.gsub!(regexp, string)
113
+
114
+ File.open(destination, "wb") { |file| file.write(content) }
115
+ success
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,699 @@
1
+ require_relative "command"
2
+ require_relative "core_ext/hash_with_indifferent_access"
3
+ require_relative "error"
4
+ require_relative "invocation"
5
+ require_relative "nested_context"
6
+ require_relative "parser"
7
+ require_relative "shell"
8
+ require_relative "line_editor"
9
+ require_relative "util"
10
+
11
+ class Thor
12
+ autoload :Actions, File.expand_path("actions", __dir__)
13
+ autoload :RakeCompat, File.expand_path("rake_compat", __dir__)
14
+ autoload :Group, File.expand_path("group", __dir__)
15
+
16
+ # Shortcuts for help.
17
+ HELP_MAPPINGS = %w(-h -? --help -D)
18
+
19
+ # Thor methods that should not be overwritten by the user.
20
+ THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root
21
+ action add_file create_file in_root inside run run_ruby_script)
22
+
23
+ TEMPLATE_EXTNAME = ".tt"
24
+
25
+ class << self
26
+ def deprecation_warning(message) #:nodoc:
27
+ unless ENV['THOR_SILENCE_DEPRECATION']
28
+ warn "Deprecation warning: #{message}\n" +
29
+ 'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.'
30
+ end
31
+ end
32
+ end
33
+
34
+ module Base
35
+ attr_accessor :options, :parent_options, :args
36
+
37
+ # It receives arguments in an Array and two hashes, one for options and
38
+ # other for configuration.
39
+ #
40
+ # Notice that it does not check if all required arguments were supplied.
41
+ # It should be done by the parser.
42
+ #
43
+ # ==== Parameters
44
+ # args<Array[Object]>:: An array of objects. The objects are applied to their
45
+ # respective accessors declared with <tt>argument</tt>.
46
+ #
47
+ # options<Hash>:: An options hash that will be available as self.options.
48
+ # The hash given is converted to a hash with indifferent
49
+ # access, magic predicates (options.skip?) and then frozen.
50
+ #
51
+ # config<Hash>:: Configuration for this Thor class.
52
+ #
53
+ def initialize(args = [], local_options = {}, config = {})
54
+ parse_options = self.class.class_options
55
+
56
+ # The start method splits inbound arguments at the first argument
57
+ # that looks like an option (starts with - or --). It then calls
58
+ # new, passing in the two halves of the arguments Array as the
59
+ # first two parameters.
60
+
61
+ command_options = config.delete(:command_options) # hook for start
62
+ parse_options = parse_options.merge(command_options) if command_options
63
+ if local_options.is_a?(Array)
64
+ array_options = local_options
65
+ hash_options = {}
66
+ else
67
+ # Handle the case where the class was explicitly instantiated
68
+ # with pre-parsed options.
69
+ array_options = []
70
+ hash_options = local_options
71
+ end
72
+
73
+ # Let Thor::Options parse the options first, so it can remove
74
+ # declared options from the array. This will leave us with
75
+ # a list of arguments that weren't declared.
76
+ stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command]
77
+ disable_required_check = self.class.disable_required_check? config[:current_command]
78
+ opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown, disable_required_check)
79
+ self.options = opts.parse(array_options)
80
+ self.options = config[:class_options].merge(options) if config[:class_options]
81
+
82
+ # If unknown options are disallowed, make sure that none of the
83
+ # remaining arguments looks like an option.
84
+ opts.check_unknown! if self.class.check_unknown_options?(config)
85
+
86
+ # Add the remaining arguments from the options parser to the
87
+ # arguments passed in to initialize. Then remove any positional
88
+ # arguments declared using #argument (this is primarily used
89
+ # by Thor::Group). Tis will leave us with the remaining
90
+ # positional arguments.
91
+ to_parse = args
92
+ to_parse += opts.remaining unless self.class.strict_args_position?(config)
93
+
94
+ thor_args = Thor::Arguments.new(self.class.arguments)
95
+ thor_args.parse(to_parse).each { |k, v| __send__("#{k}=", v) }
96
+ @args = thor_args.remaining
97
+ end
98
+
99
+ class << self
100
+ def included(base) #:nodoc:
101
+ super(base)
102
+ base.extend ClassMethods
103
+ base.send :include, Invocation
104
+ base.send :include, Shell
105
+ end
106
+
107
+ # Returns the classes that inherits from Thor or Thor::Group.
108
+ #
109
+ # ==== Returns
110
+ # Array[Class]
111
+ #
112
+ def subclasses
113
+ @subclasses ||= []
114
+ end
115
+
116
+ # Returns the files where the subclasses are kept.
117
+ #
118
+ # ==== Returns
119
+ # Hash[path<String> => Class]
120
+ #
121
+ def subclass_files
122
+ @subclass_files ||= Hash.new { |h, k| h[k] = [] }
123
+ end
124
+
125
+ # Whenever a class inherits from Thor or Thor::Group, we should track the
126
+ # class and the file on Thor::Base. This is the method responsible for it.
127
+ #
128
+ def register_klass_file(klass) #:nodoc:
129
+ file = caller[1].match(/(.*):\d+/)[1]
130
+ Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass)
131
+
132
+ file_subclasses = Thor::Base.subclass_files[File.expand_path(file)]
133
+ file_subclasses << klass unless file_subclasses.include?(klass)
134
+ end
135
+ end
136
+
137
+ module ClassMethods
138
+ def attr_reader(*) #:nodoc:
139
+ no_commands { super }
140
+ end
141
+
142
+ def attr_writer(*) #:nodoc:
143
+ no_commands { super }
144
+ end
145
+
146
+ def attr_accessor(*) #:nodoc:
147
+ no_commands { super }
148
+ end
149
+
150
+ # If you want to raise an error for unknown options, call check_unknown_options!
151
+ # This is disabled by default to allow dynamic invocations.
152
+ def check_unknown_options!
153
+ @check_unknown_options = true
154
+ end
155
+
156
+ def check_unknown_options #:nodoc:
157
+ @check_unknown_options ||= from_superclass(:check_unknown_options, false)
158
+ end
159
+
160
+ def check_unknown_options?(config) #:nodoc:
161
+ !!check_unknown_options
162
+ end
163
+
164
+ # If you want to raise an error when the default value of an option does not match
165
+ # the type call check_default_type!
166
+ # This will be the default; for compatibility a deprecation warning is issued if necessary.
167
+ def check_default_type!
168
+ @check_default_type = true
169
+ end
170
+
171
+ # If you want to use defaults that don't match the type of an option,
172
+ # either specify `check_default_type: false` or call `allow_incompatible_default_type!`
173
+ def allow_incompatible_default_type!
174
+ @check_default_type = false
175
+ end
176
+
177
+ def check_default_type #:nodoc:
178
+ @check_default_type = from_superclass(:check_default_type, nil) unless defined?(@check_default_type)
179
+ @check_default_type
180
+ end
181
+
182
+ # If true, option parsing is suspended as soon as an unknown option or a
183
+ # regular argument is encountered. All remaining arguments are passed to
184
+ # the command as regular arguments.
185
+ def stop_on_unknown_option?(command_name) #:nodoc:
186
+ false
187
+ end
188
+
189
+ # If true, option set will not suspend the execution of the command when
190
+ # a required option is not provided.
191
+ def disable_required_check?(command_name) #:nodoc:
192
+ false
193
+ end
194
+
195
+ # If you want only strict string args (useful when cascading thor classes),
196
+ # call strict_args_position! This is disabled by default to allow dynamic
197
+ # invocations.
198
+ def strict_args_position!
199
+ @strict_args_position = true
200
+ end
201
+
202
+ def strict_args_position #:nodoc:
203
+ @strict_args_position ||= from_superclass(:strict_args_position, false)
204
+ end
205
+
206
+ def strict_args_position?(config) #:nodoc:
207
+ !!strict_args_position
208
+ end
209
+
210
+ # Adds an argument to the class and creates an attr_accessor for it.
211
+ #
212
+ # Arguments are different from options in several aspects. The first one
213
+ # is how they are parsed from the command line, arguments are retrieved
214
+ # from position:
215
+ #
216
+ # thor command NAME
217
+ #
218
+ # Instead of:
219
+ #
220
+ # thor command --name=NAME
221
+ #
222
+ # Besides, arguments are used inside your code as an accessor (self.argument),
223
+ # while options are all kept in a hash (self.options).
224
+ #
225
+ # Finally, arguments cannot have type :default or :boolean but can be
226
+ # optional (supplying :optional => :true or :required => false), although
227
+ # you cannot have a required argument after a non-required argument. If you
228
+ # try it, an error is raised.
229
+ #
230
+ # ==== Parameters
231
+ # name<Symbol>:: The name of the argument.
232
+ # options<Hash>:: Described below.
233
+ #
234
+ # ==== Options
235
+ # :desc - Description for the argument.
236
+ # :required - If the argument is required or not.
237
+ # :optional - If the argument is optional or not.
238
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric.
239
+ # :default - Default value for this argument. It cannot be required and have default values.
240
+ # :banner - String to show on usage notes.
241
+ #
242
+ # ==== Errors
243
+ # ArgumentError:: Raised if you supply a required argument after a non required one.
244
+ #
245
+ def argument(name, options = {})
246
+ is_thor_reserved_word?(name, :argument)
247
+ no_commands { attr_accessor name }
248
+
249
+ required = if options.key?(:optional)
250
+ !options[:optional]
251
+ elsif options.key?(:required)
252
+ options[:required]
253
+ else
254
+ options[:default].nil?
255
+ end
256
+
257
+ remove_argument name
258
+
259
+ if required
260
+ arguments.each do |argument|
261
+ next if argument.required?
262
+ raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " \
263
+ "the non-required argument #{argument.human_name.inspect}."
264
+ end
265
+ end
266
+
267
+ options[:required] = required
268
+
269
+ arguments << Thor::Argument.new(name, options)
270
+ end
271
+
272
+ # Returns this class arguments, looking up in the ancestors chain.
273
+ #
274
+ # ==== Returns
275
+ # Array[Thor::Argument]
276
+ #
277
+ def arguments
278
+ @arguments ||= from_superclass(:arguments, [])
279
+ end
280
+
281
+ # Adds a bunch of options to the set of class options.
282
+ #
283
+ # class_options :foo => false, :bar => :required, :baz => :string
284
+ #
285
+ # If you prefer more detailed declaration, check class_option.
286
+ #
287
+ # ==== Parameters
288
+ # Hash[Symbol => Object]
289
+ #
290
+ def class_options(options = nil)
291
+ @class_options ||= from_superclass(:class_options, {})
292
+ build_options(options, @class_options) if options
293
+ @class_options
294
+ end
295
+
296
+ # Adds an option to the set of class options
297
+ #
298
+ # ==== Parameters
299
+ # name<Symbol>:: The name of the argument.
300
+ # options<Hash>:: Described below.
301
+ #
302
+ # ==== Options
303
+ # :desc:: -- Description for the argument.
304
+ # :required:: -- If the argument is required or not.
305
+ # :default:: -- Default value for this argument.
306
+ # :group:: -- The group for this options. Use by class options to output options in different levels.
307
+ # :aliases:: -- Aliases for this option. <b>Note:</b> Thor follows a convention of one-dash-one-letter options. Thus aliases like "-something" wouldn't be parsed; use either "\--something" or "-s" instead.
308
+ # :type:: -- The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
309
+ # :banner:: -- String to show on usage notes.
310
+ # :hide:: -- If you want to hide this option from the help.
311
+ #
312
+ def class_option(name, options = {})
313
+ build_option(name, options, class_options)
314
+ end
315
+
316
+ # Removes a previous defined argument. If :undefine is given, undefine
317
+ # accessors as well.
318
+ #
319
+ # ==== Parameters
320
+ # names<Array>:: Arguments to be removed
321
+ #
322
+ # ==== Examples
323
+ #
324
+ # remove_argument :foo
325
+ # remove_argument :foo, :bar, :baz, :undefine => true
326
+ #
327
+ def remove_argument(*names)
328
+ options = names.last.is_a?(Hash) ? names.pop : {}
329
+
330
+ names.each do |name|
331
+ arguments.delete_if { |a| a.name == name.to_s }
332
+ undef_method name, "#{name}=" if options[:undefine]
333
+ end
334
+ end
335
+
336
+ # Removes a previous defined class option.
337
+ #
338
+ # ==== Parameters
339
+ # names<Array>:: Class options to be removed
340
+ #
341
+ # ==== Examples
342
+ #
343
+ # remove_class_option :foo
344
+ # remove_class_option :foo, :bar, :baz
345
+ #
346
+ def remove_class_option(*names)
347
+ names.each do |name|
348
+ class_options.delete(name)
349
+ end
350
+ end
351
+
352
+ # Defines the group. This is used when thor list is invoked so you can specify
353
+ # that only commands from a pre-defined group will be shown. Defaults to standard.
354
+ #
355
+ # ==== Parameters
356
+ # name<String|Symbol>
357
+ #
358
+ def group(name = nil)
359
+ if name
360
+ @group = name.to_s
361
+ else
362
+ @group ||= from_superclass(:group, "standard")
363
+ end
364
+ end
365
+
366
+ # Returns the commands for this Thor class.
367
+ #
368
+ # ==== Returns
369
+ # Hash:: An ordered hash with commands names as keys and Thor::Command
370
+ # objects as values.
371
+ #
372
+ def commands
373
+ @commands ||= Hash.new
374
+ end
375
+ alias_method :tasks, :commands
376
+
377
+ # Returns the commands for this Thor class and all subclasses.
378
+ #
379
+ # ==== Returns
380
+ # Hash:: An ordered hash with commands names as keys and Thor::Command
381
+ # objects as values.
382
+ #
383
+ def all_commands
384
+ @all_commands ||= from_superclass(:all_commands, Hash.new)
385
+ @all_commands.merge!(commands)
386
+ end
387
+ alias_method :all_tasks, :all_commands
388
+
389
+ # Removes a given command from this Thor class. This is usually done if you
390
+ # are inheriting from another class and don't want it to be available
391
+ # anymore.
392
+ #
393
+ # By default it only remove the mapping to the command. But you can supply
394
+ # :undefine => true to undefine the method from the class as well.
395
+ #
396
+ # ==== Parameters
397
+ # name<Symbol|String>:: The name of the command to be removed
398
+ # options<Hash>:: You can give :undefine => true if you want commands the method
399
+ # to be undefined from the class as well.
400
+ #
401
+ def remove_command(*names)
402
+ options = names.last.is_a?(Hash) ? names.pop : {}
403
+
404
+ names.each do |name|
405
+ commands.delete(name.to_s)
406
+ all_commands.delete(name.to_s)
407
+ undef_method name if options[:undefine]
408
+ end
409
+ end
410
+ alias_method :remove_task, :remove_command
411
+
412
+ # All methods defined inside the given block are not added as commands.
413
+ #
414
+ # So you can do:
415
+ #
416
+ # class MyScript < Thor
417
+ # no_commands do
418
+ # def this_is_not_a_command
419
+ # end
420
+ # end
421
+ # end
422
+ #
423
+ # You can also add the method and remove it from the command list:
424
+ #
425
+ # class MyScript < Thor
426
+ # def this_is_not_a_command
427
+ # end
428
+ # remove_command :this_is_not_a_command
429
+ # end
430
+ #
431
+ def no_commands(&block)
432
+ no_commands_context.enter(&block)
433
+ end
434
+
435
+ alias_method :no_tasks, :no_commands
436
+
437
+ def no_commands_context
438
+ @no_commands_context ||= NestedContext.new
439
+ end
440
+
441
+ def no_commands?
442
+ no_commands_context.entered?
443
+ end
444
+
445
+ # Sets the namespace for the Thor or Thor::Group class. By default the
446
+ # namespace is retrieved from the class name. If your Thor class is named
447
+ # Scripts::MyScript, the help method, for example, will be called as:
448
+ #
449
+ # thor scripts:my_script -h
450
+ #
451
+ # If you change the namespace:
452
+ #
453
+ # namespace :my_scripts
454
+ #
455
+ # You change how your commands are invoked:
456
+ #
457
+ # thor my_scripts -h
458
+ #
459
+ # Finally, if you change your namespace to default:
460
+ #
461
+ # namespace :default
462
+ #
463
+ # Your commands can be invoked with a shortcut. Instead of:
464
+ #
465
+ # thor :my_command
466
+ #
467
+ def namespace(name = nil)
468
+ if name
469
+ @namespace = name.to_s
470
+ else
471
+ @namespace ||= Thor::Util.namespace_from_thor_class(self)
472
+ end
473
+ end
474
+
475
+ # Parses the command and options from the given args, instantiate the class
476
+ # and invoke the command. This method is used when the arguments must be parsed
477
+ # from an array. If you are inside Ruby and want to use a Thor class, you
478
+ # can simply initialize it:
479
+ #
480
+ # script = MyScript.new(args, options, config)
481
+ # script.invoke(:command, first_arg, second_arg, third_arg)
482
+ #
483
+ def start(given_args = ARGV, config = {})
484
+ config[:shell] ||= Thor::Base.shell.new
485
+ dispatch(nil, given_args.dup, nil, config)
486
+ rescue Thor::Error => e
487
+ config[:debug] || ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
488
+ exit(false) if exit_on_failure?
489
+ rescue Errno::EPIPE
490
+ # This happens if a thor command is piped to something like `head`,
491
+ # which closes the pipe when it's done reading. This will also
492
+ # mean that if the pipe is closed, further unnecessary
493
+ # computation will not occur.
494
+ exit(true)
495
+ end
496
+
497
+ # Allows to use private methods from parent in child classes as commands.
498
+ #
499
+ # ==== Parameters
500
+ # names<Array>:: Method names to be used as commands
501
+ #
502
+ # ==== Examples
503
+ #
504
+ # public_command :foo
505
+ # public_command :foo, :bar, :baz
506
+ #
507
+ def public_command(*names)
508
+ names.each do |name|
509
+ class_eval "def #{name}(*); super end"
510
+ end
511
+ end
512
+ alias_method :public_task, :public_command
513
+
514
+ def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
515
+ raise UndefinedCommandError.new(command, all_commands.keys, (namespace if has_namespace))
516
+ end
517
+ alias_method :handle_no_task_error, :handle_no_command_error
518
+
519
+ def handle_argument_error(command, error, args, arity) #:nodoc:
520
+ name = [command.ancestor_name, command.name].compact.join(" ")
521
+ msg = "ERROR: \"#{basename} #{name}\" was called with ".dup
522
+ msg << "no arguments" if args.empty?
523
+ msg << "arguments " << args.inspect unless args.empty?
524
+ msg << "\nUsage: \"#{banner(command).split("\n").join("\"\n \"")}\""
525
+ raise InvocationError, msg
526
+ end
527
+
528
+ # A flag that makes the process exit with status 1 if any error happens.
529
+ def exit_on_failure?
530
+ Thor.deprecation_warning "Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `#{self.name}`"
531
+ false
532
+ end
533
+
534
+ protected
535
+
536
+ # Prints the class options per group. If an option does not belong to
537
+ # any group, it's printed as Class option.
538
+ #
539
+ def class_options_help(shell, groups = {}) #:nodoc:
540
+ # Group options by group
541
+ class_options.each do |_, value|
542
+ groups[value.group] ||= []
543
+ groups[value.group] << value
544
+ end
545
+
546
+ # Deal with default group
547
+ global_options = groups.delete(nil) || []
548
+ print_options(shell, global_options)
549
+
550
+ # Print all others
551
+ groups.each do |group_name, options|
552
+ print_options(shell, options, group_name)
553
+ end
554
+ end
555
+
556
+ # Receives a set of options and print them.
557
+ def print_options(shell, options, group_name = nil)
558
+ return if options.empty?
559
+
560
+ list = []
561
+ padding = options.map { |o| o.aliases.size }.max.to_i * 4
562
+
563
+ options.each do |option|
564
+ next if option.hide
565
+ item = [option.usage(padding)]
566
+ item.push(option.description ? "# #{option.description}" : "")
567
+
568
+ list << item
569
+ list << ["", "# Default: #{option.default}"] if option.show_default?
570
+ list << ["", "# Possible values: #{option.enum.join(', ')}"] if option.enum
571
+ end
572
+
573
+ shell.say(group_name ? "#{group_name} options:" : "Options:")
574
+ shell.print_table(list, :indent => 2)
575
+ shell.say ""
576
+ end
577
+
578
+ # Raises an error if the word given is a Thor reserved word.
579
+ def is_thor_reserved_word?(word, type) #:nodoc:
580
+ return false unless THOR_RESERVED_WORDS.include?(word.to_s)
581
+ raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}"
582
+ end
583
+
584
+ # Build an option and adds it to the given scope.
585
+ #
586
+ # ==== Parameters
587
+ # name<Symbol>:: The name of the argument.
588
+ # options<Hash>:: Described in both class_option and method_option.
589
+ # scope<Hash>:: Options hash that is being built up
590
+ def build_option(name, options, scope) #:nodoc:
591
+ scope[name] = Thor::Option.new(name, {:check_default_type => check_default_type}.merge!(options))
592
+ end
593
+
594
+ # Receives a hash of options, parse them and add to the scope. This is a
595
+ # fast way to set a bunch of options:
596
+ #
597
+ # build_options :foo => true, :bar => :required, :baz => :string
598
+ #
599
+ # ==== Parameters
600
+ # Hash[Symbol => Object]
601
+ def build_options(options, scope) #:nodoc:
602
+ options.each do |key, value|
603
+ scope[key] = Thor::Option.parse(key, value)
604
+ end
605
+ end
606
+
607
+ # Finds a command with the given name. If the command belongs to the current
608
+ # class, just return it, otherwise dup it and add the fresh copy to the
609
+ # current command hash.
610
+ def find_and_refresh_command(name) #:nodoc:
611
+ if commands[name.to_s]
612
+ commands[name.to_s]
613
+ elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition
614
+ commands[name.to_s] = command.clone
615
+ else
616
+ raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found."
617
+ end
618
+ end
619
+ alias_method :find_and_refresh_task, :find_and_refresh_command
620
+
621
+ # Everytime someone inherits from a Thor class, register the klass
622
+ # and file into baseclass.
623
+ def inherited(klass)
624
+ super(klass)
625
+ Thor::Base.register_klass_file(klass)
626
+ klass.instance_variable_set(:@no_commands, 0)
627
+ end
628
+
629
+ # Fire this callback whenever a method is added. Added methods are
630
+ # tracked as commands by invoking the create_command method.
631
+ def method_added(meth)
632
+ super(meth)
633
+ meth = meth.to_s
634
+
635
+ if meth == "initialize"
636
+ initialize_added
637
+ return
638
+ end
639
+
640
+ # Return if it's not a public instance method
641
+ return unless public_method_defined?(meth.to_sym)
642
+
643
+ return if no_commands? || !create_command(meth)
644
+
645
+ is_thor_reserved_word?(meth, :command)
646
+ Thor::Base.register_klass_file(self)
647
+ end
648
+
649
+ # Retrieves a value from superclass. If it reaches the baseclass,
650
+ # returns default.
651
+ def from_superclass(method, default = nil)
652
+ if self == baseclass || !superclass.respond_to?(method, true)
653
+ default
654
+ else
655
+ value = superclass.send(method)
656
+
657
+ # Ruby implements `dup` on Object, but raises a `TypeError`
658
+ # if the method is called on immediates. As a result, we
659
+ # don't have a good way to check whether dup will succeed
660
+ # without calling it and rescuing the TypeError.
661
+ begin
662
+ value.dup
663
+ rescue TypeError
664
+ value
665
+ end
666
+
667
+ end
668
+ end
669
+
670
+ #
671
+ # The basename of the program invoking the thor class.
672
+ #
673
+ def basename
674
+ File.basename($PROGRAM_NAME).split(" ").first
675
+ end
676
+
677
+ # SIGNATURE: Sets the baseclass. This is where the superclass lookup
678
+ # finishes.
679
+ def baseclass #:nodoc:
680
+ end
681
+
682
+ # SIGNATURE: Creates a new command if valid_command? is true. This method is
683
+ # called when a new method is added to the class.
684
+ def create_command(meth) #:nodoc:
685
+ end
686
+ alias_method :create_task, :create_command
687
+
688
+ # SIGNATURE: Defines behavior when the initialize method is added to the
689
+ # class.
690
+ def initialize_added #:nodoc:
691
+ end
692
+
693
+ # SIGNATURE: The hook invoked by start.
694
+ def dispatch(command, given_args, given_opts, config) #:nodoc:
695
+ raise NotImplementedError
696
+ end
697
+ end
698
+ end
699
+ end