wijet-thor 0.14.6

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 (75) hide show
  1. data/CHANGELOG.rdoc +103 -0
  2. data/LICENSE +20 -0
  3. data/README.md +307 -0
  4. data/Thorfile +24 -0
  5. data/bin/rake2thor +86 -0
  6. data/bin/thor +6 -0
  7. data/lib/thor.rb +334 -0
  8. data/lib/thor/actions.rb +314 -0
  9. data/lib/thor/actions/create_file.rb +105 -0
  10. data/lib/thor/actions/create_link.rb +57 -0
  11. data/lib/thor/actions/directory.rb +93 -0
  12. data/lib/thor/actions/empty_directory.rb +134 -0
  13. data/lib/thor/actions/file_manipulation.rb +270 -0
  14. data/lib/thor/actions/inject_into_file.rb +109 -0
  15. data/lib/thor/base.rb +579 -0
  16. data/lib/thor/core_ext/file_binary_read.rb +9 -0
  17. data/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  18. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  19. data/lib/thor/error.rb +30 -0
  20. data/lib/thor/group.rb +273 -0
  21. data/lib/thor/invocation.rb +168 -0
  22. data/lib/thor/parser.rb +4 -0
  23. data/lib/thor/parser/argument.rb +67 -0
  24. data/lib/thor/parser/arguments.rb +161 -0
  25. data/lib/thor/parser/option.rb +120 -0
  26. data/lib/thor/parser/options.rb +173 -0
  27. data/lib/thor/rake_compat.rb +66 -0
  28. data/lib/thor/runner.rb +309 -0
  29. data/lib/thor/shell.rb +88 -0
  30. data/lib/thor/shell/basic.rb +290 -0
  31. data/lib/thor/shell/color.rb +108 -0
  32. data/lib/thor/shell/html.rb +121 -0
  33. data/lib/thor/task.rb +114 -0
  34. data/lib/thor/util.rb +229 -0
  35. data/lib/thor/version.rb +3 -0
  36. data/spec/actions/create_file_spec.rb +170 -0
  37. data/spec/actions/directory_spec.rb +136 -0
  38. data/spec/actions/empty_directory_spec.rb +98 -0
  39. data/spec/actions/file_manipulation_spec.rb +310 -0
  40. data/spec/actions/inject_into_file_spec.rb +135 -0
  41. data/spec/actions_spec.rb +322 -0
  42. data/spec/base_spec.rb +269 -0
  43. data/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
  44. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  45. data/spec/fixtures/application.rb +2 -0
  46. data/spec/fixtures/bundle/execute.rb +6 -0
  47. data/spec/fixtures/bundle/main.thor +1 -0
  48. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  49. data/spec/fixtures/doc/README +3 -0
  50. data/spec/fixtures/doc/block_helper.rb +3 -0
  51. data/spec/fixtures/doc/components/.empty_directory +0 -0
  52. data/spec/fixtures/doc/config.rb +1 -0
  53. data/spec/fixtures/group.thor +114 -0
  54. data/spec/fixtures/invoke.thor +112 -0
  55. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  56. data/spec/fixtures/script.thor +184 -0
  57. data/spec/fixtures/task.thor +10 -0
  58. data/spec/group_spec.rb +178 -0
  59. data/spec/invocation_spec.rb +100 -0
  60. data/spec/parser/argument_spec.rb +47 -0
  61. data/spec/parser/arguments_spec.rb +64 -0
  62. data/spec/parser/option_spec.rb +202 -0
  63. data/spec/parser/options_spec.rb +319 -0
  64. data/spec/rake_compat_spec.rb +68 -0
  65. data/spec/register_spec.rb +104 -0
  66. data/spec/runner_spec.rb +210 -0
  67. data/spec/shell/basic_spec.rb +223 -0
  68. data/spec/shell/color_spec.rb +41 -0
  69. data/spec/shell/html_spec.rb +27 -0
  70. data/spec/shell_spec.rb +47 -0
  71. data/spec/spec_helper.rb +54 -0
  72. data/spec/task_spec.rb +74 -0
  73. data/spec/thor_spec.rb +334 -0
  74. data/spec/util_spec.rb +163 -0
  75. metadata +193 -0
@@ -0,0 +1,88 @@
1
+ require 'rbconfig'
2
+
3
+ class Thor
4
+ module Base
5
+ # Returns the shell used in all Thor classes. If you are in a Unix platform
6
+ # it will use a colored log, otherwise it will use a basic one without color.
7
+ #
8
+ def self.shell
9
+ @shell ||= if ENV['THOR_SHELL'] && ENV['THOR_SHELL'].size > 0
10
+ Thor::Shell.const_get(ENV['THOR_SHELL'])
11
+ elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
12
+ Thor::Shell::Basic
13
+ else
14
+ Thor::Shell::Color
15
+ end
16
+ end
17
+
18
+ # Sets the shell used in all Thor classes.
19
+ #
20
+ def self.shell=(klass)
21
+ @shell = klass
22
+ end
23
+ end
24
+
25
+ module Shell
26
+ SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_table]
27
+
28
+ autoload :Basic, 'thor/shell/basic'
29
+ autoload :Color, 'thor/shell/color'
30
+ autoload :HTML, 'thor/shell/html'
31
+
32
+ # Add shell to initialize config values.
33
+ #
34
+ # ==== Configuration
35
+ # shell<Object>:: An instance of the shell to be used.
36
+ #
37
+ # ==== Examples
38
+ #
39
+ # class MyScript < Thor
40
+ # argument :first, :type => :numeric
41
+ # end
42
+ #
43
+ # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new
44
+ #
45
+ def initialize(args=[], options={}, config={})
46
+ super
47
+ self.shell = config[:shell]
48
+ self.shell.base ||= self if self.shell.respond_to?(:base)
49
+ end
50
+
51
+ # Holds the shell for the given Thor instance. If no shell is given,
52
+ # it gets a default shell from Thor::Base.shell.
53
+ def shell
54
+ @shell ||= Thor::Base.shell.new
55
+ end
56
+
57
+ # Sets the shell for this thor class.
58
+ def shell=(shell)
59
+ @shell = shell
60
+ end
61
+
62
+ # Common methods that are delegated to the shell.
63
+ SHELL_DELEGATED_METHODS.each do |method|
64
+ module_eval <<-METHOD, __FILE__, __LINE__
65
+ def #{method}(*args)
66
+ shell.#{method}(*args)
67
+ end
68
+ METHOD
69
+ end
70
+
71
+ # Yields the given block with padding.
72
+ def with_padding
73
+ shell.padding += 1
74
+ yield
75
+ ensure
76
+ shell.padding -= 1
77
+ end
78
+
79
+ protected
80
+
81
+ # Allow shell to be shared between invocations.
82
+ #
83
+ def _shared_configuration #:nodoc:
84
+ super.merge!(:shell => self.shell)
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,290 @@
1
+ require 'tempfile'
2
+
3
+ class Thor
4
+ module Shell
5
+ class Basic
6
+ attr_accessor :base, :padding
7
+
8
+ # Initialize base and padding to nil.
9
+ #
10
+ def initialize #:nodoc:
11
+ @base, @padding = nil, 0
12
+ end
13
+
14
+ # Mute everything that's inside given block
15
+ #
16
+ def mute
17
+ @mute = true
18
+ yield
19
+ ensure
20
+ @mute = false
21
+ end
22
+
23
+ # Check if base is muted
24
+ #
25
+ def mute?
26
+ @mute
27
+ end
28
+
29
+ # Sets the output padding, not allowing less than zero values.
30
+ #
31
+ def padding=(value)
32
+ @padding = [0, value].max
33
+ end
34
+
35
+ # Ask something to the user and receives a response.
36
+ #
37
+ # ==== Example
38
+ # ask("What is your name?")
39
+ #
40
+ def ask(statement, color=nil)
41
+ say("#{statement} ", color)
42
+ $stdin.gets.strip
43
+ end
44
+
45
+ # Say (print) something to the user. If the sentence ends with a whitespace
46
+ # or tab character, a new line is not appended (print + flush). Otherwise
47
+ # are passed straight to puts (behavior got from Highline).
48
+ #
49
+ # ==== Example
50
+ # say("I know you knew that.")
51
+ #
52
+ def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
53
+ message = message.to_s
54
+ message = set_color(message, color) if color
55
+
56
+ spaces = " " * padding
57
+
58
+ if force_new_line
59
+ $stdout.puts(spaces + message)
60
+ else
61
+ $stdout.print(spaces + message)
62
+ end
63
+ $stdout.flush
64
+ end
65
+
66
+ # Say a status with the given color and appends the message. Since this
67
+ # method is used frequently by actions, it allows nil or false to be given
68
+ # in log_status, avoiding the message from being shown. If a Symbol is
69
+ # given in log_status, it's used as the color.
70
+ #
71
+ def say_status(status, message, log_status=true)
72
+ return if quiet? || log_status == false
73
+ spaces = " " * (padding + 1)
74
+ color = log_status.is_a?(Symbol) ? log_status : :green
75
+
76
+ status = status.to_s.rjust(12)
77
+ status = set_color status, color, true if color
78
+
79
+ $stdout.puts "#{status}#{spaces}#{message}"
80
+ $stdout.flush
81
+ end
82
+
83
+ # Make a question the to user and returns true if the user replies "y" or
84
+ # "yes".
85
+ #
86
+ def yes?(statement, color=nil)
87
+ !!(ask(statement, color) =~ is?(:yes))
88
+ end
89
+
90
+ # Make a question the to user and returns true if the user replies "n" or
91
+ # "no".
92
+ #
93
+ def no?(statement, color=nil)
94
+ !yes?(statement, color)
95
+ end
96
+
97
+ # Prints a table.
98
+ #
99
+ # ==== Parameters
100
+ # Array[Array[String, String, ...]]
101
+ #
102
+ # ==== Options
103
+ # ident<Integer>:: Indent the first column by ident value.
104
+ # colwidth<Integer>:: Force the first column to colwidth spaces wide.
105
+ #
106
+ def print_table(table, options={})
107
+ return if table.empty?
108
+
109
+ formats, ident, colwidth = [], options[:ident].to_i, options[:colwidth]
110
+ options[:truncate] = terminal_width if options[:truncate] == true
111
+
112
+ formats << "%-#{colwidth + 2}s" if colwidth
113
+ start = colwidth ? 1 : 0
114
+
115
+ start.upto(table.first.length - 2) do |i|
116
+ maxima ||= table.max{|a,b| a[i].size <=> b[i].size }[i].size
117
+ formats << "%-#{maxima + 2}s"
118
+ end
119
+
120
+ formats[0] = formats[0].insert(0, " " * ident)
121
+ formats << "%s"
122
+
123
+ table.each do |row|
124
+ sentence = ""
125
+
126
+ row.each_with_index do |column, i|
127
+ sentence << formats[i] % column.to_s
128
+ end
129
+
130
+ sentence = truncate(sentence, options[:truncate]) if options[:truncate]
131
+ $stdout.puts sentence
132
+ end
133
+ end
134
+
135
+ # Prints a long string, word-wrapping the text to the current width of the
136
+ # terminal display. Ideal for printing heredocs.
137
+ #
138
+ # ==== Parameters
139
+ # String
140
+ #
141
+ # ==== Options
142
+ # ident<Integer>:: Indent each line of the printed paragraph by ident value.
143
+ #
144
+ def print_wrapped(message, options={})
145
+ ident = options[:ident] || 0
146
+ width = terminal_width - ident
147
+ paras = message.split("\n\n")
148
+
149
+ paras.map! do |unwrapped|
150
+ unwrapped.strip.gsub(/\n/, " ").squeeze(" ").
151
+ gsub(/.{1,#{width}}(?:\s|\Z)/){($& + 5.chr).
152
+ gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
153
+ end
154
+
155
+ paras.each do |para|
156
+ para.split("\n").each do |line|
157
+ $stdout.puts line.insert(0, " " * ident)
158
+ end
159
+ $stdout.puts unless para == paras.last
160
+ end
161
+ end
162
+
163
+ # Deals with file collision and returns true if the file should be
164
+ # overwriten and false otherwise. If a block is given, it uses the block
165
+ # response as the content for the diff.
166
+ #
167
+ # ==== Parameters
168
+ # destination<String>:: the destination file to solve conflicts
169
+ # block<Proc>:: an optional block that returns the value to be used in diff
170
+ #
171
+ def file_collision(destination)
172
+ return true if @always_force
173
+ options = block_given? ? "[Ynaqdh]" : "[Ynaqh]"
174
+
175
+ while true
176
+ answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}]
177
+
178
+ case answer
179
+ when is?(:yes), is?(:force), ""
180
+ return true
181
+ when is?(:no), is?(:skip)
182
+ return false
183
+ when is?(:always)
184
+ return @always_force = true
185
+ when is?(:quit)
186
+ say 'Aborting...'
187
+ raise SystemExit
188
+ when is?(:diff)
189
+ show_diff(destination, yield) if block_given?
190
+ say 'Retrying...'
191
+ else
192
+ say file_collision_help
193
+ end
194
+ end
195
+ end
196
+
197
+ # Called if something goes wrong during the execution. This is used by Thor
198
+ # internally and should not be used inside your scripts. If someone went
199
+ # wrong, you can always raise an exception. If you raise a Thor::Error, it
200
+ # will be rescued and wrapped in the method below.
201
+ #
202
+ def error(statement)
203
+ $stderr.puts statement
204
+ end
205
+
206
+ # Apply color to the given string with optional bold. Disabled in the
207
+ # Thor::Shell::Basic class.
208
+ #
209
+ def set_color(string, color, bold=false) #:nodoc:
210
+ string
211
+ end
212
+
213
+ protected
214
+
215
+ def is?(value) #:nodoc:
216
+ value = value.to_s
217
+
218
+ if value.size == 1
219
+ /\A#{value}\z/i
220
+ else
221
+ /\A(#{value}|#{value[0,1]})\z/i
222
+ end
223
+ end
224
+
225
+ def file_collision_help #:nodoc:
226
+ <<HELP
227
+ Y - yes, overwrite
228
+ n - no, do not overwrite
229
+ a - all, overwrite this and all others
230
+ q - quit, abort
231
+ d - diff, show the differences between the old and the new
232
+ h - help, show this help
233
+ HELP
234
+ end
235
+
236
+ def show_diff(destination, content) #:nodoc:
237
+ diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u'
238
+
239
+ Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
240
+ temp.write content
241
+ temp.rewind
242
+ system %(#{diff_cmd} "#{destination}" "#{temp.path}")
243
+ end
244
+ end
245
+
246
+ def quiet? #:nodoc:
247
+ mute? || (base && base.options[:quiet])
248
+ end
249
+
250
+ # This code was copied from Rake, available under MIT-LICENSE
251
+ # Copyright (c) 2003, 2004 Jim Weirich
252
+ def terminal_width
253
+ if ENV['THOR_COLUMNS']
254
+ result = ENV['THOR_COLUMNS'].to_i
255
+ else
256
+ result = unix? ? dynamic_width : 80
257
+ end
258
+ (result < 10) ? 80 : result
259
+ rescue
260
+ 80
261
+ end
262
+
263
+ # Calculate the dynamic width of the terminal
264
+ def dynamic_width
265
+ @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
266
+ end
267
+
268
+ def dynamic_width_stty
269
+ %x{stty size 2>/dev/null}.split[1].to_i
270
+ end
271
+
272
+ def dynamic_width_tput
273
+ %x{tput cols 2>/dev/null}.to_i
274
+ end
275
+
276
+ def unix?
277
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
278
+ end
279
+
280
+ def truncate(string, width)
281
+ if string.length <= width
282
+ string
283
+ else
284
+ ( string[0, width-3] || "" ) + "..."
285
+ end
286
+ end
287
+
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,108 @@
1
+ require 'thor/shell/basic'
2
+
3
+ class Thor
4
+ module Shell
5
+ # Inherit from Thor::Shell::Basic and add set_color behavior. Check
6
+ # Thor::Shell::Basic to see all available methods.
7
+ #
8
+ class Color < Basic
9
+ # Embed in a String to clear all previous ANSI sequences.
10
+ CLEAR = "\e[0m"
11
+ # The start of an ANSI bold sequence.
12
+ BOLD = "\e[1m"
13
+
14
+ # Set the terminal's foreground ANSI color to black.
15
+ BLACK = "\e[30m"
16
+ # Set the terminal's foreground ANSI color to red.
17
+ RED = "\e[31m"
18
+ # Set the terminal's foreground ANSI color to green.
19
+ GREEN = "\e[32m"
20
+ # Set the terminal's foreground ANSI color to yellow.
21
+ YELLOW = "\e[33m"
22
+ # Set the terminal's foreground ANSI color to blue.
23
+ BLUE = "\e[34m"
24
+ # Set the terminal's foreground ANSI color to magenta.
25
+ MAGENTA = "\e[35m"
26
+ # Set the terminal's foreground ANSI color to cyan.
27
+ CYAN = "\e[36m"
28
+ # Set the terminal's foreground ANSI color to white.
29
+ WHITE = "\e[37m"
30
+
31
+ # Set the terminal's background ANSI color to black.
32
+ ON_BLACK = "\e[40m"
33
+ # Set the terminal's background ANSI color to red.
34
+ ON_RED = "\e[41m"
35
+ # Set the terminal's background ANSI color to green.
36
+ ON_GREEN = "\e[42m"
37
+ # Set the terminal's background ANSI color to yellow.
38
+ ON_YELLOW = "\e[43m"
39
+ # Set the terminal's background ANSI color to blue.
40
+ ON_BLUE = "\e[44m"
41
+ # Set the terminal's background ANSI color to magenta.
42
+ ON_MAGENTA = "\e[45m"
43
+ # Set the terminal's background ANSI color to cyan.
44
+ ON_CYAN = "\e[46m"
45
+ # Set the terminal's background ANSI color to white.
46
+ ON_WHITE = "\e[47m"
47
+
48
+ # Set color by using a string or one of the defined constants. If a third
49
+ # option is set to true, it also adds bold to the string. This is based
50
+ # on Highline implementation and it automatically appends CLEAR to the end
51
+ # of the returned String.
52
+ #
53
+ def set_color(string, color, bold=false)
54
+ color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
55
+ bold = bold ? BOLD : ""
56
+ "#{bold}#{color}#{string}#{CLEAR}"
57
+ end
58
+
59
+ protected
60
+
61
+ # Overwrite show_diff to show diff with colors if Diff::LCS is
62
+ # available.
63
+ #
64
+ def show_diff(destination, content) #:nodoc:
65
+ if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil?
66
+ actual = File.binread(destination).to_s.split("\n")
67
+ content = content.to_s.split("\n")
68
+
69
+ Diff::LCS.sdiff(actual, content).each do |diff|
70
+ output_diff_line(diff)
71
+ end
72
+ else
73
+ super
74
+ end
75
+ end
76
+
77
+ def output_diff_line(diff) #:nodoc:
78
+ case diff.action
79
+ when '-'
80
+ say "- #{diff.old_element.chomp}", :red, true
81
+ when '+'
82
+ say "+ #{diff.new_element.chomp}", :green, true
83
+ when '!'
84
+ say "- #{diff.old_element.chomp}", :red, true
85
+ say "+ #{diff.new_element.chomp}", :green, true
86
+ else
87
+ say " #{diff.old_element.chomp}", nil, true
88
+ end
89
+ end
90
+
91
+ # Check if Diff::LCS is loaded. If it is, use it to create pretty output
92
+ # for diff.
93
+ #
94
+ def diff_lcs_loaded? #:nodoc:
95
+ return true if defined?(Diff::LCS)
96
+ return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
97
+
98
+ @diff_lcs_loaded = begin
99
+ require 'diff/lcs'
100
+ true
101
+ rescue LoadError
102
+ false
103
+ end
104
+ end
105
+
106
+ end
107
+ end
108
+ end