flex-cartesian 0.1.5 → 0.1.7

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/lib/flex-cartesian.rb +38 -28
  4. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 365e591e60a0c174cbfec4f2b80cf1e6f2cd6e2c57b27be341fc16bf10a6ac98
4
- data.tar.gz: 86030f2e3c14e8bb2e9042bcf6b639211ab65a24095d158c15f002047d7d3c99
3
+ metadata.gz: '09eb5e5463d14e3ef3b2aca14d76a0ee5e4587cdfd56dcccbdb69f9b773d74ae'
4
+ data.tar.gz: d3d786db1474627718f501879509f4e3b09a3f3da11579333eee31ac6585fde3
5
5
  SHA512:
6
- metadata.gz: 69e18d211995c7f5f5325fe0146bcf580bcbee923444aa524ec8ac13e773264d8b3fe66f8dcaed84f2b29409c9b089b00d5f4a19f7f0b74fbf25f8ed3936ba16
7
- data.tar.gz: 2395bf3d93663c0d39ea8126498b68c8e02f805ee2183387071f278f1bf8bddf44822ac80ff41bce33e88732959ff9c79017ceeea69f19609b1818e2fdf86d3f
6
+ metadata.gz: 814eeb82c514a96016a17be9d07a6daf105e98898c1512926fd31b2dccc47dca95efbe681a1968ecd5b30bba1c8ab5d312a268dbcfacb0f75c0259075e669e8e
7
+ data.tar.gz: 51532619fa94674d70f1edf8a19083e43d951297e26203e3fc92553184cb8bec9165d41c33aa90e17c14828ed51c58e76684cc88f7b07696aa90032643ac275a
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.7 - 2025-07-07
4
+ ### Added
5
+ - Support for calculated functions on dimensiona via `add_function(name, &block)`
6
+ - Calculated functions now show up in `.output`
7
+
@@ -10,7 +10,6 @@ module FlexOutput
10
10
 
11
11
  values_list = members.zip(values.map { |v| v.inspect })
12
12
 
13
- # calculate widths, if align required
14
13
  widths = align ? values_list.map { |k, v| [k.to_s.size, v.size].max } : []
15
14
 
16
15
  line = values_list.each_with_index.map do |(_, val), i|
@@ -28,27 +27,39 @@ class FlexCartesian
28
27
 
29
28
  def initialize(dimensions = nil)
30
29
  @dimensions = dimensions
30
+ @derived = {}
31
+ end
32
+
33
+ def add_function(name, &block)
34
+ raise ArgumentError, "Block required" unless block_given?
35
+ @derived[name.to_sym] = block
31
36
  end
32
37
 
33
38
  def cartesian(dims = nil, lazy: false)
34
- dimensions = dims || @dimensions
35
- return nil unless dimensions.is_a?(Hash)
39
+ dimensions = dims || @dimensions
40
+ return nil unless dimensions.is_a?(Hash)
36
41
 
37
- names = dimensions.keys
38
- values = dimensions.values.map { |dim| dim.is_a?(Enumerable) ? dim.to_a : [dim] }
42
+ names = dimensions.keys
43
+ values = dimensions.values.map { |dim| dim.is_a?(Enumerable) ? dim.to_a : [dim] }
44
+
45
+ return to_enum(:cartesian, dims, lazy: lazy) unless block_given?
46
+ return if values.any?(&:empty?)
39
47
 
40
- return to_enum(:cartesian, dims, lazy: lazy) unless block_given?
41
- return if values.any?(&:empty?)
48
+ struct_class = Struct.new(*names).tap { |sc| sc.include(FlexOutput) }
42
49
 
43
- struct_class = Struct.new(*names).tap { |sc| sc.include(FlexOutput) }
50
+ base = values.first.product(*values[1..])
51
+ enum = lazy ? base.lazy : base
44
52
 
45
- base = values.first.product(*values[1..])
46
- enum = lazy ? base.lazy : base
53
+ enum.each do |combo|
54
+ struct_instance = struct_class.new(*combo)
47
55
 
48
- enum.each do |combo|
49
- yield struct_class.new(*combo)
56
+ @derived&.each do |name, block|
57
+ struct_instance.define_singleton_method(name) { block.call(struct_instance) }
50
58
  end
59
+
60
+ yield struct_instance
51
61
  end
62
+ end
52
63
 
53
64
  def size(dims = nil)
54
65
  dimensions = dims || @dimensions
@@ -79,7 +90,7 @@ class FlexCartesian
79
90
  end
80
91
  end
81
92
 
82
- def output(separator: " | ", colorize: false, align: false, format: :plain, limit: nil)
93
+ def output(separator: " | ", colorize: false, align: false, format: :plain, limit: nil)
83
94
  rows = []
84
95
  cartesian do |v|
85
96
  rows << v
@@ -87,14 +98,15 @@ def output(separator: " | ", colorize: false, align: false, format: :plain, limi
87
98
  end
88
99
  return if rows.empty?
89
100
 
90
- headers = rows.first.members.map(&:to_s)
101
+ headers = (
102
+ rows.first.members +
103
+ rows.first.singleton_methods(false).reject { |m| m.to_s.start_with?('__') }
104
+ ).map(&:to_s)
91
105
 
92
- # Get widths
93
106
  widths = align ? headers.to_h { |h|
94
- [h, [h.size, *rows.map { |r| fmt_cell(r[h], false).size }].max]
107
+ [h, [h.size, *rows.map { |r| fmt_cell(r.send(h), false).size }].max]
95
108
  } : {}
96
109
 
97
- # Title
98
110
  case format
99
111
  when :markdown
100
112
  puts "| " + headers.map { |h| h.ljust(widths[h] || h.size) }.join(" | ") + " |"
@@ -105,9 +117,8 @@ def output(separator: " | ", colorize: false, align: false, format: :plain, limi
105
117
  puts headers.map { |h| fmt_cell(h, colorize, widths[h]) }.join(separator)
106
118
  end
107
119
 
108
- # Rows
109
120
  rows.each do |row|
110
- line = headers.map { |h| fmt_cell(row[h], colorize, widths[h]) }
121
+ line = headers.map { |h| fmt_cell(row.send(h), colorize, widths[h]) }
111
122
  puts format == :csv ? line.join(",") : line.join(separator)
112
123
  end
113
124
  end
@@ -124,14 +135,13 @@ end
124
135
 
125
136
  private
126
137
 
127
- def fmt_cell(value, colorize, width = nil)
128
- str = case value
129
- when String then value # rows - without inspect
130
- else value.inspect # the rest is good to inspect
131
- end
132
- str = str.ljust(width) if width
133
- colorize ? str.colorize(:cyan) : str
134
- end
135
-
138
+ def fmt_cell(value, colorize, width = nil)
139
+ str = case value
140
+ when String then value
141
+ else value.inspect
142
+ end
143
+ str = str.ljust(width) if width
144
+ colorize ? str.colorize(:cyan) : str
145
+ end
136
146
  end
137
147
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flex-cartesian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yury Rassokhin
@@ -52,14 +52,16 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.0'
55
- description: Supports dimension-agnostic iterators, named dimensions, tabular output,
56
- lazy/eager evaluation, progress bar, JSON/YAML loading, and export to Markdown/CSV.
55
+ description: Supports calculated functions, dimension-agnostic iterators, named dimensions,
56
+ tabular output, lazy/eager evaluation, progress bar, JSON/YAML loading, and export
57
+ to Markdown/CSV.
57
58
  email:
58
59
  - yuri.rassokhin@gmail.com
59
60
  executables: []
60
61
  extensions: []
61
62
  extra_rdoc_files: []
62
63
  files:
64
+ - CHANGELOG.md
63
65
  - Gemfile
64
66
  - LICENSE
65
67
  - README.md