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 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
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in usage_by_example.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,19 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ usage_by_example (0.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (13.0.6)
10
+
11
+ PLATFORMS
12
+ x86_64-darwin-19
13
+
14
+ DEPENDENCIES
15
+ rake (~> 13.0)
16
+ usage_by_example!
17
+
18
+ BUNDLED WITH
19
+ 2.3.7
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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UsageByExample
4
+ VERSION = "0.0.0"
5
+ end
@@ -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: []