clamp 1.2.0.beta1 → 1.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 +5 -5
- data/.editorconfig +9 -0
- data/.gitignore +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +26 -19
- data/.travis.yml +3 -6
- data/CHANGES.md +17 -1
- data/Gemfile +8 -6
- data/Guardfile +3 -1
- data/README.md +36 -43
- data/Rakefile +8 -0
- data/clamp.gemspec +8 -6
- data/examples/admin +3 -2
- data/examples/defaulted +4 -3
- data/examples/flipflop +1 -0
- data/examples/fubar +1 -0
- data/examples/gitdown +2 -1
- data/examples/scoop +3 -2
- data/examples/speak +3 -2
- data/examples/subcommand_missing +1 -0
- data/examples/word +1 -0
- data/lib/clamp.rb +3 -1
- data/lib/clamp/attribute/declaration.rb +5 -0
- data/lib/clamp/attribute/definition.rb +25 -11
- data/lib/clamp/attribute/instance.rb +25 -3
- data/lib/clamp/command.rb +9 -1
- data/lib/clamp/errors.rb +7 -3
- data/lib/clamp/help.rb +38 -17
- data/lib/clamp/messages.rb +25 -15
- data/lib/clamp/option/declaration.rb +5 -1
- data/lib/clamp/option/definition.rb +9 -3
- data/lib/clamp/option/parsing.rb +38 -43
- data/lib/clamp/parameter/declaration.rb +4 -0
- data/lib/clamp/parameter/definition.rb +9 -3
- data/lib/clamp/parameter/parsing.rb +5 -1
- data/lib/clamp/subcommand/declaration.rb +17 -15
- data/lib/clamp/subcommand/definition.rb +5 -6
- data/lib/clamp/subcommand/execution.rb +12 -1
- data/lib/clamp/subcommand/parsing.rb +4 -0
- data/lib/clamp/truthy.rb +4 -2
- data/lib/clamp/version.rb +3 -1
- data/spec/clamp/command_group_spec.rb +29 -11
- data/spec/clamp/command_spec.rb +130 -48
- data/spec/clamp/help_spec.rb +63 -0
- data/spec/clamp/messages_spec.rb +5 -4
- data/spec/clamp/option/definition_spec.rb +13 -11
- data/spec/clamp/option_module_spec.rb +3 -1
- data/spec/clamp/option_reordering_spec.rb +6 -4
- data/spec/clamp/parameter/definition_spec.rb +14 -12
- data/spec/spec_helper.rb +3 -3
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c164c63137c57502ad15e11ab471b2607661868298e5330a8a4961dfea629537
|
4
|
+
data.tar.gz: 297e0abb1ead811d567eea7e668a91ba7c99654657a358016abb5cdbfd13168d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3773151ffa64b908d26c569877bb27704bf68efe658d9b6ebd48c009bcbc1a4d0a3fce2c4f16a02ed379e126dd436ef018ff1eac56334fcc8f467402fad6c995
|
7
|
+
data.tar.gz: 8104ea9b1d9a42669234cb0d82cc441efd7a6f94ed5cba542a502ae1cb2797d977530a07bbe649d98dab551e9078b434711e091e9d0b3716799522c04436d8c9
|
data/.editorconfig
ADDED
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,17 +1,40 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.1
|
3
|
+
|
1
4
|
Eval:
|
2
5
|
Exclude:
|
3
6
|
- "Rakefile"
|
4
7
|
|
8
|
+
Layout/EmptyLinesAroundBlockBody:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Layout/EmptyLinesAroundClassBody:
|
12
|
+
EnforcedStyle: empty_lines
|
13
|
+
|
14
|
+
Layout/EmptyLinesAroundModuleBody:
|
15
|
+
Enabled: false
|
16
|
+
|
5
17
|
Metrics/AbcSize:
|
6
18
|
Enabled: false
|
7
19
|
|
20
|
+
Metrics/BlockLength:
|
21
|
+
Exclude:
|
22
|
+
- "spec/**/*"
|
23
|
+
|
8
24
|
Metrics/LineLength:
|
9
25
|
Max: 120
|
10
26
|
|
11
27
|
Metrics/MethodLength:
|
12
28
|
Max: 30
|
13
29
|
|
14
|
-
|
30
|
+
Naming/AccessorMethodName:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Naming/FileName:
|
34
|
+
Exclude:
|
35
|
+
- "bin/*"
|
36
|
+
|
37
|
+
Naming/PredicateName:
|
15
38
|
Enabled: false
|
16
39
|
|
17
40
|
Style/ClassAndModuleChildren:
|
@@ -22,35 +45,19 @@ Style/ClassAndModuleChildren:
|
|
22
45
|
Style/Documentation:
|
23
46
|
Exclude:
|
24
47
|
- "lib/**/version.rb"
|
48
|
+
- "examples/*"
|
25
49
|
- "spec/**/*"
|
26
50
|
|
27
|
-
Style/EmptyLinesAroundBlockBody:
|
28
|
-
Enabled: false
|
29
|
-
|
30
|
-
Style/EmptyLinesAroundClassBody:
|
31
|
-
EnforcedStyle: empty_lines
|
32
|
-
|
33
|
-
Style/EmptyLinesAroundModuleBody:
|
34
|
-
Enabled: false
|
35
|
-
|
36
51
|
Style/Encoding:
|
37
|
-
EnforcedStyle: when_needed
|
38
52
|
Enabled: true
|
39
53
|
|
40
|
-
Style/FileName:
|
41
|
-
Exclude:
|
42
|
-
- "bin/*"
|
43
|
-
|
44
|
-
Style/HashSyntax:
|
45
|
-
EnforcedStyle: hash_rockets
|
46
|
-
|
47
54
|
Style/Lambda:
|
48
55
|
Enabled: false
|
49
56
|
|
50
57
|
Style/NumericLiterals:
|
51
58
|
Enabled: false
|
52
59
|
|
53
|
-
Style/
|
60
|
+
Style/StderrPuts:
|
54
61
|
Enabled: false
|
55
62
|
|
56
63
|
Style/StringLiterals:
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
##
|
3
|
+
## 1.3.2 (2020-08-20)
|
4
|
+
|
5
|
+
* Fix Ruby warnings.
|
6
|
+
|
7
|
+
## 1.3.1 (2019-07-11)
|
8
|
+
|
9
|
+
* Choose a sensible column width in generated help, based on content.
|
10
|
+
* Fix issue#99: extraneous parameter names in subcommand help.
|
11
|
+
|
12
|
+
## 1.3.0 (2018-06-17)
|
13
|
+
|
14
|
+
* Add `.execute` DSL method.
|
15
|
+
* Append '(required)' to the description of required options.
|
16
|
+
* Fix issue#75: don't generate `default_XXX` method unless a default is specified.
|
17
|
+
* Fix issue#90: allow required options to be provided after subcommands.
|
18
|
+
|
19
|
+
## 1.2.0 (2018-02-12)
|
4
20
|
|
5
21
|
* Add option to `Clamp.allow_options_after_parameters`.
|
6
22
|
|
data/Gemfile
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "http://rubygems.org"
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
7
|
group :development do
|
6
|
-
gem "guard-rspec", "~> 4.
|
7
|
-
gem "
|
8
|
-
gem "
|
9
|
-
gem "
|
8
|
+
gem "guard-rspec", "~> 4.7", require: false
|
9
|
+
gem "highline"
|
10
|
+
gem "listen", "~> 3.0"
|
11
|
+
gem "rake", "~> 12.3"
|
12
|
+
gem "rubocop", "~> 0.57.2", "<= 0.58", require: false
|
10
13
|
end
|
11
14
|
|
12
15
|
group :test do
|
13
|
-
gem "rspec", "~> 3.
|
14
|
-
gem "rr", "~> 1.2.0"
|
16
|
+
gem "rspec", "~> 3.7"
|
15
17
|
end
|
data/Guardfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# A sample Guardfile
|
2
4
|
# More info at https://github.com/guard/guard#readme
|
3
5
|
|
@@ -24,7 +26,7 @@
|
|
24
26
|
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
27
|
# * 'just' rspec: 'rspec'
|
26
28
|
|
27
|
-
guard :rspec, :
|
29
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
28
30
|
require "guard/rspec/dsl"
|
29
31
|
dsl = Guard::RSpec::Dsl.new(self)
|
30
32
|
|
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Clamp
|
2
|
-
=====
|
1
|
+
# Clamp
|
3
2
|
|
4
3
|
[](http://badge.fury.io/rb/clamp)
|
5
4
|
[](http://travis-ci.org/mdub/clamp)
|
@@ -8,8 +7,7 @@ Clamp
|
|
8
7
|
|
9
8
|
It handles boring stuff like parsing the command-line, and generating help, so you can get on with making your command actually do stuff.
|
10
9
|
|
11
|
-
Not another one!
|
12
|
-
----------------
|
10
|
+
## Not another one!
|
13
11
|
|
14
12
|
Yeah, sorry. There are a bunch of existing command-line parsing libraries out there, and Clamp draws inspiration from a variety of sources, including [Thor], [optparse], and [Clip]. In the end, though, I wanted a slightly rounder wheel. (Although, Clamp has a _lot_ in common with Ara T. Howard's [main.rb]. Had I been aware of that project at the time, I might not have written Clamp.)
|
15
13
|
|
@@ -18,8 +16,7 @@ Yeah, sorry. There are a bunch of existing command-line parsing libraries out t
|
|
18
16
|
[Clip]: http://clip.rubyforge.org/
|
19
17
|
[main.rb]: https://github.com/ahoward/main
|
20
18
|
|
21
|
-
Quick Start
|
22
|
-
-----------
|
19
|
+
## Quick Start
|
23
20
|
|
24
21
|
A typical Clamp script looks like this:
|
25
22
|
|
@@ -29,11 +26,11 @@ require 'clamp'
|
|
29
26
|
Clamp do
|
30
27
|
|
31
28
|
option "--loud", :flag, "say it loud"
|
32
|
-
option ["-n", "--iterations"], "N", "say it N times", :
|
29
|
+
option ["-n", "--iterations"], "N", "say it N times", default: 1 do |s|
|
33
30
|
Integer(s)
|
34
31
|
end
|
35
32
|
|
36
|
-
parameter "WORDS ...", "the thing to say", :
|
33
|
+
parameter "WORDS ...", "the thing to say", attribute_name: :words
|
37
34
|
|
38
35
|
def execute
|
39
36
|
the_truth = words.join(" ")
|
@@ -54,11 +51,11 @@ require 'clamp'
|
|
54
51
|
class SpeakCommand < Clamp::Command
|
55
52
|
|
56
53
|
option "--loud", :flag, "say it loud"
|
57
|
-
option ["-n", "--iterations"], "N", "say it N times", :
|
54
|
+
option ["-n", "--iterations"], "N", "say it N times", default: 1 do |s|
|
58
55
|
Integer(s)
|
59
56
|
end
|
60
57
|
|
61
|
-
parameter "WORDS ...", "the thing to say", :
|
58
|
+
parameter "WORDS ...", "the thing to say", attribute_name: :words
|
62
59
|
|
63
60
|
def execute
|
64
61
|
the_truth = words.join(" ")
|
@@ -79,8 +76,7 @@ There are more examples demonstrating various features of Clamp [on Github][exam
|
|
79
76
|
|
80
77
|
[examples]: https://github.com/mdub/clamp/tree/master/examples
|
81
78
|
|
82
|
-
Declaring options
|
83
|
-
-----------------
|
79
|
+
## Declaring options
|
84
80
|
|
85
81
|
Options are declared using the `option` method. The three required arguments are:
|
86
82
|
|
@@ -105,7 +101,7 @@ end
|
|
105
101
|
If you don't like the inferred attribute name, you can override it:
|
106
102
|
|
107
103
|
```ruby
|
108
|
-
option "--type", "TYPE", "type of widget", :
|
104
|
+
option "--type", "TYPE", "type of widget", attribute_name: :widget_type
|
109
105
|
# to avoid clobbering Object#type
|
110
106
|
```
|
111
107
|
|
@@ -140,7 +136,7 @@ Clamp will handle both "`--force`" and "`--no-force`" options, setting the value
|
|
140
136
|
Although "required option" is an oxymoron, Clamp lets you mark an option as required, and will verify that a value is provided:
|
141
137
|
|
142
138
|
```ruby
|
143
|
-
option "--password", "PASSWORD", "the secret password", :
|
139
|
+
option "--password", "PASSWORD", "the secret password", required: true
|
144
140
|
```
|
145
141
|
|
146
142
|
Note that it makes no sense to mark a `:flag` option, or one with a `:default`, as `:required`.
|
@@ -150,7 +146,7 @@ Note that it makes no sense to mark a `:flag` option, or one with a `:default`,
|
|
150
146
|
Declaring an option "`:multivalued`" allows it to be specified multiple times on the command line.
|
151
147
|
|
152
148
|
```ruby
|
153
|
-
option "--format", "FORMAT", "output format", :
|
149
|
+
option "--format", "FORMAT", "output format", multivalued: true
|
154
150
|
```
|
155
151
|
|
156
152
|
The underlying attribute becomes an Array, and the suffix "`_list`" is appended to the default attribute name. In this case, an attribute called "`format_list`" would be generated (unless you override the default by specifying an `:attribute_name`).
|
@@ -160,12 +156,12 @@ The underlying attribute becomes an Array, and the suffix "`_list`" is appended
|
|
160
156
|
Declaring an option "`:hidden`" will cause it to be hidden from `--help` output.
|
161
157
|
|
162
158
|
```ruby
|
163
|
-
option "--some-option", "VALUE", "Just a little option", :
|
159
|
+
option "--some-option", "VALUE", "Just a little option", hidden: true
|
164
160
|
```
|
165
161
|
|
166
162
|
### Version option
|
167
163
|
|
168
|
-
A common idiom is to have an option `--version` that outputs the command version and doesn't run any subcommands. This can be
|
164
|
+
A common idiom is to have an option `--version` that outputs the command version and doesn't run any subcommands. This can be achieved by:
|
169
165
|
|
170
166
|
```ruby
|
171
167
|
option "--version", :flag, "Show version" do
|
@@ -174,8 +170,7 @@ option "--version", :flag, "Show version" do
|
|
174
170
|
end
|
175
171
|
```
|
176
172
|
|
177
|
-
Declaring parameters
|
178
|
-
--------------------
|
173
|
+
## Declaring parameters
|
179
174
|
|
180
175
|
Positional parameters can be declared using `parameter`, specifying
|
181
176
|
|
@@ -203,13 +198,12 @@ parameter "[TARGET_DIR]", "target directory"
|
|
203
198
|
Three dots at the end of a parameter name makes it "greedy" - it will consume all remaining command-line arguments. For example:
|
204
199
|
|
205
200
|
```ruby
|
206
|
-
parameter "FILE ...", "input files", :
|
201
|
+
parameter "FILE ...", "input files", attribute_name: :files
|
207
202
|
```
|
208
203
|
|
209
204
|
Like multivalued options, greedy parameters are backed by an Array attribute (named with a "`_list`" suffix, by default).
|
210
205
|
|
211
|
-
Parsing and validation of options and parameters
|
212
|
-
------------------------------------------------
|
206
|
+
## Parsing and validation of options and parameters
|
213
207
|
|
214
208
|
When you `#run` a command, it will first attempt to `#parse` command-line arguments, and map them onto the declared options and parameters, before invoking your `#execute` method.
|
215
209
|
|
@@ -265,15 +259,15 @@ end
|
|
265
259
|
Default values can be specified for options, and optional parameters:
|
266
260
|
|
267
261
|
```ruby
|
268
|
-
option "--flavour", "FLAVOUR", "ice-cream flavour", :
|
262
|
+
option "--flavour", "FLAVOUR", "ice-cream flavour", default: "chocolate"
|
269
263
|
|
270
|
-
parameter "[HOST]", "server host", :
|
264
|
+
parameter "[HOST]", "server host", default: "localhost"
|
271
265
|
```
|
272
266
|
|
273
267
|
For more advanced cases, you can also specify default values by defining a method called "`default_#{attribute_name}`":
|
274
268
|
|
275
269
|
```ruby
|
276
|
-
option "--http-port", "PORT", "web-server port", :
|
270
|
+
option "--http-port", "PORT", "web-server port", default: 9000
|
277
271
|
|
278
272
|
option "--admin-port", "PORT", "admin port"
|
279
273
|
|
@@ -287,29 +281,30 @@ end
|
|
287
281
|
Options (and optional parameters) can also be associated with environment variables:
|
288
282
|
|
289
283
|
```ruby
|
290
|
-
option "--port", "PORT", "the port to listen on", :
|
284
|
+
option "--port", "PORT", "the port to listen on", environment_variable: "MYAPP_PORT" do |val|
|
291
285
|
val.to_i
|
292
286
|
end
|
293
287
|
|
294
|
-
parameter "[HOST]", "server address", :
|
288
|
+
parameter "[HOST]", "server address", environment_variable: "MYAPP_HOST"
|
295
289
|
```
|
296
290
|
|
297
291
|
Clamp will check the specified envariables in the absence of values supplied on the command line, before looking for a default value.
|
298
292
|
|
299
293
|
### Allowing options after parameters
|
300
294
|
|
301
|
-
|
295
|
+
By default, Clamp only recognises options _before_ positional parameters.
|
296
|
+
|
297
|
+
Some other option-parsing libraries - notably [GNU `getopt(3)`](https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html) - allow option and parameter arguments to appear in any order on the command-line, e.g.
|
302
298
|
|
303
299
|
foobar --foo=bar something --fnord=snuffle another-thing
|
304
300
|
|
305
|
-
|
301
|
+
If you want Clamp to allow options and parameters to be "interspersed" in this way, set:
|
306
302
|
|
307
303
|
```ruby
|
308
304
|
Clamp.allow_options_after_parameters = true
|
309
305
|
```
|
310
306
|
|
311
|
-
Declaring Subcommands
|
312
|
-
---------------------
|
307
|
+
## Declaring Subcommands
|
313
308
|
|
314
309
|
Subcommand support helps you wrap a number of related commands into a single script (ala tools like "`git`"). Clamp will inspect the first command-line argument (after options are parsed), and delegate to the named subcommand.
|
315
310
|
|
@@ -400,8 +395,7 @@ Clamp do
|
|
400
395
|
end
|
401
396
|
```
|
402
397
|
|
403
|
-
Getting help
|
404
|
-
------------
|
398
|
+
## Getting help
|
405
399
|
|
406
400
|
All Clamp commands support a "`--help`" option, which outputs brief usage documentation, based on those seemingly useless extra parameters that you had to pass to `option` and `parameter`.
|
407
401
|
|
@@ -419,27 +413,27 @@ Options:
|
|
419
413
|
-h, --help print help
|
420
414
|
```
|
421
415
|
|
422
|
-
Localization
|
423
|
-
------------
|
416
|
+
## Localization
|
424
417
|
|
425
418
|
Clamp comes with support for overriding strings with custom translations. You can use localization library of your choice and override the strings at startup.
|
426
419
|
|
427
420
|
Example usage:
|
421
|
+
|
428
422
|
```ruby
|
429
423
|
require 'gettext'
|
430
424
|
|
431
425
|
Clamp.messages = {
|
432
|
-
:
|
433
|
-
:
|
434
|
-
:
|
435
|
-
:
|
426
|
+
too_many_arguments: _("too many arguments"),
|
427
|
+
option_required: _("option '%<option>s' is required"),
|
428
|
+
option_or_env_required: _("option '%<option>s' (or env %<env>s) is required"),
|
429
|
+
option_argument_error: _("option '%<switch>s': %<message>s")
|
436
430
|
# ...
|
437
431
|
}
|
438
432
|
```
|
433
|
+
|
439
434
|
See [messages.rb](https://github.com/mdub/clamp/blob/master/lib/clamp/messages.rb) for full list of available messages.
|
440
435
|
|
441
|
-
License
|
442
|
-
-------
|
436
|
+
## License
|
443
437
|
|
444
438
|
Copyright (C) 2011 [Mike Williams](mailto:mdub@dogbiscuit.org)
|
445
439
|
|
@@ -460,7 +454,6 @@ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
460
454
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
461
455
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
462
456
|
|
463
|
-
Contributing to Clamp
|
464
|
-
---------------------
|
457
|
+
## Contributing to Clamp
|
465
458
|
|
466
459
|
Source-code for Clamp is [on Github](https://github.com/mdub/clamp).
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler"
|
2
4
|
|
3
5
|
Bundler::GemHelper.install_tasks
|
@@ -10,3 +12,9 @@ RSpec::Core::RakeTask.new do |t|
|
|
10
12
|
t.pattern = "spec/**/*_spec.rb"
|
11
13
|
t.rspec_opts = ["--colour", "--format", "documentation"]
|
12
14
|
end
|
15
|
+
|
16
|
+
require "rubocop/rake_task"
|
17
|
+
|
18
|
+
RuboCop::RakeTask.new
|
19
|
+
|
20
|
+
task "default" => "rubocop"
|
data/clamp.gemspec
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path("lib", __dir__)
|
2
4
|
require "clamp/version"
|
3
5
|
|
4
6
|
Gem::Specification.new do |s|
|
@@ -8,15 +10,15 @@ Gem::Specification.new do |s|
|
|
8
10
|
s.platform = Gem::Platform::RUBY
|
9
11
|
s.authors = ["Mike Williams"]
|
10
12
|
s.email = "mdub@dogbiscuit.org"
|
11
|
-
s.homepage = "
|
13
|
+
s.homepage = "https://github.com/mdub/clamp"
|
12
14
|
|
13
15
|
s.license = "MIT"
|
14
16
|
|
15
17
|
s.summary = "a minimal framework for command-line utilities"
|
16
|
-
s.description =
|
17
|
-
Clamp provides an object-model for command-line utilities.
|
18
|
-
It handles parsing of command-line options, and generation of usage help.
|
19
|
-
|
18
|
+
s.description = <<-TEXT.gsub(/^\s+/, "")
|
19
|
+
Clamp provides an object-model for command-line utilities.
|
20
|
+
It handles parsing of command-line options, and generation of usage help.
|
21
|
+
TEXT
|
20
22
|
|
21
23
|
s.files = `git ls-files`.split("\n")
|
22
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|