samovar 1.10.0 → 2.0.0

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.
@@ -18,90 +18,16 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require_relative 'flags'
21
+ require_relative 'option'
22
22
 
23
23
  module Samovar
24
- class Option
25
- def initialize(flags, description, key: nil, default: nil, value: nil, type: nil, &block)
26
- @flags = Flags.new(flags)
27
- @description = description
28
-
29
- if key
30
- @key = key
31
- else
32
- @key = @flags.first.key
33
- end
34
-
35
- @default = default
36
-
37
- # If the value is given, it overrides the user specified input.
38
- @value = value
39
- @value ||= true if @flags.boolean?
40
-
41
- @type = type
42
- @block = block
43
- end
44
-
45
- attr :flags
46
- attr :description
47
- attr :type
48
-
49
- attr :default
50
-
51
- attr :key
52
-
53
- def coerce_type(result)
54
- if @type == Integer
55
- Integer(result)
56
- elsif @type == Float
57
- Float(result)
58
- elsif @type == Symbol
59
- result.to_sym
60
- elsif @type.respond_to? :call
61
- @type.call(result)
62
- elsif @type.respond_to? :new
63
- @type.new(result)
64
- end
65
- end
66
-
67
- def coerce(result)
68
- if @type
69
- result = coerce_type(result)
70
- end
71
-
72
- if @block
73
- result = @block.call(result)
74
- end
75
-
76
- return result
77
- end
78
-
79
- def parse(input, default = @default)
80
- if result = @flags.parse(input)
81
- @value.nil? ? coerce(result) : @value
82
- end || default
83
- end
84
-
85
- def to_s
86
- @flags
87
- end
88
-
89
- def to_a
90
- unless @default.nil?
91
- [@flags, @description, "Default: #{@default}"]
92
- else
93
- [@flags, @description]
94
- end
95
- end
96
- end
97
-
98
24
  class Options
99
25
  def self.parse(*args, **options, &block)
100
26
  options = self.new(*args, **options)
101
27
 
102
28
  options.instance_eval(&block) if block_given?
103
29
 
104
- return options
30
+ return options.freeze
105
31
  end
106
32
 
107
33
  def initialize(title = "Options", key: :options)
@@ -116,13 +42,50 @@ module Samovar
116
42
  @defaults = {}
117
43
  end
118
44
 
45
+ def initialize_dup(source)
46
+ super
47
+
48
+ @ordered = @ordered.dup
49
+ @keyed = @keyed.dup
50
+ @defaults = @defaults.dup
51
+ end
52
+
53
+ attr :title
54
+ attr :ordered
55
+
119
56
  attr :key
120
57
  attr :defaults
121
58
 
59
+ def freeze
60
+ return self if frozen?
61
+
62
+ @ordered.freeze
63
+ @keyed.freeze
64
+ @defaults.freeze
65
+
66
+ @ordered.each(&:freeze)
67
+
68
+ super
69
+ end
70
+
71
+ def each(&block)
72
+ @ordered.each(&block)
73
+ end
74
+
75
+ def empty?
76
+ @ordered.empty?
77
+ end
78
+
122
79
  def option(*args, **options, &block)
123
80
  self << Option.new(*args, **options, &block)
124
81
  end
125
82
 
83
+ def merge!(options)
84
+ options.each do |option|
85
+ self << option
86
+ end
87
+ end
88
+
126
89
  def << option
127
90
  @ordered << option
128
91
  option.flags.each do |flag|
@@ -138,7 +101,7 @@ module Samovar
138
101
  end
139
102
  end
140
103
 
141
- def parse(input, default)
104
+ def parse(input, parent = nil, default = nil)
142
105
  values = (default || @defaults).dup
143
106
 
144
107
  while option = @keyed[input.first]
@@ -18,154 +18,4 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'mapping/model'
22
-
23
- require 'event/terminal'
24
-
25
- module Samovar
26
- module Output
27
- class Header
28
- def initialize(name, object)
29
- @name = name
30
- @object = object
31
- end
32
-
33
- attr :name
34
- attr :object
35
-
36
- def align(columns)
37
- @object.command_line(@name)
38
- end
39
- end
40
-
41
- class Row < Array
42
- def initialize(object)
43
- @object = object
44
- super object.to_a.collect(&:to_s)
45
- end
46
-
47
- attr :object
48
-
49
- def align(columns)
50
- self.collect.with_index do |value, index|
51
- value.ljust(columns.widths[index])
52
- end.join(' ')
53
- end
54
- end
55
-
56
- class Columns
57
- def initialize(rows)
58
- @rows = rows
59
- @widths = calculate_widths(rows)
60
- end
61
-
62
- attr :widths
63
-
64
- def calculate_widths(rows)
65
- widths = []
66
-
67
- rows.each do |row|
68
- row.each.with_index do |column, index|
69
- (widths[index] ||= []) << column.size
70
- end
71
- end
72
-
73
- return widths.collect(&:max)
74
- end
75
- end
76
-
77
- class Rows
78
- include Enumerable
79
-
80
- def initialize(level = 0)
81
- @level = level
82
- @rows = []
83
- end
84
-
85
- attr :level
86
-
87
- def empty?
88
- @rows.empty?
89
- end
90
-
91
- def first
92
- @rows.first
93
- end
94
-
95
- def last
96
- @rows.last
97
- end
98
-
99
- def indentation
100
- @indentation ||= "\t" * @level
101
- end
102
-
103
- def each(ignore_nested: false, &block)
104
- return to_enum(:each, ignore_nested: ignore_nested) unless block_given?
105
-
106
- @rows.each do |row|
107
- if row.is_a?(self.class)
108
- row.each(&block) unless ignore_nested
109
- else
110
- yield row, self
111
- end
112
- end
113
- end
114
-
115
- def << object
116
- @rows << Row.new(object)
117
-
118
- return self
119
- end
120
-
121
- def columns
122
- @columns ||= Columns.new(@rows.select{|row| row.is_a? Array})
123
- end
124
-
125
- def nested(*args)
126
- @rows << Header.new(*args)
127
-
128
- nested_rows = self.class.new(@level + 1)
129
-
130
- yield nested_rows
131
-
132
- @rows << nested_rows
133
- end
134
- end
135
-
136
- class DetailedFormatter < Mapping::Model
137
- def self.print(rows, output)
138
- self.new(rows, output).print
139
- end
140
-
141
- def initialize(rows, output)
142
- @rows = rows
143
- @output = output
144
- @width = 80
145
-
146
- @terminal = Event::Terminal.for(@output)
147
- @terminal[:header] = @terminal.style(:blue, nil, :bright)
148
- @terminal[:description] = @terminal.style(:blue)
149
- end
150
-
151
- map(Header) do |header, rows|
152
- @terminal.puts unless header == @rows.first
153
- @terminal.puts "#{rows.indentation}#{header.object.command_line(header.name)}", style: :header
154
- @terminal.puts "#{rows.indentation}\t#{header.object.description}", style: :description
155
- @terminal.puts
156
- end
157
-
158
- map(Row) do |row, rows|
159
- @terminal.puts "#{rows.indentation}#{row.align(rows.columns)}"
160
- end
161
-
162
- map(Rows) do |items|
163
- items.collect{|row, rows| map(row, rows)}
164
- end
165
-
166
- def print
167
- map(@rows)
168
- end
169
- end
170
- end
171
- end
21
+ require_relative 'output/usage_formatter'
@@ -18,22 +18,27 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'time'
22
-
23
- require_relative 'terminal'
24
-
25
21
  module Samovar
26
- class Command
27
- def track_time
28
- start_time = Time.now
22
+ module Output
23
+ class Columns
24
+ def initialize(rows)
25
+ @rows = rows
26
+ @widths = calculate_widths(rows)
27
+ end
29
28
 
30
- yield
31
- ensure
32
- end_time = Time.now
33
- elapsed_time = end_time - start_time
29
+ attr :widths
34
30
 
35
- $stdout.flush
36
- terminal.puts("Elapsed Time: %0.3fs" % elapsed_time, style: :summary)
31
+ def calculate_widths(rows)
32
+ widths = []
33
+
34
+ rows.each do |row|
35
+ row.each.with_index do |column, index|
36
+ (widths[index] ||= []) << column.size
37
+ end
38
+ end
39
+
40
+ return widths.collect(&:max)
41
+ end
37
42
  end
38
43
  end
39
44
  end
@@ -18,14 +18,19 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'time'
22
-
23
21
  module Samovar
24
- class Command
25
- def terminal(output = $stderr)
26
- Event::Terminal.for(output).tap do |terminal|
27
- terminal[:command] = terminal.style(:blue)
28
- terminal[:summary] = terminal.style(:magenta)
22
+ module Output
23
+ class Header
24
+ def initialize(name, object)
25
+ @name = name
26
+ @object = object
27
+ end
28
+
29
+ attr :name
30
+ attr :object
31
+
32
+ def align(columns)
33
+ @object.command_line(@name)
29
34
  end
30
35
  end
31
36
  end
@@ -0,0 +1,38 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Samovar
22
+ module Output
23
+ class Row < Array
24
+ def initialize(object)
25
+ @object = object
26
+ super object.to_a.collect(&:to_s)
27
+ end
28
+
29
+ attr :object
30
+
31
+ def align(columns)
32
+ self.collect.with_index do |value, index|
33
+ value.ljust(columns.widths[index])
34
+ end.join(' ')
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,86 @@
1
+ # Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'header'
22
+ require_relative 'columns'
23
+ require_relative 'row'
24
+
25
+ module Samovar
26
+ module Output
27
+ class Rows
28
+ include Enumerable
29
+
30
+ def initialize(level = 0)
31
+ @level = level
32
+ @rows = []
33
+ end
34
+
35
+ attr :level
36
+
37
+ def empty?
38
+ @rows.empty?
39
+ end
40
+
41
+ def first
42
+ @rows.first
43
+ end
44
+
45
+ def last
46
+ @rows.last
47
+ end
48
+
49
+ def indentation
50
+ @indentation ||= "\t" * @level
51
+ end
52
+
53
+ def each(ignore_nested: false, &block)
54
+ return to_enum(:each, ignore_nested: ignore_nested) unless block_given?
55
+
56
+ @rows.each do |row|
57
+ if row.is_a?(self.class)
58
+ row.each(&block) unless ignore_nested
59
+ else
60
+ yield row, self
61
+ end
62
+ end
63
+ end
64
+
65
+ def << object
66
+ @rows << Row.new(object)
67
+
68
+ return self
69
+ end
70
+
71
+ def columns
72
+ @columns ||= Columns.new(@rows.select{|row| row.is_a? Array})
73
+ end
74
+
75
+ def nested(*args)
76
+ @rows << Header.new(*args)
77
+
78
+ nested_rows = self.class.new(@level + 1)
79
+
80
+ yield nested_rows
81
+
82
+ @rows << nested_rows
83
+ end
84
+ end
85
+ end
86
+ end