parse-argv 0.1.0

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