output_mode 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.travis.yml +13 -0
- data/Gemfile +30 -0
- data/LICENSE.txt +18 -0
- data/README.md +67 -0
- data/Rakefile +32 -0
- data/bin/console +37 -0
- data/bin/demo +60 -0
- data/bin/setup +34 -0
- data/lib/output_mode.rb +34 -0
- data/lib/output_mode/builder_dsl.rb +50 -0
- data/lib/output_mode/callable.rb +138 -0
- data/lib/output_mode/default_erb.rb +19 -0
- data/lib/output_mode/errors.rb +30 -0
- data/lib/output_mode/output.rb +127 -0
- data/lib/output_mode/outputs.rb +36 -0
- data/lib/output_mode/outputs/delimited.rb +49 -0
- data/lib/output_mode/outputs/tabulated.rb +73 -0
- data/lib/output_mode/outputs/templated.rb +128 -0
- data/lib/output_mode/tldr.rb +34 -0
- data/lib/output_mode/tldr/index.rb +55 -0
- data/lib/output_mode/tldr/show.rb +56 -0
- data/lib/output_mode/version.rb +29 -0
- data/output_mode.gemspec +59 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 459750a9a32c10353ffca23bcf3f9aa1bdb7da651570a324e82ba224c260df87
|
4
|
+
data.tar.gz: 5a1661e01600478c767d79ad27b2b499440f3d610d4255088c7c76fff0842e28
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4bddfb1d70102c00543a73d6d2bdd56dfcd7f248fd0ea57b222dc428bb1cb6928168592663f07c7bd5d18e22a16ae70af59dc2fbf5281de19004971cb9b26737
|
7
|
+
data.tar.gz: 94d113f12f084cf82a29b4a0f1e8528c3dbd8aa2138237d4dcb5ecbf8cc24352ab25e0528f6edb23a501dc2bdcec1e729698df7bb3f643d2666f8008ff0ece85
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#==============================================================================
|
2
|
+
# Copyright 2020 William McCumstie
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
#==============================================================================
|
26
|
+
|
27
|
+
source "https://rubygems.org"
|
28
|
+
|
29
|
+
# Specify your gem's dependencies in output_mode.gemspec
|
30
|
+
gemspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
This project is partially dual licensed under BSD-2-Clause OR 0BSD. Source code originating from a BSD-2-Clause licensed file must comply with terms contained within the license header block. Source code originating from files without a license header block maybe redistributed under either license.
|
2
|
+
|
3
|
+
The following is a copy of the BSD-2-Clause license:
|
4
|
+
|
5
|
+
Copyright 2020 William McCumstie
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
8
|
+
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
14
|
+
|
15
|
+
The following is a copy of the 0BSD license:
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
18
|
+
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
[![Build Status](https://travis-ci.com/WilliamMcCumstie/output_mode.svg?branch=master)](https://travis-ci.com/WilliamMcCumstie/output_mode)
|
2
|
+
|
3
|
+
# OutputMode
|
4
|
+
|
5
|
+
Provides a set of wrapper `Outputs` to common libraries: `TTY::Table`, `CSV`, and `ERB`. Focus on "what" you want to print to a terminal instead of "how" it should be formatted.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'output_mode'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install output_mode
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Checkout the [demo script](bin/demo) for a basic getting started example. It uses the two prefabricated modules:
|
26
|
+
* `OutputMode::TLDR::Index` - Tabulate the data models for humans and tab ("\t") delimit it for machines
|
27
|
+
* `OutputMode::TLDR::Show` - List the data model(s) for humans and tab ("\t") delimit it for machines
|
28
|
+
|
29
|
+
The `TLDR` modules are designed for a fairly limited use case, where:
|
30
|
+
* The humanized/machine outputs is toggled if `StandardOut` is connected to a `TTY`,
|
31
|
+
* Certain columns/fields need to be hidden based on a user supplied verbosity toggle.
|
32
|
+
|
33
|
+
A basic use case would be:
|
34
|
+
|
35
|
+
```
|
36
|
+
class Foo
|
37
|
+
extend OutputMode::TLDR::Index
|
38
|
+
|
39
|
+
# Adds a "column" to the output. Fundamentally the "column" is a block transform function
|
40
|
+
register_callable(header: 'ID') { |model| model.id }
|
41
|
+
register_callable(header: 'Name') { |model| model.name }
|
42
|
+
|
43
|
+
# Show different date formats according to verbosity, only one column will be displayed
|
44
|
+
register_callable(header: 'Create Date', verbose: true) { |m| m.create_date.to_rfc3339 }
|
45
|
+
register_callable(header: 'Create Date', verbose false) { |m| m.create_date.strftime("%F") }
|
46
|
+
end
|
47
|
+
|
48
|
+
data = [... data models ...]
|
49
|
+
puts Foo.build_output.render(*data)
|
50
|
+
```
|
51
|
+
|
52
|
+
If this use case becomes to restrictive, look at the internals of the `TLDR` modules on how they are implemented. This will give you ideas on how to implement the `outputs`/`modes` for your bespoke use case.
|
53
|
+
|
54
|
+
## Development
|
55
|
+
|
56
|
+
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.
|
57
|
+
|
58
|
+
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).
|
59
|
+
|
60
|
+
## Contributing
|
61
|
+
|
62
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/WilliamMcCumstie/output_mode.
|
63
|
+
|
64
|
+
## Copyright and License
|
65
|
+
|
66
|
+
See [LICENSE](LICENSE.txt) for dual licensing details.
|
67
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#==============================================================================
|
2
|
+
# Copyright 2020 William McCumstie
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
#==============================================================================
|
26
|
+
|
27
|
+
require "bundler/gem_tasks"
|
28
|
+
require "rspec/core/rake_task"
|
29
|
+
|
30
|
+
RSpec::Core::RakeTask.new(:spec)
|
31
|
+
|
32
|
+
task :default => :spec
|
data/bin/console
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#==============================================================================
|
3
|
+
# Copyright 2020 William McCumstie
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
19
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
20
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
21
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
22
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
23
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
24
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
25
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
#==============================================================================
|
27
|
+
|
28
|
+
require "bundler/setup"
|
29
|
+
require "output_mode"
|
30
|
+
|
31
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
32
|
+
# with your gem easier. You can also use a different console, if you like.
|
33
|
+
|
34
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
35
|
+
require "pry"
|
36
|
+
Pry.start
|
37
|
+
|
data/bin/demo
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#==============================================================================
|
3
|
+
# Refer to LICENSE.txt for licensing terms
|
4
|
+
#==============================================================================
|
5
|
+
|
6
|
+
|
7
|
+
require "bundler/setup"
|
8
|
+
require "output_mode"
|
9
|
+
|
10
|
+
module DemoIndex
|
11
|
+
extend OutputMode::TLDR::Index
|
12
|
+
|
13
|
+
register_callable(header: 'Integer') { |i| i }
|
14
|
+
register_callable(header: 'Standard') { 'always visible' }
|
15
|
+
register_callable(header: 'Verbose', verbose: true) { 'verbose visible' }
|
16
|
+
register_callable(header: 'Simplified', verbose: false) { 'simplified visible' }
|
17
|
+
register_callable(header: 'Yes/True') { true }
|
18
|
+
register_callable(header: 'No/False') { false }
|
19
|
+
register_callable(header: 'Missing') { nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
module DemoShow
|
23
|
+
extend OutputMode::TLDR::Show
|
24
|
+
|
25
|
+
register_callable(header: 'Integer') { |i| i }
|
26
|
+
register_callable(header: 'Standard') { 'always visible' }
|
27
|
+
register_callable(header: 'Verbose', verbose: true) { 'verbose visible' }
|
28
|
+
register_callable(header: 'Simplified', verbose: false) { 'simplified visible' }
|
29
|
+
register_callable(header: 'Yes/True') { true }
|
30
|
+
register_callable(header: 'No/False') { false }
|
31
|
+
register_callable(header: 'Missing') { nil }
|
32
|
+
end
|
33
|
+
|
34
|
+
data = [1, 2, 3]
|
35
|
+
|
36
|
+
puts <<~EOF
|
37
|
+
#==============================================================================
|
38
|
+
# Demo Verbose Index
|
39
|
+
#==============================================================================
|
40
|
+
#{DemoIndex.build_output(verbose: true).render(*data)}
|
41
|
+
|
42
|
+
#==============================================================================
|
43
|
+
# Demo "Simplified" Index
|
44
|
+
# NOTE: Disabled for non-interactive shell, shows the verbose output instead
|
45
|
+
#==============================================================================
|
46
|
+
#{DemoIndex.build_output(verbose: false).render(*data)}
|
47
|
+
|
48
|
+
#==============================================================================
|
49
|
+
# Demo Verbose Show
|
50
|
+
#==============================================================================
|
51
|
+
#{DemoShow.build_output(verbose: true).render(*data)}
|
52
|
+
|
53
|
+
#==============================================================================
|
54
|
+
# Demo "Simplified" Show
|
55
|
+
# NOTE: Disabled for non-interactive shell, shows the verbose output instead
|
56
|
+
#==============================================================================
|
57
|
+
#{DemoShow.build_output(verbose: false).render(*data)}
|
58
|
+
EOF
|
59
|
+
|
60
|
+
|
data/bin/setup
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
#==============================================================================
|
3
|
+
# Copyright 2020 William McCumstie
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
19
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
20
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
21
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
22
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
23
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
24
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
25
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
#==============================================================================
|
27
|
+
|
28
|
+
set -euo pipefail
|
29
|
+
IFS=$'\n\t'
|
30
|
+
set -vx
|
31
|
+
|
32
|
+
bundle install
|
33
|
+
|
34
|
+
# Do any other automated setup that you need to do here
|
data/lib/output_mode.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#==============================================================================
|
2
|
+
# Copyright 2020 William McCumstie
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
#==============================================================================
|
26
|
+
|
27
|
+
require "output_mode/version"
|
28
|
+
require 'output_mode/errors'
|
29
|
+
|
30
|
+
require 'output_mode/outputs'
|
31
|
+
require 'output_mode/callable'
|
32
|
+
require 'output_mode/builder_dsl'
|
33
|
+
require 'output_mode/tldr'
|
34
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#==============================================================================
|
2
|
+
# Copyright 2020 William McCumstie
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
#==============================================================================
|
26
|
+
|
27
|
+
module OutputMode
|
28
|
+
module BuilderDSL
|
29
|
+
# The callable objects an `output` can be built from
|
30
|
+
def output_callables
|
31
|
+
@output_callables ||= Callables.new
|
32
|
+
end
|
33
|
+
|
34
|
+
# Adds a new callable object to {output_callables}
|
35
|
+
# @abstract This maybe overridden to restrict the method signature
|
36
|
+
# @param config Directly provided to {OutputMode::Callable#initialize}
|
37
|
+
# @yield Directly provided to {OutputMode::Callable#initialize}
|
38
|
+
def register_callable(**config, &b)
|
39
|
+
output_callables << Callable.new(**config, &b)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Provides the base method signature
|
43
|
+
# @abstract Must be implemented by the main class/module
|
44
|
+
# @return OutputMode::Output The newly created output
|
45
|
+
def build_output(**config)
|
46
|
+
raise NotImplementedError
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,138 @@
|
|
1
|
+
#==============================================================================
|
2
|
+
# Copyright 2020 William McCumstie
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
#==============================================================================
|
26
|
+
|
27
|
+
module OutputMode
|
28
|
+
# Internal array like object that will convert procs to Callable
|
29
|
+
class Callables < Array
|
30
|
+
# @api private
|
31
|
+
def initialize(callables = nil)
|
32
|
+
case callables
|
33
|
+
when Array
|
34
|
+
super().tap do |all|
|
35
|
+
callables.each { |c| all << c }
|
36
|
+
end
|
37
|
+
when nil
|
38
|
+
super()
|
39
|
+
else
|
40
|
+
raise "Can not convert #{callables.class} into a #{self.class}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def <<(item)
|
45
|
+
if item.is_a? Callable
|
46
|
+
super
|
47
|
+
elsif item.respond_to?(:call)
|
48
|
+
super(Callable.new(&item))
|
49
|
+
else
|
50
|
+
raise Error, "#{item.class} is not callable"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Callable
|
56
|
+
# @!attribute [r] modes
|
57
|
+
# @return [Hash<Symbol => Boolean>] Returns the configured modes
|
58
|
+
# @!attribute [r] callable
|
59
|
+
# @return [#call] Returns the underlining block
|
60
|
+
# @!attribute [r] config
|
61
|
+
# @return [Hash] An arbitrary hash of key-value pairs
|
62
|
+
attr_reader :modes, :callable, :config
|
63
|
+
|
64
|
+
# Wraps a block/ callable object with mode query methods
|
65
|
+
# @overload initialize(modes: {}, **config)
|
66
|
+
# @param [Hash<Symbol => Boolean>] modes: Provide the preconfigured modes
|
67
|
+
# @param **config An arbitrary hash to be stored on the object
|
68
|
+
# @yield Executed by the {#call} method
|
69
|
+
# @yieldparam *a The arguments provided to {#call}
|
70
|
+
# @overload initialize(modes: []) { |*a| ... }
|
71
|
+
# @param [Array] modes: The preconfigured modes as an array, this will be converted to a hash
|
72
|
+
def initialize(modes: {}, **config, &block)
|
73
|
+
@callable = block
|
74
|
+
@modes = if modes.is_a? Hash
|
75
|
+
modes.reject { |_, v| v.nil? }
|
76
|
+
.map { |k, v| [k, v ? true : false] }
|
77
|
+
.to_h
|
78
|
+
else
|
79
|
+
modes.map { |k| [k, true] }.to_h
|
80
|
+
end
|
81
|
+
@config = config
|
82
|
+
end
|
83
|
+
|
84
|
+
# Handles the dynamic +<query>?+ and +<explicit-negation>!+ methods
|
85
|
+
#
|
86
|
+
# The +<query>?+ methods check if the mode has been set on the object. If
|
87
|
+
# +query+ is a defined mode, then the value is directly pulled from #{modes}.
|
88
|
+
# Undefined modes will return +false+.
|
89
|
+
#
|
90
|
+
# The +<explicit-negation>!+ methods are similar to queries, but undefined modes
|
91
|
+
# will return +true+. This means +<explicit-negation>!+ methods only return +false+
|
92
|
+
# if the +explicit-negation+ mode has been set to +false+ in {#modes}.
|
93
|
+
#
|
94
|
+
# @return [Boolean] The result of the query or explicit-negation
|
95
|
+
# @raises [NoMethodError] All other method calls
|
96
|
+
def method_missing(s, *a, &b)
|
97
|
+
mode = s[0..-2].to_sym
|
98
|
+
case method_char(s)
|
99
|
+
when '?'
|
100
|
+
modes.fetch(mode, false)
|
101
|
+
when '!'
|
102
|
+
modes.fetch(mode, true)
|
103
|
+
else
|
104
|
+
super
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Responds +true+ for valid dynamic methods
|
109
|
+
# @param [Symbol] s The method to be tested
|
110
|
+
# @return [Boolean] The truthiness of the underlining call to {#method_char}
|
111
|
+
def respond_to_missing?(s, *_)
|
112
|
+
method_char(s) ? true : false
|
113
|
+
end
|
114
|
+
|
115
|
+
# Determines the "type" associated with a dynamic method
|
116
|
+
# @overload method_char(bang!)
|
117
|
+
# @param bang! A symbol/string ending with !
|
118
|
+
# @return ['!']
|
119
|
+
# @overload method_char(question?)
|
120
|
+
# @param question? A symbol/string ending with ?
|
121
|
+
# @return ['?']
|
122
|
+
# @overload method_char(other)
|
123
|
+
# @param other Any other symbol/string
|
124
|
+
# @return [Nil]
|
125
|
+
def method_char(s)
|
126
|
+
char = s[-1]
|
127
|
+
['?', '!'].include?(char) ? char : nil
|
128
|
+
end
|
129
|
+
|
130
|
+
# Calls the underlining block
|
131
|
+
# @param *a The arguments to be provided to {#callable}
|
132
|
+
# @return The results from the block
|
133
|
+
def call(*a)
|
134
|
+
callable.call(*a)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|