toys-core 0.3.2
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.
- checksums.yaml +7 -0
- data/.yardopts +9 -0
- data/CHANGELOG.md +21 -0
- data/LICENSE.md +29 -0
- data/README.md +30 -0
- data/lib/toys-core.rb +54 -0
- data/lib/toys/alias.rb +94 -0
- data/lib/toys/cli.rb +268 -0
- data/lib/toys/config_dsl.rb +356 -0
- data/lib/toys/context.rb +278 -0
- data/lib/toys/core_version.rb +36 -0
- data/lib/toys/errors.rb +42 -0
- data/lib/toys/helpers.rb +52 -0
- data/lib/toys/helpers/exec.rb +469 -0
- data/lib/toys/helpers/file_utils.rb +39 -0
- data/lib/toys/loader.rb +381 -0
- data/lib/toys/middleware.rb +124 -0
- data/lib/toys/middleware/add_verbosity_switches.rb +99 -0
- data/lib/toys/middleware/base.rb +51 -0
- data/lib/toys/middleware/handle_usage_errors.rb +67 -0
- data/lib/toys/middleware/set_default_descriptions.rb +131 -0
- data/lib/toys/middleware/show_usage.rb +170 -0
- data/lib/toys/middleware/show_version.rb +99 -0
- data/lib/toys/template.rb +123 -0
- data/lib/toys/templates.rb +55 -0
- data/lib/toys/templates/clean.rb +82 -0
- data/lib/toys/templates/gem_build.rb +121 -0
- data/lib/toys/templates/minitest.rb +126 -0
- data/lib/toys/templates/rubocop.rb +86 -0
- data/lib/toys/templates/yardoc.rb +101 -0
- data/lib/toys/tool.rb +749 -0
- data/lib/toys/utils/module_lookup.rb +101 -0
- data/lib/toys/utils/usage.rb +196 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 87e34f50eb16af11bc970c170e7750509e026b237ec37352be05198860bfdeae
|
4
|
+
data.tar.gz: 6bdaeaa6577d75c25b0efd17406792c24e3f6dd57326a52badd60495dc9170cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ee18128015b86041547bcdab1e7ec4bea05a41e0eff06c30a4003f032cc1ca335c7e7b593236ea140e65f43b4f31a752ceee5c57c787227b88d3144eac22b147
|
7
|
+
data.tar.gz: e4c7b13f825d6b4131db5e08a56a306652e2f532de1095758fde3be3fe509635629cc7725241b4bd3206ce1b414ed0cc4bd09aa480bbe4f335e8b3abd4ffc7c7
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Release History
|
2
|
+
|
3
|
+
### 0.3.2 / 2018-05-07
|
4
|
+
|
5
|
+
* CHANGED: Split core engine out into "toys-core" from the "toys" gem.
|
6
|
+
* CHANGED: Renamed path types to "search" and "config" paths, and restricted the former to the CLI.
|
7
|
+
* CHANGED: Removed aliasing from the Tool interface and reimplemented in the Loader.
|
8
|
+
* CHANGED: Default descriptions are now set via a middleware rather than in the Tool.
|
9
|
+
* CHANGED: Renamed most of the middleware classes.
|
10
|
+
* CHANGED: Combined usage-displaying middleware.
|
11
|
+
* CHANGED: Standard paths logic moved from CLI to StandardCLI.
|
12
|
+
* ADDED: Middleware that responds to the "--version" switch.
|
13
|
+
* ADDED: Context#new_cli that lets you run sub-instances of toys.
|
14
|
+
* IMPROVED: Middleware can now be referenced by class and constructed implicitly.
|
15
|
+
* IMPROVED: Usage error handler can now have its exit code configured.
|
16
|
+
* IMPROVED: Help and verbosity middlewares can have their switches configured.
|
17
|
+
* IMPROVED: Help middleware can search for keywords in subcommands.
|
18
|
+
* IMPROVED: Help middleware displays the config path in verbose mode.
|
19
|
+
* IMPROVED: Context::EXIT_ON_NONZERO_STATUS controls Context#run behavior.
|
20
|
+
* DOCS: Expanded middleware documentation
|
21
|
+
* INTERNAL: Removed Context::Base and just used CLI as base context
|
data/LICENSE.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# License
|
2
|
+
|
3
|
+
Copyright 2018 Daniel Azuma
|
4
|
+
|
5
|
+
All rights reserved.
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without
|
8
|
+
modification, are permitted provided that the following conditions are met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer.
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
14
|
+
and/or other materials provided with the distribution.
|
15
|
+
* Neither the name of the copyright holder, nor the names of any other
|
16
|
+
contributors to this software, may be used to endorse or promote products
|
17
|
+
derived from this software without specific prior written permission.
|
18
|
+
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Toys
|
2
|
+
|
3
|
+
Toys is a command line binary that lets you build your own suite of command
|
4
|
+
line tools (with commands and subcommands) using a Ruby DSL. Commands can be
|
5
|
+
defined globally or scoped to directories.
|
6
|
+
|
7
|
+
Toys-Core is the command line tool framework underlying Toys. It can be used
|
8
|
+
to create command line binaries using the Toys DSL.
|
9
|
+
|
10
|
+
## Quick Start
|
11
|
+
|
12
|
+
(TODO)
|
13
|
+
|
14
|
+
## Contributing
|
15
|
+
|
16
|
+
While we appreciate contributions, please note that this software is currently
|
17
|
+
highly experimental, and the code is evolving very rapidly. Please contact the
|
18
|
+
author before embarking on a major pull request. More detailed contribution
|
19
|
+
guidelines will be provided when the software stabilizes further.
|
20
|
+
|
21
|
+
The source can be found on Github at
|
22
|
+
[https://github.com/dazuma/toys](https://github.com/dazuma/toys)
|
23
|
+
|
24
|
+
## License
|
25
|
+
|
26
|
+
Copyright 2018 Daniel Azuma
|
27
|
+
|
28
|
+
This software is licensed under the 3-clause BSD license.
|
29
|
+
|
30
|
+
See the LICENSE.md file for more information.
|
data/lib/toys-core.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright 2018 Daniel Azuma
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
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
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * 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
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
+
# contributors to this software, may be used to endorse or promote products
|
15
|
+
# derived from this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
;
|
29
|
+
|
30
|
+
##
|
31
|
+
# Toys is a Ruby library and command line tool that lets you build your own
|
32
|
+
# command line suite of tools (with commands and subcommands) using a Ruby DSL.
|
33
|
+
# You can define commands globally or configure special commands scoped to
|
34
|
+
# individual directories.
|
35
|
+
#
|
36
|
+
module Toys
|
37
|
+
##
|
38
|
+
# Namespace for common utility classes.
|
39
|
+
#
|
40
|
+
module Utils; end
|
41
|
+
end
|
42
|
+
|
43
|
+
require "toys/alias"
|
44
|
+
require "toys/cli"
|
45
|
+
require "toys/config_dsl"
|
46
|
+
require "toys/context"
|
47
|
+
require "toys/core_version"
|
48
|
+
require "toys/errors"
|
49
|
+
require "toys/helpers"
|
50
|
+
require "toys/loader"
|
51
|
+
require "toys/middleware"
|
52
|
+
require "toys/template"
|
53
|
+
require "toys/templates"
|
54
|
+
require "toys/tool"
|
data/lib/toys/alias.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Copyright 2018 Daniel Azuma
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
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
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * 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
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
+
# contributors to this software, may be used to endorse or promote products
|
15
|
+
# derived from this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
;
|
29
|
+
|
30
|
+
module Toys
|
31
|
+
##
|
32
|
+
# An alias is a name that refers to another name.
|
33
|
+
#
|
34
|
+
class Alias
|
35
|
+
##
|
36
|
+
# Create a new alias.
|
37
|
+
#
|
38
|
+
# @param [Array<String>] full_name The name of the alias.
|
39
|
+
# @param [String,Array<String>] target The name of the target. May either
|
40
|
+
# be a local reference (a single string) or a global reference (an
|
41
|
+
# array of strings)
|
42
|
+
#
|
43
|
+
def initialize(full_name, target)
|
44
|
+
@target_name =
|
45
|
+
if target.is_a?(::String)
|
46
|
+
full_name[0..-2] + [target]
|
47
|
+
else
|
48
|
+
target.dup
|
49
|
+
end
|
50
|
+
@target_name.freeze
|
51
|
+
@full_name = full_name.dup.freeze
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Return the name of the tool as an array of strings.
|
56
|
+
# This array may not be modified.
|
57
|
+
# @return [Array<String>]
|
58
|
+
#
|
59
|
+
attr_reader :full_name
|
60
|
+
|
61
|
+
##
|
62
|
+
# Return the name of the target as an array of strings.
|
63
|
+
# This array may not be modified.
|
64
|
+
# @return [Array<String>]
|
65
|
+
#
|
66
|
+
attr_reader :target_name
|
67
|
+
|
68
|
+
##
|
69
|
+
# Returns the local name of this tool.
|
70
|
+
# @return [String]
|
71
|
+
#
|
72
|
+
def simple_name
|
73
|
+
full_name.last
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Returns a displayable name of this tool, generally the full name
|
78
|
+
# delimited by spaces.
|
79
|
+
# @return [String]
|
80
|
+
#
|
81
|
+
def display_name
|
82
|
+
full_name.join(" ")
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Returns a displayable name of the target, generally the full name
|
87
|
+
# delimited by spaces.
|
88
|
+
# @return [String]
|
89
|
+
#
|
90
|
+
def display_target
|
91
|
+
target_name.join(" ")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/toys/cli.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
# Copyright 2018 Daniel Azuma
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
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
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * 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
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
+
# contributors to this software, may be used to endorse or promote products
|
15
|
+
# derived from this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
;
|
29
|
+
|
30
|
+
require "logger"
|
31
|
+
|
32
|
+
module Toys
|
33
|
+
##
|
34
|
+
# A Toys-based CLI.
|
35
|
+
#
|
36
|
+
# Use this class to implement a CLI using Toys.
|
37
|
+
#
|
38
|
+
class CLI
|
39
|
+
##
|
40
|
+
# Create a CLI
|
41
|
+
#
|
42
|
+
# @param [String,nil] binary_name The binary name displayed in help text.
|
43
|
+
# Optional. Defaults to the ruby program name.
|
44
|
+
# @param [String,nil] config_dir_name A directory with this name that
|
45
|
+
# appears in the loader path, is treated as a configuration directory
|
46
|
+
# whose contents are loaded into the toys configuration. Optional.
|
47
|
+
# If not provided, toplevel configuration directories are disabled.
|
48
|
+
# The default toys CLI sets this to `".toys"`.
|
49
|
+
# @param [String,nil] config_file_name A file with this name that appears
|
50
|
+
# in the loader path, is treated as a toplevel configuration file
|
51
|
+
# whose contents are loaded into the toys configuration. Optional.
|
52
|
+
# If not provided, toplevel configuration files are disabled.
|
53
|
+
# The default toys CLI sets this to `".toys.rb"`.
|
54
|
+
# @param [String,nil] index_file_name A file with this name that appears
|
55
|
+
# in any configuration directory (not just a toplevel directory) is
|
56
|
+
# loaded first as a standalone configuration file. If not provided,
|
57
|
+
# standalone configuration files are disabled.
|
58
|
+
# The default toys CLI sets this to `".toys.rb"`.
|
59
|
+
# @param [String,nil] preload_file_name A file with this name that appears
|
60
|
+
# in any configuration directory (not just a toplevel directory) is
|
61
|
+
# loaded before any configuration files. It is not treated as a
|
62
|
+
# configuration file in that the configuration DSL is not honored. You
|
63
|
+
# may use such a file to define auxiliary Ruby modules and classes that
|
64
|
+
# used by the tools defined in that directory.
|
65
|
+
# @param [Array] middleware_stack An array of middleware that will be used
|
66
|
+
# by default for all tools loaded by this CLI.
|
67
|
+
# @param [Logger,nil] logger The logger to use. If not provided, a default
|
68
|
+
# logger that writes to `STDERR` is used.
|
69
|
+
# @param [Integer,nil] base_level The logger level that should correspond
|
70
|
+
# to zero verbosity. If not provided, will default to the current level
|
71
|
+
# of the logger.
|
72
|
+
#
|
73
|
+
def initialize(
|
74
|
+
binary_name: nil,
|
75
|
+
config_dir_name: nil,
|
76
|
+
config_file_name: nil,
|
77
|
+
index_file_name: nil,
|
78
|
+
preload_file_name: nil,
|
79
|
+
middleware_stack: nil,
|
80
|
+
logger: nil,
|
81
|
+
base_level: nil
|
82
|
+
)
|
83
|
+
@logger = logger || self.class.default_logger
|
84
|
+
@base_level = base_level || @logger.level
|
85
|
+
@middleware_stack = middleware_stack || self.class.default_middleware_stack
|
86
|
+
@binary_name = binary_name || ::File.basename($PROGRAM_NAME)
|
87
|
+
@config_dir_name = config_dir_name
|
88
|
+
@config_file_name = config_file_name
|
89
|
+
@index_file_name = index_file_name
|
90
|
+
@preload_file_name = preload_file_name
|
91
|
+
@loader = Loader.new(
|
92
|
+
index_file_name: index_file_name,
|
93
|
+
preload_file_name: preload_file_name,
|
94
|
+
middleware_stack: middleware_stack
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Return the current loader for this CLI
|
100
|
+
# @return [Toys::Loader]
|
101
|
+
#
|
102
|
+
attr_reader :loader
|
103
|
+
|
104
|
+
##
|
105
|
+
# Return the effective binary name used for usage text in this CLI
|
106
|
+
# @return [String]
|
107
|
+
#
|
108
|
+
attr_reader :binary_name
|
109
|
+
|
110
|
+
##
|
111
|
+
# Return the logger used by this CLI
|
112
|
+
# @return [Logger]
|
113
|
+
#
|
114
|
+
attr_reader :logger
|
115
|
+
|
116
|
+
##
|
117
|
+
# Return the initial logger level in this CLI, used as the level for
|
118
|
+
# verbosity 0.
|
119
|
+
# @return [Integer]
|
120
|
+
#
|
121
|
+
attr_reader :base_level
|
122
|
+
|
123
|
+
##
|
124
|
+
# Add a configuration file or directory to the loader.
|
125
|
+
#
|
126
|
+
# If a CLI has a default tool set, it might use this to point to the
|
127
|
+
# directory that defines those tools. For example, the default Toys CLI
|
128
|
+
# uses this to load the builtin tools from the "builtins" directory.
|
129
|
+
#
|
130
|
+
# @param [String] path A path to add.
|
131
|
+
# @param [Boolean] high_priority Add the config at the head of the priority
|
132
|
+
# list rather than the tail.
|
133
|
+
#
|
134
|
+
def add_config_path(path, high_priority: false)
|
135
|
+
@loader.add_path(path, high_priority: high_priority)
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
# Searches the given directory for a well-known config directory and/or
|
141
|
+
# config file. If found, these are added to the loader.
|
142
|
+
#
|
143
|
+
# Typically, a CLI will use this to find toys configs in the current
|
144
|
+
# working directory, the user's home directory, or some other well-known
|
145
|
+
# general configuration-oriented directory such as "/etc".
|
146
|
+
#
|
147
|
+
# @param [String] search_path A path to search for configs.
|
148
|
+
# @param [Boolean] high_priority Add the configs at the head of the
|
149
|
+
# priority list rather than the tail.
|
150
|
+
#
|
151
|
+
def add_search_path(search_path, high_priority: false)
|
152
|
+
paths = []
|
153
|
+
if @config_file_name
|
154
|
+
file_path = ::File.join(search_path, @config_file_name)
|
155
|
+
paths << file_path if !::File.directory?(file_path) && ::File.readable?(file_path)
|
156
|
+
end
|
157
|
+
if @config_dir_name
|
158
|
+
dir_path = ::File.join(search_path, @config_dir_name)
|
159
|
+
paths << dir_path if ::File.directory?(dir_path) && ::File.readable?(dir_path)
|
160
|
+
end
|
161
|
+
@loader.add_path(paths, high_priority: high_priority)
|
162
|
+
self
|
163
|
+
end
|
164
|
+
|
165
|
+
##
|
166
|
+
# A convenience method that searches the current working directory, and all
|
167
|
+
# ancestor directories, for configs to add to the loader.
|
168
|
+
#
|
169
|
+
# @param [String] start The first directory to add. Defaults to the current
|
170
|
+
# working directory.
|
171
|
+
# @param [String] base The last directory to add. Defaults to `"/"`.
|
172
|
+
# @param [Boolean] high_priority Add the configs at the head of the
|
173
|
+
# priority list rather than the tail.
|
174
|
+
#
|
175
|
+
def add_search_path_hierarchy(start: nil, base: "/", high_priority: false)
|
176
|
+
path = start || ::Dir.pwd
|
177
|
+
paths = []
|
178
|
+
loop do
|
179
|
+
paths << path
|
180
|
+
break if path == base
|
181
|
+
next_path = ::File.dirname(path)
|
182
|
+
break if next_path == path
|
183
|
+
path = next_path
|
184
|
+
end
|
185
|
+
paths.reverse! if high_priority
|
186
|
+
paths.each do |p|
|
187
|
+
add_search_path(p, high_priority: high_priority)
|
188
|
+
end
|
189
|
+
self
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Run the CLI with the given command line arguments.
|
194
|
+
#
|
195
|
+
# @param [String...] args Command line arguments specifying which tool to
|
196
|
+
# run and what arguments to pass to it. You may pass either a single
|
197
|
+
# array of strings, or a series of string arguments.
|
198
|
+
# @param [Integer] verbosity Initial verbosity. Default is 0.
|
199
|
+
#
|
200
|
+
# @return [Integer] The resulting status code
|
201
|
+
#
|
202
|
+
def run(*args, verbosity: 0)
|
203
|
+
@loader.execute(self, args.flatten, verbosity: verbosity)
|
204
|
+
end
|
205
|
+
|
206
|
+
##
|
207
|
+
# Make a clone with the same settings but no paths in the loader.
|
208
|
+
#
|
209
|
+
# @return [Toys::CLI]
|
210
|
+
#
|
211
|
+
def empty_clone
|
212
|
+
CLI.new(binary_name: @binary_name,
|
213
|
+
config_dir_name: @config_dir_name,
|
214
|
+
config_file_name: @config_file_name,
|
215
|
+
index_file_name: @index_file_name,
|
216
|
+
preload_file_name: @preload_file_name,
|
217
|
+
middleware_stack: @middleware_stack,
|
218
|
+
logger: @logger,
|
219
|
+
base_level: @base_level)
|
220
|
+
end
|
221
|
+
|
222
|
+
class << self
|
223
|
+
##
|
224
|
+
# Returns a default set of middleware that may be used as a starting
|
225
|
+
# point for a typical CLI. This set includes:
|
226
|
+
#
|
227
|
+
# * {Toys::Middleware::HandleUsageErrors}
|
228
|
+
# * {Toys::Middleware::ShowUsage} adding the `--help` switch and
|
229
|
+
# providing default behavior for groups
|
230
|
+
# * {Toys::Middleware::AddVerbositySwitches} adding the `--verbose` and
|
231
|
+
# `--quiet` switches for managing the logger level
|
232
|
+
#
|
233
|
+
# @return [Array]
|
234
|
+
#
|
235
|
+
def default_middleware_stack
|
236
|
+
[
|
237
|
+
:handle_usage_errors,
|
238
|
+
:show_usage,
|
239
|
+
:add_verbosity_switches
|
240
|
+
]
|
241
|
+
end
|
242
|
+
|
243
|
+
##
|
244
|
+
# Returns a default logger that logs to `STDERR`.
|
245
|
+
#
|
246
|
+
# @return [Logger]
|
247
|
+
#
|
248
|
+
def default_logger
|
249
|
+
logger = ::Logger.new(::STDERR)
|
250
|
+
logger.formatter = proc do |severity, time, _progname, msg|
|
251
|
+
msg_str =
|
252
|
+
case msg
|
253
|
+
when ::String
|
254
|
+
msg
|
255
|
+
when ::Exception
|
256
|
+
"#{msg.message} (#{msg.class})\n" << (msg.backtrace || []).join("\n")
|
257
|
+
else
|
258
|
+
msg.inspect
|
259
|
+
end
|
260
|
+
timestr = time.strftime("%Y-%m-%d %H:%M:%S")
|
261
|
+
format("[%s %5s] %s\n", timestr, severity, msg_str)
|
262
|
+
end
|
263
|
+
logger.level = ::Logger::WARN
|
264
|
+
logger
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|