usage_by_example 0.0.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/.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: []
|