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 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
@@ -0,0 +1,5 @@
1
+ --readme README.md
2
+ --title 'ParseArgv Documentation'
3
+ --charset utf-8
4
+ --markup markdown
5
+ 'lib/**/*.rb' - 'syntax.md' 'LICENSE'
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
+
@@ -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
@@ -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