k_doc 0.0.1 → 0.0.4

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: c6d0219141addaa6425e5135a40e128ed88deb1dc42dac3989c3e7cb4f52a92f
4
- data.tar.gz: 13baebe5946adcdc788f95dbef03c58bf4023a5b0c9c7ce0152565c9445e5df3
3
+ metadata.gz: b3ade2c96c7dd68a9b948f680c63a3a3f28d79f48a3808df328435054e32048f
4
+ data.tar.gz: f932c466c175cd9258220b370ea040982e2fd57be560fd816c8a60818d4344c6
5
5
  SHA512:
6
- metadata.gz: 4009d089e065d75155cbf542ac44bb584f50e7e67318201e3b10a89bd726117e03b1ee91ef9ad019e5cac7a6937ef73f5a740677393fdf9cac0c1f1324f15214
7
- data.tar.gz: 2afd8c789286539ff68decb4c3c971bd5175c48055abc0a6b524cd8347c23dc9a77c8c29a9316b9d8f10ef1c27b167cb8e7748afa0ff8f8ef79233620435fcb9
6
+ metadata.gz: 6f18c5daebd800c3e3e33ce5c8ec882833cc64b97c7d8b415c6078abed1c7fce76a6bb59f53afe51511035e77e198fdd1e106cf746dcff6fa7a96a3d0af88128
7
+ data.tar.gz: 36ab77e3f217d639bc02f911b23674322ad0dd2c2e1aed0042f57195fda0b6b8f95e0119758e0c85f0bddb485b0ea77d73d2543b6c515b315bb5c5d95171ab77
data/.rubocop.yml CHANGED
@@ -44,6 +44,9 @@ Layout/LineLength:
44
44
  Lint/UnusedMethodArgument:
45
45
  AllowUnusedKeywordArguments: true
46
46
 
47
+ Style/Documentation:
48
+ Enabled: false
49
+
47
50
  Style/BlockComments:
48
51
  Enabled: false
49
52
  Include:
data/Guardfile ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard :bundler, cmd: 'bundle install' do
4
+ watch('Gemfile')
5
+ watch('k_doc.gemspec')
6
+ end
7
+
8
+ group :green_pass_then_cop, halt_on_fail: true do
9
+ guard :rspec, cmd: 'bundle exec rspec -f doc' do
10
+ require 'guard/rspec/dsl'
11
+ dsl = Guard::RSpec::Dsl.new(self)
12
+
13
+ # RSpec files
14
+ rspec = dsl.rspec
15
+ watch(rspec.spec_helper) { rspec.spec_dir }
16
+ watch(rspec.spec_support) { rspec.spec_dir }
17
+ watch(rspec.spec_files)
18
+
19
+ # Ruby files
20
+ ruby = dsl.ruby
21
+ dsl.watch_spec_files_for(ruby.lib_files)
22
+ watch(%r{^lib/k_doc/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
23
+ watch(%r{^lib/k_doc/commands/(.+)\.rb$}) { |m| "spec/unit/commands/#{m[1]}_spec.rb" }
24
+ end
25
+
26
+ guard :rubocop, all_on_start: false, cli: ['--format', 'clang'] do
27
+ watch(/{.+\.rb$/)
28
+ watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
29
+ end
30
+ end
data/README.md CHANGED
@@ -26,16 +26,23 @@ gem install k_doc
26
26
 
27
27
  ### Main Story
28
28
 
29
-
29
+ As a Developer, I need flexible data structures defined in DSL, so can model rich documents
30
30
 
31
31
  See all [stories](./STORIES.md)
32
32
 
33
-
34
33
  ## Usage
35
34
 
36
35
  See all [usage examples](./USAGE.md)
37
36
 
37
+ ### Basic Example
38
+
39
+ #### Basic example
38
40
 
41
+ Description for a basic example to be featured in the main README.MD file
42
+
43
+ ```ruby
44
+ class SomeRuby; end
45
+ ```
39
46
 
40
47
  ## Development
41
48
 
@@ -45,7 +52,7 @@ Checkout the repo
45
52
  git clone klueless-io/k_doc
46
53
  ```
47
54
 
48
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
55
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
49
56
 
50
57
  You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
58
 
data/STORIES.md ADDED
@@ -0,0 +1,44 @@
1
+ # K Doc
2
+
3
+ > KDoc provides a document in the form a DSL that contains flexible key/value and tabular data
4
+
5
+ As a Developer, I need flexible data structures defined in DSL, so can model rich documents
6
+
7
+ ## Development radar
8
+
9
+ ### Stories next on list
10
+
11
+ As a Developer, I need flexible data structures defined in DSL, so can model rich documents
12
+
13
+ ### Tasks next on list
14
+
15
+ Setup RubyGems and RubyDoc
16
+
17
+ - Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_doc)
18
+ - Attach documentation to [rubydoc.info](https://rubydoc.info/github/to-do-/k_doc/master)
19
+
20
+ Setup GitHub Action (test and lint)
21
+
22
+ - Setup Rspec action
23
+ - Setup RuboCop action
24
+
25
+ ## Stories and tasks
26
+
27
+ ### Tasks - completed
28
+
29
+ Setup project management, requirement and SCRUM documents
30
+
31
+ - Setup readme file
32
+ - Setup user stories and tasks
33
+ - Setup a project backlog
34
+ - Setup an examples/usage document
35
+
36
+ Setup new Ruby GEM
37
+
38
+ - Build out a standard GEM structure
39
+ - Add automated semantic versioning
40
+ - Add Rspec unit testing framework
41
+ - Add RuboCop linting
42
+ - Add Guard for automatic watch and test
43
+ - Add GitFlow support
44
+ - Add GitHub Repository
data/USAGE.md ADDED
@@ -0,0 +1,19 @@
1
+ # K Doc
2
+
3
+ > KDoc provides a document in the form a DSL that contains flexible key/value and tabular data
4
+
5
+ As a Developer, I need flexible data structures defined in DSL, so can model rich documents
6
+
7
+ ## Usage
8
+
9
+ ### Sample Classes
10
+
11
+ #### Simple example
12
+
13
+ Description for a simple example that shows up in the USAGE.MD
14
+
15
+ ```ruby
16
+ class SomeRuby
17
+ def initialize; end
18
+ end
19
+ ```
data/k_doc.gemspec CHANGED
@@ -38,5 +38,7 @@ Gem::Specification.new do |spec|
38
38
  spec.require_paths = ['lib']
39
39
  # spec.extensions = ['ext/k_doc/extconf.rb']
40
40
 
41
+ spec.add_dependency 'k_log' , '~> 0.0.0'
42
+ spec.add_dependency 'k_util' , '~> 0.0.0'
41
43
  # spec.add_dependency 'tty-box', '~> 0.5.0'
42
44
  end
data/lib/k_doc.rb CHANGED
@@ -1,10 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'securerandom'
4
+
5
+ require 'logger'
6
+ require 'table_print'
7
+ require 'k_log'
8
+ require 'k_util'
9
+ require 'k_log/log_formatter'
10
+ require 'k_log/log_helper'
11
+ require 'k_log/log_util'
12
+
3
13
  require 'k_doc/version'
14
+ require 'k_doc/data'
15
+ require 'k_doc/document'
16
+ require 'k_doc/fake_opinion'
17
+ require 'k_doc/settings'
18
+ require 'k_doc/table'
19
+ require 'k_doc/util'
4
20
 
5
21
  module KDoc
6
22
  # raise KDoc::Error, 'Sample message'
7
23
  class Error < StandardError; end
8
24
 
9
- # Your code goes here...
25
+ class << self
26
+ # Factory method to create a new document
27
+ def doc(key = nil, **options, &block)
28
+ doc = KDoc::Document.new(key, **options, &block)
29
+ doc.execute_block
30
+ doc
31
+ end
32
+
33
+ attr_accessor :opinion
34
+ attr_accessor :util
35
+ attr_accessor :log
36
+ end
37
+
38
+ KDoc.opinion = KDoc::FakeOpinion.new
39
+ KDoc.util = KDoc::Util.new
40
+
41
+ # Need to move this into a KLog factory
42
+ def self.configure_logger
43
+ logger = Logger.new($stdout)
44
+ logger.level = Logger::DEBUG
45
+ logger.formatter = KLog::LogFormatter.new
46
+ KLog::LogUtil.new(logger)
47
+ end
48
+
49
+ # KDoc.log = configure_logger
10
50
  end
51
+
52
+ L = KDoc.configure_logger
data/lib/k_doc/data.rb ADDED
@@ -0,0 +1,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ # module KDoc
4
+ # # TODO
5
+ # # Missing tests around errors
6
+ # # Make sure that error writes to resource or document appropriately
7
+ # # Puts errors onto a project manager pipeline so that they can be be printed out after the documents
8
+ # #
9
+ # # General purpose document DSL
10
+ # #
11
+ # # Made up of 0 or more setting groups and table groups
12
+ # class Data
13
+ # extend Forwardable
14
+
15
+ # attr_reader :key
16
+ # attr_reader :type
17
+ # attr_reader :namespace
18
+ # attr_reader :options
19
+ # attr_reader :error
20
+
21
+ # # State of document
22
+ # # - :initializing
23
+ # # - :initialized
24
+ # # - :loading
25
+ # # - :loaded
26
+ # # - :executing
27
+ # # - :executed
28
+ # attr_reader :state
29
+
30
+ # # Shortcut to formatter
31
+ # attr_reader :f
32
+
33
+ # attr_accessor :resource
34
+
35
+ # def_delegator :resource, :project
36
+
37
+ # def state=(state)
38
+ # @state = state
39
+ # # if [:initialized, :loaded, :executed].include?(state) &&
40
+ # # (project.nil? || project.name == 'k_dsl')
41
+ # # # pname = project.nil? ? '' : "#{project&.name} "
42
+ # # L.kv "#{unique_key} - state", state
43
+ # # end
44
+ # @state
45
+ # end
46
+
47
+ # # Create document
48
+ # #
49
+ # # @param [String|Symbol] name Name of the document
50
+ # # @param args[0] Type of the document, defaults to KDsl.config.default_document_type if not set
51
+ # # @param default: Default value (using named params), as above
52
+ # def initialize(key = SecureRandom.alphanumeric(8), *args, **options, &block)
53
+ # @key = key
54
+ # @type = args.length.positive? ? args[0] || KDsl.config.default_document_type : KDsl.config.default_document_type
55
+
56
+ # @options = options || {}
57
+ # @namespace = options[:namespace] || ''
58
+ # default_data = options[:default_data] || {}
59
+
60
+ # @namespace = @namespace.to_s
61
+ # @error = nil
62
+
63
+ # self.state = :initializing
64
+
65
+ # # Most documents live within a hash, some tabular documents such as
66
+ # # CSV will use an []
67
+ # set_data(default_data)
68
+
69
+ # @f = KDsl::Util.format
70
+
71
+ # @block = block if block_given?
72
+
73
+ # self.state = :initialized
74
+ # end
75
+
76
+ # def execute_block(run_actions: nil)
77
+ # return if @block.nil?
78
+
79
+ # # The DSL actions method will only run on run_actions: true
80
+ # @run_actions = run_actions
81
+
82
+ # # if unique_key == 'template_options_entity'
83
+ # # L.kv '2:CLASS_ID', object_id
84
+ # # end
85
+ # if initialized?
86
+ # self.state = :loading
87
+ # instance_eval(&@block)
88
+ # self.state = :loaded
89
+ # end
90
+ # # if unique_key == 'template_options_entity'
91
+ # # L.kv '3:CLASS_ID', resource_document.object_id
92
+ # # end
93
+
94
+ # if loaded? && run_actions && respond_to?(:on_action)
95
+ # @state = :executed
96
+ # on_action
97
+ # end
98
+ # rescue KDsl::Error => e
99
+ # L.error('KDsl::Error in document')
100
+ # L.kv 'key', unique_key
101
+ # L.kv 'file', KDsl::Util.data.console_file_hyperlink(resource.file, resource.file)
102
+ # L.error(e.message)
103
+ # @error = e
104
+ # # L.heading "Invalid code block in document_dsl during registration: #{k_key}"
105
+ # # L.exception exception
106
+ # raise
107
+ # rescue StandardError => e
108
+ # L.error('Standard error in document')
109
+ # L.kv 'key', unique_key
110
+ # L.kv 'file', KDsl::Util.data.console_file_hyperlink(resource.file, resource.file)
111
+ # L.error(e.message)
112
+ # @error = e
113
+ # # L.exception exception2
114
+ # raise
115
+ # ensure
116
+ # @run_actions = nil
117
+ # return
118
+ # end
119
+
120
+ # def initialized?
121
+ # @state == :initialized
122
+ # end
123
+
124
+ # def loaded?
125
+ # @state == :loaded
126
+ # end
127
+
128
+ # def executed?
129
+ # @state == :executed
130
+ # end
131
+
132
+ # def unique_key
133
+ # @unique_key ||= KDsl::Util.dsl.build_unique_key(key, type, namespace)
134
+ # end
135
+
136
+ # def settings(key = nil, **options, &block)
137
+ # options ||= {}
138
+
139
+ # opts = {}.merge(@options) # Document Options
140
+ # .merge(options) # Settings Options
141
+
142
+ # settings = settings_instance(@data, key, parent: self, &block)
143
+ # settings.run_decorators(opts)
144
+ # settings
145
+ # end
146
+
147
+ # def table(key = :table, &block)
148
+ # # NEED to add support for run_decorators I think
149
+ # table_instance(@data, key, parent: self, &block)
150
+ # end
151
+ # alias rows table
152
+
153
+ # # Sweet add-on would be builders
154
+ # # def builder(key, &block)
155
+ # # # example
156
+ # # KDsl::Builder::Shotstack.new(@data, key, &block)
157
+ # # end
158
+
159
+ # def set_data(data)
160
+ # @data = data
161
+ # end
162
+
163
+ # def data
164
+ # @data.clone
165
+ # end
166
+
167
+ # def data_struct
168
+ # KDsl::Util.data.to_struct(data)
169
+ # end
170
+ # alias d data_struct
171
+
172
+ # def raw_data_struct
173
+ # KDsl::Util.data.to_struct(raw_data)
174
+ # end
175
+
176
+ # def get_node_type(node_name)
177
+ # node_name = KDsl::Util.data.clean_symbol(node_name)
178
+ # node_data = @data[node_name]
179
+
180
+ # raise KDsl::Error, "Node not found: #{node_name}" if node_data.nil?
181
+
182
+ # if node_data.keys.length == 2 && (node_data.key?('fields') && node_data.key?('rows'))
183
+ # :table
184
+ # else
185
+ # :settings
186
+ # end
187
+ # end
188
+
189
+ # # Removes any meta data eg. "fields" from a table and just returns the raw data
190
+ # def raw_data
191
+ # # REFACT, what if this is CSV, meaning it is just an array?
192
+ # # add specs
193
+ # result = data
194
+
195
+ # result.each_key do |key|
196
+ # # ANTI: get_node_type uses @data while we are using @data.clone here
197
+ # data[key] = if get_node_type(key) == :table
198
+ # result[key].delete('fields')
199
+ # else
200
+ # result[key]
201
+ # end
202
+ # end
203
+
204
+ # data
205
+ # end
206
+
207
+ # # Move this out to the logger function when it has been refactor
208
+ # def debug(include_header = false)
209
+ # debug_header if include_header
210
+
211
+ # # tp dsls.values, :k_key, :k_type, :state, :save_at, :last_at, :data, :last_data, :source, { :file => { :width => 150 } }
212
+ # # puts JSON.pretty_generate(data)
213
+ # L.o(raw_data_struct)
214
+ # end
215
+
216
+ # def debug_header
217
+ # L.heading self.class.name
218
+ # L.kv 'key', key
219
+ # L.kv 'type', type
220
+ # L.kv 'namespace', namespace
221
+ # L.kv 'error', error
222
+ # L.kv 'state', state
223
+ # L.kv 'respond_to?(:on_import)', respond_to?(:on_import)
224
+ # L.kv 'respond_to?(:david)', respond_to?(:david)
225
+ # david if respond_to?(:david)
226
+ # # L.kv 'INITALIZED', resource_document.initialized?
227
+ # # L.kv 'EXECUTED', resource_document.executed?
228
+
229
+ # options&.keys.reject { |k| k == :namespace }&.each do |key|
230
+ # L.kv key, options[key]
231
+ # end
232
+
233
+ # L.line
234
+ # end
235
+
236
+ # # Helpers that often get called by extensions
237
+
238
+ # def project
239
+ # project ||= resource&.project
240
+ # end
241
+
242
+ # # Warning message
243
+ # def warn(message)
244
+ # L.warn message
245
+ # nil
246
+ # end
247
+
248
+ # private
249
+
250
+ # def settings_instance(data, key, **options, &block)
251
+ # KDsl.config.settings_class.new(data, key, **options, &block)
252
+ # end
253
+
254
+ # def table_instance(data, key, **options, &block)
255
+ # KDsl.config.table_class.new(data, key, **options, &block)
256
+ # end
257
+ # end
258
+ # end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KDoc
4
+ # General purpose document DSL
5
+ #
6
+ # Made up of 0 or more setting groups and table groups
7
+ class Document
8
+ attr_reader :key
9
+ attr_reader :type
10
+ attr_reader :namespace
11
+ attr_reader :options
12
+ attr_reader :error
13
+
14
+ # Create document
15
+ #
16
+ # @param [String|Symbol] name Name of the document
17
+ # @param args[0] Type of the document, defaults to KDoc:: FakeOpinion.new.default_document_type if not set
18
+ # @param default: Default value (using named params), as above
19
+ def initialize(key = SecureRandom.alphanumeric(8), **options, &block)
20
+ initialize_attributes(key, **options)
21
+
22
+ @block = block if block_given?
23
+ end
24
+
25
+ def execute_block(run_actions: nil)
26
+ return if @block.nil?
27
+
28
+ # The DSL actions method will only run on run_actions: true
29
+ @run_actions = run_actions
30
+
31
+ instance_eval(&@block)
32
+
33
+ on_action if run_actions && respond_to?(:on_action)
34
+ # rescue KDoc::Error => e
35
+ # puts('KDoc::Error in document')
36
+ # puts "key #{unique_key}"
37
+ # # puts "file #{KUtil.data.console_file_hyperlink(resource.file, resource.file)}"
38
+ # puts(e.message)
39
+ # @error = e
40
+ # raise
41
+ rescue StandardError => e
42
+ L.error('Standard error in document')
43
+ puts "key #{unique_key}"
44
+ # puts "file #{KUtil.data.console_file_hyperlink(resource.file, resource.file)}"
45
+ L.error(e.message)
46
+ @error = e
47
+ # L.exception exception2
48
+ raise
49
+ ensure
50
+ @run_actions = nil
51
+ end
52
+
53
+ def unique_key
54
+ @unique_key ||= KDoc.util.build_unique_key(key, type, namespace)
55
+ end
56
+
57
+ def settings(key = nil, **options, &block)
58
+ options ||= {}
59
+
60
+ opts = {}.merge(@options) # Document Options
61
+ .merge(options) # Settings Options
62
+ .merge(parent: self)
63
+
64
+ settings_instance(@data, key, **opts, &block)
65
+ # settings.run_decorators(opts)
66
+ end
67
+
68
+ def table(key = :table, **options, &block)
69
+ # NEED to add support for run_decorators I think
70
+ options.merge(parent: self)
71
+ table_instance(@data, key, **options, &block)
72
+ end
73
+ alias rows table
74
+
75
+ # Sweet add-on would be builders
76
+ # def builder(key, &block)
77
+ # # example
78
+ # KDoc::Builder::Shotstack.new(@data, key, &block)
79
+ # end
80
+
81
+ # def set_data(data)
82
+ # @data = data
83
+ # end
84
+
85
+ def data
86
+ @data.clone
87
+ end
88
+
89
+ def data_struct
90
+ KUtil.data.to_open_struct(data)
91
+ end
92
+ # alias d data_struct
93
+
94
+ def raw_data_struct
95
+ KUtil.data.to_open_struct(raw_data)
96
+ end
97
+
98
+ def get_node_type(node_name)
99
+ node_name = KUtil.data.clean_symbol(node_name)
100
+ node_data = @data[node_name]
101
+
102
+ raise KDoc::Error, "Node not found: #{node_name}" if node_data.nil?
103
+
104
+ if node_data.keys.length == 2 && (node_data.key?('fields') && node_data.key?('rows'))
105
+ :table
106
+ else
107
+ :settings
108
+ end
109
+ end
110
+
111
+ # Removes any meta data eg. "fields" from a table and just returns the raw data
112
+ def raw_data
113
+ # REFACT, what if this is CSV, meaning it is just an array?
114
+ # add specs
115
+ result = data
116
+
117
+ result.each_key do |key|
118
+ # ANTI: get_node_type uses @data while we are using @data.clone here
119
+ data[key] = if get_node_type(key) == :table
120
+ result[key].delete('fields')
121
+ else
122
+ result[key]
123
+ end
124
+ end
125
+
126
+ data
127
+ end
128
+
129
+ # Move this out to the logger function when it has been refactor
130
+ def debug(include_header: false)
131
+ debug_header if include_header
132
+
133
+ # tp dsls.values, :k_key, :k_type, :state, :save_at, :last_at, :data, :last_data, :source, { :file => { :width => 150 } }
134
+ # puts JSON.pretty_generate(data)
135
+ L.o(raw_data_struct)
136
+ end
137
+
138
+ def debug_header
139
+ L.heading self.class.name
140
+ L.kv 'key', key
141
+ L.kv 'type', type
142
+ L.kv 'namespace', namespace
143
+ L.kv 'error', error
144
+
145
+ debug_header_keys
146
+
147
+ L.line
148
+ end
149
+
150
+ def debug_header_keys
151
+ options&.keys&.reject { |k| k == :namespace }&.each do |key|
152
+ L.kv key, options[key]
153
+ end
154
+ end
155
+
156
+ private
157
+
158
+ def initialize_attributes(key = nil, **options)
159
+ @key = key
160
+
161
+ @options = options || {}
162
+ @type = slice_option(:type) || KDoc.opinion.default_document_type
163
+ @namespace = slice_option(:namespace) || ''
164
+ @parent = slice_option(:parent)
165
+
166
+ # Most documents live within a hash, some tabular documents such as CSV will use an []
167
+ @data = slice_option(:default_data) || {}
168
+
169
+ @error = nil
170
+ end
171
+
172
+ def settings_instance(data, key, **options, &block)
173
+ KDoc.opinion.settings_class.new(data, key, **options, &block)
174
+ end
175
+
176
+ def table_instance(data, key, **options, &block)
177
+ KDoc.opinion.table_class.new(data, key, **options, &block)
178
+ end
179
+
180
+ def slice_option(key)
181
+ return nil unless @options.key?(key)
182
+
183
+ result = @options[key]
184
+ @options.delete(key)
185
+ result
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module KDoc
6
+ # This is called fake opinion because I have not figured out
7
+ # how I want to implement this
8
+ class FakeOpinion
9
+ attr_accessor :default_document_type
10
+ attr_accessor :default_settings_key
11
+ attr_accessor :default_table_key
12
+
13
+ attr_accessor :document_class
14
+ attr_accessor :settings_class
15
+ attr_accessor :table_class
16
+
17
+ def initialize
18
+ @default_document_type = :entity
19
+ @default_settings_key = :settings
20
+ @default_table_key = :table
21
+
22
+ @document_class = KDoc::Document
23
+ @table_class = KDoc::Table
24
+ @settings_class = KDoc::Settings
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module KDoc
6
+ # Builds up key/value settings from the block
7
+ # and applies them to a key coded node on the hash
8
+ class Settings
9
+ attr_reader :parent
10
+ attr_reader :key
11
+
12
+ alias kp parent
13
+
14
+ def initialize(data, key = nil, **options, &block)
15
+ initialize_attributes(data, key, **options)
16
+
17
+ # Need a way to find out the line number for errors and report it correctly
18
+ begin
19
+ instance_eval(&block) if block_given?
20
+ # rubocop:disable Style/RescueStandardError
21
+ rescue => e
22
+ # rubocop:enable Style/RescueStandardError
23
+ puts "Invalid code block in settings_dsl: #{@key}"
24
+ puts e.message
25
+ raise
26
+ end
27
+ end
28
+
29
+ def my_data
30
+ @data[@key]
31
+ end
32
+
33
+ # def run_decorators(opts)
34
+ # decorators = KDoc::Decorator.decorate.decorators(opts[:decorators])
35
+
36
+ # return if decorators.empty?
37
+
38
+ # decorators.each do |decorator|
39
+ # decorator.send(:update, my_data) if decorator.respond_to?(:update)
40
+ # decorator.send(:call, my_data) if decorator.respond_to?(:call)
41
+ # end
42
+ # end
43
+
44
+ def respond_to_missing?(name, *_args, &_block)
45
+ # puts 'respond_to_missing?'
46
+ # puts "respond_to_missing: #{name}"
47
+ n = name.to_s
48
+ n = n[0..-2] if n.end_with?('=')
49
+ my_data.key?(n.to_s) || (!@parent.nil? && @parent.respond_to?(name, true)) || super
50
+ end
51
+
52
+ # rubocop:disable Metrics/AbcSize
53
+ def method_missing(name, *args, &_block)
54
+ # puts "method_missing: #{name}"
55
+ # puts "args.length : #{args.length}"
56
+
57
+ if name != :type && !@parent.nil? && @parent.respond_to?(name)
58
+ puts "NAME: #{name}"
59
+ return @parent.public_send(name, *args, &block)
60
+ end
61
+ raise KDoc::Error, 'Multiple setting values is not supported' if args.length > 1
62
+
63
+ add_getter_or_param_method(name)
64
+ add_setter_method(name)
65
+
66
+ send(name, args[0]) if args.length == 1 # name.end_with?('=')
67
+
68
+ super unless self.class.method_defined?(name)
69
+ end
70
+ # rubocop:enable Metrics/AbcSize
71
+
72
+ # Handles Getter method and method with single parameter
73
+ # object.my_name
74
+ # object.my_name('david')
75
+ def add_getter_or_param_method(name)
76
+ # L.progress(1, 'add_getter_or_param_method')
77
+ self.class.class_eval do
78
+ # L.progress(2, 'add_getter_or_param_method')
79
+ name = name.to_s.gsub(/=$/, '')
80
+ # L.progress(3, 'add_getter_or_param_method')
81
+ define_method(name) do |*args|
82
+ # L.progress(4, 'add_getter_or_param_method')
83
+ # L.kv 'add_getter_or_param_method', name
84
+ raise KDoc::Error, 'Multiple setting values is not supported' if args.length > 1
85
+
86
+ if args.length.zero?
87
+ get_value(name)
88
+ else
89
+ send("#{name}=", args[0])
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ # Handles Setter method
96
+ # object.my_name = 'david'
97
+ def add_setter_method(name)
98
+ # L.progress(1, 'add_setter_method')
99
+ self.class.class_eval do
100
+ # L.progress(2, 'add_setter_method')
101
+ name = name.to_s.gsub(/=$/, '')
102
+ # L.progress(3, 'add_setter_method')
103
+ # L.kv 'add_setter_method', name
104
+ define_method("#{name}=") do |value|
105
+ # L.progress(4, 'add_setter_method')
106
+ # L.kv 'value', value
107
+ my_data[name.to_s] = value
108
+ end
109
+ end
110
+ end
111
+
112
+ def get_value(name)
113
+ my_data[name.to_s]
114
+ end
115
+
116
+ def debug
117
+ puts JSON.pretty_generate(my_data)
118
+ end
119
+
120
+ private
121
+
122
+ def initialize_attributes(data, key = nil, **options)
123
+ @data = data
124
+ @key = (key || FakeOpinion.new.default_settings_key).to_s
125
+
126
+ @parent = options[:parent] if !options.nil? && options.key?(:parent)
127
+
128
+ @data[@key] = {}
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KDoc
4
+ # Build rows (aka DataTable) with field definitions and rows of data
5
+ class Table
6
+ attr_reader :parent
7
+ attr_reader :name
8
+
9
+ def initialize(data, name = nil, **options, &block)
10
+ initialize_attributes(data, name, **options)
11
+
12
+ instance_eval(&block) if block_given?
13
+ end
14
+
15
+ def fields(field_definitions)
16
+ fields = @data[@name]['fields']
17
+
18
+ field_definitions.each do |fd|
19
+ fields << if fd.is_a?(String) || fd.is_a?(Symbol)
20
+ field(fd, nil, :string)
21
+ else
22
+ fd
23
+ end
24
+ end
25
+ end
26
+
27
+ # rubocop:disable Metrics/AbcSize
28
+ def row(*args, **named_args)
29
+ fields = @data[@name]['fields']
30
+
31
+ raise "To many values for row, argument #{i}" if args.length > fields.length
32
+
33
+ # Apply column names with defaults
34
+ row = fields.each_with_object({}) do |f, hash|
35
+ hash[f['name']] = f['default']
36
+ end
37
+
38
+ # Override with positional arguments
39
+ args.each_with_index do |arg, i|
40
+ row[fields[i]['name']] = KUtil.data.clean_symbol(arg)
41
+ end
42
+
43
+ # Override with named args
44
+ named_args.each_key do |key|
45
+ row[key.to_s] = named_args[key]
46
+ end
47
+
48
+ @data[@name]['rows'] << row
49
+ row
50
+ end
51
+ # rubocop:enable Metrics/AbcSize
52
+
53
+ # rubocop:disable Naming/AccessorMethodName
54
+ def get_fields
55
+ @data[@name]['fields']
56
+ end
57
+
58
+ def get_rows
59
+ @data[@name]['rows']
60
+ end
61
+ # rubocop:enable Naming/AccessorMethodName
62
+
63
+ def find_row(key, value)
64
+ @data[@name]['rows'].find { |r| r[key] == value }
65
+ end
66
+
67
+ # Field definition
68
+ #
69
+ # @param [String|Symbol] name Name of the field
70
+ # @param args[0] Default value if not specified, nil if not set
71
+ # @param args[1] Type of data, string if not set
72
+ # @param default: Default value (using named params), as above
73
+ # @param type: Type of data (using named params), as above
74
+ # @return [Hash] Field definition
75
+ def field(name, *args, default: nil, type: nil)
76
+ # default value can be found at position 0 or default: tag (see unit test edge cases)
77
+ default_value = if args.length.positive?
78
+ args[0].nil? ? default : args[0]
79
+ else
80
+ default
81
+ end
82
+
83
+ # type can be found at position 1 or type: tag
84
+ type_value = (args.length > 1 ? args[1] : type) || :string
85
+
86
+ {
87
+ 'name' => KUtil.data.clean_symbol(name),
88
+ 'default' => KUtil.data.clean_symbol(default_value),
89
+ 'type' => KUtil.data.clean_symbol(type_value)
90
+ }
91
+ end
92
+ alias f field
93
+
94
+ private
95
+
96
+ def initialize_attributes(data, name = nil, **options)
97
+ @data = data
98
+ @name = (name || FakeOpinion.new.default_table_key.to_s).to_s
99
+
100
+ @parent = options[:parent] if !options.nil? && options.key?(:parent)
101
+
102
+ @data[@name] = { 'fields' => [], 'rows' => [] }
103
+ end
104
+
105
+ def respond_to_missing?(name, *_args, &_block)
106
+ (!@parent.nil? && @parent.respond_to?(name, true)) || super
107
+ end
108
+
109
+ def method_missing(name, *args, &block)
110
+ return super unless @parent.respond_to?(name)
111
+
112
+ @parent.public_send(name, *args, &block)
113
+ end
114
+ end
115
+ end
data/lib/k_doc/util.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KDoc
4
+ # Utility helper methods for KDoc
5
+ class Util
6
+ def build_unique_key(key, type = nil, namespace = nil)
7
+ raise KDoc::Error, 'key is required when generating unique key' if key.nil? || key.empty?
8
+
9
+ type ||= KDoc.opinion.default_document_type
10
+
11
+ namespace.nil? || namespace.empty? ? "#{key}_#{type}" : "#{namespace}_#{key}_#{type}"
12
+ end
13
+ end
14
+ end
data/lib/k_doc/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KDoc
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.4'
5
5
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: k_doc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-30 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: k_log
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: k_util
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.0
13
41
  description: " KDoc provides a document in the form a DSL that contains flexible
14
42
  key/value and tabular data\n"
15
43
  email:
@@ -24,9 +52,12 @@ files:
24
52
  - ".rubocop.yml"
25
53
  - CODE_OF_CONDUCT.md
26
54
  - Gemfile
55
+ - Guardfile
27
56
  - LICENSE.txt
28
57
  - README.md
29
58
  - Rakefile
59
+ - STORIES.md
60
+ - USAGE.md
30
61
  - bin/console
31
62
  - bin/k
32
63
  - bin/kgitsync
@@ -36,6 +67,12 @@ files:
36
67
  - hooks/update-version
37
68
  - k_doc.gemspec
38
69
  - lib/k_doc.rb
70
+ - lib/k_doc/data.rb
71
+ - lib/k_doc/document.rb
72
+ - lib/k_doc/fake_opinion.rb
73
+ - lib/k_doc/settings.rb
74
+ - lib/k_doc/table.rb
75
+ - lib/k_doc/util.rb
39
76
  - lib/k_doc/version.rb
40
77
  homepage: http://appydave.com/gems/k-doc
41
78
  licenses: