toys-core 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|