11class 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
1316end
1417
18+ class TaskNotFoundError < StandardError
19+ def initialize ( name )
20+ @name = name
21+ end
22+
23+ attr_reader :name
24+ end
25+
1526class 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
3176end
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+
3388def find_runfile
3489 previous = nil
3590 dir = Dir . pwd
@@ -49,35 +104,24 @@ def find_runfile
49104 exit 1
50105end
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
83127end
0 commit comments