thor-exclude_pattern 0.18.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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/CHANGELOG.md +130 -0
  4. data/LICENSE.md +20 -0
  5. data/README.md +34 -0
  6. data/Thorfile +30 -0
  7. data/bin/rake2thor +86 -0
  8. data/bin/thor +6 -0
  9. data/lib/thor.rb +458 -0
  10. data/lib/thor/actions.rb +318 -0
  11. data/lib/thor/actions/create_file.rb +105 -0
  12. data/lib/thor/actions/create_link.rb +60 -0
  13. data/lib/thor/actions/directory.rb +119 -0
  14. data/lib/thor/actions/empty_directory.rb +153 -0
  15. data/lib/thor/actions/file_manipulation.rb +314 -0
  16. data/lib/thor/actions/inject_into_file.rb +109 -0
  17. data/lib/thor/base.rb +649 -0
  18. data/lib/thor/command.rb +136 -0
  19. data/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  20. data/lib/thor/core_ext/io_binary_read.rb +12 -0
  21. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  22. data/lib/thor/error.rb +32 -0
  23. data/lib/thor/exclude_pattern/version.rb +5 -0
  24. data/lib/thor/group.rb +287 -0
  25. data/lib/thor/invocation.rb +172 -0
  26. data/lib/thor/parser.rb +4 -0
  27. data/lib/thor/parser/argument.rb +74 -0
  28. data/lib/thor/parser/arguments.rb +171 -0
  29. data/lib/thor/parser/option.rb +121 -0
  30. data/lib/thor/parser/options.rb +218 -0
  31. data/lib/thor/rake_compat.rb +72 -0
  32. data/lib/thor/runner.rb +322 -0
  33. data/lib/thor/shell.rb +88 -0
  34. data/lib/thor/shell/basic.rb +393 -0
  35. data/lib/thor/shell/color.rb +148 -0
  36. data/lib/thor/shell/html.rb +127 -0
  37. data/lib/thor/util.rb +270 -0
  38. data/lib/thor/version.rb +3 -0
  39. data/spec/actions/create_file_spec.rb +170 -0
  40. data/spec/actions/create_link_spec.rb +95 -0
  41. data/spec/actions/directory_spec.rb +169 -0
  42. data/spec/actions/empty_directory_spec.rb +130 -0
  43. data/spec/actions/file_manipulation_spec.rb +382 -0
  44. data/spec/actions/inject_into_file_spec.rb +135 -0
  45. data/spec/actions_spec.rb +331 -0
  46. data/spec/base_spec.rb +294 -0
  47. data/spec/command_spec.rb +80 -0
  48. data/spec/core_ext/hash_with_indifferent_access_spec.rb +48 -0
  49. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  50. data/spec/exit_condition_spec.rb +19 -0
  51. data/spec/fixtures/application.rb +2 -0
  52. data/spec/fixtures/app{1}/README +3 -0
  53. data/spec/fixtures/bundle/execute.rb +6 -0
  54. data/spec/fixtures/bundle/main.thor +1 -0
  55. data/spec/fixtures/command.thor +10 -0
  56. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  57. data/spec/fixtures/doc/COMMENTER +11 -0
  58. data/spec/fixtures/doc/README +3 -0
  59. data/spec/fixtures/doc/block_helper.rb +3 -0
  60. data/spec/fixtures/doc/config.rb +1 -0
  61. data/spec/fixtures/doc/config.yaml.tt +1 -0
  62. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
  63. data/spec/fixtures/enum.thor +10 -0
  64. data/spec/fixtures/group.thor +128 -0
  65. data/spec/fixtures/invoke.thor +112 -0
  66. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  67. data/spec/fixtures/preserve/script.sh +3 -0
  68. data/spec/fixtures/script.thor +199 -0
  69. data/spec/fixtures/subcommand.thor +17 -0
  70. data/spec/group_spec.rb +216 -0
  71. data/spec/helper.rb +67 -0
  72. data/spec/invocation_spec.rb +100 -0
  73. data/spec/parser/argument_spec.rb +53 -0
  74. data/spec/parser/arguments_spec.rb +66 -0
  75. data/spec/parser/option_spec.rb +202 -0
  76. data/spec/parser/options_spec.rb +400 -0
  77. data/spec/rake_compat_spec.rb +72 -0
  78. data/spec/register_spec.rb +197 -0
  79. data/spec/runner_spec.rb +241 -0
  80. data/spec/sandbox/application.rb +2 -0
  81. data/spec/sandbox/app{1}/README +3 -0
  82. data/spec/sandbox/bundle/execute.rb +6 -0
  83. data/spec/sandbox/bundle/main.thor +1 -0
  84. data/spec/sandbox/command.thor +10 -0
  85. data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
  86. data/spec/sandbox/doc/COMMENTER +11 -0
  87. data/spec/sandbox/doc/README +4 -0
  88. data/spec/sandbox/doc/block_helper.rb +3 -0
  89. data/spec/sandbox/doc/config.rb +1 -0
  90. data/spec/sandbox/doc/config.yaml.tt +1 -0
  91. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
  92. data/spec/sandbox/enum.thor +10 -0
  93. data/spec/sandbox/group.thor +128 -0
  94. data/spec/sandbox/invoke.thor +112 -0
  95. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  96. data/spec/sandbox/preserve/script.sh +3 -0
  97. data/spec/sandbox/script.thor +199 -0
  98. data/spec/sandbox/subcommand.thor +17 -0
  99. data/spec/shell/basic_spec.rb +311 -0
  100. data/spec/shell/color_spec.rb +95 -0
  101. data/spec/shell/html_spec.rb +32 -0
  102. data/spec/shell_spec.rb +47 -0
  103. data/spec/subcommand_spec.rb +30 -0
  104. data/spec/thor_spec.rb +469 -0
  105. data/spec/util_spec.rb +196 -0
  106. data/thor.gemspec +24 -0
  107. metadata +232 -0
@@ -0,0 +1,197 @@
1
+ require 'helper'
2
+
3
+ class BoringVendorProvidedCLI < Thor
4
+ desc "boring", "do boring stuff"
5
+ def boring
6
+ puts "bored. <yawn>"
7
+ end
8
+ end
9
+
10
+ class ExcitingPluginCLI < Thor
11
+ desc "hooray", "say hooray!"
12
+ def hooray
13
+ puts "hooray!"
14
+ end
15
+
16
+ desc "fireworks", "exciting fireworks!"
17
+ def fireworks
18
+ puts "kaboom!"
19
+ end
20
+ end
21
+
22
+ class SuperSecretPlugin < Thor
23
+ default_command :squirrel
24
+
25
+ desc "squirrel", "All of secret squirrel's secrets"
26
+ def squirrel
27
+ puts "I love nuts"
28
+ end
29
+ end
30
+
31
+ class GroupPlugin < Thor::Group
32
+ desc "part one"
33
+ def part_one
34
+ puts "part one"
35
+ end
36
+
37
+ desc "part two"
38
+ def part_two
39
+ puts "part two"
40
+ end
41
+ end
42
+
43
+ class ClassOptionGroupPlugin < Thor::Group
44
+ class_option :who,
45
+ :type => :string,
46
+ :aliases => "-w",
47
+ :default => "zebra"
48
+ end
49
+
50
+ class CompatibleWith19Plugin < ClassOptionGroupPlugin
51
+ desc "animal"
52
+ def animal
53
+ p options[:who]
54
+ end
55
+ end
56
+
57
+ class PluginWithDefault < Thor
58
+ desc "say MSG", "print MSG"
59
+ def say(msg)
60
+ puts msg
61
+ end
62
+
63
+ default_command :say
64
+ end
65
+
66
+ class PluginWithDefaultMultipleArguments < Thor
67
+ desc "say MSG [MSG]", "print multiple messages"
68
+ def say(*args)
69
+ puts args
70
+ end
71
+
72
+ default_command :say
73
+ end
74
+
75
+ class PluginWithDefaultcommandAndDeclaredArgument < Thor
76
+ desc "say MSG [MSG]", "print multiple messages"
77
+ argument :msg
78
+ def say
79
+ puts msg
80
+ end
81
+
82
+ default_command :say
83
+ end
84
+
85
+ BoringVendorProvidedCLI.register(
86
+ ExcitingPluginCLI,
87
+ "exciting",
88
+ "do exciting things",
89
+ "Various non-boring actions")
90
+
91
+ BoringVendorProvidedCLI.register(
92
+ SuperSecretPlugin,
93
+ "secret",
94
+ "secret stuff",
95
+ "Nothing to see here. Move along.",
96
+ :hide => true)
97
+
98
+ BoringVendorProvidedCLI.register(
99
+ GroupPlugin,
100
+ 'groupwork',
101
+ "Do a bunch of things in a row",
102
+ "purple monkey dishwasher")
103
+
104
+ BoringVendorProvidedCLI.register(
105
+ CompatibleWith19Plugin,
106
+ 'zoo',
107
+ "zoo [-w animal]",
108
+ "Shows a provided animal or just zebra")
109
+
110
+ BoringVendorProvidedCLI.register(
111
+ PluginWithDefault,
112
+ 'say',
113
+ 'say message',
114
+ 'subcommands ftw')
115
+
116
+ BoringVendorProvidedCLI.register(
117
+ PluginWithDefaultMultipleArguments,
118
+ 'say_multiple',
119
+ 'say message',
120
+ 'subcommands ftw')
121
+
122
+ BoringVendorProvidedCLI.register(
123
+ PluginWithDefaultcommandAndDeclaredArgument,
124
+ 'say_argument',
125
+ 'say message',
126
+ 'subcommands ftw')
127
+
128
+ describe ".register-ing a Thor subclass" do
129
+ it "registers the plugin as a subcommand" do
130
+ fireworks_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting fireworks]) }
131
+ expect(fireworks_output).to eq("kaboom!\n")
132
+ end
133
+
134
+ it "includes the plugin's usage in the help" do
135
+ help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
136
+ expect(help_output).to include('do exciting things')
137
+ end
138
+
139
+ it "invokes the default command correctly" do
140
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say hello]) }
141
+ expect(output).to include("hello")
142
+ end
143
+
144
+ it "invokes the default command correctly with multiple args" do
145
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_multiple hello adam]) }
146
+ expect(output).to include("hello")
147
+ expect(output).to include("adam")
148
+ end
149
+
150
+ it "invokes the default command correctly with a declared argument" do
151
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_argument hello]) }
152
+ expect(output).to include("hello")
153
+ end
154
+
155
+ context "when $thor_runner is false" do
156
+ it "includes the plugin's subcommand name in subcommand's help" do
157
+ begin
158
+ $thor_runner = false
159
+ help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting]) }
160
+ expect(help_output).to include('thor exciting_plugin_c_l_i fireworks')
161
+ ensure
162
+ $thor_runner = true
163
+ end
164
+ end
165
+ end
166
+
167
+ context "when hidden" do
168
+ it "omits the hidden plugin's usage from the help" do
169
+ help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
170
+ expect(help_output).not_to include('secret stuff')
171
+ end
172
+
173
+ it "registers the plugin as a subcommand" do
174
+ secret_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[secret squirrel]) }
175
+ expect(secret_output).to eq("I love nuts\n")
176
+ end
177
+ end
178
+ end
179
+
180
+ describe ".register-ing a Thor::Group subclass" do
181
+ it "registers the group as a single command" do
182
+ group_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[groupwork]) }
183
+ expect(group_output).to eq("part one\npart two\n")
184
+ end
185
+ end
186
+
187
+ describe "1.8 and 1.9 syntax compatibility" do
188
+ it "is compatible with both 1.8 and 1.9 syntax w/o command options" do
189
+ group_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[zoo]) }
190
+ expect(group_output).to match(/zebra/)
191
+ end
192
+
193
+ it "is compatible with both 1.8 and 1.9 syntax w/command options" do
194
+ group_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[zoo -w lion]) }
195
+ expect(group_output).to match(/lion/)
196
+ end
197
+ end
@@ -0,0 +1,241 @@
1
+ require 'helper'
2
+ require 'thor/runner'
3
+
4
+ describe Thor::Runner do
5
+ def when_no_thorfiles_exist
6
+ old_dir = Dir.pwd
7
+ Dir.chdir '..'
8
+ delete = Thor::Base.subclasses.select {|e| e.namespace == 'default' }
9
+ delete.each {|e| Thor::Base.subclasses.delete e }
10
+ yield
11
+ Thor::Base.subclasses.concat delete
12
+ Dir.chdir old_dir
13
+ end
14
+
15
+ describe "#help" do
16
+ it "shows information about Thor::Runner itself" do
17
+ expect(capture(:stdout) { Thor::Runner.start(["help"]) }).to match(/List the available thor commands/)
18
+ end
19
+
20
+ it "shows information about a specific Thor::Runner command" do
21
+ content = capture(:stdout) { Thor::Runner.start(["help", "list"]) }
22
+ expect(content).to match(/List the available thor commands/)
23
+ expect(content).not_to match(/help \[COMMAND\]/)
24
+ end
25
+
26
+ it "shows information about a specific Thor class" do
27
+ content = capture(:stdout) { Thor::Runner.start(["help", "my_script"]) }
28
+ expect(content).to match(/zoo\s+# zoo around/m)
29
+ end
30
+
31
+ it "shows information about an specific command from an specific Thor class" do
32
+ content = capture(:stdout) { Thor::Runner.start(["help", "my_script:zoo"]) }
33
+ expect(content).to match(/zoo around/)
34
+ expect(content).not_to match(/help \[COMMAND\]/)
35
+ end
36
+
37
+ it "shows information about a specific Thor group class" do
38
+ content = capture(:stdout) { Thor::Runner.start(["help", "my_counter"]) }
39
+ expect(content).to match(/my_counter N/)
40
+ end
41
+
42
+ it "raises error if a class/command cannot be found" do
43
+ content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
44
+ expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
45
+ end
46
+
47
+ it "raises error if a class/command cannot be found for a setup without thorfiles" do
48
+ when_no_thorfiles_exist do
49
+ Thor::Runner.should_receive :exit
50
+ content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
51
+ expect(content.strip).to eq('Could not find command "unknown".')
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#start" do
57
+ it "invokes a command from Thor::Runner" do
58
+ ARGV.replace ["list"]
59
+ expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
60
+ end
61
+
62
+ it "invokes a command from a specific Thor class" do
63
+ ARGV.replace ["my_script:zoo"]
64
+ expect(Thor::Runner.start).to be_true
65
+ end
66
+
67
+ it "invokes the default command from a specific Thor class if none is specified" do
68
+ ARGV.replace ["my_script"]
69
+ expect(Thor::Runner.start).to eq("default command")
70
+ end
71
+
72
+ it "forwads arguments to the invoked command" do
73
+ ARGV.replace ["my_script:animal", "horse"]
74
+ expect(Thor::Runner.start).to eq(["horse"])
75
+ end
76
+
77
+ it "invokes commands through shortcuts" do
78
+ ARGV.replace ["my_script", "-T", "horse"]
79
+ expect(Thor::Runner.start).to eq(["horse"])
80
+ end
81
+
82
+ it "invokes a Thor::Group" do
83
+ ARGV.replace ["my_counter", "1", "2", "--third", "3"]
84
+ expect(Thor::Runner.start).to eq([1, 2, 3, nil, nil, nil])
85
+ end
86
+
87
+ it "raises an error if class/command can't be found" do
88
+ ARGV.replace ["unknown"]
89
+ content = capture(:stderr){ Thor::Runner.start }
90
+ expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
91
+ end
92
+
93
+ it "raises an error if class/command can't be found in a setup without thorfiles" do
94
+ when_no_thorfiles_exist do
95
+ ARGV.replace ["unknown"]
96
+ Thor::Runner.should_receive :exit
97
+ content = capture(:stderr){ Thor::Runner.start }
98
+ expect(content.strip).to eq('Could not find command "unknown".')
99
+ end
100
+ end
101
+
102
+ it "does not swallow NoMethodErrors that occur inside the called method" do
103
+ ARGV.replace ["my_script:call_unexistent_method"]
104
+ expect{ Thor::Runner.start }.to raise_error(NoMethodError)
105
+ end
106
+
107
+ it "does not swallow Thor::Group InvocationError" do
108
+ ARGV.replace ["whiny_generator"]
109
+ expect{ Thor::Runner.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
110
+ end
111
+
112
+ it "does not swallow Thor InvocationError" do
113
+ ARGV.replace ["my_script:animal"]
114
+ content = capture(:stderr) { Thor::Runner.start }
115
+ expect(content.strip).to eq('thor animal requires at least 1 argument: "thor my_script:animal TYPE".')
116
+ end
117
+ end
118
+
119
+ describe "commands" do
120
+ before do
121
+ @location = "#{File.dirname(__FILE__)}/fixtures/command.thor"
122
+ @original_yaml = {
123
+ "random" => {
124
+ :location => @location,
125
+ :filename => "4a33b894ffce85d7b412fc1b36f88fe0",
126
+ :namespaces => ["amazing"]
127
+ }
128
+ }
129
+
130
+ root_file = File.join(Thor::Util.thor_root, "thor.yml")
131
+
132
+ # Stub load and save to avoid thor.yaml from being overwritten
133
+ YAML.stub!(:load_file).and_return(@original_yaml)
134
+ File.stub!(:exists?).with(root_file).and_return(true)
135
+ File.stub!(:open).with(root_file, "w")
136
+ end
137
+
138
+ describe "list" do
139
+ it "gives a list of the available commands" do
140
+ ARGV.replace ["list"]
141
+ content = capture(:stdout) { Thor::Runner.start }
142
+ expect(content).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
143
+ end
144
+
145
+ it "gives a list of the available Thor::Group classes" do
146
+ ARGV.replace ["list"]
147
+ expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
148
+ end
149
+
150
+ it "can filter a list of the available commands by --group" do
151
+ ARGV.replace ["list", "--group", "standard"]
152
+ expect(capture(:stdout) { Thor::Runner.start }).to match(/amazing:describe NAME/)
153
+ ARGV.replace []
154
+ expect(capture(:stdout) { Thor::Runner.start }).not_to match(/my_script:animal TYPE/)
155
+ ARGV.replace ["list", "--group", "script"]
156
+ expect(capture(:stdout) { Thor::Runner.start }).to match(/my_script:animal TYPE/)
157
+ end
158
+
159
+ it "can skip all filters to show all commands using --all" do
160
+ ARGV.replace ["list", "--all"]
161
+ content = capture(:stdout) { Thor::Runner.start }
162
+ expect(content).to match(/amazing:describe NAME/)
163
+ expect(content).to match(/my_script:animal TYPE/)
164
+ end
165
+
166
+ it "doesn't list superclass commands in the subclass" do
167
+ ARGV.replace ["list"]
168
+ expect(capture(:stdout) { Thor::Runner.start }).not_to match(/amazing:help/)
169
+ end
170
+
171
+ it "presents commands in the default namespace with an empty namespace" do
172
+ ARGV.replace ["list"]
173
+ expect(capture(:stdout) { Thor::Runner.start }).to match(/^thor :cow\s+# prints 'moo'/m)
174
+ end
175
+
176
+ it "runs commands with an empty namespace from the default namespace" do
177
+ ARGV.replace [":command_conflict"]
178
+ expect(capture(:stdout) { Thor::Runner.start }).to eq("command\n")
179
+ end
180
+
181
+ it "runs groups even when there is a command with the same name" do
182
+ ARGV.replace ["command_conflict"]
183
+ expect(capture(:stdout) { Thor::Runner.start }).to eq("group\n")
184
+ end
185
+
186
+ it "runs commands with no colon in the default namespace" do
187
+ ARGV.replace ["cow"]
188
+ expect(capture(:stdout) { Thor::Runner.start }).to eq("moo\n")
189
+ end
190
+ end
191
+
192
+ describe "uninstall" do
193
+ before do
194
+ path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
195
+ FileUtils.should_receive(:rm_rf).with(path)
196
+ end
197
+
198
+ it "uninstalls existing thor modules" do
199
+ silence(:stdout) { Thor::Runner.start(["uninstall", "random"]) }
200
+ end
201
+ end
202
+
203
+ describe "installed" do
204
+ before do
205
+ Dir.should_receive(:[]).and_return([])
206
+ end
207
+
208
+ it "displays the modules installed in a pretty way" do
209
+ stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
210
+ expect(stdout).to match(/random\s*amazing/)
211
+ expect(stdout).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
212
+ end
213
+ end
214
+
215
+ describe "install/update" do
216
+ before do
217
+ FileUtils.stub!(:mkdir_p)
218
+ FileUtils.stub!(:touch)
219
+ $stdin.stub!(:gets).and_return("Y")
220
+
221
+ path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
222
+ File.should_receive(:open).with(path, "w")
223
+ end
224
+
225
+ it "updates existing thor files" do
226
+ path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
227
+ if File.directory? path
228
+ FileUtils.should_receive(:rm_rf).with(path)
229
+ else
230
+ File.should_receive(:delete).with(path)
231
+ end
232
+ silence(:stdout) { Thor::Runner.start(["update", "random"]) }
233
+ end
234
+
235
+ it "installs thor files" do
236
+ ARGV.replace ["install", @location]
237
+ silence(:stdout) { Thor::Runner.start }
238
+ end
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,2 @@
1
+ class Application < Base
2
+ end
@@ -0,0 +1,3 @@
1
+ __start__
2
+ README
3
+ __end__
@@ -0,0 +1,6 @@
1
+ class Execute < Thor
2
+ desc "ls", "Execute ls"
3
+ def ls
4
+ system "ls"
5
+ end
6
+ end