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