Skip to content

Commit 5dbfadc

Browse files
committed
Fix #7: Allow task invocation from other tasks.
1 parent f9e4614 commit 5dbfadc

File tree

1 file changed

+76
-32
lines changed

1 file changed

+76
-32
lines changed

runx.rb

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,90 @@
11
class Task
2-
def initialize(name, doc, action)
2+
def initialize(name, doc, action, dir)
33
@name = name
44
@doc = doc
55
@action = action
6+
@dir = dir
67
end
78

8-
def run(args)
9-
@action.call(args)
9+
def run(context, args)
10+
Dir.chdir(@dir) do
11+
context.instance_exec(args, &@action)
12+
end
1013
end
1114

1215
attr_accessor :name, :doc
1316
end
1417

18+
class TaskNotFoundError < StandardError
19+
def initialize(name)
20+
@name = name
21+
end
22+
23+
attr_reader :name
24+
end
25+
1526
class TaskManager
1627
def initialize
28+
@tasks = {}
29+
@run_context = TaskRunContext.new(self)
30+
end
31+
32+
def load(file)
33+
dir = File.dirname(file)
34+
context = TaskDefinitionContext.new(dir)
35+
context.instance_eval(File.read(file), file)
36+
@tasks.merge!(context.tasks)
37+
end
38+
39+
def show_help
40+
puts 'Tasks:'
41+
width = @tasks.map { |name, task| name.length }.max
42+
@tasks.each do |name, task|
43+
space = ' ' * (width - name.length + 6)
44+
puts " #{task.name}#{space}#{task.doc}"
45+
end
46+
end
47+
48+
def run_task(name, *args)
49+
task = @tasks[name.to_s.downcase]
50+
if task.nil?
51+
raise TaskNotFoundError.new(name)
52+
end
53+
54+
task.run(@run_context, args)
55+
end
56+
end
57+
58+
class TaskDefinitionContext
59+
def initialize(dir)
1760
@tasks = {}
1861
@doc = nil
62+
@dir = dir
1963
end
2064

2165
def doc(doc)
2266
@doc = doc
2367
end
2468

2569
def run(name, &block)
26-
@tasks[name.to_s.downcase] = Task.new(name.to_s, @doc, block)
70+
# TODO: Check for task duplication.
71+
@tasks[name.to_s.downcase] = Task.new(name.to_s, @doc, block, @dir)
2772
@doc = nil
2873
end
2974

3075
attr_accessor :tasks
3176
end
3277

78+
class TaskRunContext
79+
def initialize(manager)
80+
@manager = manager
81+
end
82+
83+
def run(name, *args)
84+
@manager.run_task(name, *args)
85+
end
86+
end
87+
3388
def find_runfile
3489
previous = nil
3590
dir = Dir.pwd
@@ -49,35 +104,24 @@ def find_runfile
49104
exit 1
50105
end
51106

52-
runfile_dir = File.dirname(runfile)
53-
Dir.chdir(runfile_dir) do
54-
manager = TaskManager.new
55-
manager.instance_eval(File.read(runfile), runfile)
107+
manager = TaskManager.new
108+
manager.load(runfile)
56109

57-
task_name = ARGV[0]
58-
if !task_name
59-
puts 'Tasks:'
60-
width = manager.tasks.map { |name, task| name.length }.max
61-
manager.tasks.each do |name, task|
62-
space = ' ' * (width - name.length + 6)
63-
puts " #{task.name}#{space}#{task.doc}"
64-
end
65-
else
66-
task = manager.tasks[task_name.downcase]
67-
if task.nil?
68-
puts "Task '#{task_name}' not found."
69-
exit 1
70-
end
110+
task_name = ARGV[0]
111+
if !task_name
112+
manager.show_help
113+
else
114+
# Clear ARGV to avoid interference with `gets`:
115+
# http://ruby-doc.org/core-2.1.5/Kernel.html#method-i-gets
116+
args = ARGV[1...ARGV.length]
117+
ARGV.clear
71118

72-
# Clear ARGV to avoid interference with `gets`:
73-
# http://ruby-doc.org/core-2.1.5/Kernel.html#method-i-gets
74-
args = ARGV[1...ARGV.length]
75-
ARGV.clear
76-
77-
begin
78-
task.run(args)
79-
rescue Interrupt => e
80-
# Handle interrupt and exit.
81-
end
119+
begin
120+
manager.run_task(task_name, *args)
121+
rescue TaskNotFoundError => e
122+
puts "Task '#{e.name}' not found."
123+
exit 1
124+
rescue Interrupt => e
125+
# Ignore interrupt and exit.
82126
end
83127
end

0 commit comments

Comments
 (0)