psychic-runner 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/bin/psychic +1 -1
- data/lib/psychic/cli.rb +8 -1
- data/lib/psychic/output_helper.rb +84 -0
- data/lib/psychic/runner.rb +88 -16
- data/lib/psychic/runner/base_runner.rb +89 -36
- data/lib/psychic/runner/cli.rb +80 -25
- data/lib/psychic/runner/code_helper.rb +131 -0
- data/lib/psychic/runner/code_sample.rb +70 -0
- data/lib/psychic/runner/factories/ruby_factories.rb +16 -0
- data/lib/psychic/runner/{cold/shell_script_runner.rb → factories/shell_script_factories.rb} +4 -4
- data/lib/psychic/runner/{hot_runner.rb → hot_read_task_factory.rb} +4 -3
- data/lib/psychic/runner/magic_task_factory.rb +95 -0
- data/lib/psychic/runner/sample_finder.rb +36 -0
- data/lib/psychic/runner/sample_runner.rb +7 -15
- data/lib/psychic/runner/task_factory_registry.rb +31 -0
- data/lib/psychic/runner/version.rb +1 -1
- data/lib/psychic/shell/mixlib_shellout_executor.rb +3 -1
- data/lib/psychic/task.rb +14 -0
- data/spec/psychic/runner/factories/bundler_detector_spec.rb +90 -0
- data/spec/psychic/runner/{cold → factories}/shell_script_runner_spec.rb +10 -10
- data/spec/psychic/runner/{hot_runner_spec.rb → hot_read_task_factory_spec.rb} +7 -8
- data/spec/psychic/runner/sample_finder_spec.rb +34 -0
- data/spec/psychic/runner_spec.rb +7 -5
- metadata +20 -9
- data/lib/psychic/runner/cold_runner_registry.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3af75e80b40bfaa12b7fdf0c0321d653ab56b86
|
4
|
+
data.tar.gz: ed65f470ce7e85d0f62b329c34ecd476818c9c3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03565dc8cc94cca3682ce30a9e6e3967f7b682882591d5005d08f11c6722141bfad92a1642456611ce4ebe3ba0dec91d4131505a4f1b51c59a487778444b53fa
|
7
|
+
data.tar.gz: 48e7bd41635a48408e4b6a103a4e9688135e2ee75d82c7f81da9042f144b285bb1835aff15a549a6f89820d478f29df7766eade9c4647a84882a1e92acf3b8ba
|
data/Gemfile
CHANGED
data/bin/psychic
CHANGED
data/lib/psychic/cli.rb
CHANGED
@@ -11,7 +11,14 @@ module Psychic
|
|
11
11
|
|
12
12
|
def start(given_args = ARGV, config = {})
|
13
13
|
if given_args && (split_pos = given_args.index('--'))
|
14
|
-
@extra_args = given_args.slice(split_pos + 1, given_args.length)
|
14
|
+
@extra_args = given_args.slice(split_pos + 1, given_args.length).map do | arg |
|
15
|
+
# Restore quotes
|
16
|
+
next unless arg.match(/\=/)
|
17
|
+
lhs, rhs = arg.split('=')
|
18
|
+
lhs = "\"#{lhs}\"" if lhs.match(/\s/)
|
19
|
+
rhs = "\"#{rhs}\"" if rhs.match(/\s/)
|
20
|
+
[lhs, rhs].join('=')
|
21
|
+
end
|
15
22
|
given_args = given_args.slice(0, split_pos)
|
16
23
|
end
|
17
24
|
super given_args, config
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Psychic
|
2
|
+
module OutputHelper
|
3
|
+
class StringShell < Thor::Base.shell
|
4
|
+
attr_reader :io
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
@io = StringIO.new
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
alias_method :stdout, :io
|
12
|
+
alias_method :stderr, :io
|
13
|
+
|
14
|
+
def string
|
15
|
+
@io.string
|
16
|
+
end
|
17
|
+
|
18
|
+
def can_display_colors?
|
19
|
+
# Still capture colors if they can eventually be displayed.
|
20
|
+
$stdout.tty?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli
|
25
|
+
@cli ||= Thor::Base.shell.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_string
|
29
|
+
old_cli = @cli
|
30
|
+
new_cli = @cli = StringShell.new
|
31
|
+
yield
|
32
|
+
@cli = old_cli
|
33
|
+
new_cli.string
|
34
|
+
end
|
35
|
+
|
36
|
+
def reformat(string)
|
37
|
+
return if string.nil? || string.empty?
|
38
|
+
|
39
|
+
indent do
|
40
|
+
string.gsub(/^/, indent)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def indent
|
45
|
+
@indent_level ||= 0
|
46
|
+
if block_given?
|
47
|
+
@indent_level += 2
|
48
|
+
result = yield
|
49
|
+
@indent_level -= 2
|
50
|
+
result
|
51
|
+
else
|
52
|
+
' ' * @indent_level
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def say(msg)
|
57
|
+
cli.say msg if msg
|
58
|
+
end
|
59
|
+
|
60
|
+
def status(status, msg = nil, color = :cyan, colwidth = 50)
|
61
|
+
msg = yield if block_given?
|
62
|
+
cli.say(indent) if indent.length > 0
|
63
|
+
status = cli.set_color("#{status}:", color, true)
|
64
|
+
# The built-in say_status is right-aligned, we want left-aligned
|
65
|
+
cli.say format("%-#{colwidth}s %s", status, msg).rstrip
|
66
|
+
end
|
67
|
+
|
68
|
+
# TODO: Reporters for different formats
|
69
|
+
def print_table(*args)
|
70
|
+
# @reporter.print_table(*args)
|
71
|
+
cli.print_table(*args)
|
72
|
+
end
|
73
|
+
|
74
|
+
def colorize(string, *args)
|
75
|
+
return string unless @reporter.respond_to? :set_color
|
76
|
+
# @reporter.set_color(string, *args)
|
77
|
+
cli.set_color(string, *args)
|
78
|
+
end
|
79
|
+
|
80
|
+
def color_pad(string)
|
81
|
+
string + colorize('', :white)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/psychic/runner.rb
CHANGED
@@ -1,38 +1,110 @@
|
|
1
1
|
require 'psychic/runner/version'
|
2
2
|
|
3
|
+
autoload :Thor, 'thor'
|
3
4
|
autoload :YAML, 'yaml'
|
4
5
|
|
5
6
|
module Psychic
|
6
7
|
autoload :Util, 'psychic/util'
|
7
8
|
autoload :Logger, 'psychic/logger'
|
8
9
|
autoload :Shell, 'psychic/shell'
|
10
|
+
autoload :OutputHelper, 'psychic/output_helper'
|
9
11
|
class Runner
|
12
|
+
autoload :MagicTaskFactory, 'psychic/runner/magic_task_factory'
|
10
13
|
autoload :BaseRunner, 'psychic/runner/base_runner'
|
14
|
+
autoload :CodeSample, 'psychic/runner/code_sample'
|
15
|
+
autoload :SampleFinder, 'psychic/runner/sample_finder'
|
11
16
|
autoload :SampleRunner, 'psychic/runner/sample_runner'
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
autoload :HotReadTaskFactory, 'psychic/runner/hot_read_task_factory'
|
18
|
+
autoload :TaskFactoryRegistry, 'psychic/runner/task_factory_registry'
|
19
|
+
class TaskNotImplementedError < NotImplementedError
|
20
|
+
def initialize(task_name)
|
21
|
+
super("#{self.class} cannot handle task #{task_name}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
TaskFactoryRegistry.autoload_task_factories!
|
17
25
|
|
18
26
|
include BaseRunner
|
19
27
|
include SampleRunner
|
20
|
-
attr_reader :runners, :
|
28
|
+
attr_reader :runners, :hot_read_task_factory, :task_factories, :sample_factories
|
21
29
|
|
22
|
-
def initialize(opts = { cwd: Dir.pwd })
|
30
|
+
def initialize(opts = { cwd: Dir.pwd }) # rubocop:disable Metrics/MethodLength
|
31
|
+
# TODO: Will reduce method length after further splitting Runner vs TaskFactory
|
23
32
|
fail 'cwd is required' unless opts[:cwd]
|
24
|
-
|
25
|
-
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
|
33
|
+
# must be a string on windows...
|
34
|
+
opts[:cwd] = Pathname(opts[:cwd]).to_s
|
35
|
+
@opts = opts
|
36
|
+
init_attr(:cwd) { Dir.pwd }
|
37
|
+
init_hints
|
38
|
+
init_attr(:logger) { new_logger }
|
39
|
+
init_attr(:env) { ENV.to_hash }
|
40
|
+
init_attrs :cli, :interactive, :parameter_mode, :restore_mode, :dry_run
|
41
|
+
@shell_opts = select_shell_opts
|
42
|
+
@parameters = load_parameters(opts[:parameters])
|
43
|
+
# super
|
44
|
+
@hot_read_task_factory = HotReadTaskFactory.new(opts)
|
45
|
+
@sample_finder = SampleFinder.new(opts[:cwd], @hot_read_task_factory.hints['samples'])
|
46
|
+
@task_factories = TaskFactoryRegistry.active_task_factories(opts)
|
47
|
+
@runners = [@hot_read_task_factory, @task_factories].flatten
|
48
|
+
@known_tasks = @runners.flat_map(&:known_tasks).uniq
|
49
|
+
end
|
50
|
+
|
51
|
+
def known_samples
|
52
|
+
@sample_finder.known_samples
|
30
53
|
end
|
31
54
|
|
32
|
-
def
|
33
|
-
runner = runners.find { |r| r.
|
55
|
+
def task_for(task_name)
|
56
|
+
runner = runners.find { |r| r.known_task?(task_name) }
|
34
57
|
return nil unless runner
|
35
|
-
runner
|
58
|
+
runner.task_for(task_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def init_attr(var)
|
64
|
+
var_name = "@#{var}"
|
65
|
+
var_value = @opts[var]
|
66
|
+
var_value = yield if var_value.nil? && block_given?
|
67
|
+
instance_variable_set(var_name, var_value)
|
68
|
+
end
|
69
|
+
|
70
|
+
def init_attrs(*vars)
|
71
|
+
vars.each do | var |
|
72
|
+
init_attr var
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def init_hints
|
77
|
+
@hints = Psychic::Util.stringified_hash(@opts[:hints] || load_hints || {})
|
78
|
+
if @hints['options']
|
79
|
+
@opts.merge! Psychic::Util.symbolized_hash(@hints['options'])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def select_shell_opts
|
84
|
+
# Make sure to delete any option that isn't a MixLib::ShellOut option
|
85
|
+
@opts.select { |key, _| Psychic::Shell::AVAILABLE_OPTIONS.include? key }
|
86
|
+
end
|
87
|
+
|
88
|
+
def load_hints
|
89
|
+
hints_file = Dir["#{@cwd}/psychic.{yaml,yml}"].first
|
90
|
+
YAML.load(File.read(hints_file)) unless hints_file.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_parameters(parameters)
|
94
|
+
if parameters.nil? || parameters.is_a?(String)
|
95
|
+
load_parameters_file(parameters)
|
96
|
+
else
|
97
|
+
parameters
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def load_parameters_file(file = nil)
|
102
|
+
if file.nil?
|
103
|
+
file ||= File.expand_path(DEFAULT_PARAMS_FILE, cwd)
|
104
|
+
return {} unless File.exist? file
|
105
|
+
end
|
106
|
+
parameters = Psychic::Util.replace_tokens(File.read(file), @env)
|
107
|
+
YAML.load(parameters)
|
36
108
|
end
|
37
109
|
end
|
38
110
|
end
|
@@ -6,20 +6,41 @@ module Psychic
|
|
6
6
|
include Psychic::Shell
|
7
7
|
include Psychic::Logger
|
8
8
|
|
9
|
-
attr_reader :known_tasks
|
10
|
-
attr_reader :cwd
|
11
|
-
attr_reader :env
|
12
|
-
attr_reader :hints
|
9
|
+
attr_reader :known_tasks, :tasks, :cwd, :env, :hints
|
13
10
|
|
14
11
|
module ClassMethods
|
15
|
-
|
12
|
+
def register_task_factory
|
13
|
+
Psychic::Runner::TaskFactoryRegistry.register(self)
|
14
|
+
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
16
|
+
def magic_file_patterns
|
17
|
+
@magic_file_patterns ||= []
|
19
18
|
end
|
20
19
|
|
21
20
|
def magic_file(pattern) # rubocop:disable Style/TrivialAccessors
|
22
|
-
|
21
|
+
magic_file_patterns << pattern
|
22
|
+
end
|
23
|
+
|
24
|
+
def magic_env_vars
|
25
|
+
@magic_env_vars ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def magic_env_var(var)
|
29
|
+
magic_env_vars << var
|
30
|
+
end
|
31
|
+
|
32
|
+
def known_tasks
|
33
|
+
@known_tasks ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def tasks
|
37
|
+
@tasks ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def task(name, &block)
|
41
|
+
name = name.to_s
|
42
|
+
tasks[name] = block
|
43
|
+
known_tasks << name
|
23
44
|
end
|
24
45
|
end
|
25
46
|
|
@@ -27,53 +48,54 @@ module Psychic
|
|
27
48
|
base.extend(ClassMethods)
|
28
49
|
end
|
29
50
|
|
30
|
-
def initialize(opts = {}
|
31
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
51
|
+
def initialize(opts = {})
|
52
|
+
@opts = opts
|
53
|
+
init_attr(:cwd) { Dir.pwd }
|
54
|
+
init_hints
|
55
|
+
init_attr(:known_tasks) { self.class.known_tasks }
|
56
|
+
init_attr(:tasks) { self.class.tasks }
|
57
|
+
init_attr(:logger) { new_logger }
|
58
|
+
init_attr(:env) { ENV.to_hash }
|
59
|
+
init_attrs :cli, :interactive, :parameter_mode, :restore_mode, :dry_run
|
60
|
+
@shell_opts = select_shell_opts
|
38
61
|
@parameters = load_parameters(opts[:parameters])
|
39
|
-
@cli, @interactive_mode, @parameter_mode, @restore_mode, @dry_run = opts.values_at(
|
40
|
-
:cli, :interactive, :parameter_mode, :restore_mode, :dry_run)
|
41
|
-
# Make sure to delete any option that isn't a MixLib::ShellOut option
|
42
|
-
@shell_opts = opts.select { |key, _| Psychic::Shell::AVAILABLE_OPTIONS.include? key }
|
43
62
|
end
|
44
63
|
|
45
|
-
def
|
46
|
-
|
47
|
-
super
|
64
|
+
def known_task?(task_name)
|
65
|
+
known_tasks.include?(task_name.to_s)
|
48
66
|
end
|
49
67
|
|
50
|
-
def
|
51
|
-
|
52
|
-
rescue Psychic::Runner::TaskNotImplementedError
|
53
|
-
super
|
68
|
+
def task_for(task_name)
|
69
|
+
tasks[task_name] if tasks.include? task_name
|
54
70
|
end
|
55
71
|
|
56
|
-
# Reserved words
|
57
|
-
|
58
72
|
def execute(command, *args)
|
59
73
|
full_cmd = [command, *args].join(' ')
|
60
74
|
logger.info("Executing #{full_cmd}")
|
61
75
|
shell.execute(full_cmd, @shell_opts) unless dry_run?
|
62
76
|
end
|
63
77
|
|
64
|
-
def
|
65
|
-
task_name =
|
66
|
-
|
78
|
+
def build_task(task_name, *_args)
|
79
|
+
task_name = task_name.to_s
|
80
|
+
task = task_for(task_name)
|
81
|
+
task = task.call if task.respond_to? :call
|
82
|
+
fail Psychic::Runner::TaskNotImplementedError, task_name if task.nil?
|
83
|
+
task
|
67
84
|
end
|
68
85
|
|
69
|
-
def execute_task(
|
70
|
-
command =
|
71
|
-
fail Psychic::Runner::TaskNotImplementedError if command.nil?
|
86
|
+
def execute_task(task_name, *args)
|
87
|
+
command = build_task(task_name, *args)
|
72
88
|
execute(command, *args)
|
73
89
|
end
|
74
90
|
|
75
91
|
def active?
|
76
|
-
self.class.
|
92
|
+
self.class.magic_file_patterns.each do | pattern |
|
93
|
+
return true unless Dir["#{@cwd}/#{pattern}"].empty?
|
94
|
+
end
|
95
|
+
self.class.magic_env_vars.each do | var |
|
96
|
+
return true if ENV[var]
|
97
|
+
end
|
98
|
+
false
|
77
99
|
end
|
78
100
|
|
79
101
|
def dry_run?
|
@@ -82,6 +104,31 @@ module Psychic
|
|
82
104
|
|
83
105
|
private
|
84
106
|
|
107
|
+
def init_attr(var)
|
108
|
+
var_name = "@#{var}"
|
109
|
+
var_value = @opts[var]
|
110
|
+
var_value = yield if var_value.nil? && block_given?
|
111
|
+
instance_variable_set(var_name, var_value)
|
112
|
+
end
|
113
|
+
|
114
|
+
def init_attrs(*vars)
|
115
|
+
vars.each do | var |
|
116
|
+
init_attr var
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def init_hints
|
121
|
+
@hints = Psychic::Util.stringified_hash(@opts[:hints] || load_hints || {})
|
122
|
+
if @hints['options']
|
123
|
+
@opts.merge! Psychic::Util.symbolized_hash(@hints['options'])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def select_shell_opts
|
128
|
+
# Make sure to delete any option that isn't a MixLib::ShellOut option
|
129
|
+
@opts.select { |key, _| Psychic::Shell::AVAILABLE_OPTIONS.include? key }
|
130
|
+
end
|
131
|
+
|
85
132
|
def load_hints
|
86
133
|
hints_file = Dir["#{@cwd}/psychic.{yaml,yml}"].first
|
87
134
|
YAML.load(File.read(hints_file)) unless hints_file.nil?
|
@@ -103,6 +150,12 @@ module Psychic
|
|
103
150
|
parameters = Psychic::Util.replace_tokens(File.read(file), @env)
|
104
151
|
YAML.load(parameters)
|
105
152
|
end
|
153
|
+
|
154
|
+
# Blame Ruby's flatten and Array(...) behavior...
|
155
|
+
def to_ary
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
alias_method :to_a, :to_ary
|
106
159
|
end
|
107
160
|
end
|
108
161
|
end
|
data/lib/psychic/runner/cli.rb
CHANGED
@@ -1,10 +1,32 @@
|
|
1
|
+
require 'psychic/cli'
|
1
2
|
require 'psychic/runner'
|
2
3
|
|
4
|
+
# rubocop:disable Metrics/LineLength
|
5
|
+
|
3
6
|
module Psychic
|
4
|
-
|
5
|
-
class
|
7
|
+
class Runner
|
8
|
+
class RunnerCLI < Psychic::CLI
|
9
|
+
no_commands do
|
10
|
+
def runner
|
11
|
+
@runner ||= setup_runner
|
12
|
+
end
|
13
|
+
|
14
|
+
def setup_runner
|
15
|
+
runner_opts = { cwd: Dir.pwd, cli: shell, parameters: options.parameters }
|
16
|
+
runner_opts.merge!(Util.symbolized_hash(options))
|
17
|
+
Psychic::Runner.new(runner_opts)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class CLI < RunnerCLI
|
6
23
|
desc 'task <name>', 'Executes any task by name'
|
7
|
-
|
24
|
+
method_option :list, aliases: '-l', desc: 'List known tasks'
|
25
|
+
method_option :verbose, aliases: '-v', desc: 'Verbose: display more details'
|
26
|
+
method_option :cwd, desc: 'Working directory for detecting and running commands'
|
27
|
+
def task(task_name = nil)
|
28
|
+
return list_tasks if options[:list]
|
29
|
+
abort 'You must specify a task name, run with -l for a list of known tasks' unless task_name
|
8
30
|
result = runner.execute_task(task_name, *extra_args)
|
9
31
|
result.error!
|
10
32
|
say_status :success, task_name
|
@@ -15,33 +37,22 @@ module Psychic
|
|
15
37
|
|
16
38
|
BUILT_IN_TASKS.each do |task_name|
|
17
39
|
desc task_name, "Executes the #{task_name} task"
|
40
|
+
method_option :verbose, aliases: '-v', desc: 'Verbose: display more details'
|
41
|
+
method_option :cwd, desc: 'Working directory for detecting and running commands'
|
18
42
|
define_method(task_name) do
|
19
43
|
task(task_name)
|
20
44
|
end
|
21
45
|
end
|
22
46
|
|
23
47
|
desc 'sample <name>', 'Executes a code sample'
|
24
|
-
|
48
|
+
method_option :verbose, aliases: '-v', desc: 'Verbose: display more details'
|
49
|
+
method_option :cwd, desc: 'Working directory for detecting and running commands'
|
25
50
|
method_option :interactive, desc: 'Prompt for parameters?', enum: %w(always missing), lazy_default: 'missing'
|
26
51
|
method_option :parameters, desc: 'YAML file containing key/value parameters. Default: psychic-parameters.yaml'
|
27
52
|
method_option :parameter_mode, desc: 'How should the parameters be passed?', enum: %w(tokens arguments env)
|
28
53
|
method_option :dry_run, desc: 'Do not execute - just show what command would be run', lazy_default: true
|
29
|
-
|
30
|
-
|
31
|
-
sample_names.each do | sample_name |
|
32
|
-
say_status :executing, sample_name
|
33
|
-
begin
|
34
|
-
run_sample sample_name
|
35
|
-
rescue Errno::ENOENT
|
36
|
-
say_status :failed, "No code sample found for #{sample_name}", :red
|
37
|
-
# TODO: Fail on missing? Fail fast?
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def run_sample(sample_name)
|
54
|
+
def sample(sample_name = nil)
|
55
|
+
abort 'You must specify a sample name, run `psychic list samples` for a list of known samples' unless sample_name
|
45
56
|
result = runner.run_sample(sample_name, *extra_args)
|
46
57
|
if options.dry_run
|
47
58
|
say_status :dry_run, sample_name
|
@@ -51,12 +62,56 @@ module Psychic
|
|
51
62
|
end
|
52
63
|
end
|
53
64
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
65
|
+
class List < RunnerCLI
|
66
|
+
desc 'samples', 'Lists known code samples'
|
67
|
+
method_option :verbose, aliases: '-v', desc: 'Verbose: display more details'
|
68
|
+
method_option :cwd, desc: 'Working directory for detecting and running commands'
|
69
|
+
def samples
|
70
|
+
samples = runner.known_samples.map do |sample|
|
71
|
+
[set_color(sample.name, :bold), sample.source_file]
|
72
|
+
end
|
73
|
+
print_table samples
|
74
|
+
end
|
75
|
+
|
76
|
+
desc 'tasks', 'List known tasks'
|
77
|
+
method_option :verbose, aliases: '-v', desc: 'Verbose: display more details'
|
78
|
+
method_option :cwd, desc: 'Working directory for detecting and running commands'
|
79
|
+
def tasks
|
80
|
+
runner.known_tasks.map do |task|
|
81
|
+
task_id = set_color(task, :bold)
|
82
|
+
if options[:verbose]
|
83
|
+
details = runner.task_for(task)
|
84
|
+
details = details.call if details.respond_to? :call
|
85
|
+
details = "\n#{details}".lines.join(' ') if details.lines.size > 1
|
86
|
+
say "#{task_id}: #{details}"
|
87
|
+
else
|
88
|
+
say task_id
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Show < RunnerCLI
|
95
|
+
desc 'sample <name>', 'Show detailed information about a code sample'
|
96
|
+
method_option :verbose, aliases: '-v', desc: 'Verbose: display more details'
|
97
|
+
method_option :cwd, desc: 'Working directory for detecting and running commands'
|
98
|
+
def sample(sample_name)
|
99
|
+
sample = runner.find_sample(sample_name)
|
100
|
+
say sample.to_s(options[:verbose])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'list', 'List known tasks or code samples'
|
105
|
+
subcommand 'list', List
|
106
|
+
desc 'show', 'Show details about a task or code sample'
|
107
|
+
subcommand 'show', Show
|
108
|
+
|
109
|
+
no_commands do
|
110
|
+
def show_sample(_sample_name)
|
111
|
+
end
|
59
112
|
end
|
60
113
|
end
|
61
114
|
end
|
62
115
|
end
|
116
|
+
|
117
|
+
# rubocop:enable Metrics/LineLength
|