psychic-runner 0.0.7 → 0.0.8
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.
- 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
|