thor 0.13.4 → 0.14.3
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.
- data/CHANGELOG.rdoc +5 -3
- data/{README.rdoc → README.md} +65 -55
- data/Thorfile +3 -2
- data/lib/thor/actions/create_file.rb +3 -1
- data/lib/thor/actions/directory.rb +4 -2
- data/lib/thor/actions/file_manipulation.rb +30 -7
- data/lib/thor/actions.rb +31 -9
- data/lib/thor/base.rb +38 -15
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +1 -1
- data/lib/thor/group.rb +22 -20
- data/lib/thor/invocation.rb +45 -57
- data/lib/thor/parser/argument.rb +15 -15
- data/lib/thor/parser/arguments.rb +14 -3
- data/lib/thor/parser/option.rb +38 -46
- data/lib/thor/parser/options.rb +26 -22
- data/lib/thor/runner.rb +11 -16
- data/lib/thor/shell/basic.rb +48 -12
- data/lib/thor/shell/html.rb +121 -0
- data/lib/thor/shell.rb +7 -2
- data/lib/thor/task.rb +63 -51
- data/lib/thor/util.rb +15 -16
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +118 -45
- data/spec/actions/directory_spec.rb +2 -2
- data/spec/actions/file_manipulation_spec.rb +7 -0
- data/spec/actions_spec.rb +21 -3
- data/spec/base_spec.rb +9 -3
- data/spec/fixtures/doc/block_helper.rb +3 -0
- data/spec/fixtures/doc/components/.empty_directory +0 -0
- data/spec/fixtures/group.thor +16 -4
- data/spec/fixtures/path with spaces +0 -0
- data/spec/fixtures/script.thor +48 -4
- data/spec/group_spec.rb +3 -3
- data/spec/invocation_spec.rb +1 -8
- data/spec/parser/option_spec.rb +2 -2
- data/spec/parser/options_spec.rb +27 -0
- data/spec/runner_spec.rb +16 -8
- data/spec/shell/basic_spec.rb +13 -4
- data/spec/shell/html_spec.rb +27 -0
- data/spec/shell_spec.rb +13 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/task_spec.rb +7 -7
- data/spec/thor_spec.rb +103 -6
- data/spec/util_spec.rb +3 -7
- metadata +63 -7
data/lib/thor/shell/basic.rb
CHANGED
|
@@ -35,15 +35,17 @@ class Thor
|
|
|
35
35
|
# say("I know you knew that.")
|
|
36
36
|
#
|
|
37
37
|
def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
|
|
38
|
-
message
|
|
39
|
-
message
|
|
38
|
+
message = message.to_s
|
|
39
|
+
message = set_color(message, color) if color
|
|
40
|
+
|
|
41
|
+
spaces = " " * padding
|
|
40
42
|
|
|
41
43
|
if force_new_line
|
|
42
|
-
$stdout.puts(message)
|
|
44
|
+
$stdout.puts(spaces + message)
|
|
43
45
|
else
|
|
44
|
-
$stdout.print(message)
|
|
45
|
-
$stdout.flush
|
|
46
|
+
$stdout.print(spaces + message)
|
|
46
47
|
end
|
|
48
|
+
$stdout.flush
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
# Say a status with the given color and appends the message. Since this
|
|
@@ -58,14 +60,16 @@ class Thor
|
|
|
58
60
|
|
|
59
61
|
status = status.to_s.rjust(12)
|
|
60
62
|
status = set_color status, color, true if color
|
|
61
|
-
|
|
63
|
+
|
|
64
|
+
$stdout.puts "#{status}#{spaces}#{message}"
|
|
65
|
+
$stdout.flush
|
|
62
66
|
end
|
|
63
67
|
|
|
64
68
|
# Make a question the to user and returns true if the user replies "y" or
|
|
65
69
|
# "yes".
|
|
66
70
|
#
|
|
67
71
|
def yes?(statement, color=nil)
|
|
68
|
-
ask(statement, color) =~ is?(:yes)
|
|
72
|
+
!!(ask(statement, color) =~ is?(:yes))
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
# Make a question the to user and returns true if the user replies "n" or
|
|
@@ -81,16 +85,20 @@ class Thor
|
|
|
81
85
|
# Array[Array[String, String, ...]]
|
|
82
86
|
#
|
|
83
87
|
# ==== Options
|
|
84
|
-
# ident<Integer>::
|
|
88
|
+
# ident<Integer>:: Indent the first column by ident value.
|
|
89
|
+
# colwidth<Integer>:: Force the first column to colwidth spaces wide.
|
|
85
90
|
#
|
|
86
91
|
def print_table(table, options={})
|
|
87
92
|
return if table.empty?
|
|
88
93
|
|
|
89
|
-
formats, ident = [], options[:ident].to_i
|
|
94
|
+
formats, ident, colwidth = [], options[:ident].to_i, options[:colwidth]
|
|
90
95
|
options[:truncate] = terminal_width if options[:truncate] == true
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
formats << "%-#{colwidth + 2}s" if colwidth
|
|
98
|
+
start = colwidth ? 1 : 0
|
|
99
|
+
|
|
100
|
+
start.upto(table.first.length - 2) do |i|
|
|
101
|
+
maxima ||= table.max{|a,b| a[i].size <=> b[i].size }[i].size
|
|
94
102
|
formats << "%-#{maxima + 2}s"
|
|
95
103
|
end
|
|
96
104
|
|
|
@@ -105,7 +113,35 @@ class Thor
|
|
|
105
113
|
end
|
|
106
114
|
|
|
107
115
|
sentence = truncate(sentence, options[:truncate]) if options[:truncate]
|
|
108
|
-
$stdout.puts sentence
|
|
116
|
+
$stdout.puts sentence
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Prints a long string, word-wrapping the text to the current width of the
|
|
121
|
+
# terminal display. Ideal for printing heredocs.
|
|
122
|
+
#
|
|
123
|
+
# ==== Parameters
|
|
124
|
+
# String
|
|
125
|
+
#
|
|
126
|
+
# ==== Options
|
|
127
|
+
# ident<Integer>:: Indent each line of the printed paragraph by ident value.
|
|
128
|
+
#
|
|
129
|
+
def print_wrapped(message, options={})
|
|
130
|
+
ident = options[:ident] || 0
|
|
131
|
+
width = terminal_width - ident
|
|
132
|
+
paras = message.split("\n\n")
|
|
133
|
+
|
|
134
|
+
paras.map! do |unwrapped|
|
|
135
|
+
unwrapped.strip.gsub(/\n/, " ").squeeze(" ").
|
|
136
|
+
gsub(/.{1,#{width}}(?:\s|\Z)/){($& + 5.chr).
|
|
137
|
+
gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
paras.each do |para|
|
|
141
|
+
para.split("\n").each do |line|
|
|
142
|
+
$stdout.puts line.insert(0, " " * ident)
|
|
143
|
+
end
|
|
144
|
+
$stdout.puts unless para == paras.last
|
|
109
145
|
end
|
|
110
146
|
end
|
|
111
147
|
|
|
@@ -0,0 +1,121 @@
|
|
|
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 HTML < Basic
|
|
9
|
+
# The start of an HTML bold sequence.
|
|
10
|
+
BOLD = "<strong>"
|
|
11
|
+
# The end of an HTML bold sequence.
|
|
12
|
+
END_BOLD = "</strong>"
|
|
13
|
+
|
|
14
|
+
# Embed in a String to clear previous color selection.
|
|
15
|
+
CLEAR = "</span>"
|
|
16
|
+
|
|
17
|
+
# Set the terminal's foreground HTML color to black.
|
|
18
|
+
BLACK = '<span style="color: black;">'
|
|
19
|
+
# Set the terminal's foreground HTML color to red.
|
|
20
|
+
RED = '<span style="color: red;">'
|
|
21
|
+
# Set the terminal's foreground HTML color to green.
|
|
22
|
+
GREEN = '<span style="color: green;">'
|
|
23
|
+
# Set the terminal's foreground HTML color to yellow.
|
|
24
|
+
YELLOW = '<span style="color: yellow;">'
|
|
25
|
+
# Set the terminal's foreground HTML color to blue.
|
|
26
|
+
BLUE = '<span style="color: blue;">'
|
|
27
|
+
# Set the terminal's foreground HTML color to magenta.
|
|
28
|
+
MAGENTA = '<span style="color: magenta;">'
|
|
29
|
+
# Set the terminal's foreground HTML color to cyan.
|
|
30
|
+
CYAN = '<span style="color: cyan;">'
|
|
31
|
+
# Set the terminal's foreground HTML color to white.
|
|
32
|
+
WHITE = '<span style="color: white;">'
|
|
33
|
+
|
|
34
|
+
# Set the terminal's background HTML color to black.
|
|
35
|
+
ON_BLACK = '<span style="background-color: black">'
|
|
36
|
+
# Set the terminal's background HTML color to red.
|
|
37
|
+
ON_RED = '<span style="background-color: red">'
|
|
38
|
+
# Set the terminal's background HTML color to green.
|
|
39
|
+
ON_GREEN = '<span style="background-color: green">'
|
|
40
|
+
# Set the terminal's background HTML color to yellow.
|
|
41
|
+
ON_YELLOW = '<span style="background-color: yellow">'
|
|
42
|
+
# Set the terminal's background HTML color to blue.
|
|
43
|
+
ON_BLUE = '<span style="background-color: blue">'
|
|
44
|
+
# Set the terminal's background HTML color to magenta.
|
|
45
|
+
ON_MAGENTA = '<span style="background-color: magenta">'
|
|
46
|
+
# Set the terminal's background HTML color to cyan.
|
|
47
|
+
ON_CYAN = '<span style="background-color: cyan">'
|
|
48
|
+
# Set the terminal's background HTML color to white.
|
|
49
|
+
ON_WHITE = '<span style="background-color: white">'
|
|
50
|
+
|
|
51
|
+
# Set color by using a string or one of the defined constants. If a third
|
|
52
|
+
# option is set to true, it also adds bold to the string. This is based
|
|
53
|
+
# on Highline implementation and it automatically appends CLEAR to the end
|
|
54
|
+
# of the returned String.
|
|
55
|
+
#
|
|
56
|
+
def set_color(string, color, bold=false)
|
|
57
|
+
color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
|
|
58
|
+
bold, end_bold = bold ? [BOLD, END_BOLD] : ['', '']
|
|
59
|
+
"#{bold}#{color}#{string}#{CLEAR}#{end_bold}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Ask something to the user and receives a response.
|
|
63
|
+
#
|
|
64
|
+
# ==== Example
|
|
65
|
+
# ask("What is your name?")
|
|
66
|
+
#
|
|
67
|
+
# TODO: Implement #ask for Thor::Shell::HTML
|
|
68
|
+
def ask(statement, color=nil)
|
|
69
|
+
raise NotImplementedError, "Implement #ask for Thor::Shell::HTML"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
protected
|
|
73
|
+
|
|
74
|
+
# Overwrite show_diff to show diff with colors if Diff::LCS is
|
|
75
|
+
# available.
|
|
76
|
+
#
|
|
77
|
+
def show_diff(destination, content) #:nodoc:
|
|
78
|
+
if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil?
|
|
79
|
+
actual = File.binread(destination).to_s.split("\n")
|
|
80
|
+
content = content.to_s.split("\n")
|
|
81
|
+
|
|
82
|
+
Diff::LCS.sdiff(actual, content).each do |diff|
|
|
83
|
+
output_diff_line(diff)
|
|
84
|
+
end
|
|
85
|
+
else
|
|
86
|
+
super
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def output_diff_line(diff) #:nodoc:
|
|
91
|
+
case diff.action
|
|
92
|
+
when '-'
|
|
93
|
+
say "- #{diff.old_element.chomp}", :red, true
|
|
94
|
+
when '+'
|
|
95
|
+
say "+ #{diff.new_element.chomp}", :green, true
|
|
96
|
+
when '!'
|
|
97
|
+
say "- #{diff.old_element.chomp}", :red, true
|
|
98
|
+
say "+ #{diff.new_element.chomp}", :green, true
|
|
99
|
+
else
|
|
100
|
+
say " #{diff.old_element.chomp}", nil, true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Check if Diff::LCS is loaded. If it is, use it to create pretty output
|
|
105
|
+
# for diff.
|
|
106
|
+
#
|
|
107
|
+
def diff_lcs_loaded? #:nodoc:
|
|
108
|
+
return true if defined?(Diff::LCS)
|
|
109
|
+
return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
|
|
110
|
+
|
|
111
|
+
@diff_lcs_loaded = begin
|
|
112
|
+
require 'diff/lcs'
|
|
113
|
+
true
|
|
114
|
+
rescue LoadError
|
|
115
|
+
false
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
data/lib/thor/shell.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'rbconfig'
|
|
2
|
-
require 'thor/shell/color'
|
|
3
2
|
|
|
4
3
|
class Thor
|
|
5
4
|
module Base
|
|
@@ -7,7 +6,9 @@ class Thor
|
|
|
7
6
|
# it will use a colored log, otherwise it will use a basic one without color.
|
|
8
7
|
#
|
|
9
8
|
def self.shell
|
|
10
|
-
@shell ||= if
|
|
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/
|
|
11
12
|
Thor::Shell::Basic
|
|
12
13
|
else
|
|
13
14
|
Thor::Shell::Color
|
|
@@ -24,6 +25,10 @@ class Thor
|
|
|
24
25
|
module Shell
|
|
25
26
|
SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_table]
|
|
26
27
|
|
|
28
|
+
autoload :Basic, 'thor/shell/basic'
|
|
29
|
+
autoload :Color, 'thor/shell/color'
|
|
30
|
+
autoload :HTML, 'thor/shell/html'
|
|
31
|
+
|
|
27
32
|
# Add shell to initialize config values.
|
|
28
33
|
#
|
|
29
34
|
# ==== Configuration
|
data/lib/thor/task.rb
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
class Thor
|
|
2
|
-
class Task < Struct.new(:name, :description, :usage, :options)
|
|
2
|
+
class Task < Struct.new(:name, :description, :long_description, :usage, :options)
|
|
3
3
|
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def initialize(name, options=nil)
|
|
8
|
-
super(name.to_s, "A dynamically-generated task", name.to_s, options)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def run(instance, args=[])
|
|
12
|
-
if (instance.methods & [name.to_s, name.to_sym]).empty?
|
|
13
|
-
super
|
|
14
|
-
else
|
|
15
|
-
instance.class.handle_no_task_error(name)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def initialize(name, description, usage, options=nil)
|
|
21
|
-
super(name.to_s, description, usage, options || {})
|
|
5
|
+
def initialize(name, description, long_description, usage, options=nil)
|
|
6
|
+
super(name.to_s, description, long_description, usage, options || {})
|
|
22
7
|
end
|
|
23
8
|
|
|
24
9
|
def initialize_copy(other) #:nodoc:
|
|
@@ -26,6 +11,10 @@ class Thor
|
|
|
26
11
|
self.options = other.options.dup if other.options
|
|
27
12
|
end
|
|
28
13
|
|
|
14
|
+
def hidden?
|
|
15
|
+
false
|
|
16
|
+
end
|
|
17
|
+
|
|
29
18
|
# By default, a task invokes a method in the thor class. You can change this
|
|
30
19
|
# implementation to create custom tasks.
|
|
31
20
|
def run(instance, args=[])
|
|
@@ -39,18 +28,17 @@ class Thor
|
|
|
39
28
|
instance.class.handle_no_task_error(name) : (raise e)
|
|
40
29
|
end
|
|
41
30
|
|
|
42
|
-
# Returns the formatted usage by injecting given required arguments
|
|
31
|
+
# Returns the formatted usage by injecting given required arguments
|
|
43
32
|
# and required options into the given usage.
|
|
44
|
-
def formatted_usage(klass, namespace=true)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"#{namespace.gsub(/^(default|thor:runner:)/,'')}:"
|
|
50
|
-
else
|
|
51
|
-
""
|
|
33
|
+
def formatted_usage(klass, namespace = true, subcommand = false)
|
|
34
|
+
if namespace
|
|
35
|
+
namespace = klass.namespace
|
|
36
|
+
formatted = "#{namespace.gsub(/^(default)/,'')}:"
|
|
37
|
+
formatted.sub!(/.$/, ' ') if subcommand
|
|
52
38
|
end
|
|
53
39
|
|
|
40
|
+
formatted ||= ""
|
|
41
|
+
|
|
54
42
|
# Add usage with required arguments
|
|
55
43
|
formatted << if klass && !klass.arguments.empty?
|
|
56
44
|
usage.to_s.gsub(/^#{name}/) do |match|
|
|
@@ -67,36 +55,60 @@ class Thor
|
|
|
67
55
|
formatted.strip
|
|
68
56
|
end
|
|
69
57
|
|
|
70
|
-
|
|
58
|
+
protected
|
|
71
59
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
def not_debugging?(instance)
|
|
61
|
+
!(instance.class.respond_to?(:debugging) && instance.class.debugging)
|
|
62
|
+
end
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
def required_options
|
|
65
|
+
@required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
|
|
66
|
+
end
|
|
79
67
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
68
|
+
# Given a target, checks if this class name is not a private/protected method.
|
|
69
|
+
def public_method?(instance) #:nodoc:
|
|
70
|
+
collection = instance.private_methods + instance.protected_methods
|
|
71
|
+
(collection & [name.to_s, name.to_sym]).empty?
|
|
72
|
+
end
|
|
85
73
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
74
|
+
def sans_backtrace(backtrace, caller) #:nodoc:
|
|
75
|
+
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP }
|
|
76
|
+
saned -= caller
|
|
77
|
+
end
|
|
90
78
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
79
|
+
def handle_argument_error?(instance, error, caller)
|
|
80
|
+
not_debugging?(instance) && error.message =~ /wrong number of arguments/ && begin
|
|
81
|
+
saned = sans_backtrace(error.backtrace, caller)
|
|
82
|
+
# Ruby 1.9 always include the called method in the backtrace
|
|
83
|
+
saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
|
|
94
84
|
end
|
|
85
|
+
end
|
|
95
86
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
def handle_no_method_error?(instance, error, caller)
|
|
88
|
+
not_debugging?(instance) &&
|
|
89
|
+
error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# A task that is hidden in help messages but still invocable.
|
|
94
|
+
class HiddenTask < Task
|
|
95
|
+
def hidden?
|
|
96
|
+
true
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# A dynamic task that handles method missing scenarios.
|
|
101
|
+
class DynamicTask < Task
|
|
102
|
+
def initialize(name, options=nil)
|
|
103
|
+
super(name.to_s, "A dynamically-generated task", name.to_s, name.to_s, options)
|
|
104
|
+
end
|
|
100
105
|
|
|
106
|
+
def run(instance, args=[])
|
|
107
|
+
if (instance.methods & [name.to_s, name.to_sym]).empty?
|
|
108
|
+
super
|
|
109
|
+
else
|
|
110
|
+
instance.class.handle_no_task_error(name)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
101
113
|
end
|
|
102
|
-
end
|
|
114
|
+
end
|
data/lib/thor/util.rb
CHANGED
|
@@ -128,38 +128,37 @@ class Thor
|
|
|
128
128
|
# ==== Parameters
|
|
129
129
|
# namespace<String>
|
|
130
130
|
#
|
|
131
|
-
def self.find_class_and_task_by_namespace(namespace)
|
|
132
|
-
if namespace.include?(?:)
|
|
131
|
+
def self.find_class_and_task_by_namespace(namespace, fallback = true)
|
|
132
|
+
if namespace.include?(?:) # look for a namespaced task
|
|
133
133
|
pieces = namespace.split(":")
|
|
134
134
|
task = pieces.pop
|
|
135
135
|
klass = Thor::Util.find_by_namespace(pieces.join(":"))
|
|
136
136
|
end
|
|
137
|
-
|
|
138
|
-
unless klass
|
|
137
|
+
unless klass # look for a Thor::Group with the right name
|
|
139
138
|
klass, task = Thor::Util.find_by_namespace(namespace), nil
|
|
140
139
|
end
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
# The same as namespace_to_thor_class_and_task!, but raises an error if a klass
|
|
146
|
-
# could not be found.
|
|
147
|
-
def self.find_class_and_task_by_namespace!(namespace)
|
|
148
|
-
klass, task = find_class_and_task_by_namespace(namespace)
|
|
149
|
-
raise Error, "Could not find namespace or task #{namespace.inspect}." unless klass
|
|
140
|
+
if !klass && fallback # try a task in the default namespace
|
|
141
|
+
task = namespace
|
|
142
|
+
klass = Thor::Util.find_by_namespace('')
|
|
143
|
+
end
|
|
150
144
|
return klass, task
|
|
151
145
|
end
|
|
152
146
|
|
|
153
147
|
# Receives a path and load the thor file in the path. The file is evaluated
|
|
154
148
|
# inside the sandbox to avoid namespacing conflicts.
|
|
155
149
|
#
|
|
156
|
-
def self.load_thorfile(path, content=nil)
|
|
150
|
+
def self.load_thorfile(path, content=nil, debug=false)
|
|
157
151
|
content ||= File.binread(path)
|
|
158
152
|
|
|
159
153
|
begin
|
|
160
154
|
Thor::Sandbox.class_eval(content, path)
|
|
161
155
|
rescue Exception => e
|
|
162
156
|
$stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}"
|
|
157
|
+
if debug
|
|
158
|
+
$stderr.puts *e.backtrace
|
|
159
|
+
else
|
|
160
|
+
$stderr.puts e.backtrace.first
|
|
161
|
+
end
|
|
163
162
|
end
|
|
164
163
|
end
|
|
165
164
|
|
|
@@ -217,8 +216,8 @@ class Thor
|
|
|
217
216
|
#
|
|
218
217
|
def self.ruby_command
|
|
219
218
|
@ruby_command ||= begin
|
|
220
|
-
ruby = File.join(
|
|
221
|
-
ruby <<
|
|
219
|
+
ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
|
220
|
+
ruby << RbConfig::CONFIG['EXEEXT']
|
|
222
221
|
|
|
223
222
|
# escape string in case path to ruby executable contain spaces.
|
|
224
223
|
ruby.sub!(/.*\s.*/m, '"\&"')
|
data/lib/thor/version.rb
CHANGED