toys-core 0.11.5 → 0.12.0
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 +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +1 -1
- data/lib/toys-core.rb +4 -1
- data/lib/toys/acceptor.rb +3 -3
- data/lib/toys/arg_parser.rb +6 -7
- data/lib/toys/cli.rb +44 -14
- data/lib/toys/compat.rb +19 -22
- data/lib/toys/completion.rb +3 -1
- data/lib/toys/context.rb +2 -2
- data/lib/toys/core.rb +1 -1
- data/lib/toys/dsl/base.rb +85 -0
- data/lib/toys/dsl/flag.rb +3 -3
- data/lib/toys/dsl/flag_group.rb +7 -7
- data/lib/toys/dsl/internal.rb +206 -0
- data/lib/toys/dsl/positional_arg.rb +3 -3
- data/lib/toys/dsl/tool.rb +174 -216
- data/lib/toys/errors.rb +1 -0
- data/lib/toys/flag.rb +15 -18
- data/lib/toys/flag_group.rb +5 -4
- data/lib/toys/input_file.rb +4 -4
- data/lib/toys/loader.rb +189 -50
- data/lib/toys/middleware.rb +1 -1
- data/lib/toys/mixin.rb +2 -2
- data/lib/toys/positional_arg.rb +3 -3
- data/lib/toys/settings.rb +900 -0
- data/lib/toys/source_info.rb +121 -18
- data/lib/toys/standard_middleware/apply_config.rb +5 -4
- data/lib/toys/standard_middleware/set_default_descriptions.rb +18 -18
- data/lib/toys/standard_middleware/show_help.rb +17 -5
- data/lib/toys/standard_mixins/exec.rb +12 -14
- data/lib/toys/standard_mixins/git_cache.rb +48 -0
- data/lib/toys/standard_mixins/xdg.rb +56 -0
- data/lib/toys/template.rb +2 -2
- data/lib/toys/{tool.rb → tool_definition.rb} +100 -41
- data/lib/toys/utils/exec.rb +4 -5
- data/lib/toys/utils/gems.rb +8 -7
- data/lib/toys/utils/git_cache.rb +184 -0
- data/lib/toys/utils/help_text.rb +90 -34
- data/lib/toys/utils/terminal.rb +1 -1
- data/lib/toys/utils/xdg.rb +293 -0
- metadata +14 -7
data/lib/toys/utils/terminal.rb
CHANGED
@@ -0,0 +1,293 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Toys
|
4
|
+
module Utils
|
5
|
+
##
|
6
|
+
# A class that provides tools for working with the XDG Base Directory
|
7
|
+
# Specification.
|
8
|
+
#
|
9
|
+
# This class provides utility methods that locate base directories and
|
10
|
+
# search paths for application state, configuration, caches, and other
|
11
|
+
# data, according to the [XDG Base Directory Spec version
|
12
|
+
# 0.8](https://specifications.freedesktop.org/basedir-spec/0.8/).
|
13
|
+
#
|
14
|
+
# Tools can use the `:xdg` mixin for convenient access to this class.
|
15
|
+
#
|
16
|
+
# ### Example
|
17
|
+
#
|
18
|
+
# require "toys/utils/xdg"
|
19
|
+
#
|
20
|
+
# xdg = Toys::Utils::XDG.new
|
21
|
+
#
|
22
|
+
# # Get config file paths, in order from most to least inportant
|
23
|
+
# config_files = xdg.lookup_config("my-config.toml")
|
24
|
+
# config_files.each { |path| read_my_config(path) }
|
25
|
+
#
|
26
|
+
# ### Windows operation
|
27
|
+
#
|
28
|
+
# The Spec assumes a unix-like environment, and cannot be applied directly
|
29
|
+
# to Windows without modification. In general, this class will function on
|
30
|
+
# Windows, but with the following caveats:
|
31
|
+
#
|
32
|
+
# * All file paths must use Windows-style absolute paths, beginning with
|
33
|
+
# the drive letter.
|
34
|
+
# * Environment variables that can contain multiple paths (`XDG_*_DIRS`)
|
35
|
+
# use the Windows path delimiter (`;`) rather than the unix path
|
36
|
+
# delimiter (`:`).
|
37
|
+
# * Defaults for home directories (`XDG_*_HOME`) will follow unix
|
38
|
+
# conventions, using subdirectories under the user's profile directory
|
39
|
+
# rather than the Windows known folder paths.
|
40
|
+
# * Defaults for search paths (`XDG_*_DIRS`) will be empty and will not
|
41
|
+
# use the Windows known folder paths.
|
42
|
+
#
|
43
|
+
class XDG
|
44
|
+
##
|
45
|
+
# Create an instance of XDG.
|
46
|
+
#
|
47
|
+
# @param env [Hash{String=>String}] the environment variables. Normally,
|
48
|
+
# you can omit this argument, as it will default to `::ENV`.
|
49
|
+
#
|
50
|
+
def initialize(env: ::ENV)
|
51
|
+
@env = env
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Returns the absolute path to the current user's home directory.
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
#
|
59
|
+
def home_dir
|
60
|
+
@home_dir ||= validate_dir_env("HOME") || ::Dir.home
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Returns the absolute path to the single base directory relative to
|
65
|
+
# which user-specific data files should be written.
|
66
|
+
# Corresponds to the value of the `$XDG_DATA_HOME` environment variable
|
67
|
+
# and its defaults according to the XDG Base Directory Spec.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
#
|
71
|
+
def data_home
|
72
|
+
@data_home ||=
|
73
|
+
validate_dir_env("XDG_DATA_HOME") || ::File.join(home_dir, ".local", "share")
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Returns the absolute path to the single base directory relative to
|
78
|
+
# which user-specific configuration files should be written.
|
79
|
+
# Corresponds to the value of the `$XDG_CONFIG_HOME` environment variable
|
80
|
+
# and its defaults according to the XDG Base Directory Spec.
|
81
|
+
#
|
82
|
+
# @return [String]
|
83
|
+
#
|
84
|
+
def config_home
|
85
|
+
@config_home ||= validate_dir_env("XDG_CONFIG_HOME") || ::File.join(home_dir, ".config")
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Returns the absolute path to the single base directory relative to
|
90
|
+
# which user-specific state files should be written.
|
91
|
+
# Corresponds to the value of the `$XDG_STATE_HOME` environment variable
|
92
|
+
# and its defaults according to the XDG Base Directory Spec.
|
93
|
+
#
|
94
|
+
# @return [String]
|
95
|
+
#
|
96
|
+
def state_home
|
97
|
+
@state_home ||=
|
98
|
+
validate_dir_env("XDG_STATE_HOME") || ::File.join(home_dir, ".local", "state")
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Returns the absolute path to the single base directory relative to
|
103
|
+
# which user-specific non-essential (cached) data should be written.
|
104
|
+
# Corresponds to the value of the `$XDG_CACHE_HOME` environment variable
|
105
|
+
# and its defaults according to the XDG Base Directory Spec.
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
#
|
109
|
+
def cache_home
|
110
|
+
@cache_home ||= validate_dir_env("XDG_CACHE_HOME") || ::File.join(home_dir, ".cache")
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Returns the absolute path to the single base directory relative to
|
115
|
+
# which user-specific executable files may be written.
|
116
|
+
# Returns the value of `$HOME/.local/bin` as specified by the XDG Base
|
117
|
+
# Directory Spec.
|
118
|
+
#
|
119
|
+
# @return [String]
|
120
|
+
#
|
121
|
+
def executable_home
|
122
|
+
@executable_home ||= ::File.join(home_dir, ".local", "bin")
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Returns the set of preference ordered base directories relative to
|
127
|
+
# which data files should be searched, as an array of absolute paths.
|
128
|
+
# The array is ordered from most to least important, and does _not_
|
129
|
+
# include the data home directory.
|
130
|
+
# Corresponds to the value of the `$XDG_DATA_DIRS` environment variable
|
131
|
+
# and its defaults according to the XDG Base Directory Spec.
|
132
|
+
#
|
133
|
+
# @return [Array<String>]
|
134
|
+
#
|
135
|
+
def data_dirs
|
136
|
+
@data_dirs ||= validate_dirs_env("XDG_DATA_DIRS") ||
|
137
|
+
validate_dirs(["/usr/local/share", "/usr/share"]) || []
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Returns the set of preference ordered base directories relative to
|
142
|
+
# which configuration files should be searched, as an array of absolute
|
143
|
+
# paths. The array is ordered from most to least important, and does
|
144
|
+
# _not_ include the config home directory.
|
145
|
+
# Corresponds to the value of the `$XDG_CONFIG_DIRS` environment variable
|
146
|
+
# and its defaults according to the XDG Base Directory Spec.
|
147
|
+
#
|
148
|
+
# @return [Array<String>]
|
149
|
+
#
|
150
|
+
def config_dirs
|
151
|
+
@config_dirs ||= validate_dirs_env("XDG_CONFIG_DIRS") ||
|
152
|
+
validate_dirs(["/etc/xdg"]) || []
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Returns the absolute path to the single base directory relative to
|
157
|
+
# which user-specific runtime files and other file objects should be
|
158
|
+
# placed. May return `nil` if no such directory could be determined.
|
159
|
+
#
|
160
|
+
# @return [String,nil]
|
161
|
+
#
|
162
|
+
def runtime_dir
|
163
|
+
@runtime_dir = validate_dir_env("XDG_RUNTIME_DIR") unless defined? @runtime_dir
|
164
|
+
@runtime_dir
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Searches the data directories for an object with the given relative
|
169
|
+
# path, and returns an array of absolute paths to all objects found in
|
170
|
+
# the data directories (i.e. in {#data_dirs} or {#data_home}), in order
|
171
|
+
# from most to least important.
|
172
|
+
#
|
173
|
+
# @param path [String] Relative path of the object to search for
|
174
|
+
# @param type [String,Symbol,Array<String,Symbol>] The type(s) of objects
|
175
|
+
# to find. You can specify any of the types defined by
|
176
|
+
# [File::Stat#ftype](https://ruby-doc.org/core/File/Stat.html#method-i-ftype),
|
177
|
+
# such as `file` or `directory`, or the special type `any`. Types can
|
178
|
+
# be specified as strings or the corresponding symbols. If this
|
179
|
+
# argument is not provided, the default of `file` is used.
|
180
|
+
# @return [Array<String>]
|
181
|
+
#
|
182
|
+
def lookup_data(path, type: :file)
|
183
|
+
lookup_internal([data_home] + data_dirs, path, type)
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Searches the config directories for an object with the given relative
|
188
|
+
# path, and returns an array of absolute paths to all objects found in
|
189
|
+
# the config directories (i.e. in {#config_dirs} or {#config_home}), in
|
190
|
+
# order from most to least important.
|
191
|
+
#
|
192
|
+
# @param path [String] Relative path of the object to search for
|
193
|
+
# @param type [String,Symbol,Array<String,Symbol>] The type(s) of objects
|
194
|
+
# to find. You can specify any of the types defined by
|
195
|
+
# [File::Stat#ftype](https://ruby-doc.org/core/File/Stat.html#method-i-ftype),
|
196
|
+
# such as `file` or `directory`, or the special type `any`. Types can
|
197
|
+
# be specified as strings or the corresponding symbols. If this
|
198
|
+
# argument is not provided, the default of `file` is used.
|
199
|
+
# @return [Array<String>]
|
200
|
+
#
|
201
|
+
def lookup_config(path, type: :file)
|
202
|
+
lookup_internal([config_home] + config_dirs, path, type)
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Returns the absolute path to a directory under {#data_home}, creating
|
207
|
+
# it if it doesn't already exist.
|
208
|
+
#
|
209
|
+
# @param path [String] The relative path to the subdir within the base
|
210
|
+
# data directory.
|
211
|
+
# @return [String] The absolute path to the subdir.
|
212
|
+
# @raise [Errno::EEXIST] If a non-directory already exists there
|
213
|
+
#
|
214
|
+
def ensure_data_subdir(path)
|
215
|
+
ensure_subdir_internal(data_home, path)
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Returns the absolute path to a directory under {#config_home}, creating
|
220
|
+
# it if it doesn't already exist.
|
221
|
+
#
|
222
|
+
# @param path [String] The relative path to the subdir within the base
|
223
|
+
# config directory.
|
224
|
+
# @return [String] The absolute path to the subdir.
|
225
|
+
# @raise [Errno::EEXIST] If a non-directory already exists there
|
226
|
+
#
|
227
|
+
def ensure_config_subdir(path)
|
228
|
+
ensure_subdir_internal(config_home, path)
|
229
|
+
end
|
230
|
+
|
231
|
+
##
|
232
|
+
# Returns the absolute path to a directory under {#state_home}, creating
|
233
|
+
# it if it doesn't already exist.
|
234
|
+
#
|
235
|
+
# @param path [String] The relative path to the subdir within the base
|
236
|
+
# state directory.
|
237
|
+
# @return [String] The absolute path to the subdir.
|
238
|
+
# @raise [Errno::EEXIST] If a non-directory already exists there
|
239
|
+
#
|
240
|
+
def ensure_state_subdir(path)
|
241
|
+
ensure_subdir_internal(state_home, path)
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Returns the absolute path to a directory under {#cache_home}, creating
|
246
|
+
# it if it doesn't already exist.
|
247
|
+
#
|
248
|
+
# @param path [String] The relative path to the subdir within the base
|
249
|
+
# cache directory.
|
250
|
+
# @return [String] The absolute path to the subdir.
|
251
|
+
# @raise [Errno::EEXIST] If a non-directory already exists there
|
252
|
+
#
|
253
|
+
def ensure_cache_subdir(path)
|
254
|
+
ensure_subdir_internal(cache_home, path)
|
255
|
+
end
|
256
|
+
|
257
|
+
private
|
258
|
+
|
259
|
+
def validate_dir_env(name)
|
260
|
+
path = @env[name].to_s
|
261
|
+
!path.empty? && Compat.absolute_path?(path) ? path : nil
|
262
|
+
end
|
263
|
+
|
264
|
+
def validate_dirs_env(name)
|
265
|
+
validate_dirs(@env[name].to_s.split(::File::PATH_SEPARATOR))
|
266
|
+
end
|
267
|
+
|
268
|
+
def validate_dirs(paths)
|
269
|
+
paths = paths.find_all { |path| Compat.absolute_path?(path) }
|
270
|
+
paths.empty? ? nil : paths
|
271
|
+
end
|
272
|
+
|
273
|
+
def lookup_internal(dirs, path, types)
|
274
|
+
results = []
|
275
|
+
types = Array(types).map(&:to_s)
|
276
|
+
dirs.each do |dir|
|
277
|
+
to_check = ::File.join(dir, path)
|
278
|
+
stat = ::File.stat(to_check) rescue nil # rubocop:disable Style/RescueModifier
|
279
|
+
if stat&.readable? && (types.include?("any") || types.include?(stat.ftype))
|
280
|
+
results << to_check
|
281
|
+
end
|
282
|
+
end
|
283
|
+
results
|
284
|
+
end
|
285
|
+
|
286
|
+
def ensure_subdir_internal(base_dir, path)
|
287
|
+
path = ::File.join(base_dir, path)
|
288
|
+
::FileUtils.mkdir_p(path, mode: 0o700)
|
289
|
+
path
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toys-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Toys-Core is the command line tool framework underlying Toys. It can
|
14
14
|
be used to create command line executables using the Toys DSL and classes.
|
@@ -31,8 +31,10 @@ files:
|
|
31
31
|
- lib/toys/completion.rb
|
32
32
|
- lib/toys/context.rb
|
33
33
|
- lib/toys/core.rb
|
34
|
+
- lib/toys/dsl/base.rb
|
34
35
|
- lib/toys/dsl/flag.rb
|
35
36
|
- lib/toys/dsl/flag_group.rb
|
37
|
+
- lib/toys/dsl/internal.rb
|
36
38
|
- lib/toys/dsl/positional_arg.rb
|
37
39
|
- lib/toys/dsl/tool.rb
|
38
40
|
- lib/toys/errors.rb
|
@@ -44,6 +46,7 @@ files:
|
|
44
46
|
- lib/toys/mixin.rb
|
45
47
|
- lib/toys/module_lookup.rb
|
46
48
|
- lib/toys/positional_arg.rb
|
49
|
+
- lib/toys/settings.rb
|
47
50
|
- lib/toys/source_info.rb
|
48
51
|
- lib/toys/standard_middleware/add_verbosity_flags.rb
|
49
52
|
- lib/toys/standard_middleware/apply_config.rb
|
@@ -55,24 +58,28 @@ files:
|
|
55
58
|
- lib/toys/standard_mixins/exec.rb
|
56
59
|
- lib/toys/standard_mixins/fileutils.rb
|
57
60
|
- lib/toys/standard_mixins/gems.rb
|
61
|
+
- lib/toys/standard_mixins/git_cache.rb
|
58
62
|
- lib/toys/standard_mixins/highline.rb
|
59
63
|
- lib/toys/standard_mixins/terminal.rb
|
64
|
+
- lib/toys/standard_mixins/xdg.rb
|
60
65
|
- lib/toys/template.rb
|
61
|
-
- lib/toys/
|
66
|
+
- lib/toys/tool_definition.rb
|
62
67
|
- lib/toys/utils/completion_engine.rb
|
63
68
|
- lib/toys/utils/exec.rb
|
64
69
|
- lib/toys/utils/gems.rb
|
70
|
+
- lib/toys/utils/git_cache.rb
|
65
71
|
- lib/toys/utils/help_text.rb
|
66
72
|
- lib/toys/utils/terminal.rb
|
73
|
+
- lib/toys/utils/xdg.rb
|
67
74
|
- lib/toys/wrappable_string.rb
|
68
75
|
homepage: https://github.com/dazuma/toys
|
69
76
|
licenses:
|
70
77
|
- MIT
|
71
78
|
metadata:
|
72
|
-
changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.
|
79
|
+
changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.12.0/file.CHANGELOG.html
|
73
80
|
source_code_uri: https://github.com/dazuma/toys/tree/main/toys-core
|
74
81
|
bug_tracker_uri: https://github.com/dazuma/toys/issues
|
75
|
-
documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.
|
82
|
+
documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.12.0
|
76
83
|
post_install_message:
|
77
84
|
rdoc_options: []
|
78
85
|
require_paths:
|
@@ -81,14 +88,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
88
|
requirements:
|
82
89
|
- - ">="
|
83
90
|
- !ruby/object:Gem::Version
|
84
|
-
version: 2.
|
91
|
+
version: 2.4.0
|
85
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
93
|
requirements:
|
87
94
|
- - ">="
|
88
95
|
- !ruby/object:Gem::Version
|
89
96
|
version: '0'
|
90
97
|
requirements: []
|
91
|
-
rubygems_version: 3.1.
|
98
|
+
rubygems_version: 3.1.6
|
92
99
|
signing_key:
|
93
100
|
specification_version: 4
|
94
101
|
summary: Framework for creating command line executables
|