usage_by_example 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +19 -0
- data/README.md +35 -0
- data/lib/usage_by_example/version.rb +5 -0
- data/lib/usage_by_example.rb +123 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fa6ff28e421846106e76d35e80132c514df0308c59506428c884b7fd0b5ff702
|
4
|
+
data.tar.gz: dee35110be4a6d05480e067e12f913def3d52459b455232ddfc686b70a0670aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2305c27d269773f2ea7ef8112bfd618385442cc59e31b1450ee741693c8254df323f129bd10ff7e8913afc05afc57ac58be154f485f5599f8b4df3422df7064b
|
7
|
+
data.tar.gz: 28d398dcb1d4c5f71fa3aa14e43e646836d47bcf39c3287c7b109dbf773e80bdf75d13b04c05682553754f0378d392d04b3f7d8d1c5e79fba8cf89d317d5f4a1
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# UsageByExample
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/usage_by_example`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'usage_by_example'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install usage_by_example
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/usage_by_example.
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "usage_by_example/version"
|
4
|
+
|
5
|
+
|
6
|
+
class UsageByExample
|
7
|
+
|
8
|
+
def self.read(data)
|
9
|
+
return new data.read
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(text)
|
13
|
+
@usage = text.gsub('$0', File.basename($0)).gsub(/\n+\Z/, "\n\n")
|
14
|
+
|
15
|
+
# ---- 1) Parse argument names ------------------------------------
|
16
|
+
#
|
17
|
+
# Parse the usage string and extract both optional argument names
|
18
|
+
# and required argument names, for example:
|
19
|
+
#
|
20
|
+
# Usage: connect [options] [mode] host port
|
21
|
+
|
22
|
+
text =~ /Usage: (\w+|\$0) \[options\](( \[\w+\])*)(( \w+)*)/
|
23
|
+
raise RuntimeError, "Expected usage string, got none" unless $1
|
24
|
+
@argument_names_optional = $2.to_s.split.map { |match| match.tr('[]', '').downcase }
|
25
|
+
@argument_names_required = $4.to_s.split.map(&:downcase)
|
26
|
+
|
27
|
+
# ---- 2) Parse option names --------------------------------------
|
28
|
+
#
|
29
|
+
# Parse the usage message and extract option names, their short and
|
30
|
+
# long forms, and the associated argument name (if any), eg:
|
31
|
+
#
|
32
|
+
# Options:
|
33
|
+
# -s, --secure Use secure connection
|
34
|
+
# -v, --verbose Enable verbose output
|
35
|
+
# -r, --retries NUM Number of connection retries (default 3)
|
36
|
+
# -t, --timeout NUM Connection timeout in seconds (default 10)
|
37
|
+
|
38
|
+
@option_names = {}
|
39
|
+
text.scan(/((--?\w+)(, --?\w+)*) ?(\w+)?/) do
|
40
|
+
opts = $1.split(", ")
|
41
|
+
opts.each { |each| @option_names[each] = [opts.last.tr('-', ''), $4&.downcase] }
|
42
|
+
end
|
43
|
+
|
44
|
+
# ---- 3) Include help option by default --------------------------
|
45
|
+
|
46
|
+
@option_names.update("-h" => :help, "--help" => :help)
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse(argv)
|
50
|
+
array = argv.dup
|
51
|
+
@arguments = {}
|
52
|
+
@options = {}
|
53
|
+
|
54
|
+
# --- 1) Parse options --------------------------------------------
|
55
|
+
|
56
|
+
most_recent_option = nil
|
57
|
+
until array.empty? do
|
58
|
+
break unless array.first.start_with?(?-)
|
59
|
+
most_recent_option = option = array.shift
|
60
|
+
option_name, argument_name = @option_names[option]
|
61
|
+
raise "Got unknown option #{option}" if option_name.nil?
|
62
|
+
raise if option_name == :help # Show usage without error message
|
63
|
+
@options[option_name] = true
|
64
|
+
|
65
|
+
# Consume argument, if expected by most recent option
|
66
|
+
if argument_name
|
67
|
+
argument = array.shift
|
68
|
+
raise "Expected argument for option #{option}" unless /^[^-]/ === argument
|
69
|
+
@arguments[option_name] = argument
|
70
|
+
most_recent_option = nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# --- 2) Parse optional arguments ---------------------------------
|
75
|
+
|
76
|
+
stash = array.pop(@argument_names_required.length)
|
77
|
+
@argument_names_optional.each do |argument_name|
|
78
|
+
break if array.empty?
|
79
|
+
argument = array.shift
|
80
|
+
raise "Expected more arguments, got option #{option}" unless /^[^-]/ === argument
|
81
|
+
@arguments[argument_name] = argument
|
82
|
+
end
|
83
|
+
|
84
|
+
# --- 3) Parse required arguments ---------------------------------
|
85
|
+
|
86
|
+
@argument_names_required.each do |argument_name|
|
87
|
+
raise "Expected required argument #{argument_name.upcase}, got none" if stash.empty?
|
88
|
+
argument = stash.shift
|
89
|
+
raise "Expected more arguments, got option #{option}" unless /^[^-]/ === argument
|
90
|
+
@arguments[argument_name] = argument
|
91
|
+
end
|
92
|
+
|
93
|
+
# --- 4) Expect to be done ----------------------------------------
|
94
|
+
|
95
|
+
if not array.empty?
|
96
|
+
# Custom error message if most recent option did not require argument
|
97
|
+
raise "Got unexpected argument for option #{most_recent_option}" if most_recent_option
|
98
|
+
min_length = @argument_names.length
|
99
|
+
max_length = @argument_names.length + @argument_names_optional.length
|
100
|
+
raise "Expected #{min_length}#{"-#{max_length}" if max_length > min_length} arguments, got more"
|
101
|
+
end
|
102
|
+
|
103
|
+
return self
|
104
|
+
|
105
|
+
rescue RuntimeError => err
|
106
|
+
puts "ERROR: #{err.message}\n\n" unless err.message.empty?
|
107
|
+
puts @usage
|
108
|
+
exit
|
109
|
+
end
|
110
|
+
|
111
|
+
def method_missing(sym, *args, &block)
|
112
|
+
case sym
|
113
|
+
when /^argument_(.*)$/
|
114
|
+
val = @arguments[$1]
|
115
|
+
block && val ? block.call(val) : val
|
116
|
+
when /^include_(.*)\?$/
|
117
|
+
@options[$1]
|
118
|
+
else
|
119
|
+
super
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: usage_by_example
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adrian Kuhn
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
- akuhn@iam.unibe.ch
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".rspec"
|
21
|
+
- Gemfile
|
22
|
+
- Gemfile.lock
|
23
|
+
- README.md
|
24
|
+
- lib/usage_by_example.rb
|
25
|
+
- lib/usage_by_example/version.rb
|
26
|
+
homepage: https://github.com/akuhn/usage_by_example
|
27
|
+
licenses:
|
28
|
+
- MIT
|
29
|
+
metadata:
|
30
|
+
homepage_uri: https://github.com/akuhn/usage_by_example
|
31
|
+
source_code_uri: https://github.com/akuhn/usage_by_example
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.6.0
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubygems_version: 3.3.7
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: No-code options parser that extracts arguments directly from usage text.
|
51
|
+
test_files: []
|