plumb 0.0.16 → 0.0.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13814b82e58449726341c0a26a398fee38818f852fe09f19ba7754a99b7c54ce
4
- data.tar.gz: 2205b2bc5f48b19b417afe8403cdbd7afbcac3689307b6ba69237ad094718815
3
+ metadata.gz: 24a6b9a58d29c5aa9e443586d0d529aaf79fcf91a5ee724366d9153174c73fa9
4
+ data.tar.gz: c6200d6bc762aecf985e359c5326c6014003950f998406dabbfaa9c7aca8fc10
5
5
  SHA512:
6
- metadata.gz: 604b2d74cf5a78578471d5e6cf523f956025ea95c2e9b17dec7337cca41de10dc2254bc66b69ea2255ee18059b885ef6bb5bd64ea32a34a763cf095168c80022
7
- data.tar.gz: 50e065d933d9c3a00ff04a0e3e2375997d43039fc8d5c3ba6c7c1a6dc9455bda9d056bfefb11e81b4c75f0a26c01919d7f18c5b0da6aefa33c1f668ddabbaa29
6
+ metadata.gz: d683a2a89fc717f406efcc16b884cafa10dafa148be86ffc1810a377b4f065e1e40e0d21719fe70752e67d5c4eef86843076fa9ffd1513a2d345f666b705577f
7
+ data.tar.gz: 5788b7b83dfb2c342a9c59f1080b30e3db93f9ff7b3c3f6eda0060021275ae648406559bb9bbee96fe204463a3715571e7e042401771e98c9836f5d5306a4087
data/README.md CHANGED
@@ -669,6 +669,40 @@ when Readable
669
669
  end
670
670
  ```
671
671
 
672
+ Or pattern matching
673
+
674
+ ```ruby
675
+ case args
676
+ in [Iterable => list, String => id]
677
+ # etc
678
+ in [Resolvable => r]
679
+ # etc
680
+ end
681
+ ```
682
+
683
+ #### Merging interfaces
684
+
685
+ Use the `+` operator to merge two interfaces into a new one that must support both sets of method names.
686
+
687
+ ```ruby
688
+ Iterable = Types::Interface[:each, :map]
689
+ Countable = Types::Interface[:size]
690
+ # This one expects objects with methods :each, :map and :size
691
+ CountableIterable = Iterable + Countable
692
+ ```
693
+
694
+ #### Intersecting interfaces
695
+
696
+ Use the `&` operator to produce a new interface with the intersection of method names
697
+
698
+ ```ruby
699
+ I1 = Types::Interface[:a, :b, :c]
700
+ I2 = Types::Interface[:b, :c, :d]
701
+ # This one expects methods :b and :c
702
+ I3 = Types::Interface[:b, :c]
703
+ ```
704
+
705
+
672
706
  TODO: make this a bit more advanced. Check for method arity.
673
707
 
674
708
  ### `Types::Hash`
@@ -28,6 +28,34 @@ module Plumb
28
28
 
29
29
  alias [] of
30
30
 
31
+ # Merge two interfaces into a new one with the method names of both
32
+ # @example
33
+ # i1 = Types::Interface[:foo]
34
+ # i2 = Types::Interface[:bar, :lol]
35
+ # i3 = i1 + i2 # expects objects with methods :foo, :bar, :lol
36
+ #
37
+ # @param other [InterfaceClass]
38
+ # @return [InterfaceClass]
39
+ def +(other)
40
+ raise ArgumentError, "expected another Types::Interface, but got #{other.inspect}" unless other.is_a?(self.class)
41
+
42
+ self.class.new((method_names + other.method_names).uniq)
43
+ end
44
+
45
+ # Produce a new Interface with the intersection of two interfaces
46
+ # @example
47
+ # i1 = Types::Interface[:foo, :bar]
48
+ # i2 = Types::Interface[:bar, :lol]
49
+ # i3 = i1 + i2 # expects objects with methods :bar
50
+ #
51
+ # @param other [InterfaceClass]
52
+ # @return [InterfaceClass]
53
+ def &(other)
54
+ raise ArgumentError, "expected another Types::Interface, but got #{other.inspect}" unless other.is_a?(self.class)
55
+
56
+ self.class.new(method_names & other.method_names)
57
+ end
58
+
31
59
  def call(result)
32
60
  obj = result.value
33
61
  missing_methods = @method_names.reject { |m| obj.respond_to?(m) }
data/lib/plumb/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plumb
4
- VERSION = '0.0.16'
4
+ VERSION = '0.0.17'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plumb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
@@ -53,7 +53,6 @@ files:
53
53
  - bench/compare_parametric_struct.rb
54
54
  - bench/parametric_schema.rb
55
55
  - bench/plumb_hash.rb
56
- - docs/styles.css
57
56
  - examples/command_objects.rb
58
57
  - examples/concurrent_downloads.rb
59
58
  - examples/csv_stream.rb
data/docs/styles.css DELETED
@@ -1,540 +0,0 @@
1
- /* Reset and Base Styles */
2
- * {
3
- margin: 0;
4
- padding: 0;
5
- box-sizing: border-box;
6
- }
7
-
8
- :root {
9
- --primary-color: #2563eb;
10
- --primary-dark: #1e40af;
11
- --secondary-color: #64748b;
12
- --bg-color: #f8fafc;
13
- --sidebar-bg: #1e293b;
14
- --sidebar-text: #cbd5e1;
15
- --sidebar-hover: #334155;
16
- --content-bg: #ffffff;
17
- --text-color: #1e293b;
18
- --text-light: #64748b;
19
- --border-color: #e2e8f0;
20
- --code-bg: #f1f5f9;
21
- --code-border: #cbd5e1;
22
- --shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
23
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
24
- }
25
-
26
- html {
27
- scroll-behavior: smooth;
28
- }
29
-
30
- body {
31
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
32
- line-height: 1.6;
33
- color: var(--text-color);
34
- background-color: var(--bg-color);
35
- padding-top: 60px;
36
- }
37
-
38
- /* Top Menu Bar */
39
- .top-menu {
40
- position: fixed;
41
- top: 0;
42
- left: 0;
43
- right: 0;
44
- height: 60px;
45
- background-color: var(--content-bg);
46
- border-bottom: 1px solid var(--border-color);
47
- box-shadow: var(--shadow);
48
- z-index: 1000;
49
- }
50
-
51
- .top-menu-content {
52
- max-width: 100%;
53
- height: 100%;
54
- padding: 0 2rem;
55
- display: flex;
56
- justify-content: space-between;
57
- align-items: center;
58
- }
59
-
60
- .top-menu-brand {
61
- display: flex;
62
- align-items: baseline;
63
- gap: 0.75rem;
64
- }
65
-
66
- .brand-name {
67
- font-size: 1.5rem;
68
- font-weight: 700;
69
- color: var(--text-color);
70
- }
71
-
72
- .brand-tagline {
73
- font-size: 0.875rem;
74
- color: var(--text-light);
75
- font-weight: 400;
76
- }
77
-
78
- .top-menu .github-link {
79
- display: flex;
80
- align-items: center;
81
- gap: 0.5rem;
82
- padding: 0.5rem 1rem;
83
- background-color: var(--text-color);
84
- color: #ffffff;
85
- border-radius: 6px;
86
- text-decoration: none;
87
- font-weight: 600;
88
- font-size: 0.875rem;
89
- transition: all 0.2s ease;
90
- }
91
-
92
- .top-menu .github-link:hover {
93
- background-color: #000000;
94
- text-decoration: none;
95
- }
96
-
97
- .top-menu .github-link svg {
98
- width: 20px;
99
- height: 20px;
100
- }
101
-
102
- /* Layout */
103
- .container {
104
- display: flex;
105
- min-height: calc(100vh - 60px);
106
- }
107
-
108
- /* Sidebar */
109
- .sidebar {
110
- width: 280px;
111
- background-color: var(--sidebar-bg);
112
- color: var(--sidebar-text);
113
- padding: 2rem 0;
114
- position: fixed;
115
- top: 60px;
116
- height: calc(100vh - 60px);
117
- overflow-y: auto;
118
- box-shadow: var(--shadow-lg);
119
- }
120
-
121
- .sidebar::-webkit-scrollbar {
122
- width: 8px;
123
- }
124
-
125
- .sidebar::-webkit-scrollbar-track {
126
- background: var(--sidebar-bg);
127
- }
128
-
129
- .sidebar::-webkit-scrollbar-thumb {
130
- background: var(--sidebar-hover);
131
- border-radius: 4px;
132
- }
133
-
134
- .logo {
135
- padding: 0 1.5rem 1.5rem;
136
- border-bottom: 1px solid var(--sidebar-hover);
137
- margin-bottom: 1.5rem;
138
- }
139
-
140
- .logo h2 {
141
- font-size: 1.75rem;
142
- color: #ffffff;
143
- margin-bottom: 0.25rem;
144
- font-weight: 700;
145
- }
146
-
147
- .logo .tagline {
148
- font-size: 0.875rem;
149
- color: var(--sidebar-text);
150
- font-weight: 400;
151
- }
152
-
153
- .nav-menu {
154
- list-style: none;
155
- padding-left: 0;
156
- }
157
-
158
- .nav-menu li {
159
- margin: 0;
160
- }
161
-
162
- .nav-menu a {
163
- display: block;
164
- padding: 0.625rem 1.5rem;
165
- color: var(--sidebar-text);
166
- text-decoration: none;
167
- transition: all 0.2s ease;
168
- font-size: 0.9375rem;
169
- }
170
-
171
- .nav-menu li:not(.nav-submenu) > a {
172
- font-weight: 600;
173
- margin-top: 0.5rem;
174
- }
175
-
176
- .nav-submenu a {
177
- padding-left: 2.5rem;
178
- font-size: 0.875rem;
179
- color: var(--sidebar-text);
180
- opacity: 0.9;
181
- }
182
-
183
- .nav-menu a:hover {
184
- background-color: var(--sidebar-hover);
185
- color: #ffffff;
186
- }
187
-
188
- .nav-menu a.active {
189
- background-color: var(--primary-color);
190
- color: #ffffff;
191
- border-left: 3px solid #ffffff;
192
- padding-left: calc(1.5rem - 3px);
193
- }
194
-
195
- .nav-submenu a.active {
196
- padding-left: calc(2.5rem - 3px);
197
- }
198
-
199
- /* Accordion Menus */
200
- .nav-accordion {
201
- position: relative;
202
- }
203
-
204
- .accordion-toggle {
205
- display: flex;
206
- justify-content: space-between;
207
- align-items: center;
208
- cursor: pointer;
209
- }
210
-
211
- .accordion-icon {
212
- font-size: 0.75rem;
213
- transition: transform 0.2s ease;
214
- margin-left: 0.5rem;
215
- }
216
-
217
- .nav-accordion.expanded .accordion-icon {
218
- transform: rotate(-180deg);
219
- }
220
-
221
- .accordion-content {
222
- list-style: none;
223
- padding-left: 0;
224
- max-height: 0;
225
- overflow: hidden;
226
- transition: max-height 0.3s ease;
227
- }
228
-
229
- .nav-accordion.expanded .accordion-content {
230
- max-height: 500px;
231
- }
232
-
233
- .nav-h4 a {
234
- padding-left: 3.5rem;
235
- font-size: 0.8125rem;
236
- color: var(--sidebar-text);
237
- opacity: 0.85;
238
- }
239
-
240
- .nav-h4 a.active {
241
- padding-left: calc(3.5rem - 3px);
242
- }
243
-
244
- /* Main Content */
245
- .content {
246
- flex: 1;
247
- margin-left: 280px;
248
- padding: 3rem;
249
- max-width: 1200px;
250
- width: 79vw;
251
- }
252
-
253
- /* Page Header */
254
- .page-header {
255
- margin-bottom: 3rem;
256
- padding-bottom: 2rem;
257
- border-bottom: 2px solid var(--border-color);
258
- }
259
-
260
- .page-header h1 {
261
- font-size: 3rem;
262
- font-weight: 800;
263
- color: var(--text-color);
264
- margin-bottom: 0.5rem;
265
- letter-spacing: -0.025em;
266
- }
267
-
268
- .page-header .subtitle {
269
- font-size: 1.25rem;
270
- color: var(--text-light);
271
- font-weight: 400;
272
- }
273
-
274
- /* Sections */
275
- .section {
276
- margin-bottom: 4rem;
277
- }
278
-
279
- .section h2 {
280
- font-size: 2rem;
281
- font-weight: 700;
282
- color: var(--text-color);
283
- margin-bottom: 1.5rem;
284
- padding-bottom: 0.5rem;
285
- border-bottom: 2px solid var(--primary-color);
286
- }
287
-
288
- .subsection {
289
- margin-bottom: 2.5rem;
290
- background-color: var(--content-bg);
291
- padding: 2rem;
292
- border-radius: 8px;
293
- box-shadow: var(--shadow);
294
- }
295
-
296
- .subsection h3 {
297
- font-size: 1.5rem;
298
- font-weight: 600;
299
- color: var(--text-color);
300
- margin-bottom: 1rem;
301
- }
302
-
303
- .subsection h4 {
304
- font-size: 1.25rem;
305
- font-weight: 600;
306
- color: var(--text-color);
307
- margin: 1.5rem 0 1rem;
308
- }
309
-
310
- /* Typography */
311
- p {
312
- margin-bottom: 1rem;
313
- line-height: 1.75;
314
- }
315
-
316
- a {
317
- color: var(--primary-color);
318
- text-decoration: none;
319
- }
320
-
321
- a:hover {
322
- color: var(--primary-dark);
323
- text-decoration: underline;
324
- }
325
-
326
- strong {
327
- font-weight: 600;
328
- color: var(--text-color);
329
- }
330
-
331
- /* Lists */
332
- ul, ol {
333
- margin-bottom: 1rem;
334
- padding-left: 1.5rem;
335
- }
336
-
337
- li {
338
- margin-bottom: 0.5rem;
339
- }
340
-
341
- .feature-list {
342
- list-style: none;
343
- padding-left: 0;
344
- }
345
-
346
- .feature-list li {
347
- padding-left: 1.5rem;
348
- position: relative;
349
- margin-bottom: 0.75rem;
350
- }
351
-
352
- .feature-list li::before {
353
- content: "→";
354
- position: absolute;
355
- left: 0;
356
- color: var(--primary-color);
357
- font-weight: bold;
358
- }
359
-
360
- /* Code Blocks */
361
- code {
362
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
363
- font-size: 0.875em;
364
- background-color: var(--code-bg);
365
- padding: 0.2em 0.4em;
366
- border-radius: 3px;
367
- border: 1px solid var(--code-border);
368
- }
369
-
370
- pre {
371
- margin: 1.5rem 0;
372
- padding: 0;
373
- overflow-x: auto;
374
- border-radius: 6px;
375
- box-shadow: var(--shadow);
376
- background-color: #282c34;
377
- }
378
-
379
- pre code {
380
- display: block;
381
- padding: 1.25rem;
382
- background-color: transparent;
383
- color: inherit;
384
- border: none;
385
- border-radius: 6px;
386
- line-height: 1.6;
387
- overflow-x: auto;
388
- }
389
-
390
- pre code::-webkit-scrollbar {
391
- height: 8px;
392
- }
393
-
394
- pre code::-webkit-scrollbar-track {
395
- background: var(--sidebar-hover);
396
- border-radius: 4px;
397
- }
398
-
399
- pre code::-webkit-scrollbar-thumb {
400
- background: var(--sidebar-text);
401
- border-radius: 4px;
402
- }
403
-
404
- /* Images */
405
- .image-container {
406
- margin: 2rem 0;
407
- text-align: center;
408
- }
409
-
410
- .image-container img {
411
- max-width: 100%;
412
- height: auto;
413
- }
414
-
415
- .image-container .caption {
416
- margin-top: 0.75rem;
417
- font-size: 0.875rem;
418
- color: var(--text-light);
419
- font-style: italic;
420
- }
421
-
422
- @media (max-width: 1248px) {
423
- .content p img {
424
- width: 64vw;
425
- height: auto;
426
- }
427
- }
428
-
429
- /* Responsive Design */
430
- @media (max-width: 1024px) {
431
- .sidebar {
432
- width: 240px;
433
- }
434
-
435
- .content {
436
- width: 76vw;
437
- margin-left: 240px;
438
- padding: 2rem;
439
- }
440
- }
441
-
442
- @media (max-width: 768px) {
443
- /* Stack sidebar and content vertically on handhelds */
444
- .container {
445
- flex-direction: column;
446
- }
447
- .top-menu-content {
448
- padding: 0 1rem;
449
- }
450
-
451
- .brand-tagline {
452
- display: none;
453
- }
454
-
455
- .top-menu .github-link span {
456
- display: none;
457
- }
458
-
459
- .top-menu .github-link {
460
- padding: 0.5rem;
461
- }
462
-
463
- .sidebar {
464
- display:none;
465
- }
466
-
467
- .content {
468
- margin-left: 0;
469
- width: 100vw;
470
- padding: 1.5rem;
471
- }
472
-
473
- .content p img {
474
- width: 78vw;
475
- height: auto;
476
- }
477
- .page-header h1 {
478
- font-size: 2rem;
479
- }
480
-
481
- .page-header .subtitle {
482
- font-size: 1rem;
483
- }
484
-
485
- .section h2 {
486
- font-size: 1.5rem;
487
- }
488
-
489
- .subsection {
490
- padding: 1.5rem;
491
- }
492
-
493
- .subsection h3 {
494
- font-size: 1.25rem;
495
- }
496
-
497
- pre code {
498
- padding: 1rem;
499
- font-size: 0.8125rem;
500
- }
501
- }
502
-
503
- /* Smooth Scrolling and Anchor Offset */
504
- section {
505
- scroll-margin-top: 5rem;
506
- }
507
-
508
- article {
509
- scroll-margin-top: 5rem;
510
- }
511
-
512
- /* Print Styles */
513
- @media print {
514
- .top-menu {
515
- display: none;
516
- }
517
-
518
- body {
519
- padding-top: 0;
520
- }
521
-
522
- .sidebar {
523
- display: none;
524
- }
525
-
526
- .content {
527
- margin-left: 0;
528
- max-width: 100%;
529
- }
530
-
531
- .subsection {
532
- box-shadow: none;
533
- border: 1px solid var(--border-color);
534
- }
535
-
536
- pre code {
537
- background-color: var(--code-bg);
538
- color: var(--text-color);
539
- }
540
- }