spud 0.2.3 → 0.2.4

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/spud.rb +3 -2
  3. data/lib/spud/block_param_info.rb +80 -0
  4. data/lib/spud/cli/options.rb +35 -0
  5. data/lib/spud/cli/parser.rb +22 -19
  6. data/lib/spud/cli/results.rb +18 -11
  7. data/lib/spud/driver.rb +134 -0
  8. data/lib/spud/error.rb +1 -0
  9. data/lib/spud/help.rb +13 -14
  10. data/lib/spud/lister.rb +27 -22
  11. data/lib/spud/task_arg.rb +15 -12
  12. data/lib/spud/task_args.rb +20 -18
  13. data/lib/spud/task_runners/make/task.rb +66 -0
  14. data/lib/spud/task_runners/package.json/task.rb +70 -0
  15. data/lib/spud/{build_tools/spud → task_runners/spud_task_runner}/dependency.rb +3 -2
  16. data/lib/spud/task_runners/spud_task_runner/file_dsl.rb +56 -0
  17. data/lib/spud/task_runners/spud_task_runner/shell/command.rb +58 -0
  18. data/lib/spud/{build_tools/spud → task_runners/spud_task_runner}/shell/result.rb +9 -4
  19. data/lib/spud/task_runners/spud_task_runner/task.rb +143 -0
  20. data/lib/spud/task_runners/spud_task_runner/task_dsl.rb +82 -0
  21. data/lib/spud/task_runners/task.rb +43 -0
  22. data/lib/spud/task_runners/task_runners.rb +25 -0
  23. data/lib/spud/version.rb +2 -1
  24. data/lib/spud/watch.rb +73 -0
  25. metadata +46 -17
  26. data/lib/spud/build_tools/build_tools.rb +0 -13
  27. data/lib/spud/build_tools/make/task.rb +0 -27
  28. data/lib/spud/build_tools/package.json/task.rb +0 -47
  29. data/lib/spud/build_tools/spud/block_param_info.rb +0 -77
  30. data/lib/spud/build_tools/spud/dsl/file.rb +0 -23
  31. data/lib/spud/build_tools/spud/dsl/task.rb +0 -63
  32. data/lib/spud/build_tools/spud/shell/command.rb +0 -52
  33. data/lib/spud/build_tools/spud/task.rb +0 -177
  34. data/lib/spud/build_tools/task.rb +0 -41
  35. data/lib/spud/options.rb +0 -14
  36. data/lib/spud/runtime.rb +0 -114
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c426d3d847aaa06b411cb1eba2e84ddf7ea45ff43d9d02781075637cac24f395
4
- data.tar.gz: 2e37705b14ca816367dd038eb51d402e20d4fac00e144f263fcc8a930654023e
3
+ metadata.gz: f3508c944aca0510946f7705ce2f1fb057632619f11182a872affe5bced27a8e
4
+ data.tar.gz: 3f6c06be53831bad47cfcee5314982e1d2cd165078607b98b2f48b25a75ca2f6
5
5
  SHA512:
6
- metadata.gz: 44a4bd5790ca2613a7af968fc04c7460264a83743ca68ce77513eaafa41098b4fedea9d8a95163100eef2ddb48f2f91182ba7d38df0cdf4a04ae05d8f146b641
7
- data.tar.gz: 17f6f57907780792ee7606520a53a2b373b722ab88bf981eb8193663975e716583f3597835035c228e79c9b8d7c6ea43ea88ab3d63be615b1c6530949c1da7cc
6
+ metadata.gz: b4f6ed2d24030f329187f61475ccfebddf169cec0fdc7c17a8679de302747da7fe1ce74d8a4d92b000af8e50e3e927f103f00d445861e0e6b8cc8f85d8ff62b7
7
+ data.tar.gz: 7a68fd902c3a6494fd2659edf642b924d10a240b59fa7b0780b42392bf69b0dd5f254872ced0490911870b7f49a2eda8f4451b4547140dca89214473c41e02a3
@@ -1,7 +1,8 @@
1
- require_relative 'spud/runtime'
1
+ # typed: true
2
+ require_relative 'spud/driver'
2
3
 
3
4
  module Spud
4
5
  def self.run!
5
- Runtime.run!
6
+ Driver.new.run!
6
7
  end
7
8
  end
@@ -0,0 +1,80 @@
1
+ # typed: true
2
+ require 'sorbet-runtime'
3
+ require 'spud/task_arg'
4
+
5
+ module Spud
6
+ class BlockParamInfo
7
+ extend T::Sig
8
+
9
+ sig {params(filename: String, block: Proc).void}
10
+ def initialize(filename, &block)
11
+ @filename = filename
12
+ @block = block
13
+ end
14
+
15
+ sig {returns(T::Array[TaskArg])}
16
+ def task_args
17
+ parameters.map do |type, name|
18
+ name_string = name.to_s
19
+
20
+ case type
21
+ when :req
22
+ TaskArg.new(name_string, 'ordered')
23
+ when :opt
24
+ TaskArg.new(name_string, 'ordered', default: arg_values[name])
25
+ when :keyreq
26
+ TaskArg.new(name_string, 'named')
27
+ when :key
28
+ TaskArg.new(name_string, 'named', default: arg_values[name])
29
+ else
30
+ raise "invalid proc arg type: '#{type}'"
31
+ end
32
+ end
33
+ end
34
+
35
+ sig {returns([T::Array[NilClass], T::Hash[Symbol, NilClass]])}
36
+ def dummy_args
37
+ [dummy_ordered_args, dummy_named_args]
38
+ end
39
+
40
+ sig {returns(T::Array[NilClass])}
41
+ def dummy_ordered_args
42
+ Array.new(parameters.count { |p| p.first == :req })
43
+ end
44
+
45
+ sig {returns(T::Hash[Symbol, NilClass])}
46
+ def dummy_named_args
47
+ parameters.select { |p| p.first == :keyreq }.map(&:last).each_with_object({}) { |n, h| h[n] = nil }
48
+ end
49
+
50
+ sig {returns(String)}
51
+ def arg_hash_string
52
+ "{ #{parameters.map(&:last).map { |n| "#{n}: #{n}" }.join(', ')} }"
53
+ end
54
+
55
+ sig {returns(T::Hash[Symbol, T.nilable(String)])}
56
+ def arg_values
57
+ @arg_values ||= begin
58
+ ordered, named = dummy_args
59
+ T.unsafe(lambda(arg_hash_string)).call(*ordered, **named)
60
+ end
61
+ end
62
+
63
+ sig {returns(T::Array[[Symbol, Symbol]])}
64
+ def parameters
65
+ @parameters ||= lambda.parameters
66
+ end
67
+
68
+ sig {params(body: T.nilable(String)).returns(Proc)}
69
+ def lambda(body = nil)
70
+ line = File.read(@filename).split("\n")[@block.source_location.last - 1]
71
+
72
+ match = /(do|{)\s*\|(?<params>[^|]+)\|/.match(line)
73
+ return -> {} unless match
74
+
75
+ param_source = T.must(match[:params])
76
+ param_source += ', _: nil, __: nil, ___: nil' if body
77
+ eval "-> (#{param_source}) { #{body} }"
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,35 @@
1
+ # typed: true
2
+ require 'sorbet-runtime'
3
+
4
+ module Spud
5
+ module CLI
6
+ class Options
7
+ extend T::Sig
8
+
9
+ attr_writer :help
10
+ attr_writer :files
11
+ attr_writer :inspect
12
+
13
+ sig {returns(T::Array[String])}
14
+ def watches
15
+ @watches = T.let(@watches, T.nilable(T::Array[String]))
16
+ @watches ||= []
17
+ end
18
+
19
+ sig {returns(T::Boolean)}
20
+ def help?
21
+ !!@help
22
+ end
23
+
24
+ sig {returns(T::Boolean)}
25
+ def files?
26
+ !!@files
27
+ end
28
+
29
+ sig {returns(T::Boolean)}
30
+ def inspect?
31
+ !!@inspect
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,29 +1,33 @@
1
+ # typed: true
2
+ require 'sorbet-runtime'
1
3
  require 'spud/cli/results'
4
+ require 'spud/cli/options'
2
5
 
3
6
  module Spud
4
7
  module CLI
5
8
  class Parser
6
- # @return [Spud::CLI::Results]
9
+ extend T::Sig
10
+
11
+ sig {returns(Results)}
7
12
  attr_reader :results
8
13
 
9
- # @return [void]
14
+ sig {returns(Results)}
10
15
  def self.parse!
11
16
  parse(ARGV)
12
17
  end
13
18
 
14
- # @param args [Array<String>]
15
- # @return [Spud::CLI::Results]
19
+ sig {params(args: T::Array[String]).returns(Results)}
16
20
  def self.parse(args)
17
21
  new(args).parse!
18
22
  end
19
23
 
20
- # @param args [Array<String>]
24
+ sig {params(args: T::Array[String]).void}
21
25
  def initialize(args)
22
26
  @args = args.dup
23
27
  @results = Results.new
24
28
  end
25
29
 
26
- # @return [void]
30
+ sig {returns(Results)}
27
31
  def parse!
28
32
  parse_arg! until done?
29
33
  results
@@ -31,7 +35,7 @@ module Spud
31
35
 
32
36
  private
33
37
 
34
- # @return [void]
38
+ sig {void}
35
39
  def parse_arg!
36
40
  if before_task_name?
37
41
  flag? ? handle_option! : set_task_name!
@@ -39,61 +43,60 @@ module Spud
39
43
  if flag?
40
44
  results.named[lstrip_hyphens(take!)] = take!
41
45
  else
42
- results.positional << take!
46
+ results.ordered << take!
43
47
  end
44
48
  end
45
49
  end
46
50
 
47
- # @return [void]
51
+ sig {void}
48
52
  def handle_option!
49
53
  flag = take!
50
54
  case flag
51
55
  when '-h', '--help' then options.help = true
56
+ when '-w', '--watch' then options.watches << take!
52
57
  when '-f', '--files' then options.files = true
53
58
  when '-i', '--inspect' then options.inspect = true
54
- when '-w', '--watch' then options.watches << take!
55
- when '--debug' then options.debug = true
56
59
  else raise Error, "invalid option: '#{flag}'"
57
60
  end
58
61
  end
59
62
 
60
- # @return [Spud::Options]
63
+ sig {returns(Options)}
61
64
  def options
62
65
  results.options
63
66
  end
64
67
 
65
- # @param flag [String]
66
- # @return [String]
68
+ sig {params(flag: String).returns(String)}
67
69
  def lstrip_hyphens(flag)
68
70
  flag.gsub(/^-+/, '')
69
71
  end
70
72
 
71
- # @return [Boolean]
73
+ sig {returns(T::Boolean)}
72
74
  def before_task_name?
73
75
  !results.task
74
76
  end
75
77
 
76
- # @return [void]
78
+ sig {void}
77
79
  def set_task_name!
78
80
  results.task = take!
79
81
  end
80
82
 
81
- # @return [String]
83
+ sig {returns(String)}
82
84
  def take!
83
85
  @args.shift
84
86
  end
85
87
 
86
88
  # @return [String]
89
+ sig {returns(String)}
87
90
  def arg
88
91
  @args.first
89
92
  end
90
93
 
91
- # @return [Boolean]
94
+ sig {returns(T::Boolean)}
92
95
  def flag?
93
96
  arg.start_with?('-')
94
97
  end
95
98
 
96
- # @return [Boolean]
99
+ sig {returns(T::Boolean)}
97
100
  def done?
98
101
  @args.empty?
99
102
  end
@@ -1,25 +1,32 @@
1
- require 'spud/options'
1
+ # typed: strict
2
+ require 'sorbet-runtime'
3
+ require 'spud/cli/options'
2
4
 
3
5
  module Spud
4
6
  module CLI
5
7
  class Results
6
- # @return [String]
7
- attr_accessor :task
8
+ extend T::Sig
8
9
 
9
- # @return [Spud::Options]
10
- def options
11
- @options ||= Options.new
12
- end
10
+ sig {returns(T.nilable(String))}
11
+ attr_accessor :task
13
12
 
14
- # @return [Array<String>]
15
- def positional
16
- @positional ||= []
13
+ sig {returns(T::Array[String])}
14
+ def ordered
15
+ @ordered = T.let(@ordered, T.nilable(T::Array[String]))
16
+ @ordered ||= []
17
17
  end
18
18
 
19
- # @return [Hash{String->String}]
19
+ sig {returns(T::Hash[String, String])}
20
20
  def named
21
+ @named = T.let(@named, T.nilable(T::Hash[String, String]))
21
22
  @named ||= {}
22
23
  end
24
+
25
+ sig {returns(Options)}
26
+ def options
27
+ @options = T.let(@options, T.nilable(Options))
28
+ @options ||= Options.new
29
+ end
23
30
  end
24
31
  end
25
32
  end
@@ -0,0 +1,134 @@
1
+ # typed: true
2
+ require 'sorbet-runtime'
3
+ require 'spud/error'
4
+ require 'spud/help'
5
+ require 'spud/lister'
6
+ require 'spud/watch'
7
+ require 'spud/cli/parser'
8
+ require 'spud/cli/options'
9
+ require 'spud/task_runners/task'
10
+ require 'spud/task_runners/task_runners'
11
+
12
+ module Spud
13
+ class Driver
14
+ extend T::Sig
15
+
16
+ sig {returns(T.nilable(Integer))}
17
+ attr_reader :subprocess_pid
18
+
19
+ def initialize
20
+ @subprocess_pid = nil
21
+ end
22
+
23
+ sig {void}
24
+ def run!
25
+ if debug?
26
+ puts "options: #{options.inspect}"
27
+ puts "task: #{args.task}"
28
+ puts "ordered: #{args.ordered}"
29
+ puts "named: #{args.named}"
30
+ end
31
+
32
+ if options.help?
33
+ Help.print!
34
+ return
35
+ end
36
+
37
+ if options.files?
38
+ lister.list_filenames!
39
+ return
40
+ end
41
+
42
+ unless args.task
43
+ lister.list_tasks!
44
+ return
45
+ end
46
+
47
+ task = T.must(args.task)
48
+ if options.inspect?
49
+ puts get_task(task).details
50
+ return
51
+ end
52
+
53
+ unless options.watches.empty?
54
+ watch!
55
+ return
56
+ end
57
+
58
+ invoke(task, args.ordered, args.named)
59
+ rescue Error => error
60
+ puts error.message
61
+ raise error if debug?
62
+ rescue SystemExit, Interrupt => error
63
+ puts "handled interrupt #{error}" if debug?
64
+ rescue => error
65
+ puts "fatal: #{error.message}"
66
+ raise error if debug?
67
+ end
68
+
69
+ sig {params(name: String, ordered: T::Array[String], named: T::Hash[T.any(String, Symbol), String]).void}
70
+ def invoke(name, ordered, named)
71
+ get_task(name).invoke(ordered, stringify_keys(named))
72
+ end
73
+
74
+ sig {params(pid: T.nilable(Integer)).void}
75
+ def register_subprocess(pid)
76
+ @subprocess_pid = pid
77
+ end
78
+
79
+ sig {returns(T::Boolean)}
80
+ def debug?
81
+ @debug ||= ENV.key?('SPUD_DEBUG') && ENV['SPUD_DEBUG'] != 'false'
82
+ end
83
+
84
+ private
85
+
86
+ sig {void}
87
+ def watch!
88
+ Watch.run!(
89
+ driver: self,
90
+ task: T.must(args.task),
91
+ ordered: args.ordered,
92
+ named: args.named,
93
+ watches: options.watches,
94
+ )
95
+ end
96
+
97
+ sig {params(task_name: String).returns(TaskRunners::Task)}
98
+ def get_task(task_name)
99
+ task = tasks[task_name]
100
+ raise Error, "no task found for '#{task_name}'" unless task
101
+
102
+ task
103
+ end
104
+
105
+ sig {returns(T::Hash[String, TaskRunners::Task])}
106
+ def tasks
107
+ @tasks ||= TaskRunners.get.each_with_object({}) do |task_runner, tasks|
108
+ task_runner.tasks(self).each do |task|
109
+ tasks[task.name] = task
110
+ end
111
+ end
112
+ end
113
+
114
+ sig {returns(CLI::Results)}
115
+ def args
116
+ @args ||= CLI::Parser.parse!
117
+ end
118
+
119
+ sig {returns(Lister)}
120
+ def lister
121
+ @lister ||= Lister.new(tasks.values)
122
+ end
123
+
124
+ sig {returns(CLI::Options)}
125
+ def options
126
+ args.options
127
+ end
128
+
129
+ sig {params(hash: T::Hash[T.any(String, Symbol), T.untyped]).returns(T::Hash[String, T.untyped])}
130
+ def stringify_keys(hash)
131
+ hash.each_with_object({}) { |(key, value), new_hash| new_hash[key.to_s] = value }
132
+ end
133
+ end
134
+ end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  module Spud
2
3
  class Error < StandardError
3
4
  # @return [String]
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  require 'stringio'
2
3
  require 'spud/version'
3
4
 
@@ -5,20 +6,18 @@ module Spud
5
6
  module Help
6
7
  # @return [void]
7
8
  def self.print!
8
- help = StringIO.new
9
-
10
- help.puts "spud #{VERSION}"
11
- help.puts
12
- help.puts 'usage:'
13
- help.puts ' spud [options] <task> [args]'
14
- help.puts
15
- help.puts 'options:'
16
- help.puts ' -h, --help show this help dialog'
17
- help.puts ' -f, --files list parsed files'
18
- help.puts ' -i, --inspect show details about a task'
19
- help.puts ' --debug run in debug mode'
20
-
21
- puts help.string
9
+ puts <<~HELP
10
+ spud #{VERSION}
11
+
12
+ usage:
13
+ spud [options] <task> [args]
14
+
15
+ options:
16
+ -h, --help show this help dialog
17
+ -w, --watch <glob> re-run task any time glob changes
18
+ -f, --files list parsed files
19
+ -i, --inspect show details about a task
20
+ HELP
22
21
  end
23
22
  end
24
23
  end