parse-argv 0.1.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 +7 -0
- data/.yardopts +5 -0
- data/LICENSE +28 -0
- data/ReadMe.md +101 -0
- data/examples/ReadMe.md +29 -0
- data/examples/check.rb +109 -0
- data/examples/conversion.rb +47 -0
- data/examples/multi.rb +79 -0
- data/examples/simple.rb +37 -0
- data/lib/parse-argv/conversion.rb +398 -0
- data/lib/parse-argv/version.rb +8 -0
- data/lib/parse-argv.rb +900 -0
- data/lib/parse_argv.rb +3 -0
- data/syntax.md +158 -0
- metadata +70 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '08c6221625a88b034352b5dbb8fb673bf2224ab76c3d535ef1fe43c5b33ae1fa'
|
4
|
+
data.tar.gz: faf7ef2645091f3cf6de86ea23104105830530cfbc03e1237cd0bad16d077658
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '0486e25acc34d509335f469a30bfb2fb32d038ca7de45a3ab5ff19039f34110f01adade82a47d0c277403c97767182c0881fef734950ff63c22ccaf2d464bdd4'
|
7
|
+
data.tar.gz: a6c629bfd3c6103a1cf09c80b7efbe38036b24051b473d2f488e47b8b4c6b15045ae92910f9583e2be749ddabf5458ecd0db1ddfa6c7e48da55328f32922e580
|
data/.yardopts
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
BSD 3-Clause License
|
2
|
+
|
3
|
+
Copyright (c) 2017-2021, Mike Blumtritt. 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
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
13
|
+
and/or other materials provided with the distribution.
|
14
|
+
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
16
|
+
contributors may be used to endorse or promote products derived from
|
17
|
+
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 ARE
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/ReadMe.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# ParseArgv
|
2
|
+
|
3
|
+
A command line parser that only needs your help text.
|
4
|
+
|
5
|
+
- Gem: [rubygems.org](https://rubygems.org/gems/parse-argv)
|
6
|
+
- Source: [github.com](https://github.com/mblumtritt/parse-argv)
|
7
|
+
- Help: [rubydoc.info](https://rubydoc.info/gems/parse-argv)
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
Just write the help text for your application and ParseArgv will take care of your command line. It works sort of the other way around than OptParse, where you write a lot of code to get a command line parser and generated help text. ParseArgv simply takes your help text and parses the command line and presents you the results.
|
12
|
+
|
13
|
+
You can use ParseArgv for simpler programs just as well as for CLI with multi-level sub-commands (git-like commands). ParseArgv is easy to use, fast and also helps you convert the data types of command line arguments.
|
14
|
+
|
15
|
+
## Example
|
16
|
+
|
17
|
+
The given help text
|
18
|
+
|
19
|
+
```
|
20
|
+
usage: test [options] <infile> [<outfile>]
|
21
|
+
|
22
|
+
This is just a demonstration.
|
23
|
+
|
24
|
+
options:
|
25
|
+
-f, --format <format> specify the format
|
26
|
+
--verbose enable verbose mode
|
27
|
+
-h, --help print this help text
|
28
|
+
```
|
29
|
+
|
30
|
+
will be interpreted as
|
31
|
+
|
32
|
+
- there is a command "test"
|
33
|
+
- which requires and argument "infile"
|
34
|
+
- optionally accepts an second argument "outfile"
|
35
|
+
- accepts an option named "format" when `-f` or `--format` are given
|
36
|
+
- defines the boolean option "verbose" when `--verbose` is given
|
37
|
+
- defines the boolean option "help" when `-h` or `--help` are given
|
38
|
+
|
39
|
+
## How To Use
|
40
|
+
|
41
|
+
Please, see the [Gem's help](https://rubydoc.info/gems/parse-argv) for detailed information, or have a look at the [`./examples`](./examples) directory which contains some commands to play around.
|
42
|
+
|
43
|
+
The supported help text syntax and the command line interface syntax are described in the [syntax help](./syntax.md).
|
44
|
+
|
45
|
+
In general you just specify the help text and get the parsed command line:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'parse-argv'
|
49
|
+
|
50
|
+
args = ParseArgv.from <<~HELP
|
51
|
+
usage: test [options] <infile> [<outfile>]
|
52
|
+
|
53
|
+
This is just a demonstration.
|
54
|
+
|
55
|
+
options:
|
56
|
+
-f, --format <format> specify the format
|
57
|
+
--verbose enable verbose mode
|
58
|
+
-h, --help print this help text
|
59
|
+
HELP
|
60
|
+
|
61
|
+
args.verbose?
|
62
|
+
#=> true, when "--verbose" argument was specified
|
63
|
+
#=> false, when "--verbose" argument was not specified
|
64
|
+
|
65
|
+
args[:infile].as(File, :readable)
|
66
|
+
#=> file name
|
67
|
+
|
68
|
+
args.outfile?
|
69
|
+
#=> true, when second argument was specified
|
70
|
+
args.outfile
|
71
|
+
#=> second argument or nil when not specified
|
72
|
+
```
|
73
|
+
|
74
|
+
## Installation
|
75
|
+
|
76
|
+
Use [Bundler](http://gembundler.com/) to add ParseArgv in your own project:
|
77
|
+
|
78
|
+
Include in your `Gemfile`:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
gem 'parse-argv'
|
82
|
+
```
|
83
|
+
|
84
|
+
and install it by running Bundler:
|
85
|
+
|
86
|
+
```bash
|
87
|
+
bundle
|
88
|
+
```
|
89
|
+
|
90
|
+
To install the gem globally use:
|
91
|
+
|
92
|
+
```bash
|
93
|
+
gem install parse-argv
|
94
|
+
```
|
95
|
+
|
96
|
+
After that you need only a single line of code in your project to have it on board:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
require 'parse-argv'
|
100
|
+
```
|
101
|
+
|
data/examples/ReadMe.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Examples
|
2
|
+
|
3
|
+
This directory contains some examples for using ParseArgv. Play around and get an impression how an application will handle the command line by using ParseArgv.
|
4
|
+
|
5
|
+
To run an example just start with:
|
6
|
+
|
7
|
+
```shell
|
8
|
+
ruby examples/simple.rb --help
|
9
|
+
```
|
10
|
+
|
11
|
+
## check.rb
|
12
|
+
|
13
|
+
Can be used to test your help text syntax. Try the following to see it in action:
|
14
|
+
|
15
|
+
```shell
|
16
|
+
ruby examples/check.rb examples/multi.rb
|
17
|
+
```
|
18
|
+
|
19
|
+
## conversion.rb
|
20
|
+
|
21
|
+
This example demonstrates the conversion capabilities.
|
22
|
+
|
23
|
+
## multi.rb
|
24
|
+
|
25
|
+
This is an example of a "git-like" command - a command with subcommands.
|
26
|
+
|
27
|
+
## simple.rb
|
28
|
+
|
29
|
+
A simple and very basic demonstration.
|
data/examples/check.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/parse-argv'
|
5
|
+
|
6
|
+
ARGS = ParseArgv.from <<~HELP
|
7
|
+
Test the syntax of your help text for ParseArgv.
|
8
|
+
|
9
|
+
Usage: check [options] <files>...
|
10
|
+
|
11
|
+
Options:
|
12
|
+
-f, --format <format> display format: default, json, usage
|
13
|
+
-c, --command <name> display command with <name> only
|
14
|
+
-h, --help display this help
|
15
|
+
-v, --version display version information
|
16
|
+
HELP
|
17
|
+
|
18
|
+
puts(ARGS) or exit if ARGS.help?
|
19
|
+
puts("check v#{ParseArgv::VERSION}") or exit if ARGS.version?
|
20
|
+
|
21
|
+
cmds =
|
22
|
+
begin
|
23
|
+
ParseArgv.parse(ARGS[:files].as(:file_content).join("\n"))
|
24
|
+
rescue ArgumentError => e
|
25
|
+
ARGS.error!("invalid syntax - #{e}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_command(all, name)
|
29
|
+
command = all.find { |cmd| cmd[:full_name] == name || cmd[:name] == name }
|
30
|
+
command or ARGS.error!("no such command - #{name}")
|
31
|
+
end
|
32
|
+
|
33
|
+
cmds = [find_command(cmds, ARGS[:name].as(:string))] if ARGS.name?
|
34
|
+
|
35
|
+
module Format
|
36
|
+
class Json
|
37
|
+
def self.show(commands)
|
38
|
+
commands.each { |command| command.delete(:help) }
|
39
|
+
require('json')
|
40
|
+
puts(JSON.dump(commands))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Usage
|
45
|
+
def self.show(commands)
|
46
|
+
puts(commands.map { |command| new(command) }.join("\n"))
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(command)
|
50
|
+
@command = command
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
name, args = @command.fetch_values(:full_name, :arguments)
|
55
|
+
ret = "usage: #{name}"
|
56
|
+
args.each_pair { |arg_name, info| ret << as_str(arg_name, info) }
|
57
|
+
ret
|
58
|
+
end
|
59
|
+
|
60
|
+
def as_str(name, info)
|
61
|
+
case info[:type]
|
62
|
+
when :argument
|
63
|
+
info[:required] ? " <#{name}>" : " [<#{name}>]"
|
64
|
+
when :argument_array
|
65
|
+
info[:required] ? " <#{name}>..." : " [<#{name}>...]"
|
66
|
+
when :option
|
67
|
+
names = info[:names].map { |n| n.size == 1 ? "-#{n}" : "--#{n}" }
|
68
|
+
" [#{names.join(', ')} <#{name}>]"
|
69
|
+
when :switch
|
70
|
+
names = info[:names].map { |n| n.size == 1 ? "-#{n}" : "--#{n}" }
|
71
|
+
" [#{names.join(', ')}]"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Default < Usage
|
77
|
+
def self.show(commands)
|
78
|
+
puts(commands.map { |command| new(command) }.join("\n\n"))
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_s
|
82
|
+
full_name, name, args =
|
83
|
+
@command.fetch_values(:full_name, :name, :arguments)
|
84
|
+
ret = ["#{full_name == name ? 'Command' : 'Subcommand'}: #{name}"]
|
85
|
+
return ret if args.empty?
|
86
|
+
width = args.keys.max_by(&:size).size
|
87
|
+
args.each_pair do |arg_name, info|
|
88
|
+
ret << " #{arg_name.to_s.ljust(width)} #{as_str(info)}"
|
89
|
+
end
|
90
|
+
ret.join("\n")
|
91
|
+
end
|
92
|
+
|
93
|
+
def as_str(info)
|
94
|
+
case info[:type]
|
95
|
+
when :argument
|
96
|
+
info[:required] ? 'argument: required' : 'argument'
|
97
|
+
when :argument_array
|
98
|
+
info[:required] ? 'arguments array: required' : 'arguments array'
|
99
|
+
when :option, :switch
|
100
|
+
names = info[:names].map { |n| n.size == 1 ? "-#{n}" : "--#{n}" }
|
101
|
+
"#{info[:type]} #{names.join(', ')}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
Format.const_get(
|
108
|
+
ARGS[:format].as(%w[default json usage], default: 'default').capitalize
|
109
|
+
).show(cmds)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/parse-argv'
|
5
|
+
|
6
|
+
ARGS = ParseArgv.from <<~HELP
|
7
|
+
ParseARGS Demo about conversions
|
8
|
+
This example demonstrates the build-in conversions.
|
9
|
+
|
10
|
+
usage: conversion [options]
|
11
|
+
|
12
|
+
options:
|
13
|
+
-s, --string <string> accept any non-empty String
|
14
|
+
-a, --array <array> accept an array of String
|
15
|
+
-r, --regexp <regexp> convert to a regular expression
|
16
|
+
-i, --integer <integer> convert to Integer
|
17
|
+
-f, --float <float> convert to Float
|
18
|
+
-n, --number <number> convert to Numeric (Integer or Float)
|
19
|
+
-b, --byte <byte> convert to number of byte
|
20
|
+
-d, --date <date> convert to Date
|
21
|
+
-t, --time <time> convert to Time
|
22
|
+
-N, --filename <filename> convert to a (relative) file name String
|
23
|
+
-F, --fname <file> accept name of an existing file
|
24
|
+
-D, --dname <dir> accept name of an existing directory
|
25
|
+
-A, --files <files> accept an array of file names
|
26
|
+
-1, --one <oneof> accept one of 'foo', 'bar', 'baz'
|
27
|
+
-h, --help print this help
|
28
|
+
HELP
|
29
|
+
|
30
|
+
puts(ARGS) or exit if ARGS.help?
|
31
|
+
|
32
|
+
puts <<~RESULT
|
33
|
+
string #{ARGS[:string].as(String).inspect}
|
34
|
+
array #{ARGS[:array].as(Array).inspect}
|
35
|
+
filename #{ARGS[:filename].as(:file_name).inspect}
|
36
|
+
regexp #{ARGS[:regexp].as(Regexp).inspect}
|
37
|
+
integer #{ARGS[:integer].as(Integer)}
|
38
|
+
float #{ARGS[:float].as(Float)}
|
39
|
+
number #{ARGS[:number].as(Numeric)}
|
40
|
+
byte #{ARGS[:byte].as(:byte)}
|
41
|
+
date #{ARGS[:date].as(:date)}
|
42
|
+
time #{ARGS[:time].as(Time)}
|
43
|
+
file #{ARGS[:file].as(File).inspect}
|
44
|
+
dir #{ARGS[:dir].as(Dir).inspect}
|
45
|
+
files #{ARGS[:files].as([File]).inspect}
|
46
|
+
oneof #{ARGS[:oneof].as(%w[foo bar baz])}
|
47
|
+
RESULT
|
data/examples/multi.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/parse-argv'
|
5
|
+
|
6
|
+
ARGS = ParseArgv.from <<~HELP
|
7
|
+
ParseARGS Demo for a CLI with subcommands
|
8
|
+
This example demonstrates a CLI with subcommands. It processes an imganinary
|
9
|
+
key/value store that can be synchronized with a server.
|
10
|
+
|
11
|
+
usage: multi <command>
|
12
|
+
|
13
|
+
commands:
|
14
|
+
var get a variable
|
15
|
+
var add add a variable
|
16
|
+
var remove remove a variable
|
17
|
+
push push all vars
|
18
|
+
pull pull all vars
|
19
|
+
help show command specific help
|
20
|
+
-h, --help show this help
|
21
|
+
-v, --version show version information
|
22
|
+
|
23
|
+
Play with different command line parameters and options to see how it works!
|
24
|
+
|
25
|
+
usage: multi var <name>
|
26
|
+
|
27
|
+
Get variable <name>.
|
28
|
+
|
29
|
+
usage: multi var add [options] <name> <value>...
|
30
|
+
|
31
|
+
Add a variable <name> with given <value>.
|
32
|
+
|
33
|
+
options:
|
34
|
+
-f, --force allow to overwrite existing variable <name>
|
35
|
+
|
36
|
+
usage: multi var remove <name>
|
37
|
+
|
38
|
+
Remove variable <name>.
|
39
|
+
|
40
|
+
usage: multi push [options] <url>
|
41
|
+
|
42
|
+
Push all variables to server at <url>.
|
43
|
+
|
44
|
+
options:
|
45
|
+
-t, --token <token> user token
|
46
|
+
-f, --force force push
|
47
|
+
|
48
|
+
usage: multi pull [options] <url>
|
49
|
+
|
50
|
+
Pull all variables from server at <url>.
|
51
|
+
|
52
|
+
options:
|
53
|
+
-t, --token <token> user token
|
54
|
+
-f, --force force pull (override local variables)
|
55
|
+
|
56
|
+
usage: multi help [<command>...]
|
57
|
+
|
58
|
+
Show help for given <command>.
|
59
|
+
HELP
|
60
|
+
|
61
|
+
case ARGS.current_command.name
|
62
|
+
when 'multi'
|
63
|
+
puts(ARGS.help? ? ARGS : 'multi sample v1.0.0')
|
64
|
+
when 'help'
|
65
|
+
if ARGS.command?
|
66
|
+
command = ARGS.find_command(ARGS.command)
|
67
|
+
ARGS.error!("unknown command - #{ARGS.command.join(' ')}") if command.nil?
|
68
|
+
puts(command.help)
|
69
|
+
else
|
70
|
+
puts(ARGS.main_command.help)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
puts "command '#{ARGS.current_command}':"
|
74
|
+
arguments = ARGS.to_h
|
75
|
+
width = arguments.keys.max_by(&:size).size + 3
|
76
|
+
arguments.each_pair do |name, value|
|
77
|
+
puts(" #{name.to_s.ljust(width)}#{value.inspect}")
|
78
|
+
end
|
79
|
+
end
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/parse-argv'
|
5
|
+
|
6
|
+
ARGS = ParseArgv.from <<~HELP
|
7
|
+
Simple ParseArgv Demo
|
8
|
+
|
9
|
+
This is a demo for the command `simple`, which requires an <input> argument and
|
10
|
+
accepts optional an <output> argument. It accepts also some options.
|
11
|
+
|
12
|
+
Usage: simple [options] <input> [<output>]
|
13
|
+
|
14
|
+
Options:
|
15
|
+
-f, --format <format> select a format: txt, html, md
|
16
|
+
-c, --count <count> set a count (default 10)
|
17
|
+
|
18
|
+
The command's options can be defined in different paragraphs.
|
19
|
+
|
20
|
+
More Options:
|
21
|
+
-h, --help display this help
|
22
|
+
-v, --version display version information
|
23
|
+
--verbose enable verbose mode
|
24
|
+
|
25
|
+
Play with different command line parameters and options to see how it works!
|
26
|
+
HELP
|
27
|
+
|
28
|
+
puts(ARGS) or exit if ARGS.help?
|
29
|
+
puts('simple v1.0.0') or exit if ARGS.version?
|
30
|
+
puts <<~RESULT
|
31
|
+
arguments:
|
32
|
+
input #{ARGS.input}
|
33
|
+
output #{ARGS.output}
|
34
|
+
format #{ARGS[:format].as(%w[txt html md], default: 'txt')}
|
35
|
+
count #{ARGS[:count].as(Integer, :positive, default: 10)}
|
36
|
+
verbose #{ARGS.verbose}
|
37
|
+
RESULT
|