bauk-core 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c26e013cd92aea58476b87be37ccfe4122b19ef1f0c398b0a453153e96772a16
4
+ data.tar.gz: 86a35845e0ae1eff4153229347f54ca41921440c86bdf6201932a609930afe4f
5
+ SHA512:
6
+ metadata.gz: 5b234d77cd7d0f0d3623fc4fb018f1b7422ae4d38196dd2f6ebc68b1c387f4c73b552381d69abe0c46d019d07f8bfedca545d983d99c5d4ffc225d7bc2bcbe7f
7
+ data.tar.gz: 47193c3ecebe854c4027b8c24ed43a593e649f6393b0e9c0f27685ae66e1bb25b82bd24d774e1c046a211579c10556f3c3143ba318dd68fdf5c63f37f9bbc8a6
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ /Gemfile.lock
14
+
15
+ /rubocop/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.3
7
+ before_install: gem install bundler -v 2.0.2
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at kubajasko@hotmail.co.uk. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in bauk-core.gemspec
6
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Kuba Jasko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ # Bauk::Core
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bauk/core`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'bauk-core'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install bauk-core
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bauk-core. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the Bauk::Core project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/bauk-core/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'bauk/core/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'bauk-core'
9
+ spec.version = Bauk::Core::VERSION
10
+ spec.authors = ['Kuba Jasko']
11
+ spec.email = ['kubajasko@hotmail.co.uk']
12
+
13
+ spec.summary = 'Core functionality/modules used by bauk gems'
14
+ spec.description = 'This gem includes things such as log and parser' \
15
+ ' wrappers, used by other bauk gems'
16
+ spec.homepage = 'https://gitlab.com/BAUK/bauk-core'
17
+ spec.license = 'MIT'
18
+
19
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = 'https://gitlab.com/BAUK/bauk-core'
23
+ spec.metadata['changelog_uri'] = 'https://gitlab.com/BAUK/bauk-core/commits/master'
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # This loads the files in the RubyGem that have been added to git.
27
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
+ `git ls-files -z`.split("\x0").reject do |f|
29
+ f.match(%r{^(test|spec|features)/})
30
+ end
31
+ end
32
+ spec.bindir = 'exe'
33
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34
+ spec.require_paths = ['lib']
35
+
36
+ spec.add_development_dependency 'bundler', '~> 2.0'
37
+ spec.add_development_dependency 'rake', '~> 10.0'
38
+ spec.add_development_dependency 'rspec', '~> 3.0'
39
+ spec.add_development_dependency 'rubocop', '~> 0.74'
40
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'bauk/core'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bauk/core/version'
4
+
5
+ module Bauk
6
+ module Core
7
+ class Error < StandardError; end
8
+ # Your code goes here...
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bauk
4
+ module Core
5
+ VERSION = `git describe --tags --always`.sub(/^v/, '')
6
+ end
7
+ end
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BAUK
4
+ module Utils
5
+ # This class wraps optparse and provides come common functionality.
6
+ # Common functionality includes:
7
+ # - Logging levels
8
+ # The basic functionality can be invoked with calls to #order!
9
+ #
10
+ # It also enables sub-options to be passed into the initializer with the
11
+ # following options:
12
+ # - info : A string line that gets displayed explaining the sub-command
13
+ # - opts : Any options pertaining to this sub-command lineage
14
+ # - action : The lambda to execute on action called
15
+ # - aliases : List of alternative names to go down this route
16
+ # - ... : Any further keys are treated as extra sub-options
17
+ #
18
+ # The sub-command functionality can be invoked with calls to #parse
19
+ class BaseParser
20
+ require 'optparse'
21
+ require 'bauk/utils/log'
22
+ require 'bauk/utils/hash_utils'
23
+ include Log
24
+ # Accepts a hash of actions. E.g:
25
+ # BaseParser.new({
26
+ # opts: lambda do |opts|
27
+ # # opts.on ...
28
+ # end,
29
+ # sub_action_a: {
30
+ # aliases: %w[a action_a],
31
+ # info: 'Please choose me!',
32
+ # opts: lambda do |opts|
33
+ # # Only accesible if 'sub_action_a' chosen
34
+ # end,
35
+ # action: ->() { function_call() },
36
+ # sub_action_a_sub: {
37
+ # # Only accessible after sub_action_a called
38
+ # }
39
+ # }
40
+ # })
41
+ # Alternatively the top-level opts can be passed in as a block:
42
+ # BaseParser.new() do |opts|
43
+ # # opts.on ...
44
+ # end
45
+ # Options penetrate down the sub-command chain so the parent command options
46
+ # can be called from child commands.
47
+ # These can however be overwritten by child options.
48
+ def initialize(actions = {}) # :yields: opts
49
+ @actions = actions # To store action map
50
+ @action_chain = [] # To stop chain of actions called
51
+ @config ||= {} # To store the config required for the accelerator
52
+ if block_given? && actions[:opts]
53
+ raise 'Cannot pass a block and set the main opts : They are the same'
54
+ elsif block_given?
55
+ actions[:opts] = Proc.new
56
+ end
57
+
58
+ initialize_parser
59
+ end
60
+
61
+ # The order of execution is:
62
+ # 1. Any extra options are evaluated
63
+ # 2. The command action is executed if present
64
+ # 3. Parse is called again if there are sub-commands
65
+ # Options:
66
+ # - args:: args to parse. Defaults to ARGV.
67
+ # - map:: optional hash at end with the following values:
68
+ # - parse_children: false # To not parse arguments after an action, before executing it
69
+ # - continue: true # Used internally. Set this to continue parsing from gathered action chain. Used as this function loops
70
+ # - continue_on_error: true # Set this to true to not return 3 on invalid/no action provided
71
+ def parse(args = nil, map = {})
72
+ args ||= ARGV
73
+ @action_chain = [] unless map[:continue]
74
+
75
+ order!(args)
76
+ # Build up action chain
77
+ action_name = args.shift
78
+ action = next_action(action_name) if action_name
79
+
80
+ if action_name
81
+ if action.is_a? Hash
82
+ initialize_parser
83
+ # First get any extra opts
84
+ order!(args) unless map[:parse_children] == false
85
+ # Then run this action
86
+ action[:action].call if action[:action].respond_to?(:call)
87
+ # Then continue down into sub-actions
88
+ parse(args, { continue: true }.merge(map))
89
+ elsif action.respond_to? :call
90
+ # First get any trailing args
91
+ order!(args)
92
+ # This is the end of the chain, call the sub and finish
93
+ action.call
94
+ elsif action.nil?
95
+ puts "Invalid action: #{action_name}"
96
+ puts available_actions
97
+ exit 3 unless map[:continue_on_error]
98
+ else
99
+ raise 'Invalid action: Needs to be a Hash or block'
100
+ end
101
+ elsif !current_action(only_child_actions: true).empty?
102
+ # If there are sub-actions that were not called, inform the user of these
103
+ puts available_actions
104
+ exit 3 unless map[:continue_on_error]
105
+ end
106
+ unless args.empty?
107
+ puts "Unknown args: #{args}"
108
+ exit 3 unless map[:continue_on_error]
109
+ end
110
+ end
111
+
112
+ # Lists available child actions based on the current @action_chain
113
+ def available_actions
114
+ # Put *'s if this has an action
115
+ ret = "#{program_name} - Available actions (--help for more info):\n"
116
+ max = 0
117
+ ca = current_action only_child_actions: true
118
+ ca.each_key { |key| max = key.length if key.length > max }
119
+ ca.each_key do |a|
120
+ if ca[a].is_a? Hash
121
+ ret << (ca[a][:action] ? ' * ' : ' - ') # If it has an action, use * bullets
122
+ ret << format("%-#{max}s : ", a) # Add the name
123
+ ret << "<#{ca[a][:aliases].join(',')}> " if ca[a][:aliases]&.is_a?(Array)
124
+ ret << ca[a][:info] if ca[a][:info]&.is_a?(String)
125
+ ret << "\n" # Add a newline
126
+ else
127
+ ret << format(" * %-#{max}s\n", a)
128
+ end
129
+ end
130
+ ret
131
+ end
132
+
133
+ def order(*args)
134
+ @parser.order(*args)
135
+ end
136
+
137
+ def order!(*args)
138
+ @parser.order!(*args)
139
+ end
140
+
141
+ # Passes common options to opts
142
+ def common_opts(opts)
143
+ opts.separator ''
144
+ opts.separator 'Common options:'
145
+ opts.on('-v', '--verbose [[CLASS=]LEVEL]', 'Set/Increase verbosity level') do |v|
146
+ type = ''
147
+ if v =~ /=/
148
+ type, v = v.split('=')
149
+ v = Integer(v)
150
+ elsif v =~ /^[0-9]*$/
151
+ v = v.to_i
152
+ elsif v =~ /./
153
+ type = v
154
+ v = nil
155
+ end
156
+ if v
157
+ BAUK::Utils::Log.set_log_level(v, type)
158
+ else
159
+ BAUK::Utils::Log.increase_logging(type)
160
+ end
161
+ end
162
+ end
163
+
164
+ # Passes the user-defined options to opts
165
+ def custom_opts(opts)
166
+ # TODO: allow opts to just pass in a hash reference and a symbol list
167
+ name = program_name child_actions: false
168
+ actions = { name => @actions }
169
+ [name, *@action_chain].each do |a|
170
+ actions = actions[a]
171
+ next unless actions[:opts]
172
+
173
+ opts.separator ''
174
+ opts.separator "#{a.capitalize} options:"
175
+ actions[:opts].call(opts)
176
+ end
177
+ end
178
+
179
+ private
180
+
181
+ def initialize_parser
182
+ @parser = OptionParser.new do |opts|
183
+ opts.banner = "Usage: #{program_name child_actions: true} [options]"
184
+ # If info provided, give it in the help menu but remove it as an action
185
+ opts.separator "\n#{current_action[:info]}" if current_action[:info].is_a? String
186
+ common_opts opts
187
+ custom_opts opts
188
+ end
189
+ end
190
+
191
+ def next_action(name)
192
+ current = current_action
193
+ name = name.to_sym
194
+ action = current[name]
195
+ current.each do |k, map|
196
+ next unless map.is_a? Hash
197
+
198
+ v = map[:aliases]
199
+ next unless v&.is_a?(Array)
200
+
201
+ if v.include? name
202
+ action = current[k]
203
+ name = k
204
+ end
205
+ end
206
+ @action_chain << name if action
207
+ action
208
+ end
209
+
210
+ def current_action(map = {})
211
+ action = @actions
212
+ @action_chain.each { |a| action = action[a] }
213
+ # Remove any entries that are not child actions
214
+ if map[:only_child_actions]
215
+ action = action.reject do |k, v|
216
+ case k
217
+ when :opts then v.respond_to? :call
218
+ when :info then v.is_a? String
219
+ when :action then v.respond_to? :call
220
+ when :aliases then v.is_a? Array
221
+ end
222
+ end
223
+ end
224
+ action || {}
225
+ end
226
+
227
+ def program_name(map = {})
228
+ program_name = $PROGRAM_NAME.gsub(%r{.*/}, '')
229
+ @action_chain.each { |a| program_name << " #{a}" } unless map[:child_actions] == false
230
+ if map[:child_actions]
231
+ sub_actions = current_action only_child_actions: true
232
+ program_name << " #{sub_actions.empty? ? '' : "<#{sub_actions.keys.join('|')}>"}"
233
+ end
234
+ program_name
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BAUK
4
+ module Utils
5
+ # This mixin ia a wrapper around log4r and enables logging functionality.
6
+ # It auto-names loggers in relation to the class they are included in,
7
+ # unless a name is specified.
8
+ module Log
9
+ require 'log4r'
10
+ Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
11
+
12
+ # Creates a new Log4r instance with the provided name
13
+ # Unless one already exists, in which case it returns it
14
+ # It also adds it to the list of loggers for future verboseness changing
15
+ def self.create(name)
16
+ log = loggers[name][:instance]
17
+ if log.nil?
18
+ log = Log4r::Logger.new(name)
19
+ log.level = Log.loggers[name][:level]
20
+ Log.loggers[name][:outputters].each { |o| log.add o }
21
+ log.debug("Initialized loger #{name} to: #{log.level}")
22
+ loggers[name] = loggers[name].clone # Take default values
23
+ loggers[name][:instance] = log
24
+ end
25
+ log
26
+ end
27
+
28
+ # Increases logging from all loggers, unless a name is specified
29
+ # (See set_log_level for runes on name provided).
30
+ # Due to the inverse of log4r, more logging means a lower log level
31
+ def self.increase_logging(name = '')
32
+ set_log_level(-1, name, true)
33
+ end
34
+
35
+ # Decreases logging from all loggers, unless a name is specified
36
+ # (See set_log_level for runes on name provided).
37
+ # Due to the inverse of log4r, less logging means a higher log level
38
+ def self.decrease_logging(name = '')
39
+ set_log_level(1, name, true)
40
+ end
41
+
42
+ # Sets the log level for all loggers matching the name.
43
+ # If the add flag is set, it increases/decreases the log level by the specified amount.
44
+ # The name is as follows:
45
+ # '':: Blank to edit all loggers
46
+ # logger_name:: To edit that logger and any child loggers
47
+ def self.set_log_level(level, name = '', add = false)
48
+ level += loggers[name][:level] if add
49
+ level = check_level(level)
50
+ if name != ''
51
+ # In case not set yet, set the logger to default values
52
+ # (If name = false, we want to edit the default directly)
53
+ loggers[name] = loggers[name].clone
54
+ end
55
+ loggers[name][:level] = level
56
+ # Change all active Child loggers
57
+ loggers.each do |n, logger|
58
+ next unless n =~ /^#{name}(::.*)*$/ || name == ''
59
+
60
+ logger[:level] = level
61
+ logger[:instance].level = level if logger[:instance]
62
+ end
63
+ end
64
+
65
+ # Returns the log_level of the provided logger
66
+ # If no name provided, returns the default log level
67
+ def self.log_level(name = '')
68
+ loggers[name][:level]
69
+ end
70
+
71
+ private_class_method
72
+ # Stores the list of created loggers
73
+ @@loggers_list = nil
74
+ def self.loggers
75
+ @@loggers_list ||= Hash.new(level: Log4r::WARN,
76
+ outputters: [Log4r::Outputter.stderr])
77
+ @@loggers_list
78
+ end
79
+
80
+ # FATAL = 5, DEBUG = 1, so high level is less logging...
81
+ def self.check_level(level)
82
+ if level > Log4r::FATAL
83
+ puts "Log level #{level} too high, setting to max(#{Log4r::FATAL})"
84
+ level = Log4r::FATAL
85
+ elsif level < Log4r::DEBUG
86
+ puts "Log level #{level} too low, setting to min (#{Log4r::DEBUG})"
87
+ level = Log4r::DEBUG
88
+ end
89
+ level
90
+ end
91
+
92
+ # INSTANCE METHODS::
93
+
94
+ # Used to access log4r inside a class which includes this class
95
+ def log
96
+ @log = Log.create(self.class.name || 'anonymous') if @log.nil?
97
+ @log
98
+ end
99
+
100
+ # Prints the designated title to the screen with an underline
101
+ def title(string)
102
+ space = 4
103
+ overhang = 1
104
+ puts ' ' * space + string
105
+ puts((' ' * space + string.gsub(/./, '=')).sub(' ' * overhang + '=', '=' * overhang + '=').sub(/$/, '=' * overhang))
106
+ end
107
+
108
+ # Increases logging globally for the name of this logger.
109
+ # See ::increase_logging
110
+ def increase_logging
111
+ Log.increase_logging(log.name)
112
+ end
113
+
114
+ # Decreases logging globally for the name of this logger.
115
+ # See ::decrease_logging
116
+ def decrease_logging
117
+ Log.decrease_logging(log.name)
118
+ end
119
+
120
+ # Setts the log level of this logger only
121
+ def log_level=(level)
122
+ log.level = Log.check_level(level)
123
+ end
124
+
125
+ # Prints a variety of log messages at each log level.
126
+ def test_logging
127
+ log.debug 'DEBUG'
128
+ log.info 'INFO'
129
+ log.warn 'WARN'
130
+ log.error 'ERROR'
131
+ log.fatal 'FATAL'
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BAUK
4
+ module Utils
5
+ # This mixin is used to allow user input through a series of methods.
6
+ # It relies upon Data as it uses the interactive mode to decide whether to
7
+ # throw an error/return default value if present, or ask user for input.
8
+ module UserInput
9
+ require 'io/console'
10
+ require 'yaml'
11
+
12
+ require 'bauk/utils/hash_utils'
13
+ require 'bauk/utils/string_utils'
14
+
15
+ def askYN(question, default = nil)
16
+ default = data.get_with_default(:default_yn, nil) if default.nil?
17
+ loop do
18
+ ans = user_input("#{question} y/n #{case default
19
+ when true then '[y]'
20
+ when false then '[n]'
21
+ end}: ", default: default)
22
+ return default if (ans == '') && !default.nil?
23
+ return true if /^y(es)*$/i =~ ans
24
+ return false if /^n(o)*$/i =~ ans
25
+ end
26
+ end
27
+
28
+ def ask(question, options, map = {})
29
+ map.default_value(max_tries: 5)
30
+ question << " [#{map[:default]}]" if map.key? :default
31
+ question << ' :'
32
+ if options.is_a? Array
33
+ options = options.map do |o|
34
+ [o, []]
35
+ end.to_h
36
+ end
37
+ try = 0
38
+ while map[:max_tries] != try # So if 0 is passed, it goes indefinitely
39
+ try += 1
40
+ ans = user_input(question)
41
+ options.each do |option, aliases|
42
+ return option if ans == option || ans =~ /^#{option}$/
43
+
44
+ aliases.each do |a|
45
+ return option if ans =~ /^#{a}$/
46
+ end
47
+ end
48
+ return map[:default] if map.key?(:default) && ans == ''
49
+
50
+ puts 'Options:'
51
+ options.each { |o, a| puts " - #{o} #{a.empty? ? '' : ": #{a.join ', '}"}" }
52
+ end
53
+ raise "Ran out of tries (#{try})."
54
+ end
55
+
56
+ # This def needs to be kept inside Data to prevent a circular dependency
57
+ def user_input(question, map = {})
58
+ data.user_input(question, map)
59
+ end
60
+
61
+ private
62
+
63
+ def data
64
+ @data ||= Data.instance
65
+ @data
66
+ end
67
+ end
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bauk-core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kuba Jasko
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-08-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.74'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.74'
69
+ description: This gem includes things such as log and parser wrappers, used by other
70
+ bauk gems
71
+ email:
72
+ - kubajasko@hotmail.co.uk
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".travis.yml"
80
+ - CODE_OF_CONDUCT.md
81
+ - Gemfile
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - bauk-core.gemspec
86
+ - bin/console
87
+ - bin/setup
88
+ - lib/bauk/core.rb
89
+ - lib/bauk/core/version.rb
90
+ - lib/bauk/utils/base_parser.rb
91
+ - lib/bauk/utils/log.rb
92
+ - lib/bauk/utils/user_input.rb
93
+ homepage: https://gitlab.com/BAUK/bauk-core
94
+ licenses:
95
+ - MIT
96
+ metadata:
97
+ allowed_push_host: https://rubygems.org
98
+ homepage_uri: https://gitlab.com/BAUK/bauk-core
99
+ source_code_uri: https://gitlab.com/BAUK/bauk-core
100
+ changelog_uri: https://gitlab.com/BAUK/bauk-core/commits/master
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.0.4
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Core functionality/modules used by bauk gems
120
+ test_files: []