trailblazer-developer 0.0.10 → 0.0.11
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/README.md +1 -1
- data/lib/trailblazer/developer.rb +3 -0
- data/lib/trailblazer/developer/CHANGES.md +6 -0
- data/lib/trailblazer/developer/trace.rb +44 -26
- data/lib/trailblazer/developer/trace/focusable.rb +75 -0
- data/lib/trailblazer/developer/trace/inspector.rb +48 -0
- data/lib/trailblazer/developer/trace/present.rb +24 -22
- data/lib/trailblazer/developer/version.rb +1 -1
- data/lib/trailblazer/developer/wtf.rb +47 -72
- data/lib/trailblazer/developer/wtf/renderer.rb +78 -0
- data/trailblazer-developer.gemspec +1 -0
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bd9598d12d74fcd1dcbe20a50d53642ee2fe9ca8aad9648332630dee4b8fb7a
|
4
|
+
data.tar.gz: bc6b62c30541f118e756d72646da251cdbc2eef1d95dcb806c22aca10c1b64d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce2bc17462233a132411006e1bcb0d2b992e8e378faef8293d2be1d2916c691aba17def994644d7ae1428f65302d8d6496dc0fe583e484c036015415d9e4349e
|
7
|
+
data.tar.gz: f621040bab0043a71332f8a5ff325aae117612ba105116c527b57b4caacdeb52e067a2d8b5d5f6fadd5d290231fbb1c07ca1a036635d17d13a92d52c3e702629
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ _Developer tools for Trailblazers._
|
|
4
4
|
|
5
5
|
## Documentation
|
6
6
|
|
7
|
-
Find the complete documentation on the project website: [http://
|
7
|
+
Find the complete documentation on the project website: [http://2019.trailblazer.to/2.1/docs/developer.html]
|
8
8
|
|
9
9
|
## Summary
|
10
10
|
|
@@ -7,8 +7,11 @@ module Trailblazer
|
|
7
7
|
end
|
8
8
|
|
9
9
|
require "trailblazer/developer/wtf"
|
10
|
+
require "trailblazer/developer/wtf/renderer"
|
10
11
|
require "trailblazer/developer/trace"
|
11
12
|
require "trailblazer/developer/trace/present"
|
13
|
+
require "trailblazer/developer/trace/focusable"
|
14
|
+
require "trailblazer/developer/trace/inspector"
|
12
15
|
require "trailblazer/developer/generate"
|
13
16
|
require "trailblazer/developer/render/circuit"
|
14
17
|
require "trailblazer/developer/render/linear"
|
@@ -1,3 +1,9 @@
|
|
1
|
+
# 0.0.11
|
2
|
+
|
3
|
+
* Allow injecting custom data collector in Trace API, to collect custom input/output ctx of task nodes.
|
4
|
+
* Allow focusing on specfic steps and ctx variables in Dev.wtf?
|
5
|
+
* Allow custom inspection while tracing using Inspector definations
|
6
|
+
|
1
7
|
# 0.0.10
|
2
8
|
|
3
9
|
* Make Generate::Pipeline an activity for better customization/extendability.
|
@@ -17,16 +17,23 @@ module Trailblazer::Developer
|
|
17
17
|
|
18
18
|
alias_method :invoke, :call
|
19
19
|
|
20
|
-
def arguments_for_call(activity, (options,
|
21
|
-
|
20
|
+
def arguments_for_call(activity, (options, original_flow_options), **original_circuit_options)
|
21
|
+
default_flow_options = {
|
22
22
|
stack: Trace::Stack.new,
|
23
|
+
|
24
|
+
input_data_collector: Trace.method(:default_input_data_collector),
|
25
|
+
output_data_collector: Trace.method(:default_output_data_collector),
|
23
26
|
}
|
24
27
|
|
25
|
-
|
28
|
+
flow_options = { **default_flow_options, **Hash( original_flow_options ) }
|
29
|
+
|
30
|
+
default_circuit_options = {
|
26
31
|
wrap_runtime: ::Hash.new(Trace.merge_plan), # DISCUSS: this overrides existing {:wrap_runtime}.
|
27
32
|
}
|
28
33
|
|
29
|
-
|
34
|
+
circuit_options = { **original_circuit_options, **default_circuit_options }
|
35
|
+
|
36
|
+
return activity, [ options, flow_options ], circuit_options
|
30
37
|
end
|
31
38
|
end
|
32
39
|
|
@@ -42,38 +49,45 @@ module Trailblazer::Developer
|
|
42
49
|
)
|
43
50
|
end
|
44
51
|
|
52
|
+
# It's important to understand that {flow[:stack]} is mutated by design. This is needed so
|
53
|
+
# in case of exceptions we still have a "global" trace - unfortunately Ruby doesn't allow
|
54
|
+
# us a better way.
|
45
55
|
# taskWrap step to capture incoming arguments of a step.
|
46
|
-
def capture_args(wrap_config,
|
47
|
-
|
56
|
+
def capture_args(wrap_config, ((ctx, flow), circuit_options))
|
57
|
+
flow[:stack].indent!
|
48
58
|
|
49
|
-
|
59
|
+
flow[:stack] << Entity::Input.new(
|
60
|
+
wrap_config[:task],
|
61
|
+
circuit_options[:activity],
|
62
|
+
flow[:input_data_collector].call(wrap_config, [ctx, flow], circuit_options)
|
63
|
+
).freeze
|
64
|
+
|
65
|
+
return wrap_config, [[ctx, flow], circuit_options]
|
50
66
|
end
|
51
67
|
|
52
68
|
# taskWrap step to capture outgoing arguments from a step.
|
53
|
-
def capture_return(wrap_config,
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
69
|
+
def capture_return(wrap_config, ((ctx, flow), circuit_options))
|
70
|
+
flow[:stack] << Entity::Output.new(
|
71
|
+
wrap_config[:task],
|
72
|
+
{},
|
73
|
+
flow[:output_data_collector].call(wrap_config, [ctx, flow], circuit_options)
|
58
74
|
).freeze
|
59
75
|
|
60
|
-
|
76
|
+
flow[:stack].unindent!
|
61
77
|
|
62
|
-
|
63
|
-
return wrap_config, original_args
|
78
|
+
return wrap_config, [[ctx, flow], circuit_options]
|
64
79
|
end
|
65
80
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
flow[:stack].indent!
|
81
|
+
def default_input_data_collector(wrap_config, (ctx, _), circuit_options)
|
82
|
+
graph = Trailblazer::Activity::Introspect::Graph(circuit_options[:activity])
|
83
|
+
task = wrap_config[:task]
|
84
|
+
name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
|
71
85
|
|
72
|
-
|
73
|
-
|
74
|
-
).freeze
|
86
|
+
{ ctx: ctx, task_name: name }
|
87
|
+
end
|
75
88
|
|
76
|
-
|
89
|
+
def default_output_data_collector(wrap_config, (ctx, _), _)
|
90
|
+
{ ctx: ctx, signal: wrap_config[:return_signal] }
|
77
91
|
end
|
78
92
|
|
79
93
|
# Structures used in {capture_args} and {capture_return}.
|
@@ -115,6 +129,8 @@ module Trailblazer::Developer
|
|
115
129
|
|
116
130
|
# Mutable/stateful per design. We want a (global) stack!
|
117
131
|
class Stack
|
132
|
+
attr_reader :top
|
133
|
+
|
118
134
|
def initialize
|
119
135
|
@nested = Level.new
|
120
136
|
@stack = [ @nested ]
|
@@ -129,8 +145,10 @@ module Trailblazer::Developer
|
|
129
145
|
@stack.pop
|
130
146
|
end
|
131
147
|
|
132
|
-
def <<(
|
133
|
-
|
148
|
+
def <<(entity)
|
149
|
+
@top = entity
|
150
|
+
|
151
|
+
current << entity
|
134
152
|
end
|
135
153
|
|
136
154
|
def to_a
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'hirb'
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
module Developer
|
5
|
+
module Trace
|
6
|
+
|
7
|
+
module Focusable
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Get inspect of {focus_on.variables} or current {ctx}
|
11
|
+
def capture_variables_from(ctx, focus_on:, inspector: Trace::Inspector, **flow_options)
|
12
|
+
# ctx keys to be captured, for example [:current_user, :model, ....]
|
13
|
+
variables = (selected = focus_on[:variables]).any? ? selected : ctx.keys
|
14
|
+
|
15
|
+
variables.each_with_object({}) do |variable, result|
|
16
|
+
if variable.is_a?(Proc) # To allow deep key access from ctx
|
17
|
+
result[:Custom] = inspector.(variable.call(ctx), **flow_options)
|
18
|
+
else
|
19
|
+
result[variable] = inspector.(ctx[variable], **flow_options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Generate Hirb's vertical table nodes from captured ctx of each step
|
25
|
+
# |-- some step name
|
26
|
+
# | |-- ********** Input **********
|
27
|
+
# message: "WTF!"
|
28
|
+
# seq: []
|
29
|
+
# | `-- ********** Output **********
|
30
|
+
# message: "WTF!"
|
31
|
+
# seq: [:a]
|
32
|
+
def tree_nodes_for(level, input:, output:, **options)
|
33
|
+
input_output_nodes = { Input: input, Output: output }.compact.collect do |table_header, entity|
|
34
|
+
next unless Array( entity.data[:focused_variables] ).any?
|
35
|
+
|
36
|
+
table = vertical_table_for(entity.data[:focused_variables], table_header: table_header)
|
37
|
+
Present::TreeNodes::Node.new(level + 1, table, input, output, options).freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
input_output_nodes.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
# @private
|
44
|
+
def vertical_table_for(focused_variables, table_header:)
|
45
|
+
patched_vertical_table.render(
|
46
|
+
Array[ focused_variables ],
|
47
|
+
description: nil,
|
48
|
+
table_header: table_header, # Custom option, not from Hirb
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Overrding `Hirb::Helpers::VerticalTable#render_rows` because there is no option
|
53
|
+
# to customize vertical table's row header :(
|
54
|
+
# We need it to print if given entity is Input/Output
|
55
|
+
#
|
56
|
+
# @private
|
57
|
+
def patched_vertical_table
|
58
|
+
table = Class.new(Hirb::Helpers::VerticalTable)
|
59
|
+
|
60
|
+
table.send(:define_method, :render_rows) do
|
61
|
+
longest_header = Hirb::String.size (@headers.values.sort_by {|e| Hirb::String.size(e) }.last || '')
|
62
|
+
stars = "*" * [(longest_header + (longest_header / 2)), 3].max
|
63
|
+
|
64
|
+
@rows.map do |row|
|
65
|
+
"#{stars} #{@options[:table_header]} #{stars}\n" +
|
66
|
+
@fields.map{ |f| "#{Hirb::String.rjust(@headers[f], longest_header)}: #{row[f]}" }.join("\n")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
table
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Trailblazer
|
2
|
+
module Developer
|
3
|
+
module Trace
|
4
|
+
|
5
|
+
# This module does the inspection of given `ctx` with deep traversal.
|
6
|
+
# It only gets called when focusing is going on (i.e. focus_on API).
|
7
|
+
module Inspector
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def call(value, default_inspector: method(:default_inspector), **)
|
11
|
+
return hash_inspector(value, default_inspector: default_inspector) if value.is_a?(Hash)
|
12
|
+
return array_inspector(value, default_inspector: default_inspector) if value.is_a?(Array)
|
13
|
+
|
14
|
+
default_inspector.(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash_inspector(value, default_inspector:)
|
18
|
+
Hash[
|
19
|
+
value.collect do |key, nested_value|
|
20
|
+
[key, call(nested_value, default_inspector: default_inspector)]
|
21
|
+
end
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
def array_inspector(value, default_inspector:)
|
26
|
+
value.collect do |nested_value|
|
27
|
+
call(nested_value, default_inspector: default_inspector)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# To avoid additional query that AR::Relation#inspect makes,
|
32
|
+
# we're calling AR::Relation#to_sql to get plain SQL string instead.
|
33
|
+
def activerecord_relation_inspector(value)
|
34
|
+
{ query: value.to_sql }
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_inspector(value)
|
38
|
+
if defined?(ActiveRecord) && value.is_a?(ActiveRecord::Relation)
|
39
|
+
return activerecord_relation_inspector(value)
|
40
|
+
end
|
41
|
+
|
42
|
+
value.inspect
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,15 +1,12 @@
|
|
1
|
-
require '
|
1
|
+
require 'hirb'
|
2
2
|
|
3
3
|
module Trailblazer::Developer
|
4
4
|
module Trace
|
5
5
|
module Present
|
6
6
|
module_function
|
7
7
|
|
8
|
-
INDENTATION = " |".freeze
|
9
|
-
STEP_PREFIX = "-- ".freeze
|
10
|
-
|
11
8
|
def default_renderer(task_node:, **)
|
12
|
-
[ task_node
|
9
|
+
[ task_node.level, %{#{task_node.value}} ]
|
13
10
|
end
|
14
11
|
|
15
12
|
def call(stack, level: 1, tree: [], renderer: method(:default_renderer), **options)
|
@@ -23,29 +20,14 @@ module Trailblazer::Developer
|
|
23
20
|
renderer.(task_node: task_node, position: position, tree: tree)
|
24
21
|
end
|
25
22
|
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def render_tree_for(nodes)
|
30
|
-
nodes.map { |level, node|
|
31
|
-
indentation = INDENTATION * (level -1)
|
32
|
-
indentation = indentation[0...-1] + "`" if level == 1 || /End./.match(node) # start or end step
|
33
|
-
indentation + STEP_PREFIX + node
|
34
|
-
}.join("\n")
|
23
|
+
Hirb::Console.format_output(nodes, class: :tree, type: :directory, multi_line_nodes: true)
|
35
24
|
end
|
36
25
|
|
37
26
|
def tree_for(stack, level, tree:, **options)
|
38
27
|
stack.each do |lvl| # always a Stack::Task[input, ..., output]
|
39
28
|
input, output, nested = Trace::Level.input_output_nested_for_level(lvl)
|
40
29
|
|
41
|
-
|
42
|
-
|
43
|
-
graph = Trailblazer::Activity::Introspect::Graph(input.activity)
|
44
|
-
|
45
|
-
name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
|
46
|
-
name ||= task # FIXME: bullshit
|
47
|
-
|
48
|
-
tree << { level: level, input: input, output: output, name: name, **options }
|
30
|
+
tree.push(*TreeNodes.for(level, options.merge(input: input, output: output)))
|
49
31
|
|
50
32
|
if nested.any? # nesting
|
51
33
|
tree_for(nested, level + 1, options.merge(tree: tree))
|
@@ -54,6 +36,26 @@ module Trailblazer::Developer
|
|
54
36
|
tree
|
55
37
|
end
|
56
38
|
end
|
39
|
+
|
40
|
+
module TreeNodes
|
41
|
+
Node = Struct.new(:level, :value, :input, :output, :options) do
|
42
|
+
# Allow access to any custom key from options, eg. color_map
|
43
|
+
def method_missing(name, *)
|
44
|
+
options[name]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module_function
|
49
|
+
|
50
|
+
def for(level, input:, output:, **options)
|
51
|
+
nodes = Array[ Node.new(level, input.data[:task_name], input, output, options).freeze ]
|
52
|
+
|
53
|
+
focused_nodes = Trace::Focusable.tree_nodes_for(level, input: input, output: output, **options)
|
54
|
+
nodes += focused_nodes if focused_nodes.length > 0
|
55
|
+
|
56
|
+
nodes
|
57
|
+
end
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
@@ -12,95 +12,70 @@ module Trailblazer::Developer
|
|
12
12
|
module Wtf
|
13
13
|
module_function
|
14
14
|
|
15
|
-
COLOR_MAP = { pass: :green, fail: :brown }
|
16
|
-
|
17
|
-
SIGNALS_MAP = {
|
18
|
-
'Trailblazer::Activity::Right': :pass,
|
19
|
-
'Trailblazer::Activity::FastTrack::PassFast': :pass,
|
20
|
-
|
21
|
-
'Trailblazer::Activity::Left': :fail,
|
22
|
-
'Trailblazer::Activity::FastTrack::FailFast': :fail,
|
23
|
-
}
|
24
|
-
|
25
15
|
# Run {activity} with tracing enabled and inject a mutable {Stack} instance.
|
26
16
|
# This allows to display the trace even when an exception happened
|
27
|
-
def invoke(activity, (ctx, flow_options), *
|
28
|
-
|
29
|
-
|
30
|
-
# this instance gets mutated with every step. unfortunately, there is
|
31
|
-
# no other way in Ruby to keep the trace even when an exception was thrown.
|
32
|
-
stack = Trace::Stack.new
|
33
|
-
|
34
|
-
_returned_stack, *returned = Trace.invoke(
|
35
|
-
activity,
|
36
|
-
[
|
37
|
-
ctx,
|
38
|
-
flow_options.merge(stack: stack)
|
39
|
-
],
|
40
|
-
*args
|
17
|
+
def invoke(activity, (ctx, flow_options), *circuit_options)
|
18
|
+
activity, (ctx, flow_options), circuit_options = Wtf.arguments_for_trace(
|
19
|
+
activity, [ctx, flow_options], *circuit_options
|
41
20
|
)
|
42
21
|
|
43
|
-
|
22
|
+
_returned_stack, signal, (ctx, flow_options) = Trace.invoke(
|
23
|
+
activity, [ctx, flow_options], *circuit_options
|
24
|
+
)
|
25
|
+
|
26
|
+
return signal, [ctx, flow_options], circuit_options
|
44
27
|
ensure
|
45
28
|
puts Trace::Present.(
|
46
|
-
stack,
|
47
|
-
renderer:
|
48
|
-
color_map:
|
29
|
+
flow_options[:stack],
|
30
|
+
renderer: Wtf::Renderer,
|
31
|
+
color_map: Wtf::Renderer::DEFAULT_COLOR_MAP.merge( flow_options[:color_map] || {} ),
|
49
32
|
)
|
50
33
|
end
|
51
34
|
|
52
|
-
def
|
53
|
-
|
35
|
+
def arguments_for_trace(activity, (ctx, original_flow_options), **circuit_options)
|
36
|
+
default_flow_options = {
|
37
|
+
# this instance gets mutated with every step. unfortunately, there is
|
38
|
+
# no other way in Ruby to keep the trace even when an exception was thrown.
|
39
|
+
stack: Trace::Stack.new,
|
54
40
|
|
55
|
-
|
56
|
-
|
57
|
-
|
41
|
+
input_data_collector: method(:trace_input_data_collector),
|
42
|
+
output_data_collector: method(:trace_output_data_collector),
|
43
|
+
}
|
58
44
|
|
59
|
-
|
60
|
-
|
61
|
-
end
|
45
|
+
# Merge default options with flow_options as an order of precedence
|
46
|
+
flow_options = { **default_flow_options, **Hash( original_flow_options ) }
|
62
47
|
|
63
|
-
|
64
|
-
|
48
|
+
# Normalize `focus_on` param to
|
49
|
+
# 1. Wrap step and variable names into an array if not already
|
50
|
+
flow_options[:focus_on] = {
|
51
|
+
steps: Array( flow_options.dig(:focus_on, :steps) ),
|
52
|
+
variables: Array( flow_options.dig(:focus_on, :variables) ),
|
53
|
+
}
|
65
54
|
|
66
|
-
|
67
|
-
return line unless style
|
68
|
-
String.send(style, line)
|
55
|
+
return activity, [ ctx, flow_options ], circuit_options
|
69
56
|
end
|
70
57
|
|
71
|
-
|
72
|
-
|
73
|
-
|
58
|
+
# Overring default input and output data collectors to collect/capture
|
59
|
+
# 1. inspect of focusable variables for given focusable step
|
60
|
+
def trace_input_data_collector(wrap_config, (ctx, flow_options), circuit_options)
|
61
|
+
data = Trace.default_input_data_collector(wrap_config, [ctx, flow_options], circuit_options)
|
62
|
+
|
63
|
+
if flow_options[:focus_on][:steps].include?(data[:task_name])
|
64
|
+
data[:focused_variables] = Trace::Focusable.capture_variables_from(ctx, **flow_options)
|
65
|
+
end
|
66
|
+
|
67
|
+
data
|
74
68
|
end
|
75
69
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
def blue(str); "\e[34m#{str}\e[0m" end
|
86
|
-
def magenta(str); "\e[35m#{str}\e[0m" end
|
87
|
-
def cyan(str); "\e[36m#{str}\e[0m" end
|
88
|
-
def gray(str); "\e[37m#{str}\e[0m" end
|
89
|
-
|
90
|
-
def bg_black(str); "\e[40m#{str}\e[0m" end
|
91
|
-
def bg_red(str); "\e[41m#{str}\e[0m" end
|
92
|
-
def bg_green(str); "\e[42m#{str}\e[0m" end
|
93
|
-
def bg_brown(str); "\e[43m#{str}\e[0m" end
|
94
|
-
def bg_blue(str); "\e[44m#{str}\e[0m" end
|
95
|
-
def bg_magenta(str); "\e[45m#{str}\e[0m" end
|
96
|
-
def bg_cyan(str); "\e[46m#{str}\e[0m" end
|
97
|
-
def bg_gray(str); "\e[47m#{str}\e[0m" end
|
98
|
-
|
99
|
-
def bold(str); "\e[1m#{str}\e[22m" end
|
100
|
-
def italic(str); "\e[3m#{str}\e[23m" end
|
101
|
-
def underline(str); "\e[4m#{str}\e[24m" end
|
102
|
-
def blink(str); "\e[5m#{str}\e[25m" end
|
103
|
-
def reverse_color(str); "\e[7m#{str}\e[27m" end
|
70
|
+
def trace_output_data_collector(wrap_config, (ctx, flow_options), circuit_options)
|
71
|
+
data = Trace.default_output_data_collector(wrap_config, [ctx, flow_options], circuit_options)
|
72
|
+
|
73
|
+
input = flow_options[:stack].top
|
74
|
+
if flow_options[:focus_on][:steps].include?(input.data[:task_name])
|
75
|
+
data[:focused_variables] = Trace::Focusable.capture_variables_from(ctx, **flow_options)
|
76
|
+
end
|
77
|
+
|
78
|
+
data
|
104
79
|
end
|
105
80
|
end
|
106
81
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Trailblazer::Developer
|
2
|
+
module Wtf
|
3
|
+
|
4
|
+
module Renderer
|
5
|
+
DEFAULT_COLOR_MAP = { pass: :green, fail: :brown }
|
6
|
+
|
7
|
+
SIGNALS_MAP = {
|
8
|
+
:'Trailblazer::Activity::Right' => :pass,
|
9
|
+
:'Trailblazer::Activity::FastTrack::PassFast' => :pass,
|
10
|
+
|
11
|
+
:'Trailblazer::Activity::Left' => :fail,
|
12
|
+
:'Trailblazer::Activity::FastTrack::FailFast' => :fail,
|
13
|
+
}
|
14
|
+
|
15
|
+
module_function
|
16
|
+
|
17
|
+
# tree: Array of Trace::TreeNodes::Node
|
18
|
+
# task_node - current Trace::TreeNodes::Node to render
|
19
|
+
# position - task_node's position in tree
|
20
|
+
def call(tree:, task_node:, position:)
|
21
|
+
value = value_for(tree, task_node, position)
|
22
|
+
[task_node.level, value]
|
23
|
+
end
|
24
|
+
|
25
|
+
def value_for(tree, task_node, position)
|
26
|
+
if task_node.output.nil? && tree[position.next].nil? # i.e. when exception raised
|
27
|
+
return %{#{fmt(fmt(task_node.value, :red), :bold)}}
|
28
|
+
end
|
29
|
+
|
30
|
+
if task_node.output.nil? # i.e. on entry/exit point of activity
|
31
|
+
return %{#{task_node.value}}
|
32
|
+
end
|
33
|
+
|
34
|
+
%{#{fmt(task_node.value, task_node.color_map[ signal_of(task_node) ])}}
|
35
|
+
end
|
36
|
+
|
37
|
+
def fmt(line, style)
|
38
|
+
return line unless style
|
39
|
+
String.send(style, line)
|
40
|
+
end
|
41
|
+
|
42
|
+
def signal_of(task_node)
|
43
|
+
entity_signal = task_node.output.data[:signal]
|
44
|
+
entity_klass = entity_signal.is_a?(Class) ? entity_signal : entity_signal.class
|
45
|
+
|
46
|
+
SIGNALS_MAP[entity_klass.name.to_sym]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Stolen from https://stackoverflow.com/questions/1489183/colorized-ruby-output
|
50
|
+
#
|
51
|
+
# TODO: this is just prototyping
|
52
|
+
module String
|
53
|
+
module_function
|
54
|
+
def black(str); "\e[30m#{str}\e[0m" end
|
55
|
+
def red(str); "\e[31m#{str}\e[0m" end
|
56
|
+
def green(str); "\e[32m#{str}\e[0m" end
|
57
|
+
def brown(str); "\e[33m#{str}\e[0m" end
|
58
|
+
def blue(str); "\e[34m#{str}\e[0m" end
|
59
|
+
def magenta(str); "\e[35m#{str}\e[0m" end
|
60
|
+
def cyan(str); "\e[36m#{str}\e[0m" end
|
61
|
+
def gray(str); "\e[37m#{str}\e[0m" end
|
62
|
+
|
63
|
+
def bg_black(str); "\e[40m#{str}\e[0m" end
|
64
|
+
def bg_red(str); "\e[41m#{str}\e[0m" end
|
65
|
+
def bg_green(str); "\e[42m#{str}\e[0m" end
|
66
|
+
def bg_brown(str); "\e[43m#{str}\e[0m" end
|
67
|
+
def bg_blue(str); "\e[44m#{str}\e[0m" end
|
68
|
+
def bg_magenta(str); "\e[45m#{str}\e[0m" end
|
69
|
+
def bg_cyan(str); "\e[46m#{str}\e[0m" end
|
70
|
+
def bg_gray(str); "\e[47m#{str}\e[0m" end
|
71
|
+
|
72
|
+
def bold(str); "\e[1m#{str}\e[22m" end
|
73
|
+
def italic(str); "\e[3m#{str}\e[23m" end
|
74
|
+
def underline(str); "\e[4m#{str}\e[24m" end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-developer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -128,6 +128,20 @@ dependencies:
|
|
128
128
|
- - ">="
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: hirb
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :runtime
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
131
145
|
description: 'Developer tools for Trailblazer: debugger, tracing, visual editor integration.'
|
132
146
|
email:
|
133
147
|
- apotonick@gmail.com
|
@@ -152,9 +166,12 @@ files:
|
|
152
166
|
- lib/trailblazer/developer/render/circuit.rb
|
153
167
|
- lib/trailblazer/developer/render/linear.rb
|
154
168
|
- lib/trailblazer/developer/trace.rb
|
169
|
+
- lib/trailblazer/developer/trace/focusable.rb
|
170
|
+
- lib/trailblazer/developer/trace/inspector.rb
|
155
171
|
- lib/trailblazer/developer/trace/present.rb
|
156
172
|
- lib/trailblazer/developer/version.rb
|
157
173
|
- lib/trailblazer/developer/wtf.rb
|
174
|
+
- lib/trailblazer/developer/wtf/renderer.rb
|
158
175
|
- lib/trailblazer/diagram/bpmn.rb
|
159
176
|
- trailblazer-developer.gemspec
|
160
177
|
homepage: http://trailblazer.to
|
@@ -176,8 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
193
|
- !ruby/object:Gem::Version
|
177
194
|
version: '0'
|
178
195
|
requirements: []
|
179
|
-
|
180
|
-
rubygems_version: 2.7.3
|
196
|
+
rubygems_version: 3.0.6
|
181
197
|
signing_key:
|
182
198
|
specification_version: 4
|
183
199
|
summary: Developer tools for Trailblazer.
|