Module: Wisco::Commands::List

Defined in:
lib/wisco/commands/list.rb

Constant Summary collapse

TREE_FORK =
'├── '
TREE_LAST =
'└── '
TREE_PIPE =
''
TREE_BLANK =
'    '
EXPANDABLE_KEYS =
%i[actions triggers object_definitions methods pick_lists].freeze
SORT_FIELDS =
%w[key title].freeze

Class Method Summary collapse

Class Method Details

.build_connector_hash(connector) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/wisco/commands/list.rb', line 116

def build_connector_hash(connector)
  # Full connector serialization with context-aware lambda handling
  data = serialize_value(connector, context: :root)

  # Post-process object_definitions: convert Hash to sorted array of keys
  if data.is_a?(Hash) && data['object_definitions'].is_a?(Hash)
    data['object_definitions'] = data['object_definitions'].keys.map(&:to_s).sort
  end

  data
end

.determine_context(key, parent_context) ⇒ Object



156
157
158
159
160
161
162
163
# File 'lib/wisco/commands/list.rb', line 156

def determine_context(key, parent_context)
  # When traversing into :methods or :pick_lists hashes, set context for param extraction
  case key
  when :methods then :methods
  when :pick_lists then :pick_lists
  else parent_context
  end
end

.humanise_key(key) ⇒ Object



173
174
175
# File 'lib/wisco/commands/list.rb', line 173

def humanise_key(key)
  key.to_s.split('_').map(&:capitalize).join(' ')
end

.render_children_tree(value, prefix) ⇒ Object



252
253
254
255
256
257
258
# File 'lib/wisco/commands/list.rb', line 252

def render_children_tree(value, prefix)
  child_keys = value.keys.sort
  child_keys.each_with_index do |ck, ci|
    cl = ci == child_keys.size - 1
    puts "#{prefix}#{cl ? TREE_LAST : TREE_FORK}#{ck}"
  end
end

.render_connection_tree(conn, prefix) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/wisco/commands/list.rb', line 230

def render_connection_tree(conn, prefix)
  keys = conn.keys
  keys.each_with_index do |key, idx|
    last = idx == keys.size - 1
    connector = last ? TREE_LAST : TREE_FORK
    child_prefix = prefix + (last ? TREE_BLANK : TREE_PIPE)
    value = conn[key]

    if value.is_a?(Hash)
      puts "#{prefix}#{connector}#{key}"
      sub_keys = value.keys
      sub_keys.each_with_index do |sk, si|
        sl = si == sub_keys.size - 1
        sc = sl ? TREE_LAST : TREE_FORK
        puts "#{child_prefix}#{sc}#{sk}"
      end
    else
      puts "#{prefix}#{connector}#{key} #{value_label(value)}"
    end
  end
end

.render_markdown_table(headers, rows) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/wisco/commands/list.rb', line 189

def render_markdown_table(headers, rows)
  all_rows = [headers] + rows
  widths = headers.length.times.map do |i|
    all_rows.map { |r| r[i].to_s.length }.max
  end

  fmt = widths.map { |w| "%-#{w}s" }.join(' | ')
  sep = widths.map { |w| '-' * w }.join('-|-')

  puts "| #{format(fmt, *headers)} |"
  puts "|-#{sep}-|"
  rows.each { |r| puts "| #{format(fmt, *r)} |" }
end

.run(subcommand, target, sort: nil, format: nil) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/wisco/commands/list.rb', line 15

def run(subcommand, target, sort: nil, format: nil)
  validate_sort!(sort)

  if format
    run_formatted(target, format: format)
    return
  end

  case subcommand
  when nil        then run_tree(target)
  when 'actions'  then run_actions(target, sort: sort)
  when 'triggers' then run_triggers(target, sort: sort)
  when 'all'      then run_all(target, sort: sort)
  else
    warn "Error: Unknown list subcommand '#{subcommand}'"
    warn "Run '#{Wisco::CLI_NAME} --help' for usage."
    exit 1
  end
end

.run_actions(target_dir, sort: nil) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/wisco/commands/list.rb', line 62

def run_actions(target_dir, sort: nil)
  connector = Wisco::Connector.load_connector_from_config(target_dir)
  actions = connector[:actions]

  if actions.nil? || actions.empty?
    puts 'No actions defined.'
    return
  end

  rows = actions.map { |key, item| [key, title_for(key, item), subtitle_for(item)] }
  rows = sort_rows(rows, sort)
  render_markdown_table(%w[Key Title Subtitle], rows)
end

.run_all(target_dir, sort: nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/wisco/commands/list.rb', line 90

def run_all(target_dir, sort: nil)
  puts '## Overview'
  run_tree(target_dir)
  puts
  puts '## Actions'
  run_actions(target_dir, sort: sort)
  puts
  puts '## Triggers'
  run_triggers(target_dir, sort: sort)
end

.run_formatted(target_dir, format:) ⇒ Object


Machine-readable output




105
106
107
108
109
110
111
112
113
114
# File 'lib/wisco/commands/list.rb', line 105

def run_formatted(target_dir, format:)
  require 'yaml' if format.downcase == 'yaml'
  connector = Wisco::Connector.load_connector_from_config(target_dir)
  data = build_connector_hash(connector)
  if format.downcase == 'yaml'
    puts data.to_yaml
  else
    puts JSON.pretty_generate(data)
  end
end

.run_tree(target_dir) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/wisco/commands/list.rb', line 35

def run_tree(target_dir)
  connector = Wisco::Connector.load_connector_from_config(target_dir)
  puts connector[:title]

  keys = connector.keys
  keys.each_with_index do |key, idx|
    last = idx == keys.size - 1
    connector_str = last ? TREE_LAST : TREE_FORK
    child_prefix = last ? TREE_BLANK : TREE_PIPE
    value = connector[key]

    if key == :connection && value.is_a?(Hash)
      puts "#{connector_str}#{key}"
      render_connection_tree(value, child_prefix)
    elsif EXPANDABLE_KEYS.include?(key) && value.is_a?(Hash) && !value.empty?
      puts "#{connector_str}#{key} [#{value.size}]"
      render_children_tree(value, child_prefix)
    elsif value.is_a?(Hash)
      puts "#{connector_str}#{key} [#{value.size}]"
    elsif value.is_a?(Array)
      puts "#{connector_str}#{key} [#{value.size}]"
    else
      puts "#{connector_str}#{key}"
    end
  end
end

.run_triggers(target_dir, sort: nil) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/wisco/commands/list.rb', line 76

def run_triggers(target_dir, sort: nil)
  connector = Wisco::Connector.load_connector_from_config(target_dir)
  triggers = connector[:triggers]

  if triggers.nil? || triggers.empty?
    puts 'No triggers defined.'
    return
  end

  rows = triggers.map { |key, item| [key, title_for(key, item), subtitle_for(item)] }
  rows = sort_rows(rows, sort)
  render_markdown_table(%w[Key Title Subtitle], rows)
end

.serialize_value(value, context: nil) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/wisco/commands/list.rb', line 128

def serialize_value(value, context: nil)
  case value
  when Proc
    case context
    when :methods, :pick_lists
      # Extract parameter info; format type as string
      {
        'parameters' => value.parameters.map { |type, name| [type.to_s, name.to_s] }
      }
    else
      # All other lambdas become "__is_lambda__" string
      '__is_lambda__'
    end
  when Hash
    # Recursively serialize each key-value pair, tracking context
    value.each_with_object({}) do |(k, v), h|
      next_context = determine_context(k, context)
      h[k.to_s] = serialize_value(v, context: next_context)
    end
  when Array
    value.map { |v| serialize_value(v, context: context) }
  when Symbol
    value.to_s
  else
    value
  end
end

.sort_rows(rows, sort) ⇒ Object



210
211
212
213
214
215
# File 'lib/wisco/commands/list.rb', line 210

def sort_rows(rows, sort)
  return rows if sort.nil?

  index = SORT_FIELDS.index(sort)
  rows.sort_by { |row| [row[index].to_s.downcase, row[0].to_s.downcase] }
end

.strip_html(str) ⇒ Object


List utilities




169
170
171
# File 'lib/wisco/commands/list.rb', line 169

def strip_html(str)
  str.to_s.gsub(/<[^>]+>/, '').squeeze(' ').strip
end

.subtitle_for(item) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/wisco/commands/list.rb', line 181

def subtitle_for(item)
  return '' unless item.is_a?(Hash)
  return item[:subtitle] if item[:subtitle]

  strip_html(item[:description]) if item[:description]
  item[:subtitle] || strip_html(item[:description].to_s)
end

.title_for(key, item) ⇒ Object



177
178
179
# File 'lib/wisco/commands/list.rb', line 177

def title_for(key, item)
  item.is_a?(Hash) && item[:title] ? item[:title] : humanise_key(key)
end

.validate_sort!(sort) ⇒ Object



203
204
205
206
207
208
# File 'lib/wisco/commands/list.rb', line 203

def validate_sort!(sort)
  return if sort.nil? || SORT_FIELDS.include?(sort)

  warn "Error: Unsupported sort field '#{sort}'. Valid values: #{SORT_FIELDS.join(', ')}."
  exit 1
end

.value_label(value) ⇒ Object


Tree rendering




221
222
223
224
225
226
227
228
# File 'lib/wisco/commands/list.rb', line 221

def value_label(value)
  case value
  when Hash  then "[#{value.size}]"
  when Array then "[#{value.size}]"
  when Proc  then '(lambda)'
  else            value.to_s
  end
end