sod 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ed0e633c091b67d809287f755ef22f95c8625bb62a381033d2460fcc674a0cd
4
- data.tar.gz: 0556220a0042ef1ee187c5b6ef042de2c948ed360350e6100cd4d4efcd47863f
3
+ metadata.gz: c23697cbcb0d37aa7c92b530d1952f535e8f8d338a1bfb1bc8a0f1279b589eb6
4
+ data.tar.gz: 2cbeba3bf1b3a47507735469537db88a8f9ea47fe98277a4802816d25eaf7163
5
5
  SHA512:
6
- metadata.gz: c6a68109cf04ecbc9c030061b04bc7dac9974464a3756b7be2ee3a6af792a7001078367d889e50f914572af940c255467969602308287bf4e8deff68939ec4b4
7
- data.tar.gz: 9f9e4015d492451a15b350bd5ee343c9e8976f067798ff0c0363f9e6c28785c69e683cb932a4bbc54006f570aa0996af522ca53af3dd650619aa7a951fcfa08f
6
+ metadata.gz: 003a046aacafec0865dd1b64b450b4fe3e4b1f6896fed015110f3df766a99f4c56fc5188fdd8c7fd1fdd94fb04cc8046b81fb67e2aeafaa6d311709cc488b7fb
7
+ data.tar.gz: d4c84e4ab0c83cfd4a537e8584c6f62ad6d5b5af737a94244b8222f1dd0a93afb6b340befe1da7d7c7ffc869c7593428c5dcf1306e4ca3ee3132e8edec69c056
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -3,7 +3,6 @@
3
3
  :figure-caption!:
4
4
 
5
5
  :cogger_link: link:https://alchemists.io/projects/cogger[Cogger]
6
- :dry_container_link: link:https://dry-rb.org/gems/dry-container[Dry Container]
7
6
  :etcher_link: link:https://alchemists.io/projects/etcher[Etcher]
8
7
  :gemsmith_link: link:https://alchemists.io/projects/gemsmith[Gemsmith]
9
8
  :git-lint_link: link:https://alchemists.io/projects/git-lint[Git Lint]
@@ -13,7 +12,6 @@
13
12
  :option_parser_link: link:https://rubyapi.org/o/s?q=OptionParser[Option Parser]
14
13
  :pennyworth_link: link:https://alchemists.io/projects/pennyworth[Pennyworth]
15
14
  :pragmater_link: link:https://alchemists.io/projects/pragmater[Pragmater]
16
- :rake_link: link:https://github.com/ruby/rake[Rake]
17
15
  :rubysmith_link: link:https://alchemists.io/projects/rubysmith[Rubysmith]
18
16
  :runcom_link: link:https://alchemists.io/projects/runcom[Runcom]
19
17
  :spek_link: link:https://alchemists.io/projects/spek[Spek]
@@ -43,11 +41,11 @@ toc::[]
43
41
 
44
42
  *DSL*
45
43
 
46
- image::https://alchemists.io/images/projects/sod/screenshots/dsl.png[A screenshot of the DSL syntax,width=597,height=512,role=focal_point]
44
+ image::https://alchemists.io/images/projects/sod/screenshots/dsl.png[A screenshot of the DSL syntax,width=539,height=479,role=focal_point]
47
45
 
48
46
  *Output*
49
47
 
50
- image::https://alchemists.io/images/projects/sod/screenshots/output.png[A screenshot of the generated help documentation,width=473,height=500,role=focal_point]
48
+ image::https://alchemists.io/images/projects/sod/screenshots/output.png[A screenshot of the generated help documentation,width=472,height=498,role=focal_point]
51
49
 
52
50
  == Requirements
53
51
 
@@ -122,8 +120,8 @@ Notice, with only a few extra lines of code, you can build upon the initial _bla
122
120
  cli = Sod.new :demo, banner: "Demo 0.0.0: A demonstration." do
123
121
  on Sod::Prefabs::Actions::Help, self
124
122
 
125
- on "generate", "Generate project templates."
126
- on "db", "Manage database."
123
+ on :generate, "Generate project templates."
124
+ on :db, "Manage database."
127
125
  end
128
126
 
129
127
  cli.call
@@ -208,11 +206,11 @@ You've already seen some of the DSL syntax, via the earlier examples, but now we
208
206
  [source,ruby]
209
207
  ----
210
208
  Sod.new :demo, banner: "Demo 0.0.0: A demonstration." do
211
- on "db", "Manage database." do
209
+ on :db, "Manage database." do
212
210
  on Start
213
211
  on Stop
214
212
 
215
- on "structure", "Manage database structure." do
213
+ on :structure, "Manage database structure." do
216
214
  on Dump
217
215
  end
218
216
  end
@@ -265,11 +263,11 @@ To further understand the DSL, commands, and actions you'll need to start with a
265
263
 
266
264
  ==== Actions
267
265
 
268
- Actions are the lowest building blocks of the DSL which allow you to quickly implement, test, reuse, and compose more complex architectures. They provide a nice wrapper around native {option_parser_link} functionality so if you are familiar with how `OptionParser#on` works, then you'll feel at home with actions.
266
+ Actions are the lowest building blocks of the DSL which allow you to quickly implement, test, reuse, and compose more complex architectures. They provide a nice layer atop native `OptionParser#on` functionality.
269
267
 
270
268
  There are two kinds of actions: custom and prefabricated. We'll start with custom actions and explore prefabricated actions later. Custom actions allow you to define your own functionality by inheriting from `Sod::Action` and leveraging the DSL that comes with it. Here's a high level breakdown of the macros you can use:
271
269
 
272
- * `description`: Optional (but strongly encouraged). Allows you to describe your action and appears within help documentation. If the description is not defined, then your action will be runnable while hidden from help documentation (this is similar to how {rake_link} task descriptions work).
270
+ * `description`: Optional (but strongly encouraged). Allows you to describe your action and appears within help documentation. If the description is not defined, then only your action's handle (i.e. aliases) will be shown.
273
271
  * `ancillary`: Optional. Allows you to provide supplemental text in addition to your description that might be helpful to know about when displaying help documentation. This can accept single or multiple arguments. Order matters since each argument will appear on a separate line in the order listed.
274
272
  * `on`: Required. Allows you to define the behavior of your action through keyword arguments. Otherwise, if not defined, the action will be ignored. This macro mimics {option_parser_link} `#on` behavior via the following positional and keyword arguments:
275
273
  ** `aliases`: Required. This is a positional argument and defines the short and long form aliases of your action. Your aliases can be a single string (i.e. `on "--version"`) or an array of short and long form aliases. For example, using `on %w[-v --version]` would allow you to use `-v` or `--version` from the command line to call your action. You can also use boolean aliases such as `--build` or `--[no-]build` which the option parser will supply to your `#call` method as a boolean value.
@@ -283,7 +281,7 @@ There are two kinds of actions: custom and prefabricated. We'll start with custo
283
281
  ** `default`: Optional. Allows you to supply a default value and is a handy for simple values which don't require lazy evaluation via the corresponding default macro. ⚠️ This is ignored if the corresponding macro is used so ensure you use one or the other but not both.
284
282
  ** `description`: Optional. Allows you to define a description. Handy for short descriptions that can fit on a single line. Otherwise, for longer descriptions, use the macro. ⚠️ This is ignored if the corresponding macro is used so ensure you use one or the other but not both.
285
283
  ** `ancillary`: Optional. Allows you to define ancillary text to supplement your description. It can accept a string or an array. Handy for short, supplementary, text that can fit on a single line. Otherwise, for more verbose details, use the macro. ⚠️ This is ignored if the corresponding macro is used so ensure you use one or the other but not both.
286
- * `default`: Optional. Uses a block, which is lazy evaluated, so you can define a default value. This is most helpful when used in combination with an _optional_ `argument` and/or `type` which can fallback to a safe default. This information shows up in the help text too. If your default value is a boolean then it will be color coded green for `true` and red for `false`.
284
+ * `default`: Optional. Uses a block, which is lazy evaluated, so you can define a default value. This is most helpful when used in combination with an _optional_ `argument` and/or `type` which can fallback to a safe default. This information shows up in the help text where the value will be rendered green text. In the case of booleans, they will be rendered as green for `true` and red for `false`.
287
285
 
288
286
  At a minimum, you want to define the `description` and `on` macros while implementing the `#call` message. Here's an example of implementing an action that echoes input as output:
289
287
 
@@ -451,53 +449,57 @@ Commands are a step up from actions in that they allow you to organize and group
451
449
 
452
450
  [source,ruby]
453
451
  ----
454
- options = {}
452
+ #! /usr/bin/env ruby
453
+ # frozen_string_literal: true
454
+
455
+ # Save as `snippet`, then `chmod 755 snippet`, and run as `./snippet`.
456
+
457
+ require "optparse"
458
+
459
+ input = {}
455
460
 
456
461
  # Command
457
- OptionParser.new do |parser|
462
+ parser = OptionParser.new do |instance|
458
463
  # Actions
459
- parser.on("--one", "One.") { |value| options[:one] = value }
460
- parser.on("--two", "Two.") { |value| options[:two] = value }
461
- parser.on("--three", "Three.") { |value| options[:three] = value }
464
+ instance.on("--[no-]one", "One.") { |value| input[:one] = value }
465
+ instance.on("--[no-]two", "Two.") { |value| input[:two] = value }
462
466
  end
467
+
468
+ parser.parse ["--one", "--no-two"]
469
+ puts input
470
+
471
+ # {:one=>true, :two=>false}
463
472
  ----
464
473
 
465
474
  The equivalent of the above, as provided by this gem, is:
466
475
 
467
476
  [source,ruby]
468
477
  ----
469
- require "dry/container"
470
- require "infusible"
471
- require "refinements/structs"
472
- require "sod"
478
+ #! /usr/bin/env ruby
479
+ # frozen_string_literal: true
473
480
 
474
- module Container
475
- extend Dry::Container::Mixin
481
+ # Save as `snippet`, then `chmod 755 snippet`, and run as `./snippet`.
476
482
 
477
- register(:input, memoize: true) { Hash.new }
478
- end
483
+ require "bundler/inline"
479
484
 
480
- Import = Infusible.with Container
485
+ gemfile true do
486
+ source "https://rubygems.org"
487
+ gem "sod", path: "~/Engineering/OSS/sod"
488
+ end
481
489
 
482
490
  class One < Sod::Action
483
- include Import[:input]
484
-
485
491
  on "--[no-]one", description: "One."
486
492
 
487
- def call(value) = input[:one] = value
493
+ def call(value) = context.input[:one] = value
488
494
  end
489
495
 
490
496
  class Two < Sod::Action
491
- include Import[:input]
492
-
493
497
  on "--[no-]two", description: "Two."
494
498
 
495
- def call(value) = input[:two] = value
499
+ def call(value) = context.input[:two] = value
496
500
  end
497
501
 
498
502
  class Demo < Sod::Command
499
- include Import[:input]
500
-
501
503
  handle "demo"
502
504
 
503
505
  description "A demonstration command."
@@ -505,11 +507,13 @@ class Demo < Sod::Command
505
507
  on One
506
508
  on Two
507
509
 
508
- def call = puts input
510
+ def call = puts context.input
509
511
  end
510
512
 
511
- cli = Sod.new :demo, banner: "Demo 0.0.0: A demonstration" do
512
- on Demo
513
+ context = Sod::Context[input: {}]
514
+
515
+ cli = Sod.new banner: "Demo 0.0.0: A demonstration" do
516
+ on(Demo, context:)
513
517
  on Sod::Prefabs::Actions::Help, self
514
518
  end
515
519
 
@@ -518,15 +522,13 @@ cli.call ["demo", "--one", "--no-two"]
518
522
  # {:one => true, :two => false}
519
523
  ----
520
524
 
521
- You might be thinking: "Hey, that's more lines of code!" True but -- more importantly -- you get the benefit of composible and reusable architectures -- because each command/action is encapsulated -- which you don't get with {option_parser_link}.
522
-
523
- By the way, the above example uses the {dry_container_link} gem for defining dependencies and the {infusible_link} gem for injecting those dependencies. You'll also notice that the `input` hash is memoized within the container to allow for mutation. The fact that you have to mutate input is a bummer and you should strive to avoid mutation whenever you can. In this case, mutation is necessary because the underlining architecture of the {option_parser_link} doesn't provide any other way to share state amongst your commands and actions. So this is one example of how you can do that.
525
+ You might be thinking: "Hey, that's more lines of code!" True but -- more importantly -- you get the benefit of composible and reusable architectures -- because each command/action is encapsulated -- which you don't get with {option_parser_link}. You'll also notice that the `input` hash is mutated. The fact that you have to mutate input is a bummer and you should strive to avoid mutation whenever you can. In this case, mutation is necessary because the underlining architecture of the {option_parser_link} doesn't provide any other way to share state amongst your commands and actions. So this is one example of how you can do that.
524
526
 
525
- You'll also notice, as mentioned with actions earlier, that commands share, roughly, the same DSL as actions with a few differences in terms of macros:
527
+ As mentioned earlier with actions, commands share a similar DSL with a few differences in terms of macros:
526
528
 
527
- * `handle`: Required. The name of your command or the _namespace_ for which you group multiple actions. Otherwise, if not defined, then your command won't be runnable.
528
- * `description`: Optional (but strongly recommended). Defines what your command is about and shows up in the help documentation. Otherwise, if not provided, your command's description will be blank.
529
- * `ancillary`: Optional. Allows you to provide supplemental text for your description that might be helpful to know about when displaying help documentation. This can accept single or multiple arguments. Order matters since each argument will appear on a separate line in the order listed.
529
+ * `handle`: Required. The name of your command or the _namespace_ for which you group multiple actions. Must be a string. Otherwise, if not defined, you'll get a `Sod::Error`.
530
+ * `description`: Optional (but strongly recommended). Defines what your command is about and shows up in the help documentation. Otherwise, if not provided, only your command's handle will be shown.
531
+ * `ancillary`: Optional. Allows you to provide supplemental text for your description. Can accept single or multiple arguments. Order matters since each argument will appear on a separate line in the order listed below your description.
530
532
  * `on`: Required. The syntax for this is identical to the CLI DSL where you define your action (constant) as the first positional argument followed by any number of positional and/or keyword arguments that you want to feed into your action when the `.new` method is called.
531
533
 
532
534
  If we reuse the above example and print the help documentation, you'll see the following output:
@@ -573,7 +575,7 @@ Inline commands provide a lightweight way to namespace your actions when you don
573
575
  [source,ruby]
574
576
  ----
575
577
  cli = Sod.new :demo, banner: "Demo 0.0.0: A demonstration" do
576
- on "demo", "A demonstration command." do
578
+ on :demo, "A demonstration command." do
577
579
  on One
578
580
  on Two
579
581
  end
@@ -587,7 +589,7 @@ Inline commands can have ancillary text by passing in additional arguments _afte
587
589
  [source,ruby]
588
590
  ----
589
591
  cli = Sod.new :demo, banner: "Demo 0.0.0: A demonstration" do
590
- on "demo", "A demonstration command.", "Some text.", "Some more text."
592
+ on :demo, "A demonstration command.", "Some text.", "Some more text."
591
593
  end
592
594
  ----
593
595
 
@@ -602,7 +604,7 @@ A _reusable_ command is what you saw earlier where you can subclass from `Sod::C
602
604
  [source,ruby]
603
605
  ----
604
606
  class Demo < Sod::Command
605
- handle "demo"
607
+ handle :demo
606
608
 
607
609
  description "A demonstration command."
608
610
 
@@ -664,7 +666,7 @@ context.defaults_path # "path/to/defaults.yml"
664
666
  context["my/path", :defaults_path] # "my/path"
665
667
  ----
666
668
 
667
- The override is handy for situations where you have a default value that you would prefer to use (i.e. first argument) but want to fallback to the `:defaults_path` if the override is `nil`. When you put all of this together, this means you can build a single context and use it within your commands and actions by injecting it:
669
+ The override is handy for situations where you have a value (first argument) that you would prefer to use while still being able to fallback to the `:defaults_path` if the override is `nil`. When you put all of this together, this means you can build a single context and use it within your commands and actions by injecting it:
668
670
 
669
671
  [source,ruby]
670
672
  ----
@@ -681,7 +683,7 @@ end
681
683
 
682
684
  ==== Types
683
685
 
684
- Types are a way to extend default {option_parser_link} functionality. Two types, not provided by {option_parser_link}, that are worth being aware of are:
686
+ Types are a way to extend default {option_parser_link} functionality. Two types -- not provided by {option_parser_link} -- worth being aware of are:
685
687
 
686
688
  **Pathname**
687
689
 
@@ -843,7 +845,7 @@ class Echo < Sod::Action
843
845
  end
844
846
 
845
847
  cli = Sod.new :demo, banner: "Demo 0.0.0: A demonstration." do
846
- on "db", "Manage database." do
848
+ on :db, "Manage database." do
847
849
  on Start
848
850
  on Stop
849
851
  end
@@ -925,6 +927,12 @@ You can also use the IRB console for direct access to all objects:
925
927
  bin/console
926
928
  ----
927
929
 
930
+ === Architecture
931
+
932
+ The architecture of this gem is built entirely around {option_parser_link} by using a graph of nodes (i.e. commands) which can be walked since each node within the graph may or may not have children (i.e. nesting).
933
+
934
+ image::https://alchemists.io/images/projects/sod/doc/architecture.svg[Architecture Diagram]
935
+
928
936
  == Tests
929
937
 
930
938
  To test, run:
data/lib/sod/action.rb CHANGED
@@ -8,9 +8,9 @@ module Sod
8
8
  class Action
9
9
  extend Forwardable
10
10
 
11
- def self.inherited base
11
+ def self.inherited subclass
12
12
  super
13
- base.class_eval { @attributes = {} }
13
+ subclass.class_eval { @attributes = {} }
14
14
  end
15
15
 
16
16
  def self.description text
@@ -42,11 +42,12 @@ module Sod
42
42
 
43
43
  @record = model[
44
44
  **klass.instance_variable_get(:@attributes),
45
- description: klass.instance_variable_get(:@description),
46
- ancillary: Array(klass.instance_variable_get(:@ancillary)).compact,
45
+ description: load(:description),
46
+ ancillary: Array(load(:ancillary)).compact,
47
47
  default: load_default
48
48
  ]
49
49
 
50
+ verify_aliases
50
51
  verify_argument
51
52
  end
52
53
 
@@ -68,12 +69,23 @@ module Sod
68
69
 
69
70
  private
70
71
 
72
+ def verify_aliases
73
+ fail Error, "Aliases must be defined." unless aliases
74
+ end
75
+
71
76
  def verify_argument
72
77
  return unless argument && !argument.start_with?("[") && default
73
78
 
74
79
  fail Error, "Required argument can't be used with default."
75
80
  end
76
81
 
82
+ def load attribute
83
+ klass = self.class
84
+ fallback = klass.instance_variable_get(:@attributes)[attribute]
85
+
86
+ klass.instance_variable_get("@#{attribute}") || fallback
87
+ end
88
+
77
89
  def load_default
78
90
  klass = self.class
79
91
  fallback = klass.instance_variable_get(:@attributes)[:default].method :itself
data/lib/sod/command.rb CHANGED
@@ -10,9 +10,9 @@ module Sod
10
10
 
11
11
  include Import[:logger]
12
12
 
13
- def self.inherited base
13
+ def self.inherited subclass
14
14
  super
15
- base.class_eval { @actions = Set.new }
15
+ subclass.class_eval { @actions = Set.new }
16
16
  end
17
17
 
18
18
  def self.handle text
@@ -35,16 +35,10 @@ module Sod
35
35
 
36
36
  def initialize(context: Context::EMPTY, model: Models::Command, **)
37
37
  super(**)
38
- klass = self.class
39
38
  @context = context
39
+ @record = build_record model
40
40
 
41
- @record = model[
42
- handle: klass.instance_variable_get(:@handle),
43
- description: klass.instance_variable_get(:@description),
44
- ancillary: Array(klass.instance_variable_get(:@ancillary)).compact,
45
- actions: Set[*build_actions],
46
- operation: method(:call)
47
- ]
41
+ verify_handle
48
42
  end
49
43
 
50
44
  def call
@@ -65,10 +59,26 @@ module Sod
65
59
 
66
60
  private
67
61
 
62
+ def build_record model
63
+ klass = self.class
64
+
65
+ model[
66
+ handle: klass.instance_variable_get(:@handle),
67
+ description: klass.instance_variable_get(:@description),
68
+ ancillary: Array(klass.instance_variable_get(:@ancillary)).compact,
69
+ actions: Set[*build_actions],
70
+ operation: method(:call)
71
+ ]
72
+ end
73
+
68
74
  def build_actions
69
75
  self.class.instance_variable_get(:@actions).map do |action, positionals, keywords|
70
76
  action.new(*positionals, **keywords.merge!(context:))
71
77
  end
72
78
  end
79
+
80
+ def verify_handle
81
+ fail Error, "Invalid handle: #{handle.inspect}. Must be a string." unless handle in String
82
+ end
73
83
  end
74
84
  end
data/lib/sod/context.rb CHANGED
@@ -11,11 +11,10 @@ module Sod
11
11
  @attributes = attributes
12
12
  end
13
13
 
14
- # :reek:ControlParameter
15
- def [] default, fallback
16
- default || public_send(fallback)
14
+ def [] override, fallback
15
+ override || public_send(fallback)
17
16
  rescue NoMethodError
18
- raise Error, "Invalid context. Default or fallback (#{fallback.inspect}) values are missing."
17
+ raise Error, "Invalid context. Override or fallback (#{fallback.inspect}) values are missing."
19
18
  end
20
19
 
21
20
  def to_h = attributes.dup
@@ -28,14 +28,12 @@ module Sod
28
28
 
29
29
  def get_child(*lineage, node: self) = lineage.empty? ? node : get(lineage, node, __method__)
30
30
 
31
- def on(object, *, **, &block)
31
+ def on(object, *, **, &)
32
32
  lineage.clear if depth.zero?
33
33
 
34
34
  process(object, *, **)
35
-
36
- increment
37
- instance_eval(&block) if block
38
- decrement
35
+ visit(&)
36
+ self
39
37
  end
40
38
 
41
39
  def call = (operation.call if operation)
@@ -46,8 +44,6 @@ module Sod
46
44
 
47
45
  attr_accessor :depth
48
46
 
49
- # :reek:TooManyStatements
50
- # rubocop:todo Metrics/AbcSize
51
47
  def process(object, *, **)
52
48
  ancestry = object.is_a?(Class) ? object.ancestors : []
53
49
 
@@ -61,7 +57,6 @@ module Sod
61
57
  fail Error, "Invalid command or action. Unable to add: #{object.inspect}."
62
58
  end
63
59
  end
64
- # rubocop:enable Metrics/AbcSize
65
60
 
66
61
  def add_inline_command handle, *positionals
67
62
  description, *ancillary = positionals
@@ -99,6 +94,12 @@ module Sod
99
94
  public_send(message, *lineage, node:)
100
95
  end
101
96
 
97
+ def visit &block
98
+ increment
99
+ instance_eval(&block) if block
100
+ decrement
101
+ end
102
+
102
103
  def increment = self.depth += 1
103
104
 
104
105
  def decrement = self.depth -= 1
@@ -16,7 +16,7 @@ module Sod
16
16
  using Refinements::Arrays
17
17
  using Refinements::Strings
18
18
 
19
- delegate Graph::Node.members => :node
19
+ delegate %i[handle description ancillary operation children] => :node
20
20
 
21
21
  attr_reader :actions
22
22
 
@@ -32,9 +32,9 @@ module Sod
32
32
  # rubocop:enable Metrics/ParameterLists
33
33
 
34
34
  def to_s
35
- [banner, "", *usage, "", *colored_actions, "", *colored_commands].tap(&:compact!)
36
- .join("\n")
37
- .strip
35
+ [banner, body, "", *usage, "", *colored_actions, "", *colored_commands].tap(&:compact!)
36
+ .join("\n")
37
+ .strip
38
38
  end
39
39
 
40
40
  private
@@ -43,6 +43,8 @@ module Sod
43
43
 
44
44
  def banner = color[description, :bold]
45
45
 
46
+ def body = ancillary.empty? ? nil : ancillary.join("\n").prepend("\n")
47
+
46
48
  def usage
47
49
  actions = " #{colored_handle} [OPTIONS]" unless all.empty?
48
50
  commands = " #{colored_handle} COMMAND [OPTIONS]" unless children.empty?
data/sod.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "sod"
5
- spec.version = "0.0.0"
5
+ spec.version = "0.1.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/sod"
9
- spec.summary = "A Domain Specific Language for creating composable Command Line Interfaces."
9
+ spec.summary = "A domain specific language for creating composable command line interfaces."
10
10
  spec.license = "Hippocratic-2.1"
11
11
 
12
12
  spec.metadata = {
data.tar.gz.sig CHANGED
@@ -1,4 +1,3 @@
1
- �ē�U����{�RAm���� \�oCO�%�~���}h�%J�p�g�}�o�ދ[_��N��� ��-ǩ2��&Y�'9���(�$�؍���vq�����"W���Ǽa��a`)p�.p0(z2���Gp)r5g��u�X���a����ć��LW
2
- ��F���o��c`��'���U�$�^�`cTe!P��
3
- ���z�����-R?�I%d{L62=�#}Pp��ʫ6sVѣ�H
4
- i�����7/v|
1
+ I�n�����M`U�sbÉn�aV����m�-ᭌ�bi ���1U ����%�8���Y���xmV�j���n��t �JQtx�gH��i��z*y�����~�iV٢�X�R4z o�.S��,z��3�w{
2
+ i���ȖR��a�J�Kjx��l�aA-�w �M�z�"t/B��H[�1Ę��F@O��
3
+ ^(�RF���~(x���X׳�r��|6�^).�r?�mO�\�xy�0�
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2023-06-15 00:00:00.000000000 Z
38
+ date: 2023-06-20 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: cogger
@@ -186,5 +186,5 @@ requirements: []
186
186
  rubygems_version: 3.4.14
187
187
  signing_key:
188
188
  specification_version: 4
189
- summary: A Domain Specific Language for creating composable Command Line Interfaces.
189
+ summary: A domain specific language for creating composable command line interfaces.
190
190
  test_files: []
metadata.gz.sig CHANGED
Binary file