├── .document ├── .editorconfig ├── .github ├── actions │ └── package │ │ └── action.yml ├── dependabot.yml └── workflows │ ├── codeql.yml │ ├── push_gem.yml │ └── test.yml ├── .gitignore ├── .rdoc_options ├── BSDL ├── COPYING ├── Gemfile ├── README.md ├── Rakefile ├── doc └── optparse │ ├── .document │ ├── argument_converters.rdoc │ ├── creates_option.rdoc │ ├── option_params.rdoc │ ├── ruby │ ├── argument_abbreviation.rb │ ├── argument_keywords.rb │ ├── argument_strings.rb │ ├── argv.rb │ ├── array.rb │ ├── basic.rb │ ├── block.rb │ ├── collected_options.rb │ ├── custom_converter.rb │ ├── date.rb │ ├── datetime.rb │ ├── decimal_integer.rb │ ├── decimal_numeric.rb │ ├── default_values.rb │ ├── descriptions.rb │ ├── explicit_array_values.rb │ ├── explicit_hash_values.rb │ ├── false_class.rb │ ├── float.rb │ ├── help.rb │ ├── help_banner.rb │ ├── help_format.rb │ ├── help_program_name.rb │ ├── integer.rb │ ├── long_names.rb │ ├── long_optional.rb │ ├── long_required.rb │ ├── long_simple.rb │ ├── long_with_negation.rb │ ├── match_converter.rb │ ├── matched_values.rb │ ├── method.rb │ ├── missing_options.rb │ ├── mixed_names.rb │ ├── name_abbrev.rb │ ├── no_abbreviation.rb │ ├── numeric.rb │ ├── object.rb │ ├── octal_integer.rb │ ├── optional_argument.rb │ ├── parse.rb │ ├── parse_bang.rb │ ├── proc.rb │ ├── regexp.rb │ ├── required_argument.rb │ ├── shellwords.rb │ ├── short_names.rb │ ├── short_optional.rb │ ├── short_range.rb │ ├── short_required.rb │ ├── short_simple.rb │ ├── string.rb │ ├── terminator.rb │ ├── time.rb │ ├── true_class.rb │ └── uri.rb │ └── tutorial.rdoc ├── lib ├── optionparser.rb ├── optparse.rb └── optparse │ ├── ac.rb │ ├── date.rb │ ├── kwargs.rb │ ├── shellwords.rb │ ├── time.rb │ ├── uri.rb │ └── version.rb ├── misc ├── rb_optparse.bash └── rb_optparse.zsh ├── optparse.gemspec ├── rakelib ├── .document ├── changelogs.rake ├── epoch.rake └── version.rake └── test ├── lib └── helper.rb └── optparse ├── test_acceptable.rb ├── test_autoconf.rb ├── test_bash_completion.rb ├── test_cclass.rb ├── test_did_you_mean.rb ├── test_getopts.rb ├── test_kwargs.rb ├── test_load.rb ├── test_noarg.rb ├── test_optarg.rb ├── test_optparse.rb ├── test_placearg.rb ├── test_reqarg.rb ├── test_summary.rb └── test_zsh_completion.rb /.document: -------------------------------------------------------------------------------- 1 | COPYING 2 | ChangeLog 3 | README.md 4 | doc/ 5 | lib/ 6 | logs/ 7 | misc/ 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | max_line_length = 80 11 | 12 | [*.zsh] 13 | indent_size = 4 14 | -------------------------------------------------------------------------------- /.github/actions/package/action.yml: -------------------------------------------------------------------------------- 1 | name: Upload built package 2 | description: >- 3 | Build and update package. 4 | 5 | inputs: 6 | upload-files: 7 | required: false 8 | default: 'pkg/*.gem' 9 | description: File name pattern to upload. 10 | 11 | package-name: 12 | required: false 13 | default: '${GITHUB_REPOSITORY#*/}-${RUNNER_OS%-*}' 14 | description: Package name to upload. 15 | 16 | build-program: 17 | required: false 18 | default: rake build 19 | description: Command to build package files. 20 | 21 | runs: 22 | using: composite 23 | 24 | steps: 25 | - id: setup 26 | run: | 27 | : Setup 28 | PS4="##[command]"; set -x 29 | : Fetch deeper for changelogs 30 | git fetch --force --no-tags origin 'refs/tags/v*:refs/tags/v*' 31 | set -- "$(git symbolic-ref --short HEAD)" $(git tag --list --no-contains HEAD --sort -version:refname) 32 | branch=$1 prev=$2 33 | git fetch ${prev:+--shallow-exclude=}${prev:---unshallow} origin ${branch} 34 | : Re-checkout with LF 35 | git config core.autocrlf false 36 | git config core.eol lf 37 | git checkout -f 38 | shell: bash 39 | 40 | - id: build 41 | run: | 42 | : Build 43 | if command -v shasum > /dev/null; then 44 | shasum=(shasum -a 256 -b) # Ubuntu, macOS 45 | elif command -v sha256sum > /dev/null; then 46 | shasum=(sha256sum -b) # Windows 47 | else # fallback 48 | shasum=(ruby -rdigest -e "ARGV.each{|f| print Digest::SHA256.file(f).hexdigest, ' *'; puts f}") 49 | fi 50 | PS4="##[command]"; set -x 51 | ${{ inputs.build-program }} 52 | : Show info 53 | ls -l ${{ inputs.upload-files }} 54 | "${shasum[@]}" ${{ inputs.upload-files }} 55 | echo pkg="${{ inputs.package-name }}" >> $GITHUB_OUTPUT 56 | shell: bash 57 | 58 | - id: upload 59 | uses: actions/upload-artifact@v4 60 | with: 61 | path: ${{ inputs.upload-files }} 62 | name: ${{ steps.build.outputs.pkg }} 63 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'github-actions' 4 | directory: '/' 5 | schedule: 6 | interval: 'weekly' 7 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | branches: [ "master" ] 19 | schedule: 20 | - cron: '35 1 * * 0' 21 | 22 | jobs: 23 | analyze: 24 | name: Analyze 25 | # Runner size impacts CodeQL analysis time. To learn more, please see: 26 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 27 | # - https://gh.io/supported-runners-and-hardware-resources 28 | # - https://gh.io/using-larger-runners 29 | # Consider using larger runners for possible analysis time improvements. 30 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 31 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 32 | permissions: 33 | # required for all workflows 34 | security-events: write 35 | 36 | # only required for workflows in private repositories 37 | actions: read 38 | contents: read 39 | 40 | strategy: 41 | fail-fast: false 42 | matrix: 43 | language: [ 'ruby' ] 44 | # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] 45 | # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both 46 | # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both 47 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 48 | 49 | steps: 50 | - name: Checkout repository 51 | uses: actions/checkout@v4 52 | 53 | # Initializes the CodeQL tools for scanning. 54 | - name: Initialize CodeQL 55 | uses: github/codeql-action/init@v3 56 | with: 57 | languages: ${{ matrix.language }} 58 | # If you wish to specify custom queries, you can do so here or in a config file. 59 | # By default, queries listed here will override any specified in a config file. 60 | # Prefix the list here with "+" to use these queries and those in the config file. 61 | 62 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 63 | # queries: security-extended,security-and-quality 64 | 65 | 66 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). 67 | # If this step fails, then you should remove it and run the build manually (see below) 68 | - name: Autobuild 69 | uses: github/codeql-action/autobuild@v3 70 | 71 | # ℹ️ Command-line programs to run using the OS shell. 72 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 73 | 74 | # If the Autobuild fails above, remove it and uncomment the following three lines. 75 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 76 | 77 | # - run: | 78 | # echo "Run, Build Application using script" 79 | # ./location_of_script_within_repo/buildscript.sh 80 | 81 | - name: Perform CodeQL Analysis 82 | uses: github/codeql-action/analyze@v3 83 | with: 84 | category: "/language:${{matrix.language}}" 85 | -------------------------------------------------------------------------------- /.github/workflows/push_gem.yml: -------------------------------------------------------------------------------- 1 | name: Publish gem to rubygems.org 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | push: 13 | if: github.repository == 'ruby/optparse' 14 | runs-on: ubuntu-latest 15 | 16 | environment: 17 | name: rubygems.org 18 | url: https://rubygems.org/gems/optparse 19 | 20 | permissions: 21 | contents: write 22 | id-token: write 23 | 24 | steps: 25 | - name: Harden Runner 26 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 27 | with: 28 | egress-policy: audit 29 | 30 | - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 31 | 32 | - name: Set up Ruby 33 | uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 34 | with: 35 | bundler-cache: true 36 | ruby-version: ruby 37 | 38 | - name: Publish to RubyGems 39 | uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1 40 | 41 | - name: Create GitHub release 42 | run: | 43 | tag_name="$(git describe --tags --abbrev=0)" 44 | gh release create "${tag_name}" --verify-tag --generate-notes 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }} 47 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | schedule: 8 | - cron: '3 11 * * 4' 9 | 10 | jobs: 11 | ruby-versions: 12 | uses: ruby/actions/.github/workflows/ruby_versions.yml@master 13 | with: 14 | min_version: 2.5 15 | 16 | test: 17 | needs: ruby-versions 18 | name: build (${{ matrix.ruby }} / ${{ matrix.os }}) 19 | strategy: 20 | matrix: 21 | ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }} 22 | os: [ ubuntu-latest, macos-latest, windows-latest ] 23 | exclude: 24 | - { os: macos-latest, ruby: 2.5 } 25 | - { os: windows-latest, ruby: truffleruby-head } 26 | - { os: windows-latest, ruby: truffleruby } 27 | - { os: windows-latest, ruby: jruby-head } 28 | - { os: windows-latest, ruby: jruby } 29 | runs-on: ${{ matrix.os }} 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Set up Ruby 33 | uses: ruby/setup-ruby@v1 34 | with: 35 | ruby-version: ${{ matrix.ruby }} 36 | - name: Install dependencies 37 | run: bundle install 38 | - name: Run test 39 | run: rake test 40 | 41 | - uses: ./.github/actions/package 42 | if: ${{ matrix.ruby == needs.ruby-versions.outputs.latest }} 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /rdoc/ 6 | /logs/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | /Gemfile.lock 11 | /ChangeLog 12 | -------------------------------------------------------------------------------- /.rdoc_options: -------------------------------------------------------------------------------- 1 | --- 2 | page_dir: doc 3 | main_page: README.md 4 | title: Documentation for OptionParser 5 | op_dir: rdoc 6 | -------------------------------------------------------------------------------- /BSDL: -------------------------------------------------------------------------------- 1 | Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 16 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 | SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Ruby is copyrighted free software by Yukihiro Matsumoto . 2 | You can redistribute it and/or modify it under either the terms of the 3 | 2-clause BSDL (see the file BSDL), or the conditions below: 4 | 5 | 1. You may make and give away verbatim copies of the source form of the 6 | software without restriction, provided that you duplicate all of the 7 | original copyright notices and associated disclaimers. 8 | 9 | 2. You may modify your copy of the software in any way, provided that 10 | you do at least ONE of the following: 11 | 12 | a. place your modifications in the Public Domain or otherwise 13 | make them Freely Available, such as by posting said 14 | modifications to Usenet or an equivalent medium, or by allowing 15 | the author to include your modifications in the software. 16 | 17 | b. use the modified software only within your corporation or 18 | organization. 19 | 20 | c. give non-standard binaries non-standard names, with 21 | instructions on where to get the original software distribution. 22 | 23 | d. make other distribution arrangements with the author. 24 | 25 | 3. You may distribute the software in object code or binary form, 26 | provided that you do at least ONE of the following: 27 | 28 | a. distribute the binaries and library files of the software, 29 | together with instructions (in the manual page or equivalent) 30 | on where to get the original distribution. 31 | 32 | b. accompany the distribution with the machine-readable source of 33 | the software. 34 | 35 | c. give non-standard binaries non-standard names, with 36 | instructions on where to get the original software distribution. 37 | 38 | d. make other distribution arrangements with the author. 39 | 40 | 4. You may modify and include the part of the software into any other 41 | software (possibly commercial). But some files in the distribution 42 | are not written by the author, so that they are not under these terms. 43 | 44 | For the list of those files and their copying conditions, see the 45 | file LEGAL. 46 | 47 | 5. The scripts and library files supplied as input to or produced as 48 | output from the software do not automatically fall under the 49 | copyright of the software, but belong to whomever generated them, 50 | and may be sold commercially, and may be aggregated with this 51 | software. 52 | 53 | 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR 54 | IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 55 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 | PURPOSE. 57 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rake" 4 | gem "test-unit" 5 | gem "test-unit-ruby-core" 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OptionParser 2 | 3 | OptionParser is a class for command-line option analysis. It is much more 4 | advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented 5 | solution. 6 | 7 | ## Features 8 | 9 | 1. The argument specification and the code to handle it are written in the 10 | same place. 11 | 2. It can output an option summary; you don't need to maintain this string 12 | separately. 13 | 3. Optional and mandatory arguments are specified very gracefully. 14 | 4. Arguments can be automatically converted to a specified class. 15 | 5. Arguments can be restricted to a certain set. 16 | 17 | ## Installation 18 | 19 | Add this line to your application's Gemfile: 20 | 21 | ```ruby 22 | gem 'optparse' 23 | ``` 24 | 25 | And then execute: 26 | 27 | $ bundle install 28 | 29 | Or install it yourself as: 30 | 31 | $ gem install optparse 32 | 33 | ## Usage 34 | 35 | ```ruby 36 | require 'optparse' 37 | 38 | options = {} 39 | OptionParser.new do |opts| 40 | opts.banner = "Usage: example.rb [options]" 41 | 42 | opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| 43 | options[:verbose] = v 44 | end 45 | end.parse! 46 | 47 | p options 48 | p ARGV 49 | ``` 50 | 51 | ## Development 52 | 53 | After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests. 54 | 55 | 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 56 | 57 | ## Contributing 58 | 59 | Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/optparse. 60 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rake/testtask" 3 | 4 | Rake::TestTask.new(:test) do |t| 5 | t.libs << "test/lib" 6 | t.ruby_opts << "-rhelper" 7 | t.test_files = FileList["test/**/test_*.rb"] 8 | end 9 | 10 | task :default => :test 11 | 12 | task :rdoc do 13 | sh("rdoc", *Bundler::GemHelper.instance.gemspec.rdoc_options, ".") 14 | end 15 | -------------------------------------------------------------------------------- /doc/optparse/.document: -------------------------------------------------------------------------------- 1 | *.rdoc 2 | -------------------------------------------------------------------------------- /doc/optparse/argument_converters.rdoc: -------------------------------------------------------------------------------- 1 | == Argument Converters 2 | 3 | An option can specify that its argument is to be converted 4 | from the default +String+ to an instance of another class. 5 | 6 | === Contents 7 | 8 | - {Built-In Argument Converters}[#label-Built-In+Argument+Converters] 9 | - {Date}[#label-Date] 10 | - {DateTime}[#label-DateTime] 11 | - {Time}[#label-Time] 12 | - {URI}[#label-URI] 13 | - {Shellwords}[#label-Shellwords] 14 | - {Integer}[#label-Integer] 15 | - {Float}[#label-Float] 16 | - {Numeric}[#label-Numeric] 17 | - {DecimalInteger}[#label-DecimalInteger] 18 | - {OctalInteger}[#label-OctalInteger] 19 | - {DecimalNumeric}[#label-DecimalNumeric] 20 | - {TrueClass}[#label-TrueClass] 21 | - {FalseClass}[#label-FalseClass] 22 | - {Object}[#label-Object] 23 | - {String}[#label-String] 24 | - {Array}[#label-Array] 25 | - {Regexp}[#label-Regexp] 26 | - {Custom Argument Converters}[#label-Custom+Argument+Converters] 27 | 28 | === Built-In Argument Converters 29 | 30 | +OptionParser+ has a number of built-in argument converters, 31 | which are demonstrated below. 32 | 33 | ==== +Date+ 34 | 35 | File +date.rb+ 36 | defines an option whose argument is to be converted to a +Date+ object. 37 | The argument is converted by method Date#parse. 38 | 39 | :include: ruby/date.rb 40 | 41 | Executions: 42 | 43 | $ ruby date.rb --date 2001-02-03 44 | [#, Date] 45 | $ ruby date.rb --date 20010203 46 | [#, Date] 47 | $ ruby date.rb --date "3rd Feb 2001" 48 | [#, Date] 49 | 50 | ==== +DateTime+ 51 | 52 | File +datetime.rb+ 53 | defines an option whose argument is to be converted to a +DateTime+ object. 54 | The argument is converted by method DateTime#parse. 55 | 56 | :include: ruby/datetime.rb 57 | 58 | Executions: 59 | 60 | $ ruby datetime.rb --datetime 2001-02-03T04:05:06+07:00 61 | [#, DateTime] 62 | $ ruby datetime.rb --datetime 20010203T040506+0700 63 | [#, DateTime] 64 | $ ruby datetime.rb --datetime "3rd Feb 2001 04:05:06 PM" 65 | [#, DateTime] 66 | 67 | ==== +Time+ 68 | 69 | File +time.rb+ 70 | defines an option whose argument is to be converted to a +Time+ object. 71 | The argument is converted by method Time#httpdate or Time#parse. 72 | 73 | :include: ruby/time.rb 74 | 75 | Executions: 76 | 77 | $ ruby time.rb --time "Thu, 06 Oct 2011 02:26:12 GMT" 78 | [2011-10-06 02:26:12 UTC, Time] 79 | $ ruby time.rb --time 2010-10-31 80 | [2010-10-31 00:00:00 -0500, Time] 81 | 82 | ==== +URI+ 83 | 84 | File +uri.rb+ 85 | defines an option whose argument is to be converted to a +URI+ object. 86 | The argument is converted by method URI#parse. 87 | 88 | :include: ruby/uri.rb 89 | 90 | Executions: 91 | 92 | $ ruby uri.rb --uri https://github.com 93 | [#, URI::HTTPS] 94 | $ ruby uri.rb --uri http://github.com 95 | [#, URI::HTTP] 96 | $ ruby uri.rb --uri file://~/var 97 | [#, URI::File] 98 | 99 | ==== +Shellwords+ 100 | 101 | File +shellwords.rb+ 102 | defines an option whose argument is to be converted to an +Array+ object by method 103 | Shellwords#shellwords. 104 | 105 | :include: ruby/shellwords.rb 106 | 107 | Executions: 108 | 109 | $ ruby shellwords.rb --shellwords "ruby my_prog.rb | less" 110 | [["ruby", "my_prog.rb", "|", "less"], Array] 111 | $ ruby shellwords.rb --shellwords "here are 'two words'" 112 | [["here", "are", "two words"], Array] 113 | 114 | ==== +Integer+ 115 | 116 | File +integer.rb+ 117 | defines an option whose argument is to be converted to an +Integer+ object. 118 | The argument is converted by method Kernel#Integer. 119 | 120 | :include: ruby/integer.rb 121 | 122 | Executions: 123 | 124 | $ ruby integer.rb --integer 100 125 | [100, Integer] 126 | $ ruby integer.rb --integer -100 127 | [-100, Integer] 128 | $ ruby integer.rb --integer 0100 129 | [64, Integer] 130 | $ ruby integer.rb --integer 0x100 131 | [256, Integer] 132 | $ ruby integer.rb --integer 0b100 133 | [4, Integer] 134 | 135 | ==== +Float+ 136 | 137 | File +float.rb+ 138 | defines an option whose argument is to be converted to a +Float+ object. 139 | The argument is converted by method Kernel#Float. 140 | 141 | :include: ruby/float.rb 142 | 143 | Executions: 144 | 145 | $ ruby float.rb --float 1 146 | [1.0, Float] 147 | $ ruby float.rb --float 3.14159 148 | [3.14159, Float] 149 | $ ruby float.rb --float 1.234E2 150 | [123.4, Float] 151 | $ ruby float.rb --float 1.234E-2 152 | [0.01234, Float] 153 | 154 | ==== +Numeric+ 155 | 156 | File +numeric.rb+ 157 | defines an option whose argument is to be converted to an instance 158 | of +Rational+, +Float+, or +Integer+. 159 | The argument is converted by method Kernel#Rational, 160 | Kernel#Float, or Kernel#Integer. 161 | 162 | :include: ruby/numeric.rb 163 | 164 | Executions: 165 | 166 | $ ruby numeric.rb --numeric 1/3 167 | [(1/3), Rational] 168 | $ ruby numeric.rb --numeric 3.333E-1 169 | [0.3333, Float] 170 | $ ruby numeric.rb --numeric 3 171 | [3, Integer] 172 | 173 | ==== +DecimalInteger+ 174 | 175 | File +decimal_integer.rb+ 176 | defines an option whose argument is to be converted to an +Integer+ object. 177 | The argument is converted by method Kernel#Integer. 178 | 179 | :include: ruby/decimal_integer.rb 180 | 181 | The argument may not be in a binary or hexadecimal format; 182 | a leading zero is ignored (not parsed as octal). 183 | 184 | Executions: 185 | 186 | $ ruby decimal_integer.rb --decimal_integer 100 187 | [100, Integer] 188 | $ ruby decimal_integer.rb --decimal_integer -100 189 | [-100, Integer] 190 | $ ruby decimal_integer.rb --decimal_integer 0100 191 | [100, Integer] 192 | $ ruby decimal_integer.rb --decimal_integer -0100 193 | [-100, Integer] 194 | 195 | ==== +OctalInteger+ 196 | 197 | File +octal_integer.rb+ 198 | defines an option whose argument is to be converted to an +Integer+ object. 199 | The argument is converted by method Kernel#Integer. 200 | 201 | :include: ruby/octal_integer.rb 202 | 203 | The argument may not be in a binary or hexadecimal format; 204 | it is parsed as octal, regardless of whether it has a leading zero. 205 | 206 | Executions: 207 | 208 | $ ruby octal_integer.rb --octal_integer 100 209 | [64, Integer] 210 | $ ruby octal_integer.rb --octal_integer -100 211 | [-64, Integer] 212 | $ ruby octal_integer.rb --octal_integer 0100 213 | [64, Integer] 214 | 215 | ==== +DecimalNumeric+ 216 | 217 | File +decimal_numeric.rb+ 218 | defines an option whose argument is to be converted to an +Integer+ object. 219 | The argument is converted by method Kernel#Integer 220 | 221 | :include: ruby/decimal_numeric.rb 222 | 223 | The argument may not be in a binary or hexadecimal format; 224 | a leading zero causes the argument to be parsed as octal. 225 | 226 | Executions: 227 | 228 | $ ruby decimal_numeric.rb --decimal_numeric 100 229 | [100, Integer] 230 | $ ruby decimal_numeric.rb --decimal_numeric -100 231 | [-100, Integer] 232 | $ ruby decimal_numeric.rb --decimal_numeric 0100 233 | [64, Integer] 234 | 235 | ==== +TrueClass+ 236 | 237 | File +true_class.rb+ 238 | defines an option whose argument is to be converted to +true+ or +false+. 239 | The argument is evaluated by method Object#nil?. 240 | 241 | :include: ruby/true_class.rb 242 | 243 | The argument may be any of those shown in the examples below. 244 | 245 | Executions: 246 | 247 | $ ruby true_class.rb --true_class true 248 | [true, TrueClass] 249 | $ ruby true_class.rb --true_class yes 250 | [true, TrueClass] 251 | $ ruby true_class.rb --true_class + 252 | [true, TrueClass] 253 | $ ruby true_class.rb --true_class false 254 | [false, FalseClass] 255 | $ ruby true_class.rb --true_class no 256 | [false, FalseClass] 257 | $ ruby true_class.rb --true_class - 258 | [false, FalseClass] 259 | $ ruby true_class.rb --true_class nil 260 | [false, FalseClass] 261 | 262 | ==== +FalseClass+ 263 | 264 | File +false_class.rb+ 265 | defines an option whose argument is to be converted to +true+ or +false+. 266 | The argument is evaluated by method Object#nil?. 267 | 268 | :include: ruby/false_class.rb 269 | 270 | The argument may be any of those shown in the examples below. 271 | 272 | Executions: 273 | 274 | $ ruby false_class.rb --false_class false 275 | [false, FalseClass] 276 | $ ruby false_class.rb --false_class no 277 | [false, FalseClass] 278 | $ ruby false_class.rb --false_class - 279 | [false, FalseClass] 280 | $ ruby false_class.rb --false_class nil 281 | [false, FalseClass] 282 | $ ruby false_class.rb --false_class true 283 | [true, TrueClass] 284 | $ ruby false_class.rb --false_class yes 285 | [true, TrueClass] 286 | $ ruby false_class.rb --false_class + 287 | [true, TrueClass] 288 | 289 | ==== +Object+ 290 | 291 | File +object.rb+ 292 | defines an option whose argument is not to be converted from +String+. 293 | 294 | :include: ruby/object.rb 295 | 296 | Executions: 297 | 298 | $ ruby object.rb --object foo 299 | ["foo", String] 300 | $ ruby object.rb --object nil 301 | ["nil", String] 302 | 303 | ==== +String+ 304 | 305 | File +string.rb+ 306 | defines an option whose argument is not to be converted from +String+. 307 | 308 | :include: ruby/string.rb 309 | 310 | Executions: 311 | 312 | $ ruby string.rb --string foo 313 | ["foo", String] 314 | $ ruby string.rb --string nil 315 | ["nil", String] 316 | 317 | ==== +Array+ 318 | 319 | File +array.rb+ 320 | defines an option whose argument is to be converted from +String+ 321 | to an array of strings, based on comma-separated substrings. 322 | 323 | :include: ruby/array.rb 324 | 325 | Executions: 326 | 327 | $ ruby array.rb --array "" 328 | [[], Array] 329 | $ ruby array.rb --array foo,bar,baz 330 | [["foo", "bar", "baz"], Array] 331 | $ ruby array.rb --array "foo, bar, baz" 332 | [["foo", " bar", " baz"], Array] 333 | 334 | ==== +Regexp+ 335 | 336 | File +regexp.rb+ 337 | defines an option whose argument is to be converted to a +Regexp+ object. 338 | 339 | :include: ruby/regexp.rb 340 | 341 | Executions: 342 | 343 | $ ruby regexp.rb --regexp foo 344 | 345 | === Custom Argument Converters 346 | 347 | You can create custom argument converters. 348 | To create a custom converter, call OptionParser#accept with: 349 | 350 | - An identifier, which may be any object. 351 | - An optional match pattern, which defaults to /.*/m. 352 | - A block that accepts the argument and returns the converted value. 353 | 354 | This custom converter accepts any argument and converts it, 355 | if possible, to a +Complex+ object. 356 | 357 | :include: ruby/custom_converter.rb 358 | 359 | Executions: 360 | 361 | $ ruby custom_converter.rb --complex 0 362 | [(0+0i), Complex] 363 | $ ruby custom_converter.rb --complex 1 364 | [(1+0i), Complex] 365 | $ ruby custom_converter.rb --complex 1+2i 366 | [(1+2i), Complex] 367 | $ ruby custom_converter.rb --complex 0.3-0.5i 368 | [(0.3-0.5i), Complex] 369 | 370 | This custom converter accepts any 1-word argument 371 | and capitalizes it, if possible. 372 | 373 | :include: ruby/match_converter.rb 374 | 375 | Executions: 376 | 377 | $ ruby match_converter.rb --capitalize foo 378 | ["Foo", String] 379 | $ ruby match_converter.rb --capitalize "foo bar" 380 | match_converter.rb:9:in '
': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument) 381 | -------------------------------------------------------------------------------- /doc/optparse/creates_option.rdoc: -------------------------------------------------------------------------------- 1 | Creates an option from the given parameters +params+. 2 | See {Parameters for New Options}[optparse/option_params.rdoc]. 3 | 4 | The block, if given, is the handler for the created option. 5 | When the option is encountered during command-line parsing, 6 | the block is called with the argument given for the option, if any. 7 | See {Option Handlers}[optparse/option_params.rdoc#label-Option+Handlers]. 8 | -------------------------------------------------------------------------------- /doc/optparse/option_params.rdoc: -------------------------------------------------------------------------------- 1 | == Parameters for New Options 2 | 3 | Option-creating methods in +OptionParser+ 4 | accept arguments that determine the behavior of a new option: 5 | 6 | - OptionParser#on 7 | - OptionParser#on_head 8 | - OptionParser#on_tail 9 | - OptionParser#define 10 | - OptionParser#define_head 11 | - OptionParser#define_tail 12 | - OptionParser#make_switch 13 | 14 | The code examples on this page use: 15 | 16 | - OptionParser#on, to define options. 17 | - OptionParser#parse!, to parse the command line. 18 | - Built-in option --help, to display defined options. 19 | 20 | Contents: 21 | 22 | - {Option Names}[#label-Option+Names] 23 | - {Short Names}[#label-Short+Names] 24 | - {Simple Short Names}[#label-Simple+Short+Names] 25 | - {Short Names with Required Arguments}[#label-Short+Names+with+Required+Arguments] 26 | - {Short Names with Optional Arguments}[#label-Short+Names+with+Optional+Arguments] 27 | - {Short Names from Range}[#label-Short+Names+from+Range] 28 | - {Long Names}[#label-Long+Names] 29 | - {Simple Long Names}[#label-Simple+Long+Names] 30 | - {Long Names with Required Arguments}[#label-Long+Names+with+Required+Arguments] 31 | - {Long Names with Optional Arguments}[#label-Long+Names+with+Optional+Arguments] 32 | - {Long Names with Negation}[#label-Long+Names+with+Negation] 33 | - {Mixed Names}[#label-Mixed+Names] 34 | - {Argument Strings}[#label-Argument+Strings] 35 | - {Argument Values}[#label-Argument+Values] 36 | - {Explicit Argument Values}[#label-Explicit+Argument+Values] 37 | - {Explicit Values in Array}[#label-Explicit+Values+in+Array] 38 | - {Explicit Values in Hash}[#label-Explicit+Values+in+Hash] 39 | - {Argument Value Patterns}[#label-Argument+Value+Patterns] 40 | - {Argument Converters}[#label-Argument+Converters] 41 | - {Descriptions}[#label-Descriptions] 42 | - {Option Handlers}[#label-Option+Handlers] 43 | - {Handler Blocks}[#label-Handler+Blocks] 44 | - {Handler Procs}[#label-Handler+Procs] 45 | - {Handler Methods}[#label-Handler+Methods] 46 | 47 | === Option Names 48 | 49 | There are two kinds of option names: 50 | 51 | - Short option name, consisting of a single hyphen and a single character. 52 | - Long option name, consisting of two hyphens and one or more characters. 53 | 54 | ==== Short Names 55 | 56 | ===== Simple Short Names 57 | 58 | File +short_simple.rb+ defines two options: 59 | 60 | - One with short name -x. 61 | - The other with two short names, in effect, aliases, -1 and -%. 62 | 63 | :include: ruby/short_simple.rb 64 | 65 | Executions: 66 | 67 | $ ruby short_simple.rb --help 68 | Usage: short_simple [options] 69 | -x One short name 70 | -1, -% Two short names (aliases) 71 | $ ruby short_simple.rb -x 72 | ["-x", true] 73 | $ ruby short_simple.rb -1 -x -% 74 | ["-1 or -%", true] 75 | ["-x", true] 76 | ["-1 or -%", true] 77 | 78 | ===== Short Names with Required Arguments 79 | 80 | A short name followed (no whitespace) by a dummy word 81 | defines an option that requires an argument. 82 | 83 | File +short_required.rb+ defines an option -x 84 | that requires an argument. 85 | 86 | :include: ruby/short_required.rb 87 | 88 | Executions: 89 | 90 | $ ruby short_required.rb --help 91 | Usage: short_required [options] 92 | -xXXX Short name with required argument 93 | $ ruby short_required.rb -x 94 | short_required.rb:6:in '
': missing argument: -x (OptionParser::MissingArgument) 95 | $ ruby short_required.rb -x FOO 96 | ["-x", "FOO"] 97 | 98 | ===== Short Names with Optional Arguments 99 | 100 | A short name followed (with whitespace) by a dummy word in square brackets 101 | defines an option that allows an optional argument. 102 | 103 | File +short_optional.rb+ defines an option -x 104 | that allows an optional argument. 105 | 106 | :include: ruby/short_optional.rb 107 | 108 | Executions: 109 | 110 | $ ruby short_optional.rb --help 111 | Usage: short_optional [options] 112 | -x [XXX] Short name with optional argument 113 | $ ruby short_optional.rb -x 114 | ["-x", nil] 115 | $ ruby short_optional.rb -x FOO 116 | ["-x", "FOO"] 117 | 118 | ===== Short Names from Range 119 | 120 | You can define an option with multiple short names 121 | taken from a range of characters. 122 | The parser yields both the actual character cited and the value. 123 | 124 | File +short_range.rb+ defines an option with short names 125 | for all printable characters from ! to ~: 126 | 127 | :include: ruby/short_range.rb 128 | 129 | Executions: 130 | 131 | $ ruby short_range.rb --help 132 | Usage: short_range [options] 133 | -[!-~] Short names in (very large) range 134 | $ ruby short_range.rb -! 135 | ["!-~", "!", nil] 136 | $ ruby short_range.rb -! 137 | ["!-~", "!", nil] 138 | $ ruby short_range.rb -A 139 | ["!-~", "A", nil] 140 | $ ruby short_range.rb -z 141 | ["!-~", "z", nil] 142 | 143 | ==== Long Names 144 | 145 | ===== Simple Long Names 146 | 147 | File +long_simple.rb+ defines two options: 148 | 149 | - One with long name -xxx. 150 | - The other with two long names, in effect, aliases, 151 | --y1% and --z2#. 152 | 153 | :include: ruby/long_simple.rb 154 | 155 | Executions: 156 | 157 | $ ruby long_simple.rb --help 158 | Usage: long_simple [options] 159 | --xxx One long name 160 | --y1%, --z2# Two long names (aliases) 161 | $ ruby long_simple.rb --xxx 162 | ["--xxx", true] 163 | $ ruby long_simple.rb --y1% --xxx --z2# 164 | ["--y1% or --z2#", true] 165 | ["--xxx", true] 166 | ["--y1% or --z2#", true] 167 | 168 | ===== Long Names with Required Arguments 169 | 170 | A long name followed (with whitespace) by a dummy word 171 | defines an option that requires an argument. 172 | 173 | File +long_required.rb+ defines an option --xxx 174 | that requires an argument. 175 | 176 | :include: ruby/long_required.rb 177 | 178 | Executions: 179 | 180 | $ ruby long_required.rb --help 181 | Usage: long_required [options] 182 | --xxx XXX Long name with required argument 183 | $ ruby long_required.rb --xxx 184 | long_required.rb:6:in '
': missing argument: --xxx (OptionParser::MissingArgument) 185 | $ ruby long_required.rb --xxx FOO 186 | ["--xxx", "FOO"] 187 | 188 | ===== Long Names with Optional Arguments 189 | 190 | A long name followed (with whitespace) by a dummy word in square brackets 191 | defines an option that allows an optional argument. 192 | 193 | File +long_optional.rb+ defines an option --xxx 194 | that allows an optional argument. 195 | 196 | :include: ruby/long_optional.rb 197 | 198 | Executions: 199 | 200 | $ ruby long_optional.rb --help 201 | Usage: long_optional [options] 202 | --xxx [XXX] Long name with optional argument 203 | $ ruby long_optional.rb --xxx 204 | ["--xxx", nil] 205 | $ ruby long_optional.rb --xxx FOO 206 | ["--xxx", "FOO"] 207 | 208 | ===== Long Names with Negation 209 | 210 | A long name may be defined with both positive and negative senses. 211 | 212 | File +long_with_negation.rb+ defines an option that has both senses. 213 | 214 | :include: ruby/long_with_negation.rb 215 | 216 | Executions: 217 | 218 | $ ruby long_with_negation.rb --help 219 | Usage: long_with_negation [options] 220 | --[no-]binary Long name with negation 221 | $ ruby long_with_negation.rb --binary 222 | [true, TrueClass] 223 | $ ruby long_with_negation.rb --no-binary 224 | [false, FalseClass] 225 | 226 | ==== Mixed Names 227 | 228 | An option may have both short and long names. 229 | 230 | File +mixed_names.rb+ defines a mixture of short and long names. 231 | 232 | :include: ruby/mixed_names.rb 233 | 234 | Executions: 235 | 236 | $ ruby mixed_names.rb --help 237 | Usage: mixed_names [options] 238 | -x, --xxx Short and long, no argument 239 | -y, --yyyYYY Short and long, required argument 240 | -z, --zzz [ZZZ] Short and long, optional argument 241 | $ ruby mixed_names.rb -x 242 | ["--xxx", true] 243 | $ ruby mixed_names.rb --xxx 244 | ["--xxx", true] 245 | $ ruby mixed_names.rb -y 246 | mixed_names.rb:12:in '
': missing argument: -y (OptionParser::MissingArgument) 247 | $ ruby mixed_names.rb -y FOO 248 | ["--yyy", "FOO"] 249 | $ ruby mixed_names.rb --yyy 250 | mixed_names.rb:12:in '
': missing argument: --yyy (OptionParser::MissingArgument) 251 | $ ruby mixed_names.rb --yyy BAR 252 | ["--yyy", "BAR"] 253 | $ ruby mixed_names.rb -z 254 | ["--zzz", nil] 255 | $ ruby mixed_names.rb -z BAZ 256 | ["--zzz", "BAZ"] 257 | $ ruby mixed_names.rb --zzz 258 | ["--zzz", nil] 259 | $ ruby mixed_names.rb --zzz BAT 260 | ["--zzz", "BAT"] 261 | 262 | === Argument Keywords 263 | 264 | As seen above, a given option name string may itself 265 | indicate whether the option has no argument, a required argument, 266 | or an optional argument. 267 | 268 | An alternative is to use a separate symbol keyword, 269 | which is one of :NONE (the default), 270 | :REQUIRED, :OPTIONAL. 271 | 272 | File +argument_keywords.rb+ defines an option with a required argument. 273 | 274 | :include: ruby/argument_keywords.rb 275 | 276 | Executions: 277 | 278 | $ ruby argument_keywords.rb --help 279 | Usage: argument_keywords [options] 280 | -x, --xxx Required argument 281 | $ ruby argument_styles.rb --xxx 282 | argument_styles.rb:6:in '
': missing argument: --xxx (OptionParser::MissingArgument) 283 | $ ruby argument_styles.rb --xxx FOO 284 | ["--xxx", "FOO"] 285 | 286 | === Argument Strings 287 | 288 | Still another way to specify a required argument 289 | is to define it in a string separate from the name string. 290 | 291 | File +argument_strings.rb+ defines an option with a required argument. 292 | 293 | :include: ruby/argument_strings.rb 294 | 295 | Executions: 296 | 297 | $ ruby argument_strings.rb --help 298 | Usage: argument_strings [options] 299 | -x, --xxx=XXX Required argument 300 | $ ruby argument_strings.rb --xxx 301 | argument_strings.rb:9:in '
': missing argument: --xxx (OptionParser::MissingArgument) 302 | $ ruby argument_strings.rb --xxx FOO 303 | ["--xxx", "FOO"] 304 | 305 | === Argument Values 306 | 307 | Permissible argument values may be restricted 308 | either by specifying explicit values 309 | or by providing a pattern that the given value must match. 310 | 311 | ==== Explicit Argument Values 312 | 313 | You can specify argument values in either of two ways: 314 | 315 | - Specify values an array of strings. 316 | - Specify values a hash. 317 | 318 | ===== Explicit Values in Array 319 | 320 | You can specify explicit argument values in an array of strings. 321 | The argument value must be one of those strings, or an unambiguous abbreviation. 322 | 323 | File +explicit_array_values.rb+ defines options with explicit argument values. 324 | 325 | :include: ruby/explicit_array_values.rb 326 | 327 | Executions: 328 | 329 | $ ruby explicit_array_values.rb --help 330 | Usage: explicit_array_values [options] 331 | -xXXX Values for required argument 332 | -y [YYY] Values for optional argument 333 | $ ruby explicit_array_values.rb -x 334 | explicit_array_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) 335 | $ ruby explicit_array_values.rb -x foo 336 | ["-x", "foo"] 337 | $ ruby explicit_array_values.rb -x f 338 | ["-x", "foo"] 339 | $ ruby explicit_array_values.rb -x bar 340 | ["-x", "bar"] 341 | $ ruby explicit_array_values.rb -y ba 342 | explicit_array_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) 343 | $ ruby explicit_array_values.rb -x baz 344 | explicit_array_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) 345 | 346 | 347 | ===== Explicit Values in Hash 348 | 349 | You can specify explicit argument values in a hash with string keys. 350 | The value passed must be one of those keys, or an unambiguous abbreviation; 351 | the value yielded will be the value for that key. 352 | 353 | File +explicit_hash_values.rb+ defines options with explicit argument values. 354 | 355 | :include: ruby/explicit_hash_values.rb 356 | 357 | Executions: 358 | 359 | $ ruby explicit_hash_values.rb --help 360 | Usage: explicit_hash_values [options] 361 | -xXXX Values for required argument 362 | -y [YYY] Values for optional argument 363 | $ ruby explicit_hash_values.rb -x 364 | explicit_hash_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) 365 | $ ruby explicit_hash_values.rb -x foo 366 | ["-x", 0] 367 | $ ruby explicit_hash_values.rb -x f 368 | ["-x", 0] 369 | $ ruby explicit_hash_values.rb -x bar 370 | ["-x", 1] 371 | $ ruby explicit_hash_values.rb -x baz 372 | explicit_hash_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) 373 | $ ruby explicit_hash_values.rb -y 374 | ["-y", nil] 375 | $ ruby explicit_hash_values.rb -y baz 376 | ["-y", 2] 377 | $ ruby explicit_hash_values.rb -y bat 378 | ["-y", 3] 379 | $ ruby explicit_hash_values.rb -y ba 380 | explicit_hash_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) 381 | $ ruby explicit_hash_values.rb -y bam 382 | ["-y", nil] 383 | 384 | ==== Argument Value Patterns 385 | 386 | You can restrict permissible argument values 387 | by specifying a +Regexp+ that the given argument must match, 388 | or a +Range+ or +Array+ that the converted value must be included in. 389 | 390 | File +matched_values.rb+ defines options with matched argument values. 391 | 392 | :include: ruby/matched_values.rb 393 | 394 | Executions: 395 | 396 | $ ruby matched_values.rb --help 397 | Usage: matched_values [options] 398 | --xxx XXX Matched values 399 | --yyy YYY Check by range 400 | --zzz ZZZ Check by list 401 | $ ruby matched_values.rb --xxx foo 402 | ["--xxx", "foo"] 403 | $ ruby matched_values.rb --xxx FOO 404 | ["--xxx", "FOO"] 405 | $ ruby matched_values.rb --xxx bar 406 | matched_values.rb:12:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) 407 | $ ruby matched_values.rb --yyy 1 408 | ["--yyy", 1] 409 | $ ruby matched_values.rb --yyy 4 410 | matched_values.rb:12:in '
': invalid argument: --yyy 4 (OptionParser::InvalidArgument) 411 | $ ruby matched_values.rb --zzz 1 412 | ["--zzz", 1] 413 | $ ruby matched_values.rb --zzz 2 414 | matched_values.rb:12:in '
': invalid argument: --zzz 2 (OptionParser::InvalidArgument) 415 | 416 | === Argument Converters 417 | 418 | An option can specify that its argument is to be converted 419 | from the default +String+ to an instance of another class. 420 | 421 | There are a number of built-in converters. 422 | You can also define custom converters. 423 | 424 | See {Argument Converters}[./argument_converters.rdoc]. 425 | 426 | === Descriptions 427 | 428 | A description parameter is any string parameter 429 | that is not recognized as an 430 | {option name}[#label-Option+Names] or a 431 | {terminator}[#label-Terminators]; 432 | in other words, it does not begin with a hyphen. 433 | 434 | You may give any number of description parameters; 435 | each becomes a line in the text generated by option --help. 436 | 437 | File +descriptions.rb+ has six strings in its array +descriptions+. 438 | These are all passed as parameters to OptionParser#on, so that they 439 | all, line for line, become the option's description. 440 | 441 | :include: ruby/descriptions.rb 442 | 443 | Executions: 444 | 445 | $ ruby descriptions.rb --help 446 | Usage: descriptions [options] 447 | --xxx Lorem ipsum dolor sit amet, consectetuer 448 | adipiscing elit. Aenean commodo ligula eget. 449 | Aenean massa. Cum sociis natoque penatibus 450 | et magnis dis parturient montes, nascetur 451 | ridiculus mus. Donec quam felis, ultricies 452 | nec, pellentesque eu, pretium quis, sem. 453 | $ ruby descriptions.rb --xxx 454 | ["--xxx", true] 455 | 456 | === Option Handlers 457 | 458 | The handler for an option is an executable that will be called 459 | when the option is encountered. The handler may be: 460 | 461 | - A block (this is most often seen). 462 | - A proc. 463 | - A method. 464 | 465 | ==== Handler Blocks 466 | 467 | An option handler may be a block. 468 | 469 | File +block.rb+ defines an option that has a handler block. 470 | 471 | :include: ruby/block.rb 472 | 473 | Executions: 474 | 475 | $ ruby block.rb --help 476 | Usage: block [options] 477 | --xxx Option with no argument 478 | --yyy YYY Option with required argument 479 | $ ruby block.rb --xxx 480 | ["Handler block for -xxx called with value:", true] 481 | $ ruby block.rb --yyy FOO 482 | ["Handler block for -yyy called with value:", "FOO"] 483 | 484 | ==== Handler Procs 485 | 486 | An option handler may be a Proc. 487 | 488 | File +proc.rb+ defines an option that has a handler proc. 489 | 490 | :include: ruby/proc.rb 491 | 492 | Executions: 493 | 494 | $ ruby proc.rb --help 495 | Usage: proc [options] 496 | --xxx Option with no argument 497 | --yyy YYY Option with required argument 498 | $ ruby proc.rb --xxx 499 | ["Handler proc for -xxx called with value:", true] 500 | $ ruby proc.rb --yyy FOO 501 | ["Handler proc for -yyy called with value:", "FOO"] 502 | 503 | ==== Handler Methods 504 | 505 | An option handler may be a Method. 506 | 507 | File +proc.rb+ defines an option that has a handler method. 508 | 509 | :include: ruby/method.rb 510 | 511 | Executions: 512 | 513 | $ ruby method.rb --help 514 | Usage: method [options] 515 | --xxx Option with no argument 516 | --yyy YYY Option with required argument 517 | $ ruby method.rb --xxx 518 | ["Handler method for -xxx called with value:", true] 519 | $ ruby method.rb --yyy FOO 520 | ["Handler method for -yyy called with value:", "FOO"] 521 | -------------------------------------------------------------------------------- /doc/optparse/ruby/argument_abbreviation.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx=VALUE', %w[ABC def], 'Argument abbreviations') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('-y', '--yyy=VALUE', {"abc"=>"XYZ", def: "FOO"}, 'Argument abbreviations') do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/argument_keywords.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx', :REQUIRED, 'Required argument') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/argument_strings.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx', '=XXX', 'Required argument') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/argv.rb: -------------------------------------------------------------------------------- 1 | p ARGV 2 | 3 | -------------------------------------------------------------------------------- /doc/optparse/ruby/array.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--array=ARRAY', Array) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/basic.rb: -------------------------------------------------------------------------------- 1 | # Require the OptionParser code. 2 | require 'optparse' 3 | # Create an OptionParser object. 4 | parser = OptionParser.new 5 | # Define one or more options. 6 | parser.on('-x', 'Whether to X') do |value| 7 | p ['x', value] 8 | end 9 | parser.on('-y', 'Whether to Y') do |value| 10 | p ['y', value] 11 | end 12 | parser.on('-z', 'Whether to Z') do |value| 13 | p ['z', value] 14 | end 15 | # Parse the command line and return pared-down ARGV. 16 | p parser.parse! 17 | 18 | -------------------------------------------------------------------------------- /doc/optparse/ruby/block.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx', 'Option with no argument') do |value| 4 | p ['Handler block for -xxx called with value:', value] 5 | end 6 | parser.on('--yyy YYY', 'Option with required argument') do |value| 7 | p ['Handler block for -yyy called with value:', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/collected_options.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx', 'Short and long, no argument') 4 | parser.on('-yYYY', '--yyy', 'Short and long, required argument') 5 | parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') 6 | options = {} 7 | parser.parse!(into: options) 8 | p options 9 | -------------------------------------------------------------------------------- /doc/optparse/ruby/custom_converter.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/date' 2 | parser = OptionParser.new 3 | parser.accept(Complex) do |value| 4 | value.to_c 5 | end 6 | parser.on('--complex COMPLEX', Complex) do |value| 7 | p [value, value.class] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/date.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/date' 2 | parser = OptionParser.new 3 | parser.on('--date=DATE', Date) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/datetime.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/date' 2 | parser = OptionParser.new 3 | parser.on('--datetime=DATETIME', DateTime) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/decimal_integer.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | include OptionParser::Acceptables 3 | parser = OptionParser.new 4 | parser.on('--decimal_integer=DECIMAL_INTEGER', DecimalInteger) do |value| 5 | p [value, value.class] 6 | end 7 | parser.parse! 8 | -------------------------------------------------------------------------------- /doc/optparse/ruby/decimal_numeric.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | include OptionParser::Acceptables 3 | parser = OptionParser.new 4 | parser.on('--decimal_numeric=DECIMAL_NUMERIC', DecimalNumeric) do |value| 5 | p [value, value.class] 6 | end 7 | parser.parse! 8 | -------------------------------------------------------------------------------- /doc/optparse/ruby/default_values.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx', 'Short and long, no argument') 4 | parser.on('-yYYY', '--yyy', 'Short and long, required argument') 5 | parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') 6 | options = {yyy: 'AAA', zzz: 'BBB'} 7 | parser.parse!(into: options) 8 | p options 9 | -------------------------------------------------------------------------------- /doc/optparse/ruby/descriptions.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | description = <<-EOT 4 | Lorem ipsum dolor sit amet, consectetuer 5 | adipiscing elit. Aenean commodo ligula eget. 6 | Aenean massa. Cum sociis natoque penatibus 7 | et magnis dis parturient montes, nascetur 8 | ridiculus mus. Donec quam felis, ultricies 9 | nec, pellentesque eu, pretium quis, sem. 10 | EOT 11 | descriptions = description.split($/) 12 | parser.on('--xxx', *descriptions) do |value| 13 | p ['--xxx', value] 14 | end 15 | parser.parse! 16 | -------------------------------------------------------------------------------- /doc/optparse/ruby/explicit_array_values.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-xXXX', ['foo', 'bar'], 'Values for required argument' ) do |value| 4 | p ['-x', value] 5 | end 6 | parser.on('-y [YYY]', ['baz', 'bat'], 'Values for optional argument') do |value| 7 | p ['-y', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/explicit_hash_values.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-xXXX', {foo: 0, bar: 1}, 'Values for required argument' ) do |value| 4 | p ['-x', value] 5 | end 6 | parser.on('-y [YYY]', {baz: 2, bat: 3}, 'Values for optional argument') do |value| 7 | p ['-y', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/false_class.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--false_class=FALSE_CLASS', FalseClass) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/float.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--float=FLOAT', Float) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/help.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on( 4 | '-x', '--xxx', 5 | 'Adipiscing elit. Aenean commodo ligula eget.', 6 | 'Aenean massa. Cum sociis natoque penatibus', 7 | ) 8 | parser.on( 9 | '-y', '--yyy YYY', 10 | 'Lorem ipsum dolor sit amet, consectetuer.' 11 | ) 12 | parser.on( 13 | '-z', '--zzz [ZZZ]', 14 | 'Et magnis dis parturient montes, nascetur', 15 | 'ridiculus mus. Donec quam felis, ultricies', 16 | 'nec, pellentesque eu, pretium quis, sem.', 17 | ) 18 | parser.parse! 19 | -------------------------------------------------------------------------------- /doc/optparse/ruby/help_banner.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.banner = "Usage: ruby help_banner.rb" 4 | parser.parse! 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /doc/optparse/ruby/help_format.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new( 3 | 'ruby help_format.rb [options]', # Banner 4 | 20, # Width of options field 5 | ' ' * 2 # Indentation 6 | ) 7 | parser.on( 8 | '-x', '--xxx', 9 | 'Adipiscing elit. Aenean commodo ligula eget.', 10 | 'Aenean massa. Cum sociis natoque penatibus', 11 | ) 12 | parser.on( 13 | '-y', '--yyy YYY', 14 | 'Lorem ipsum dolor sit amet, consectetuer.' 15 | ) 16 | parser.on( 17 | '-z', '--zzz [ZZZ]', 18 | 'Et magnis dis parturient montes, nascetur', 19 | 'ridiculus mus. Donec quam felis, ultricies', 20 | 'nec, pellentesque eu, pretium quis, sem.', 21 | ) 22 | parser.parse! 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /doc/optparse/ruby/help_program_name.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.program_name = 'help_program_name.rb' 4 | parser.parse! 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /doc/optparse/ruby/integer.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--integer=INTEGER', Integer) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/long_names.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx', 'Long name') do |value| 4 | p ['-xxx', value] 5 | end 6 | parser.on('--y1%', '--z2#', "Two long names") do |value| 7 | p ['--y1% or --z2#', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/long_optional.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx [XXX]', 'Long name with optional argument') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/long_required.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx XXX', 'Long name with required argument') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/long_simple.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx', 'One long name') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('--y1%', '--z2#', 'Two long names (aliases)') do |value| 7 | p ['--y1% or --z2#', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/long_with_negation.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--[no-]binary', 'Long name with negation') do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/match_converter.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/date' 2 | parser = OptionParser.new 3 | parser.accept(:capitalize, /\w*/) do |value| 4 | value.capitalize 5 | end 6 | parser.on('--capitalize XXX', :capitalize) do |value| 7 | p [value, value.class] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/matched_values.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx XXX', /foo/i, 'Matched values') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('--yyy YYY', Integer, 'Check by range', 1..3) do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.on('--zzz ZZZ', Integer, 'Check by list', [1, 3, 4]) do |value| 10 | p ['--zzz', value] 11 | end 12 | parser.parse! 13 | -------------------------------------------------------------------------------- /doc/optparse/ruby/method.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | def xxx_handler(value) 4 | p ['Handler method for -xxx called with value:', value] 5 | end 6 | parser.on('--xxx', 'Option with no argument', method(:xxx_handler)) 7 | def yyy_handler(value) 8 | p ['Handler method for -yyy called with value:', value] 9 | end 10 | parser.on('--yyy YYY', 'Option with required argument', method(:yyy_handler)) 11 | parser.parse! 12 | -------------------------------------------------------------------------------- /doc/optparse/ruby/missing_options.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx', 'Short and long, no argument') 4 | parser.on('-yYYY', '--yyy', 'Short and long, required argument') 5 | parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') 6 | options = {} 7 | parser.parse!(into: options) 8 | required_options = [:xxx, :zzz] 9 | missing_options = required_options - options.keys 10 | unless missing_options.empty? 11 | fail "Missing required options: #{missing_options}" 12 | end 13 | -------------------------------------------------------------------------------- /doc/optparse/ruby/mixed_names.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', '--xxx', 'Short and long, no argument') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('-yYYY', '--yyy', 'Short and long, required argument') do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') do |value| 10 | p ['--zzz', value] 11 | end 12 | parser.parse! 13 | -------------------------------------------------------------------------------- /doc/optparse/ruby/name_abbrev.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-n', '--dry-run',) do |value| 4 | p ['--dry-run', value] 5 | end 6 | parser.on('-d', '--draft',) do |value| 7 | p ['--draft', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/no_abbreviation.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-n', '--dry-run',) do |value| 4 | p ['--dry-run', value] 5 | end 6 | parser.on('-d', '--draft',) do |value| 7 | p ['--draft', value] 8 | end 9 | parser.require_exact = true 10 | parser.parse! 11 | -------------------------------------------------------------------------------- /doc/optparse/ruby/numeric.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--numeric=NUMERIC', Numeric) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/object.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--object=OBJECT', Object) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/octal_integer.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | include OptionParser::Acceptables 3 | parser = OptionParser.new 4 | parser.on('--octal_integer=OCTAL_INTEGER', OctalInteger) do |value| 5 | p [value, value.class] 6 | end 7 | parser.parse! 8 | -------------------------------------------------------------------------------- /doc/optparse/ruby/optional_argument.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x [XXX]', '--xxx', 'Optional argument via short name') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('-y', '--yyy [YYY]', 'Optional argument via long name') do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/parse.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('--yyy YYY') do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.on('--zzz [ZZZ]') do |value| 10 | p ['--zzz', value] 11 | end 12 | ret = parser.parse(ARGV) 13 | puts "Returned: #{ret} (#{ret.class})" 14 | -------------------------------------------------------------------------------- /doc/optparse/ruby/parse_bang.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--xxx') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('--yyy YYY') do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.on('--zzz [ZZZ]') do |value| 10 | p ['--zzz', value] 11 | end 12 | ret = parser.parse! 13 | puts "Returned: #{ret} (#{ret.class})" 14 | -------------------------------------------------------------------------------- /doc/optparse/ruby/proc.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on( 4 | '--xxx', 5 | 'Option with no argument', 6 | ->(value) {p ['Handler proc for -xxx called with value:', value]} 7 | ) 8 | parser.on( 9 | '--yyy YYY', 10 | 'Option with required argument', 11 | ->(value) {p ['Handler proc for -yyy called with value:', value]} 12 | ) 13 | parser.parse! 14 | -------------------------------------------------------------------------------- /doc/optparse/ruby/regexp.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--regexp=REGEXP', Regexp) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/required_argument.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x XXX', '--xxx', 'Required argument via short name') do |value| 4 | p ['--xxx', value] 5 | end 6 | parser.on('-y', '--y YYY', 'Required argument via long name') do |value| 7 | p ['--yyy', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/shellwords.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/shellwords' 2 | parser = OptionParser.new 3 | parser.on('--shellwords=SHELLWORDS', Shellwords) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/short_names.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', 'Short name') do |value| 4 | p ['x', value] 5 | end 6 | parser.on('-1', '-%', 'Two short names') do |value| 7 | p ['-1 or -%', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/short_optional.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x [XXX]', 'Short name with optional argument') do |value| 4 | p ['-x', value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/short_range.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-[!-~]', 'Short names in (very large) range') do |name, value| 4 | p ['!-~', name, value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/short_required.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-xXXX', 'Short name with required argument') do |value| 4 | p ['-x', value] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/short_simple.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('-x', 'One short name') do |value| 4 | p ['-x', value] 5 | end 6 | parser.on('-1', '-%', 'Two short names (aliases)') do |value| 7 | p ['-1 or -%', value] 8 | end 9 | parser.parse! 10 | -------------------------------------------------------------------------------- /doc/optparse/ruby/string.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--string=STRING', String) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/terminator.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--my_option XXX') do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/time.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/time' 2 | parser = OptionParser.new 3 | parser.on('--time=TIME', Time) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/true_class.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | parser = OptionParser.new 3 | parser.on('--true_class=TRUE_CLASS', TrueClass) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/ruby/uri.rb: -------------------------------------------------------------------------------- 1 | require 'optparse/uri' 2 | parser = OptionParser.new 3 | parser.on('--uri=URI', URI) do |value| 4 | p [value, value.class] 5 | end 6 | parser.parse! 7 | -------------------------------------------------------------------------------- /doc/optparse/tutorial.rdoc: -------------------------------------------------------------------------------- 1 | == Tutorial 2 | 3 | === Why +OptionParser+? 4 | 5 | When a Ruby program executes, it captures its command-line arguments 6 | and options into variable ARGV. 7 | This simple program just prints its +ARGV+: 8 | 9 | :include: ruby/argv.rb 10 | 11 | Execution, with arguments and options: 12 | 13 | $ ruby argv.rb foo --bar --baz bat bam 14 | ["foo", "--bar", "--baz", "bat", "bam"] 15 | 16 | The executing program is responsible for parsing and handling 17 | the command-line options. 18 | 19 | OptionParser offers methods for parsing and handling those options. 20 | 21 | With +OptionParser+, you can define options so that for each option: 22 | 23 | - The code that defines the option and code that handles that option 24 | are in the same place. 25 | - The option may take no argument, a required argument, or an optional argument. 26 | - The argument may be automatically converted to a specified class. 27 | - The argument may be restricted to specified _forms_. 28 | - The argument may be restricted to specified _values_. 29 | 30 | The class also has method #help, which displays automatically-generated help text. 31 | 32 | === Contents 33 | 34 | - {To Begin With}[#label-To+Begin+With] 35 | - {Defining Options}[#label-Defining+Options] 36 | - {Option Names}[#label-Option+Names] 37 | - {Short Option Names}[#label-Short+Option+Names] 38 | - {Long Option Names}[#label-Long+Option+Names] 39 | - {Mixing Option Names}[#label-Mixing+Option+Names] 40 | - {Option Name Abbreviations}[#label-Option+Name+Abbreviations] 41 | - {Option Arguments}[#label-Option+Arguments] 42 | - {Option with No Argument}[#label-Option+with+No+Argument] 43 | - {Option with Required Argument}[#label-Option+with+Required+Argument] 44 | - {Option with Optional Argument}[#label-Option+with+Optional+Argument] 45 | - {Argument Abbreviations}[#label-Argument+Abbreviations] 46 | - {Argument Values}[#label-Argument+Values] 47 | - {Explicit Argument Values}[#label-Explicit+Argument+Values] 48 | - {Explicit Values in Array}[#label-Explicit+Values+in+Array] 49 | - {Explicit Values in Hash}[#label-Explicit+Values+in+Hash] 50 | - {Argument Value Patterns}[#label-Argument+Value+Patterns] 51 | - {Keyword Argument into}[#label-Keyword+Argument+into] 52 | - {Collecting Options}[#label-Collecting+Options] 53 | - {Checking for Missing Options}[#label-Checking+for+Missing+Options] 54 | - {Default Values for Options}[#label-Default+Values+for+Options] 55 | - {Argument Converters}[#label-Argument+Converters] 56 | - {Help}[#label-Help] 57 | - {Top List and Base List}[#label-Top+List+and+Base+List] 58 | - {Methods for Defining Options}[#label-Methods+for+Defining+Options] 59 | - {Parsing}[#label-Parsing] 60 | - {Method parse!}[#label-Method+parse-21] 61 | - {Method parse}[#label-Method+parse] 62 | - {Method order!}[#label-Method+order-21] 63 | - {Method order}[#label-Method+order] 64 | - {Method permute!}[#label-Method+permute-21] 65 | - {Method permute}[#label-Method+permute] 66 | 67 | === To Begin With 68 | 69 | To use +OptionParser+: 70 | 71 | 1. Require the +OptionParser+ code. 72 | 2. Create an +OptionParser+ object. 73 | 3. Define one or more options. 74 | 4. Parse the command line. 75 | 76 | File +basic.rb+ defines three options, -x, 77 | -y, and -z, each with a descriptive string, 78 | and each with a block. 79 | 80 | :include: ruby/basic.rb 81 | 82 | From these defined options, the parser automatically builds help text: 83 | 84 | $ ruby basic.rb --help 85 | Usage: basic [options] 86 | -x Whether to X 87 | -y Whether to Y 88 | -z Whether to Z 89 | 90 | When an option is found during parsing, 91 | the block defined for the option is called with the argument value. 92 | An invalid option raises an exception. 93 | 94 | Method #parse!, which is used most often in this tutorial, 95 | removes from +ARGV+ the options and arguments it finds, 96 | leaving other non-option arguments for the program to handle on its own. 97 | The method returns the possibly-reduced +ARGV+ array. 98 | 99 | Executions: 100 | 101 | $ ruby basic.rb -x -z 102 | ["x", true] 103 | ["z", true] 104 | [] 105 | $ ruby basic.rb -z -y -x 106 | ["z", true] 107 | ["y", true] 108 | ["x", true] 109 | [] 110 | $ ruby basic.rb -x input_file.txt output_file.txt 111 | ["x", true] 112 | ["input_file.txt", "output_file.txt"] 113 | $ ruby basic.rb -a 114 | basic.rb:16:in '
': invalid option: -a (OptionParser::InvalidOption) 115 | 116 | === Defining Options 117 | 118 | A common way to define an option in +OptionParser+ 119 | is with instance method OptionParser#on. 120 | 121 | The method may be called with any number of arguments 122 | (whose order does not matter), 123 | and may also have a trailing optional keyword argument +into+. 124 | 125 | The given arguments determine the characteristics of the new option. 126 | These may include: 127 | 128 | - One or more short option names. 129 | - One or more long option names. 130 | - Whether the option takes no argument, an optional argument, or a required argument. 131 | - Acceptable _forms_ for the argument. 132 | - Acceptable _values_ for the argument. 133 | - A proc or method to be called when the parser encounters the option. 134 | - String descriptions for the option. 135 | 136 | === Option Names 137 | 138 | You can give an option one or more names of two types: 139 | 140 | - Short (1-character) name, beginning with one hyphen (-). 141 | - Long (multi-character) name, beginning with two hyphens (--). 142 | 143 | ==== Short Option Names 144 | 145 | A short option name consists of a hyphen and a single character. 146 | 147 | File +short_names.rb+ 148 | defines an option with a short name, -x, 149 | and an option with two short names (aliases, in effect) -y and -z. 150 | 151 | :include: ruby/short_names.rb 152 | 153 | Executions: 154 | 155 | $ ruby short_names.rb --help 156 | Usage: short_names [options] 157 | -x Short name 158 | -1, -% Two short names 159 | $ ruby short_names.rb -x 160 | ["x", true] 161 | $ ruby short_names.rb -1 162 | ["-1 or -%", true] 163 | $ ruby short_names.rb -% 164 | ["-1 or -%", true] 165 | 166 | Multiple short names can "share" a hyphen: 167 | 168 | $ ruby short_names.rb -x1% 169 | ["x", true] 170 | ["-1 or -%", true] 171 | ["-1 or -%", true] 172 | 173 | ==== Long Option Names 174 | 175 | A long option name consists of two hyphens and a one or more characters 176 | (usually two or more characters). 177 | 178 | File +long_names.rb+ 179 | defines an option with a long name, --xxx, 180 | and an option with two long names (aliases, in effect) --y1% and --z2#. 181 | 182 | :include: ruby/long_names.rb 183 | 184 | Executions: 185 | 186 | $ ruby long_names.rb --help 187 | Usage: long_names [options] 188 | --xxx Long name 189 | --y1%, --z2# Two long names 190 | $ ruby long_names.rb --xxx 191 | ["-xxx", true] 192 | $ ruby long_names.rb --y1% 193 | ["--y1% or --z2#", true] 194 | $ ruby long_names.rb --z2# 195 | ["--y1% or --z2#", true] 196 | 197 | A long name may be defined with both positive and negative senses. 198 | 199 | File +long_with_negation.rb+ defines an option that has both senses. 200 | 201 | :include: ruby/long_with_negation.rb 202 | 203 | Executions: 204 | 205 | $ ruby long_with_negation.rb --help 206 | Usage: long_with_negation [options] 207 | --[no-]binary Long name with negation 208 | $ ruby long_with_negation.rb --binary 209 | [true, TrueClass] 210 | $ ruby long_with_negation.rb --no-binary 211 | [false, FalseClass] 212 | 213 | ==== Mixing Option Names 214 | 215 | Many developers like to mix short and long option names, 216 | so that a short name is in effect an abbreviation of a long name. 217 | 218 | File +mixed_names.rb+ 219 | defines options that each have both a short and a long name. 220 | 221 | :include: ruby/mixed_names.rb 222 | 223 | Executions: 224 | 225 | $ ruby mixed_names.rb --help 226 | Usage: mixed_names [options] 227 | -x, --xxx Short and long, no argument 228 | -y, --yyyYYY Short and long, required argument 229 | -z, --zzz [ZZZ] Short and long, optional argument 230 | $ ruby mixed_names.rb -x 231 | ["--xxx", true] 232 | $ ruby mixed_names.rb --xxx 233 | ["--xxx", true] 234 | $ ruby mixed_names.rb -y 235 | mixed_names.rb:12:in '
': missing argument: -y (OptionParser::MissingArgument) 236 | $ ruby mixed_names.rb -y FOO 237 | ["--yyy", "FOO"] 238 | $ ruby mixed_names.rb --yyy 239 | mixed_names.rb:12:in '
': missing argument: --yyy (OptionParser::MissingArgument) 240 | $ ruby mixed_names.rb --yyy BAR 241 | ["--yyy", "BAR"] 242 | $ ruby mixed_names.rb -z 243 | ["--zzz", nil] 244 | $ ruby mixed_names.rb -z BAZ 245 | ["--zzz", "BAZ"] 246 | $ ruby mixed_names.rb --zzz 247 | ["--zzz", nil] 248 | $ ruby mixed_names.rb --zzz BAT 249 | ["--zzz", "BAT"] 250 | 251 | ==== Option Name Abbreviations 252 | 253 | By default, abbreviated option names on the command-line are allowed. 254 | An abbreviated name is valid if it is unique among abbreviated option names. 255 | 256 | :include: ruby/name_abbrev.rb 257 | 258 | Executions: 259 | 260 | $ ruby name_abbrev.rb --help 261 | Usage: name_abbrev [options] 262 | -n, --dry-run 263 | -d, --draft 264 | $ ruby name_abbrev.rb -n 265 | ["--dry-run", true] 266 | $ ruby name_abbrev.rb --dry-run 267 | ["--dry-run", true] 268 | $ ruby name_abbrev.rb -d 269 | ["--draft", true] 270 | $ ruby name_abbrev.rb --draft 271 | ["--draft", true] 272 | $ ruby name_abbrev.rb --d 273 | name_abbrev.rb:9:in '
': ambiguous option: --d (OptionParser::AmbiguousOption) 274 | $ ruby name_abbrev.rb --dr 275 | name_abbrev.rb:9:in '
': ambiguous option: --dr (OptionParser::AmbiguousOption) 276 | $ ruby name_abbrev.rb --dry 277 | ["--dry-run", true] 278 | $ ruby name_abbrev.rb --dra 279 | ["--draft", true] 280 | 281 | You can disable abbreviation using method +require_exact+. 282 | 283 | :include: ruby/no_abbreviation.rb 284 | 285 | Executions: 286 | 287 | $ ruby no_abbreviation.rb --dry-ru 288 | no_abbreviation.rb:10:in '
': invalid option: --dry-ru (OptionParser::InvalidOption) 289 | $ ruby no_abbreviation.rb --dry-run 290 | ["--dry-run", true] 291 | 292 | === Option Arguments 293 | 294 | An option may take no argument, a required argument, or an optional argument. 295 | 296 | ==== Option with No Argument 297 | 298 | All the examples above define options with no argument. 299 | 300 | ==== Option with Required Argument 301 | 302 | Specify a required argument for an option by adding a dummy word 303 | to its name definition. 304 | 305 | File +required_argument.rb+ defines two options; 306 | each has a required argument because the name definition has a following dummy word. 307 | 308 | :include: ruby/required_argument.rb 309 | 310 | When an option is found, the given argument is yielded. 311 | 312 | Executions: 313 | 314 | $ ruby required_argument.rb --help 315 | Usage: required_argument [options] 316 | -x, --xxx XXX Required argument via short name 317 | -y, --y YYY Required argument via long name 318 | $ ruby required_argument.rb -x AAA 319 | ["--xxx", "AAA"] 320 | $ ruby required_argument.rb -y BBB 321 | ["--yyy", "BBB"] 322 | 323 | Omitting a required argument raises an error: 324 | 325 | $ ruby required_argument.rb -x 326 | required_argument.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) 327 | 328 | ==== Option with Optional Argument 329 | 330 | Specify an optional argument for an option by adding a dummy word 331 | enclosed in square brackets to its name definition. 332 | 333 | File +optional_argument.rb+ defines two options; 334 | each has an optional argument because the name definition has a following dummy word 335 | in square brackets. 336 | 337 | :include: ruby/optional_argument.rb 338 | 339 | When an option with an argument is found, the given argument yielded. 340 | 341 | Executions: 342 | 343 | $ ruby optional_argument.rb --help 344 | Usage: optional_argument [options] 345 | -x, --xxx [XXX] Optional argument via short name 346 | -y, --yyy [YYY] Optional argument via long name 347 | $ ruby optional_argument.rb -x AAA 348 | ["--xxx", "AAA"] 349 | $ ruby optional_argument.rb -y BBB 350 | ["--yyy", "BBB"] 351 | 352 | Omitting an optional argument does not raise an error. 353 | 354 | ==== Argument Abbreviations 355 | 356 | Specify an argument list as an Array or a Hash. 357 | 358 | :include: ruby/argument_abbreviation.rb 359 | 360 | When an argument is abbreviated, the expanded argument yielded. 361 | 362 | Executions: 363 | 364 | $ ruby argument_abbreviation.rb --help 365 | Usage: argument_abbreviation [options] 366 | Usage: argument_abbreviation [options] 367 | -x, --xxx=VALUE Argument abbreviations 368 | -y, --yyy=VALUE Argument abbreviations 369 | $ ruby argument_abbreviation.rb --xxx A 370 | ["--xxx", "ABC"] 371 | $ ruby argument_abbreviation.rb --xxx c 372 | argument_abbreviation.rb:9:in '
': invalid argument: --xxx c (OptionParser::InvalidArgument) 373 | $ ruby argument_abbreviation.rb --yyy a --yyy d 374 | ["--yyy", "XYZ"] 375 | ["--yyy", "FOO"] 376 | 377 | === Argument Values 378 | 379 | Permissible argument values may be restricted 380 | either by specifying explicit values 381 | or by providing a pattern that the given value must match. 382 | 383 | ==== Explicit Argument Values 384 | 385 | You can specify argument values in either of two ways: 386 | 387 | - Specify values an array of strings. 388 | - Specify values a hash. 389 | 390 | ===== Explicit Values in Array 391 | 392 | You can specify explicit argument values in an array of strings. 393 | The argument value must be one of those strings, or an unambiguous abbreviation. 394 | 395 | File +explicit_array_values.rb+ defines options with explicit argument values. 396 | 397 | :include: ruby/explicit_array_values.rb 398 | 399 | Executions: 400 | 401 | $ ruby explicit_array_values.rb --help 402 | Usage: explicit_array_values [options] 403 | -xXXX Values for required argument 404 | -y [YYY] Values for optional argument 405 | $ ruby explicit_array_values.rb -x 406 | explicit_array_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) 407 | $ ruby explicit_array_values.rb -x foo 408 | ["-x", "foo"] 409 | $ ruby explicit_array_values.rb -x f 410 | ["-x", "foo"] 411 | $ ruby explicit_array_values.rb -x bar 412 | ["-x", "bar"] 413 | $ ruby explicit_array_values.rb -y ba 414 | explicit_array_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) 415 | $ ruby explicit_array_values.rb -x baz 416 | explicit_array_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) 417 | 418 | 419 | ===== Explicit Values in Hash 420 | 421 | You can specify explicit argument values in a hash with string keys. 422 | The value passed must be one of those keys, or an unambiguous abbreviation; 423 | the value yielded will be the value for that key. 424 | 425 | File +explicit_hash_values.rb+ defines options with explicit argument values. 426 | 427 | :include: ruby/explicit_hash_values.rb 428 | 429 | Executions: 430 | 431 | $ ruby explicit_hash_values.rb --help 432 | Usage: explicit_hash_values [options] 433 | -xXXX Values for required argument 434 | -y [YYY] Values for optional argument 435 | $ ruby explicit_hash_values.rb -x 436 | explicit_hash_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) 437 | $ ruby explicit_hash_values.rb -x foo 438 | ["-x", 0] 439 | $ ruby explicit_hash_values.rb -x f 440 | ["-x", 0] 441 | $ ruby explicit_hash_values.rb -x bar 442 | ["-x", 1] 443 | $ ruby explicit_hash_values.rb -x baz 444 | explicit_hash_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) 445 | $ ruby explicit_hash_values.rb -y 446 | ["-y", nil] 447 | $ ruby explicit_hash_values.rb -y baz 448 | ["-y", 2] 449 | $ ruby explicit_hash_values.rb -y bat 450 | ["-y", 3] 451 | $ ruby explicit_hash_values.rb -y ba 452 | explicit_hash_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) 453 | $ ruby explicit_hash_values.rb -y bam 454 | ["-y", nil] 455 | 456 | ==== Argument Value Patterns 457 | 458 | You can restrict permissible argument values 459 | by specifying a Regexp that the given argument must match. 460 | 461 | File +matched_values.rb+ defines options with matched argument values. 462 | 463 | :include: ruby/matched_values.rb 464 | 465 | Executions: 466 | 467 | $ ruby matched_values.rb --help 468 | Usage: matched_values [options] 469 | --xxx XXX Matched values 470 | $ ruby matched_values.rb --xxx foo 471 | ["--xxx", "foo"] 472 | $ ruby matched_values.rb --xxx FOO 473 | ["--xxx", "FOO"] 474 | $ ruby matched_values.rb --xxx bar 475 | matched_values.rb:6:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) 476 | 477 | === Keyword Argument +into+ 478 | 479 | In parsing options, you can add keyword option +into+ with a hash-like argument; 480 | each parsed option will be added as a name/value pair. 481 | 482 | This is useful for: 483 | 484 | - Collecting options. 485 | - Checking for missing options. 486 | - Providing default values for options. 487 | 488 | ==== Collecting Options 489 | 490 | Use keyword argument +into+ to collect options. 491 | 492 | :include: ruby/collected_options.rb 493 | 494 | Executions: 495 | 496 | $ ruby collected_options.rb --help 497 | Usage: into [options] 498 | -x, --xxx Short and long, no argument 499 | -y, --yyyYYY Short and long, required argument 500 | -z, --zzz [ZZZ] Short and long, optional argument 501 | $ ruby collected_options.rb --xxx 502 | {:xxx=>true} 503 | $ ruby collected_options.rb --xxx --yyy FOO 504 | {:xxx=>true, :yyy=>"FOO"} 505 | $ ruby collected_options.rb --xxx --yyy FOO --zzz Bar 506 | {:xxx=>true, :yyy=>"FOO", :zzz=>"Bar"} 507 | $ ruby collected_options.rb --xxx --yyy FOO --yyy BAR 508 | {:xxx=>true, :yyy=>"BAR"} 509 | 510 | Note in the last execution that the argument value for option --yyy 511 | was overwritten. 512 | 513 | ==== Checking for Missing Options 514 | 515 | Use the collected options to check for missing options. 516 | 517 | :include: ruby/missing_options.rb 518 | 519 | Executions: 520 | 521 | $ ruby missing_options.rb --help 522 | Usage: missing_options [options] 523 | -x, --xxx Short and long, no argument 524 | -y, --yyyYYY Short and long, required argument 525 | -z, --zzz [ZZZ] Short and long, optional argument 526 | $ ruby missing_options.rb --yyy FOO 527 | missing_options.rb:11:in '
': Missing required options: [:xxx, :zzz] (RuntimeError) 528 | 529 | ==== Default Values for Options 530 | 531 | Initialize the +into+ argument to define default values for options. 532 | 533 | :include: ruby/default_values.rb 534 | 535 | Executions: 536 | 537 | $ ruby default_values.rb --help 538 | Usage: default_values [options] 539 | -x, --xxx Short and long, no argument 540 | -y, --yyyYYY Short and long, required argument 541 | -z, --zzz [ZZZ] Short and long, optional argument 542 | $ ruby default_values.rb --yyy FOO 543 | {:yyy=>"FOO", :zzz=>"BBB"} 544 | 545 | === Argument Converters 546 | 547 | An option can specify that its argument is to be converted 548 | from the default +String+ to an instance of another class. 549 | There are a number of built-in converters. 550 | 551 | Example: File +date.rb+ 552 | defines an option whose argument is to be converted to a +Date+ object. 553 | The argument is converted by method Date#parse. 554 | 555 | :include: ruby/date.rb 556 | 557 | Executions: 558 | 559 | $ ruby date.rb --date 2001-02-03 560 | [#, Date] 561 | $ ruby date.rb --date 20010203 562 | [#, Date] 563 | $ ruby date.rb --date "3rd Feb 2001" 564 | [#, Date] 565 | 566 | You can also define custom converters. 567 | See {Argument Converters}[./argument_converters.rdoc] 568 | for both built-in and custom converters. 569 | 570 | === Help 571 | 572 | +OptionParser+ makes automatically generated help text available. 573 | 574 | The help text consists of: 575 | 576 | - A banner, showing the usage. 577 | - Option short and long names. 578 | - Option dummy argument names. 579 | - Option descriptions. 580 | 581 | Example code: 582 | 583 | :include: ruby/help.rb 584 | 585 | The option names and dummy argument names are defined as described above. 586 | 587 | The option description consists of the strings that are not themselves option names; 588 | An option can have more than one description string. 589 | Execution: 590 | 591 | Usage: help [options] 592 | -x, --xxx Adipiscing elit. Aenean commodo ligula eget. 593 | Aenean massa. Cum sociis natoque penatibus 594 | -y, --yyy YYY Lorem ipsum dolor sit amet, consectetuer. 595 | -z, --zzz [ZZZ] Et magnis dis parturient montes, nascetur 596 | ridiculus mus. Donec quam felis, ultricies 597 | nec, pellentesque eu, pretium quis, sem. 598 | 599 | The program name is included in the default banner: 600 | Usage: #{program_name} [options]; 601 | you can change the program name. 602 | 603 | :include: ruby/help_program_name.rb 604 | 605 | Execution: 606 | 607 | $ ruby help_program_name.rb --help 608 | Usage: help_program_name.rb [options] 609 | 610 | You can also change the entire banner. 611 | 612 | :include: ruby/help_banner.rb 613 | 614 | Execution: 615 | 616 | $ ruby help_banner.rb --help 617 | Usage: ruby help_banner.rb 618 | 619 | By default, the option names are indented 4 spaces 620 | and the width of the option-names field is 32 spaces. 621 | 622 | You can change these values, along with the banner, 623 | by passing parameters to OptionParser.new. 624 | 625 | :include: ruby/help_format.rb 626 | 627 | Execution: 628 | 629 | $ ruby help_format.rb --help 630 | ruby help_format.rb [options] 631 | -x, --xxx Adipiscing elit. Aenean commodo ligula eget. 632 | Aenean massa. Cum sociis natoque penatibus 633 | -y, --yyy YYY Lorem ipsum dolor sit amet, consectetuer. 634 | -z, --zzz [ZZZ] Et magnis dis parturient montes, nascetur 635 | ridiculus mus. Donec quam felis, ultricies 636 | nec, pellentesque eu, pretium quis, sem. 637 | 638 | === Top List and Base List 639 | 640 | An +OptionParser+ object maintains a stack of OptionParser::List objects, 641 | each of which has a collection of zero or more options. 642 | It is unlikely that you'll need to add or take away from that stack. 643 | 644 | The stack includes: 645 | 646 | - The top list, given by OptionParser#top. 647 | - The base list, given by OptionParser#base. 648 | 649 | When +OptionParser+ builds its help text, the options in the top list 650 | precede those in the base list. 651 | 652 | === Methods for Defining Options 653 | 654 | Option-defining methods allow you to create an option, and also append/prepend it 655 | to the top list or append it to the base list. 656 | 657 | Each of these next three methods accepts a sequence of parameter arguments and a block, 658 | creates an option object using method OptionParser#make_switch (see below), 659 | and returns the created option: 660 | 661 | - \Method OptionParser#define appends the created option to the top list. 662 | 663 | - \Method OptionParser#define_head prepends the created option to the top list. 664 | 665 | - \Method OptionParser#define_tail appends the created option to the base list. 666 | 667 | These next three methods are identical to the three above, 668 | except for their return values: 669 | 670 | - \Method OptionParser#on is identical to method OptionParser#define, 671 | except that it returns the parser object +self+. 672 | 673 | - \Method OptionParser#on_head is identical to method OptionParser#define_head, 674 | except that it returns the parser object +self+. 675 | 676 | - \Method OptionParser#on_tail is identical to method OptionParser#define_tail, 677 | except that it returns the parser object +self+. 678 | 679 | Though you may never need to call it directly, 680 | here's the core method for defining an option: 681 | 682 | - \Method OptionParser#make_switch accepts an array of parameters and a block. 683 | See {Parameters for New Options}[optparse/option_params.rdoc]. 684 | This method is unlike others here in that it: 685 | - Accepts an array of parameters; 686 | others accept a sequence of parameter arguments. 687 | - Returns an array containing the created option object, 688 | option names, and other values; 689 | others return either the created option object 690 | or the parser object +self+. 691 | 692 | === Parsing 693 | 694 | +OptionParser+ has six instance methods for parsing. 695 | 696 | Three have names ending with a "bang" (!): 697 | 698 | - parse! 699 | - order! 700 | - permute! 701 | 702 | Each of these methods: 703 | 704 | - Accepts an optional array of string arguments +argv+; 705 | if not given, +argv+ defaults to the value of OptionParser#default_argv, 706 | whose initial value is ARGV. 707 | - Accepts an optional keyword argument +into+ 708 | (see {Keyword Argument into}[#label-Keyword+Argument+into]). 709 | - Returns +argv+, possibly with some elements removed. 710 | 711 | The three other methods have names _not_ ending with a "bang": 712 | 713 | - parse 714 | - order 715 | - permute 716 | 717 | Each of these methods: 718 | 719 | - Accepts an array of string arguments 720 | _or_ zero or more string arguments. 721 | - Accepts an optional keyword argument +into+ and its value _into_. 722 | (see {Keyword Argument into}[#label-Keyword+Argument+into]). 723 | - Returns +argv+, possibly with some elements removed. 724 | 725 | ==== \Method +parse!+ 726 | 727 | \Method +parse!+: 728 | 729 | - Accepts an optional array of string arguments +argv+; 730 | if not given, +argv+ defaults to the value of OptionParser#default_argv, 731 | whose initial value is ARGV. 732 | - Accepts an optional keyword argument +into+ 733 | (see {Keyword Argument into}[#label-Keyword+Argument+into]). 734 | - Returns +argv+, possibly with some elements removed. 735 | 736 | The method processes the elements in +argv+ beginning at argv[0], 737 | and ending, by default, at the end. 738 | 739 | Otherwise processing ends and the method returns when: 740 | 741 | - The terminator argument -- is found; 742 | the terminator argument is removed before the return. 743 | - Environment variable +POSIXLY_CORRECT+ is defined 744 | and a non-option argument is found; 745 | the non-option argument is not removed. 746 | Note that the _value_ of that variable does not matter, 747 | as only its existence is checked. 748 | 749 | File +parse_bang.rb+: 750 | 751 | :include: ruby/parse_bang.rb 752 | 753 | Help: 754 | 755 | $ ruby parse_bang.rb --help 756 | Usage: parse_bang [options] 757 | --xxx 758 | --yyy YYY 759 | --zzz [ZZZ] 760 | 761 | Default behavior: 762 | 763 | $ ruby parse_bang.rb input_file.txt output_file.txt --xxx --yyy FOO --zzz BAR 764 | ["--xxx", true] 765 | ["--yyy", "FOO"] 766 | ["--zzz", "BAR"] 767 | Returned: ["input_file.txt", "output_file.txt"] (Array) 768 | 769 | Processing ended by terminator argument: 770 | 771 | $ ruby parse_bang.rb input_file.txt output_file.txt --xxx --yyy FOO -- --zzz BAR 772 | ["--xxx", true] 773 | ["--yyy", "FOO"] 774 | Returned: ["input_file.txt", "output_file.txt", "--zzz", "BAR"] (Array) 775 | 776 | Processing ended by non-option found when +POSIXLY_CORRECT+ is defined: 777 | 778 | $ POSIXLY_CORRECT=true ruby parse_bang.rb --xxx input_file.txt output_file.txt -yyy FOO 779 | ["--xxx", true] 780 | Returned: ["input_file.txt", "output_file.txt", "-yyy", "FOO"] (Array) 781 | 782 | ==== \Method +parse+ 783 | 784 | \Method +parse+: 785 | 786 | - Accepts an array of string arguments 787 | _or_ zero or more string arguments. 788 | - Accepts an optional keyword argument +into+ and its value _into_. 789 | (see {Keyword Argument into}[#label-Keyword+Argument+into]). 790 | - Returns +argv+, possibly with some elements removed. 791 | 792 | If given an array +ary+, the method forms array +argv+ as ary.dup. 793 | If given zero or more string arguments, those arguments are formed 794 | into array +argv+. 795 | 796 | The method calls 797 | 798 | parse!(argv, into: into) 799 | 800 | Note that environment variable +POSIXLY_CORRECT+ 801 | and the terminator argument -- are honored. 802 | 803 | File +parse.rb+: 804 | 805 | :include: ruby/parse.rb 806 | 807 | Help: 808 | 809 | $ ruby parse.rb --help 810 | Usage: parse [options] 811 | --xxx 812 | --yyy YYY 813 | --zzz [ZZZ] 814 | 815 | Default behavior: 816 | 817 | $ ruby parse.rb input_file.txt output_file.txt --xxx --yyy FOO --zzz BAR 818 | ["--xxx", true] 819 | ["--yyy", "FOO"] 820 | ["--zzz", "BAR"] 821 | Returned: ["input_file.txt", "output_file.txt"] (Array) 822 | 823 | Processing ended by terminator argument: 824 | 825 | $ ruby parse.rb input_file.txt output_file.txt --xxx --yyy FOO -- --zzz BAR 826 | ["--xxx", true] 827 | ["--yyy", "FOO"] 828 | Returned: ["input_file.txt", "output_file.txt", "--zzz", "BAR"] (Array) 829 | 830 | Processing ended by non-option found when +POSIXLY_CORRECT+ is defined: 831 | 832 | $ POSIXLY_CORRECT=true ruby parse.rb --xxx input_file.txt output_file.txt -yyy FOO 833 | ["--xxx", true] 834 | Returned: ["input_file.txt", "output_file.txt", "-yyy", "FOO"] (Array) 835 | 836 | ==== \Method +order!+ 837 | 838 | Calling method OptionParser#order! gives exactly the same result as 839 | calling method OptionParser#parse! with environment variable 840 | +POSIXLY_CORRECT+ defined. 841 | 842 | ==== \Method +order+ 843 | 844 | Calling method OptionParser#order gives exactly the same result as 845 | calling method OptionParser#parse with environment variable 846 | +POSIXLY_CORRECT+ defined. 847 | 848 | ==== \Method +permute!+ 849 | 850 | Calling method OptionParser#permute! gives exactly the same result as 851 | calling method OptionParser#parse! with environment variable 852 | +POSIXLY_CORRECT+ _not_ defined. 853 | 854 | ==== \Method +permute+ 855 | 856 | Calling method OptionParser#permute gives exactly the same result as 857 | calling method OptionParser#parse with environment variable 858 | +POSIXLY_CORRECT+ _not_ defined. 859 | -------------------------------------------------------------------------------- /lib/optionparser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'optparse' 3 | -------------------------------------------------------------------------------- /lib/optparse/ac.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative '../optparse' 3 | 4 | # 5 | # autoconf-like options. 6 | # 7 | class OptionParser::AC < OptionParser 8 | # :stopdoc: 9 | private 10 | 11 | def _check_ac_args(name, block) 12 | unless /\A\w[-\w]*\z/ =~ name 13 | raise ArgumentError, name 14 | end 15 | unless block 16 | raise ArgumentError, "no block given", ParseError.filter_backtrace(caller) 17 | end 18 | end 19 | 20 | ARG_CONV = proc {|val| val.nil? ? true : val} 21 | private_constant :ARG_CONV 22 | 23 | def _ac_arg_enable(prefix, name, help_string, block) 24 | _check_ac_args(name, block) 25 | 26 | sdesc = [] 27 | ldesc = ["--#{prefix}-#{name}"] 28 | desc = [help_string] 29 | q = name.downcase 30 | ac_block = proc {|val| block.call(ARG_CONV.call(val))} 31 | enable = Switch::PlacedArgument.new(nil, ARG_CONV, sdesc, ldesc, nil, desc, ac_block) 32 | disable = Switch::NoArgument.new(nil, proc {false}, sdesc, ldesc, nil, desc, ac_block) 33 | top.append(enable, [], ["enable-" + q], disable, ['disable-' + q]) 34 | enable 35 | end 36 | 37 | # :startdoc: 38 | 39 | public 40 | 41 | # Define --enable / --disable style option 42 | # 43 | # Appears as --enable-name in help message. 44 | def ac_arg_enable(name, help_string, &block) 45 | _ac_arg_enable("enable", name, help_string, block) 46 | end 47 | 48 | # Define --enable / --disable style option 49 | # 50 | # Appears as --disable-name in help message. 51 | def ac_arg_disable(name, help_string, &block) 52 | _ac_arg_enable("disable", name, help_string, block) 53 | end 54 | 55 | # Define --with / --without style option 56 | # 57 | # Appears as --with-name in help message. 58 | def ac_arg_with(name, help_string, &block) 59 | _check_ac_args(name, block) 60 | 61 | sdesc = [] 62 | ldesc = ["--with-#{name}"] 63 | desc = [help_string] 64 | q = name.downcase 65 | with = Switch::PlacedArgument.new(*search(:atype, String), sdesc, ldesc, nil, desc, block) 66 | without = Switch::NoArgument.new(nil, proc {}, sdesc, ldesc, nil, desc, block) 67 | top.append(with, [], ["with-" + q], without, ['without-' + q]) 68 | with 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/optparse/date.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative '../optparse' 3 | require 'date' 4 | 5 | OptionParser.accept(DateTime) do |s,| 6 | begin 7 | DateTime.parse(s) if s 8 | rescue ArgumentError 9 | raise OptionParser::InvalidArgument, s 10 | end 11 | end 12 | OptionParser.accept(Date) do |s,| 13 | begin 14 | Date.parse(s) if s 15 | rescue ArgumentError 16 | raise OptionParser::InvalidArgument, s 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/optparse/kwargs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require_relative '../optparse' 3 | 4 | class OptionParser 5 | # :call-seq: 6 | # define_by_keywords(options, method, **params) 7 | # 8 | # :include: ../../doc/optparse/creates_option.rdoc 9 | # 10 | # Defines options which set in to _options_ for keyword parameters 11 | # of _method_. 12 | # 13 | # Parameters for each keywords are given as elements of _params_. 14 | # 15 | def define_by_keywords(options, method, **params) 16 | method.parameters.each do |type, name| 17 | case type 18 | when :key, :keyreq 19 | op, cl = *(type == :key ? %w"[ ]" : ["", ""]) 20 | define("--#{name}=#{op}#{name.upcase}#{cl}", *params[name]) do |o| 21 | options[name] = o 22 | end 23 | end 24 | end 25 | options 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/optparse/shellwords.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | # -*- ruby -*- 3 | 4 | require 'shellwords' 5 | require_relative '../optparse' 6 | 7 | OptionParser.accept(Shellwords) {|s,| Shellwords.shellwords(s)} 8 | -------------------------------------------------------------------------------- /lib/optparse/time.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative '../optparse' 3 | require 'time' 4 | 5 | OptionParser.accept(Time) do |s,| 6 | begin 7 | (Time.httpdate(s) rescue Time.parse(s)) if s 8 | rescue 9 | raise OptionParser::InvalidArgument, s 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/optparse/uri.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | # -*- ruby -*- 3 | 4 | require_relative '../optparse' 5 | require 'uri' 6 | 7 | OptionParser.accept(URI) {|s,| URI.parse(s) if s} 8 | -------------------------------------------------------------------------------- /lib/optparse/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | # OptionParser internal utility 3 | 4 | class << OptionParser 5 | # 6 | # Shows version string in packages if Version is defined. 7 | # 8 | # +pkgs+:: package list 9 | # 10 | def show_version(*pkgs) 11 | progname = ARGV.options.program_name 12 | result = false 13 | show = proc do |klass, cname, version| 14 | str = "#{progname}" 15 | unless klass == ::Object and cname == :VERSION 16 | version = version.join(".") if Array === version 17 | str << ": #{klass}" unless klass == Object 18 | str << " version #{version}" 19 | end 20 | [:Release, :RELEASE].find do |rel| 21 | if klass.const_defined?(rel) 22 | str << " (#{klass.const_get(rel)})" 23 | end 24 | end 25 | puts str 26 | result = true 27 | end 28 | if pkgs.size == 1 and pkgs[0] == "all" 29 | self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version| 30 | unless cname[1] == ?e and klass.const_defined?(:Version) 31 | show.call(klass, cname.intern, version) 32 | end 33 | end 34 | else 35 | pkgs.each do |pkg| 36 | begin 37 | pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)} 38 | v = case 39 | when pkg.const_defined?(:Version) 40 | pkg.const_get(n = :Version) 41 | when pkg.const_defined?(:VERSION) 42 | pkg.const_get(n = :VERSION) 43 | else 44 | n = nil 45 | "unknown" 46 | end 47 | show.call(pkg, n, v) 48 | rescue NameError 49 | end 50 | end 51 | end 52 | result 53 | end 54 | 55 | # :stopdoc: 56 | 57 | def each_const(path, base = ::Object) 58 | path.split(/::|\//).inject(base) do |klass, name| 59 | raise NameError, path unless Module === klass 60 | klass.constants.grep(/#{name}/i) do |c| 61 | klass.const_defined?(c) or next 62 | klass.const_get(c) 63 | end 64 | end 65 | end 66 | 67 | def search_const(klass, name) 68 | klasses = [klass] 69 | while klass = klasses.shift 70 | klass.constants.each do |cname| 71 | klass.const_defined?(cname) or next 72 | const = klass.const_get(cname) 73 | yield klass, cname, const if name === cname 74 | klasses << const if Module === const and const != ::Object 75 | end 76 | end 77 | end 78 | 79 | # :startdoc: 80 | end 81 | -------------------------------------------------------------------------------- /misc/rb_optparse.bash: -------------------------------------------------------------------------------- 1 | # -*- bash -*- 2 | # 3 | # Completion for bash: 4 | # 5 | # (1) install this file, 6 | # 7 | # (2) load the script, and 8 | # . ~/.profile.d/rb_optparse.bash 9 | # 10 | # (3) define completions in your .bashrc, 11 | # rb_optparse command_using_optparse_1 12 | # rb_optparse command_using_optparse_2 13 | 14 | _rb_optparse() { 15 | COMPREPLY=($("${COMP_WORDS[0]}" "--*-completion-bash=${COMP_WORDS[COMP_CWORD]}")) 16 | return 0 17 | } 18 | 19 | rb_optparse () { 20 | [ $# = 0 ] || complete -o default -F _rb_optparse "$@" 21 | } 22 | -------------------------------------------------------------------------------- /misc/rb_optparse.zsh: -------------------------------------------------------------------------------- 1 | # -*- zsh -*- 2 | # 3 | # Completion for zsh: 4 | # (based on ) 5 | # 6 | # (1) install this file. 7 | # mkdir -p ~/.zsh.d 8 | # cp rb_optparse.zsh ~/.zsh.d/rb_optparse.zsh 9 | # 10 | # (2) load the script, and add a directory to fpath before compinit. 11 | # echo '. ~/.zsh.d/rb_optparse.zsh' >> "${ZDOTDIR:-~}/.zshrc" 12 | # echo 'fpath=(~/.zsh.d/Completion $fpath)' >> "${ZDOTDIR:-~}/.zshrc" 13 | # echo 'autoload -U compinit; compinit' >> "${ZDOTDIR:-~}/.zshrc" 14 | # 15 | # (3) restart zsh. 16 | # 17 | # (4) generate completion files once. 18 | # generate-complete-function/ruby/optparse COMMAND1 19 | # generate-complete-function/ruby/optparse COMMAND2 20 | # 21 | 22 | generate-complete-function/ruby/optparse () 23 | { 24 | local cmpl="_${1:t}" 25 | mkdir -p "${ZSH_COMPLETION_DIR-$HOME/.zsh.d/Completion}" 26 | $1 "--*-completion-zsh=${1:t}" >! "${ZSH_COMPLETION_DIR-$HOME/.zsh.d/Completion}/$cmpl" 27 | if [[ $(type -w "$cmpl") == "${cmpl}: function" ]]; then 28 | unfunction "$cmpl" 29 | autoload -U "$cmpl" 30 | else 31 | compinit "$cmpl" 32 | fi 33 | } 34 | 35 | compdef _command generate-complete-function/ruby/optparse 36 | 37 | for cmd in "$@"; do 38 | generate-complete-function/ruby/optparse "$cmd" 39 | done 40 | -------------------------------------------------------------------------------- /optparse.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | name = File.basename(__FILE__, ".gemspec") 4 | version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir| 5 | break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| 6 | /^\s*OptionParser::Version\s*=\s*"(.*)"/ =~ line and break $1 7 | end rescue nil 8 | end 9 | 10 | Gem::Specification.new do |spec| 11 | spec.name = name 12 | spec.version = version 13 | spec.authors = ["Nobu Nakada"] 14 | spec.email = ["nobu@ruby-lang.org"] 15 | 16 | spec.summary = %q{OptionParser is a class for command-line option analysis.} 17 | spec.description = File.open(File.join(__dir__, "README.md")) do |readme| 18 | readme.gets("") # heading 19 | readme.gets("").chomp 20 | end rescue spec.summary 21 | spec.homepage = "https://github.com/ruby/optparse" 22 | spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") 23 | spec.licenses = ["Ruby", "BSD-2-Clause"] 24 | 25 | spec.metadata["homepage_uri"] = spec.homepage 26 | spec.metadata["source_code_uri"] = spec.homepage 27 | 28 | spec.files = Dir["{doc,lib,misc}/**/{*,.document}"] + 29 | %w[README.md ChangeLog COPYING .document .rdoc_options] 30 | spec.bindir = "exe" 31 | spec.executables = [] 32 | spec.require_paths = ["lib"] 33 | end 34 | -------------------------------------------------------------------------------- /rakelib/.document: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby/optparse/541e99d4aadac96c42dbdaed7863cc91a15d6336/rakelib/.document -------------------------------------------------------------------------------- /rakelib/changelogs.rake: -------------------------------------------------------------------------------- 1 | task "build" => "changelogs" 2 | 3 | changelog = proc do |output, ver = nil, prev = nil| 4 | ver &&= Gem::Version.new(ver) 5 | range = [[prev], [ver, "HEAD"]].map {|ver, branch| ver ? "v#{ver.to_s}" : branch}.compact.join("..") 6 | cmd = %W[git log --date=iso --format=fuller --topo-order --no-merges 7 | --invert-grep --fixed-strings --grep=#{'[ci skip]'} 8 | #{range} --] 9 | IO.popen(cmd) do |log| 10 | line = log.gets 11 | FileUtils.mkpath(File.dirname(output)) 12 | File.open(output, "wb") do |f| 13 | f.print "-*- coding: utf-8 -*-\n\n", line 14 | log.each_line do |line| 15 | line.sub!(/^(?!:)(?:Author|Commit)?(?:Date)?: /, ' \&') 16 | line.sub!(/ +$/, '') 17 | f.print(line) 18 | end 19 | end 20 | end 21 | end 22 | 23 | tags = IO.popen(%w[git tag -l v[0-9]*]).grep(/v(.*)/) {$1} 24 | unless tags.empty? 25 | tags.sort_by! {|tag| tag.scan(/\d+/).map(&:to_i)} 26 | tags.pop if IO.popen(%W[git rev-list --right-only --count v#{tags.last}..HEAD --], &:read).to_i == 0 27 | tags.inject(nil) do |prev, tag| 28 | task("logs/ChangeLog-#{tag}") {|t| changelog[t.name, tag, prev]} 29 | tag 30 | end 31 | end 32 | 33 | desc "Make ChangeLog" 34 | task "ChangeLog", [:ver, :prev] do |t, ver: nil, prev: tags.last| 35 | changelog[t.name, ver, prev] 36 | end 37 | 38 | changelogs = ["ChangeLog", *tags.map {|tag| "logs/ChangeLog-#{tag}"}] 39 | task "changelogs" => changelogs 40 | CLOBBER.concat(changelogs) << "logs" 41 | -------------------------------------------------------------------------------- /rakelib/epoch.rake: -------------------------------------------------------------------------------- 1 | task "build" => "date_epoch" 2 | 3 | task "date_epoch" do 4 | ENV["SOURCE_DATE_EPOCH"] = IO.popen(%W[git -C #{__dir__} log -1 --format=%ct], &:read).chomp 5 | end 6 | -------------------------------------------------------------------------------- /rakelib/version.rake: -------------------------------------------------------------------------------- 1 | class << (helper = Bundler::GemHelper.instance) 2 | def mainfile 3 | "lib/#{File.basename(gemspec.loaded_from, ".gemspec")}.rb" 4 | end 5 | 6 | def update_version 7 | File.open(mainfile, "r+b") do |f| 8 | d = f.read 9 | if d.sub!(/^(\s*OptionParser::Version\s*=\s*)".*"/) {$1 + gemspec.version.to_s.dump} 10 | f.rewind 11 | f.truncate(0) 12 | f.print(d) 13 | end 14 | end 15 | end 16 | 17 | def commit_bump 18 | sh(%W[git -C #{File.dirname(gemspec.loaded_from)} commit -m bump\ up\ to\ #{gemspec.version} 19 | #{mainfile}]) 20 | end 21 | 22 | def version=(v) 23 | gemspec.version = v 24 | update_version 25 | commit_bump 26 | end 27 | 28 | def bump(major, minor = 0, teeny = 0, pre: nil) 29 | self.version = [major, minor, teeny, pre].compact.join(".") 30 | end 31 | 32 | def next_prerelease(*prefix, num) 33 | if num 34 | [*prefix, num.succ] 35 | else 36 | "dev.1" 37 | end 38 | end 39 | end 40 | 41 | major, minor, teeny, *prerelease = helper.gemspec.version.segments 42 | 43 | task "bump:dev", [:pre] do |t, pre: helper.next_prerelease(*prerelease)| 44 | helper.bump(major, minor, teeny, pre: pre) 45 | end 46 | 47 | task "bump:teeny", [:pre] do |t, pre: nil| 48 | helper.bump(major, minor, teeny+1, pre: pre) 49 | end 50 | 51 | task "bump:minor", [:pre] do |t, pre: nil| 52 | helper.bump(major, minor+1, pre: pre) 53 | end 54 | 55 | task "bump:major", [:pre] do |t, pre: nil| 56 | helper.bump(major+1, pre: pre) 57 | end 58 | 59 | task "bump" => "bump:teeny" 60 | 61 | task "tag" do 62 | helper.__send__(:tag_version) 63 | end 64 | -------------------------------------------------------------------------------- /test/lib/helper.rb: -------------------------------------------------------------------------------- 1 | require "test/unit" 2 | require "core_assertions" 3 | 4 | Test::Unit::TestCase.include Test::Unit::CoreAssertions 5 | -------------------------------------------------------------------------------- /test/optparse/test_acceptable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | class TestOptionParserAcceptable < TestOptionParser 5 | 6 | def setup 7 | super 8 | @opt.def_option("--integer VAL", Integer) { |v| @integer = v } 9 | @opt.def_option("--float VAL", Float) { |v| @float = v } 10 | @opt.def_option("--numeric VAL", Numeric) { |v| @numeric = v } 11 | @opt.def_option("--array VAL", Array) { |v| @array = v } 12 | 13 | @opt.def_option("--decimal-integer VAL", 14 | OptionParser::DecimalInteger) { |i| @decimal_integer = i } 15 | @opt.def_option("--octal-integer VAL", 16 | OptionParser::OctalInteger) { |i| @octal_integer = i } 17 | @opt.def_option("--decimal-numeric VAL", 18 | OptionParser::DecimalNumeric) { |i| @decimal_numeric = i } 19 | end 20 | 21 | def test_integer 22 | assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0")}) 23 | assert_equal(0, @integer) 24 | 25 | assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0b10")}) 26 | assert_equal(2, @integer) 27 | 28 | assert_equal(%w"", no_error {@opt.parse!(%w"--integer 077")}) 29 | assert_equal(63, @integer) 30 | 31 | assert_equal(%w"", no_error {@opt.parse!(%w"--integer 10")}) 32 | assert_equal(10, @integer) 33 | 34 | assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0x3")}) 35 | assert_equal(3, @integer) 36 | 37 | assert_raise(OptionParser::InvalidArgument) do 38 | @opt.parse!(%w"--integer 0b") 39 | end 40 | 41 | assert_raise(OptionParser::InvalidArgument) do 42 | @opt.parse!(%w"--integer 09") 43 | end 44 | 45 | assert_raise(OptionParser::InvalidArgument) do 46 | @opt.parse!(%w"--integer 0x") 47 | end 48 | 49 | assert_raise(OptionParser::InvalidArgument) do 50 | @opt.parse!(%w"--integer 1234xyz") 51 | end 52 | end 53 | 54 | def test_float 55 | assert_equal(%w"", no_error {@opt.parse!(%w"--float 0")}) 56 | assert_in_epsilon(0.0, @float) 57 | 58 | assert_equal(%w"", no_error {@opt.parse!(%w"--float 0.0")}) 59 | assert_in_epsilon(0.0, @float) 60 | 61 | assert_equal(%w"", no_error {@opt.parse!(%w"--float 1.2")}) 62 | assert_in_epsilon(1.2, @float) 63 | 64 | assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E2")}) 65 | assert_in_epsilon(100, @float) 66 | 67 | assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E-2")}) 68 | assert_in_epsilon(0.01, @float) 69 | 70 | assert_raise(OptionParser::InvalidArgument) do 71 | @opt.parse!(%w"--float 0e") 72 | end 73 | 74 | assert_raise(OptionParser::InvalidArgument) do 75 | @opt.parse!(%w"--float 1.234xyz") 76 | end 77 | end 78 | 79 | def test_numeric 80 | assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0")}) 81 | assert_equal(0, @numeric) 82 | 83 | assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0/1")}) 84 | assert_equal(0, @numeric) 85 | 86 | assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1/2")}) 87 | assert_equal(Rational(1, 2), @numeric) 88 | 89 | assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 010")}) 90 | assert_equal(8, @numeric) 91 | 92 | assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1.2/2.3")}) 93 | assert_equal(Rational(12, 23), @numeric) 94 | 95 | assert_raise(OptionParser::InvalidArgument) do 96 | @opt.parse!(%w"--numeric 1/") 97 | end 98 | 99 | assert_raise(OptionParser::InvalidArgument) do 100 | @opt.parse!(%w"--numeric 12/34xyz") 101 | end 102 | 103 | assert_raise(OptionParser::InvalidArgument) do 104 | @opt.parse!(%w"--numeric 12x/34yz") 105 | end 106 | end 107 | 108 | def test_decimal_integer 109 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 0")}) 110 | assert_equal(0, @decimal_integer) 111 | 112 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 10")}) 113 | assert_equal(10, @decimal_integer) 114 | 115 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 010")}) 116 | assert_equal(10, @decimal_integer) 117 | 118 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 09")}) 119 | assert_equal(9, @decimal_integer) 120 | 121 | assert_raise(OptionParser::InvalidArgument) do 122 | @opt.parse!(%w"--decimal-integer 0b1") 123 | end 124 | 125 | assert_raise(OptionParser::InvalidArgument) do 126 | @opt.parse!(%w"--decimal-integer x") 127 | end 128 | 129 | assert_raise(OptionParser::InvalidArgument) do 130 | @opt.parse!(%w"--decimal-integer 1234xyz") 131 | end 132 | end 133 | 134 | def test_octal_integer 135 | assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 0")}) 136 | assert_equal(0, @octal_integer) 137 | 138 | assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 6")}) 139 | assert_equal(6, @octal_integer) 140 | 141 | assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 07")}) 142 | assert_equal(7, @octal_integer) 143 | 144 | assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 10")}) 145 | assert_equal(8, @octal_integer) 146 | 147 | assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 011")}) 148 | assert_equal(9, @octal_integer) 149 | 150 | assert_raise(OptionParser::InvalidArgument) do 151 | @opt.parse!(%w"--octal-integer 09") 152 | end 153 | 154 | assert_raise(OptionParser::InvalidArgument) do 155 | @opt.parse!(%w"--octal-integer 0b1") 156 | end 157 | 158 | assert_raise(OptionParser::InvalidArgument) do 159 | @opt.parse!(%w"--octal-integer x") 160 | end 161 | 162 | assert_raise(OptionParser::InvalidArgument) do 163 | @opt.parse!(%w"--octal-integer 01234xyz") 164 | end 165 | end 166 | 167 | def test_decimal_numeric 168 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 0")}) 169 | assert_equal(0, @decimal_numeric) 170 | 171 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 01")}) 172 | assert_equal(1, @decimal_numeric) 173 | 174 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1.2")}) 175 | assert_in_delta(1.2, @decimal_numeric) 176 | 177 | assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1E2")}) 178 | assert_in_delta(100.0, @decimal_numeric) 179 | 180 | assert_raise(OptionParser::InvalidArgument) do 181 | @opt.parse!(%w"--decimal-numeric 0b1") 182 | end 183 | 184 | e = assert_raise(OptionParser::InvalidArgument) do 185 | @opt.parse!(%w"--decimal-numeric 09") 186 | end 187 | 188 | assert_equal("invalid argument: --decimal-numeric 09", e.message) 189 | 190 | assert_raise(OptionParser::InvalidArgument) do 191 | @opt.parse!(%w"--decimal-integer 1234xyz") 192 | end 193 | 194 | assert_raise(OptionParser::InvalidArgument) do 195 | @opt.parse!(%w"--decimal-integer 12.34xyz") 196 | end 197 | end 198 | 199 | def test_array 200 | assert_equal(%w"", no_error {@opt.parse!(%w"--array a,b,c")}) 201 | assert_equal(%w"a b c", @array) 202 | assert_equal(%w"", no_error {@opt.parse!(%w"--array a")}) 203 | assert_equal(%w"a", @array) 204 | end 205 | end 206 | -------------------------------------------------------------------------------- /test/optparse/test_autoconf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse/ac' 4 | 5 | class TestOptionParserAutoConf < Test::Unit::TestCase 6 | def setup 7 | @opt = OptionParser::AC.new 8 | @foo = @bar = self.class 9 | @opt.ac_arg_enable("foo", "foo option") {|x| @foo = x} 10 | @opt.ac_arg_disable("bar", "bar option") {|x| @bar = x} 11 | @opt.ac_arg_with("zot", "zot option") {|x| @zot = x} 12 | end 13 | 14 | class DummyOutput < String 15 | alias write concat 16 | end 17 | def no_error(*args) 18 | $stderr, stderr = DummyOutput.new, $stderr 19 | assert_nothing_raised(*args) {return yield} 20 | ensure 21 | stderr, $stderr = $stderr, stderr 22 | $!.backtrace.delete_if {|e| /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}/o =~ e} if $! 23 | assert_empty(stderr) 24 | end 25 | 26 | def test_enable 27 | @opt.parse!(%w"--enable-foo") 28 | assert_equal(true, @foo) 29 | @opt.parse!(%w"--enable-bar") 30 | assert_equal(true, @bar) 31 | end 32 | 33 | def test_enable_value 34 | @opt.parse!(%w"--enable-foo=A") 35 | assert_equal("A", @foo) 36 | @opt.parse!(%w"--enable-bar=B") 37 | assert_equal("B", @bar) 38 | end 39 | 40 | def test_disable 41 | @opt.parse!(%w"--disable-foo") 42 | assert_equal(false, @foo) 43 | @opt.parse!(%w"--disable-bar") 44 | assert_equal(false, @bar) 45 | end 46 | 47 | def test_with 48 | @opt.parse!(%w"--with-zot=foobar") 49 | assert_equal("foobar", @zot) 50 | @opt.parse!(%w"--without-zot") 51 | assert_nil(@zot) 52 | end 53 | 54 | def test_without 55 | @opt.parse!(%w"--without-zot") 56 | assert_nil(@zot) 57 | assert_raise(OptionParser::NeedlessArgument) {@opt.parse!(%w"--without-zot=foobar")} 58 | end 59 | 60 | def test_help 61 | help = @opt.help 62 | assert_match(/--enable-foo/, help) 63 | assert_match(/--disable-bar/, help) 64 | assert_match(/--with-zot/, help) 65 | assert_not_match(/--disable-foo/, help) 66 | assert_not_match(/--enable-bar/, help) 67 | assert_not_match(/--without/, help) 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /test/optparse/test_bash_completion.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse' 4 | 5 | class TestOptionParserBashCompletion < Test::Unit::TestCase 6 | def setup 7 | @opt = OptionParser.new 8 | @opt.define("-z", "zzz") {} 9 | @opt.define("--foo") {} 10 | @opt.define("--bar=BAR") {} 11 | @opt.define("--for=TYPE", [:hello, :help, :zot]) {} 12 | end 13 | 14 | def test_empty 15 | assert_equal([], @opt.candidate("")) 16 | end 17 | 18 | def test_one_hyphen 19 | assert_equal(%w[-z --foo --bar= --for=], @opt.candidate("-")) 20 | end 21 | 22 | def test_two_hyphen 23 | assert_equal(%w[--foo --bar= --for=], @opt.candidate("--")) 24 | end 25 | 26 | def test_long_f 27 | assert_equal(%w[--foo --for=], @opt.candidate("--f")) 28 | end 29 | 30 | def test_long_for_option 31 | assert_equal(%w[--for=], @opt.candidate("--for")) 32 | end 33 | 34 | def test_long_for_option_args 35 | assert_equal(%w[hello help zot], @opt.candidate("--for=")) 36 | end 37 | 38 | def test_long_for_option_complete 39 | assert_equal(%w[hello help], @opt.candidate("--for=h")) 40 | end 41 | 42 | def test_case_sensitive 43 | @opt.define("-Z") {} 44 | assert_equal(%w[-z], @opt.candidate("-z")) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /test/optparse/test_cclass.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | class TestOptionParserCClass < TestOptionParser 5 | def test_no_argument 6 | flags = [] 7 | @opt.def_option("-[a-z]") {|x| flags << x} 8 | no_error {@opt.parse!(%w"-a")} 9 | assert_equal(%w"a", flags) 10 | end 11 | 12 | def test_required_argument 13 | flags = [] 14 | @opt.def_option("-[a-z]X") {|x| flags << x} 15 | no_error {@opt.parse!(%w"-a")} 16 | assert_equal(%w"a", flags) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/optparse/test_did_you_mean.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | begin 4 | require "did_you_mean" 5 | rescue LoadError 6 | return 7 | end 8 | 9 | class TestOptionParserDidYouMean < TestOptionParser 10 | def setup 11 | super 12 | @opt.def_option("--foo", Integer) { |v| @foo = v } 13 | @opt.def_option("--bar", Integer) { |v| @bar = v } 14 | @opt.def_option("--baz", Integer) { |v| @baz = v } 15 | @formatter = ::DidYouMean.formatter 16 | if ::DidYouMean.const_defined?(:Formatter) 17 | ::DidYouMean.formatter = ::DidYouMean::Formatter 18 | else 19 | case @formatter 20 | when ::DidYouMean::PlainFormatter 21 | else 22 | ::DidYouMean.formatter = ::DidYouMean::PlainFormatter.new 23 | end 24 | end 25 | end 26 | 27 | def teardown 28 | ::DidYouMean.formatter = @formatter 29 | end 30 | 31 | def test_no_suggestion 32 | assert_raise_with_message(OptionParser::InvalidOption, "invalid option: --cuz") do 33 | @opt.permute!(%w"--cuz") 34 | end 35 | end 36 | 37 | def test_plain 38 | assert_raise_with_message(OptionParser::InvalidOption, /invalid option: --baa\nDid you mean\?\s+bar\s+baz\Z/) do 39 | @opt.permute!(%w"--baa") 40 | end 41 | end 42 | 43 | def test_ambiguous 44 | assert_raise_with_message(OptionParser::AmbiguousOption, /ambiguous option: --ba\nDid you mean\?\s+bar\s+baz\Z/) do 45 | @opt.permute!(%w"--ba") 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /test/optparse/test_getopts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse' 4 | 5 | class TestOptionParserGetopts < Test::Unit::TestCase 6 | def setup 7 | @opt = OptionParser.new 8 | end 9 | 10 | def test_short_noarg 11 | o = @opt.getopts(%w[-a], "ab") 12 | assert_equal(true, o['a']) 13 | assert_equal(false, o['b']) 14 | 15 | o = @opt.getopts(%w[-a], "ab", symbolize_names: true) 16 | assert_equal(true, o[:a]) 17 | assert_equal(false, o[:b]) 18 | end 19 | 20 | def test_short_arg 21 | o = @opt.getopts(%w[-a1], "a:b:") 22 | assert_equal("1", o['a']) 23 | assert_equal(nil, o['b']) 24 | 25 | o = @opt.getopts(%w[-a1], "a:b:", symbolize_names: true) 26 | assert_equal("1", o[:a]) 27 | assert_equal(nil, o[:b]) 28 | end 29 | 30 | def test_long_noarg 31 | o = @opt.getopts(%w[--foo], "", "foo", "bar") 32 | assert_equal(true, o['foo']) 33 | assert_equal(false, o['bar']) 34 | 35 | o = @opt.getopts(%w[--foo], "", "foo", "bar", symbolize_names: true) 36 | assert_equal(true, o[:foo]) 37 | assert_equal(false, o[:bar]) 38 | end 39 | 40 | def test_long_arg 41 | o = @opt.getopts(%w[--bar ZOT], "", "foo:FOO", "bar:BAR") 42 | assert_equal("FOO", o['foo']) 43 | assert_equal("ZOT", o['bar']) 44 | 45 | o = @opt.getopts(%w[--bar ZOT], "", "foo:FOO", "bar:BAR", symbolize_names: true) 46 | assert_equal("FOO", o[:foo]) 47 | assert_equal("ZOT", o[:bar]) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/optparse/test_kwargs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse' 4 | require 'optparse/kwargs' 5 | 6 | class TestOptionParserKwArg < Test::Unit::TestCase 7 | class K 8 | def initialize(host:, port: 8080) 9 | @host = host 10 | @port = port 11 | end 12 | end 13 | 14 | class DummyOutput < String 15 | alias write concat 16 | end 17 | def assert_no_error(*args) 18 | $stderr, stderr = DummyOutput.new, $stderr 19 | assert_nothing_raised(*args) {return yield} 20 | ensure 21 | stderr, $stderr = $stderr, stderr 22 | $!.backtrace.delete_if {|e| /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}/o =~ e} if $! 23 | assert_empty(stderr) 24 | end 25 | alias no_error assert_no_error 26 | 27 | def test_kwarg 28 | opt = OptionParser.new 29 | options = opt.define_by_keywords({}, K.instance_method(:initialize), 30 | port: [Integer]) 31 | assert_raise(OptionParser::MissingArgument) {opt.parse!(%w"--host")} 32 | assert_nothing_raised {opt.parse!(%w"--host=localhost")} 33 | assert_equal("localhost", options[:host]) 34 | assert_nothing_raised {opt.parse!(%w"--port")} 35 | assert_nothing_raised {opt.parse!(%w"--port=80")} 36 | assert_equal(80, options[:port]) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /test/optparse/test_load.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse' 4 | require 'tmpdir' 5 | 6 | class TestOptionParserLoad < Test::Unit::TestCase 7 | def setup 8 | @tmpdir = Dir.mktmpdir("optparse_test-") 9 | @basename = File.basename($0, '.*') 10 | @envs = %w[HOME XDG_CONFIG_HOME XDG_CONFIG_DIRS].each_with_object({}) do |v, h| 11 | h[v] = ENV.delete(v) 12 | end 13 | end 14 | 15 | def teardown 16 | ENV.update(@envs) 17 | FileUtils.rm_rf(@tmpdir) 18 | end 19 | 20 | def new_parser 21 | @result = nil 22 | OptionParser.new do |opt| 23 | opt.on("--test=arg") {|v| @result = v} 24 | end 25 | end 26 | 27 | def assert_load(result) 28 | assert new_parser.load 29 | assert_equal(result, @result) 30 | assert new_parser.load(into: into = {}) 31 | assert_equal({test: result}, into) 32 | end 33 | 34 | def setup_options(env, dir, suffix = nil) 35 | optdir = File.join(@tmpdir, dir) 36 | FileUtils.mkdir_p(optdir) 37 | file = File.join(optdir, [@basename, suffix].join("")) 38 | File.write(file, "--test=#{dir}") 39 | ENV.update(env) 40 | if block_given? 41 | begin 42 | yield dir, optdir 43 | ensure 44 | File.unlink(file) 45 | Dir.rmdir(optdir) rescue nil 46 | end 47 | else 48 | return dir, optdir 49 | end 50 | end 51 | 52 | def setup_options_home(&block) 53 | setup_options({'HOME'=>@tmpdir}, ".options", &block) 54 | end 55 | 56 | def setup_options_xdg_config_home(&block) 57 | setup_options({'XDG_CONFIG_HOME'=>@tmpdir+"/xdg"}, "xdg", ".options", &block) 58 | end 59 | 60 | def setup_options_home_config(&block) 61 | setup_options({'HOME'=>@tmpdir}, ".config", ".options", &block) 62 | end 63 | 64 | def setup_options_xdg_config_dirs(&block) 65 | setup_options({'XDG_CONFIG_DIRS'=>@tmpdir+"/xdgconf"}, "xdgconf", ".options", &block) 66 | end 67 | 68 | def setup_options_home_config_settings(&block) 69 | setup_options({'HOME'=>@tmpdir}, "config/settings", ".options", &block) 70 | end 71 | 72 | def test_load_home_options 73 | result, = setup_options_home 74 | assert_load(result) 75 | 76 | setup_options_xdg_config_home do 77 | assert_load(result) 78 | end 79 | 80 | setup_options_home_config do 81 | assert_load(result) 82 | end 83 | 84 | setup_options_xdg_config_dirs do 85 | assert_load(result) 86 | end 87 | 88 | setup_options_home_config_settings do 89 | assert_load(result) 90 | end 91 | end 92 | 93 | def test_load_xdg_config_home 94 | result, = setup_options_xdg_config_home 95 | assert_load(result) 96 | 97 | setup_options_home_config do 98 | assert_load(result) 99 | end 100 | 101 | setup_options_xdg_config_dirs do 102 | assert_load(result) 103 | end 104 | 105 | setup_options_home_config_settings do 106 | assert_load(result) 107 | end 108 | end 109 | 110 | def test_load_home_config 111 | result, = setup_options_home_config 112 | assert_load(result) 113 | 114 | setup_options_xdg_config_dirs do 115 | assert_load(result) 116 | end 117 | 118 | setup_options_home_config_settings do 119 | assert_load(result) 120 | end 121 | end 122 | 123 | def test_load_xdg_config_dirs 124 | result, = setup_options_xdg_config_dirs 125 | assert_load(result) 126 | 127 | setup_options_home_config_settings do 128 | assert_load(result) 129 | end 130 | end 131 | 132 | def test_load_home_config_settings 133 | result, = setup_options_home_config_settings 134 | assert_load(result) 135 | end 136 | 137 | def test_load_nothing 138 | assert !new_parser.load 139 | assert_nil @result 140 | end 141 | end 142 | -------------------------------------------------------------------------------- /test/optparse/test_noarg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | module TestOptionParserNoArg 5 | def setup 6 | super 7 | @opt.def_option "--with_underscore" do |x| @flag = x end 8 | @opt.def_option "--with-hyphen" do |x| @flag = x end 9 | end 10 | 11 | class Def1 < TestOptionParser 12 | include TestOptionParserNoArg 13 | def setup 14 | super 15 | @opt.def_option("-x") {|x| @flag = x} 16 | @opt.def_option("--option") {|x| @flag = x} 17 | end 18 | end 19 | class Def2 < TestOptionParser 20 | include TestOptionParserNoArg 21 | def setup 22 | super 23 | @opt.def_option("-x", "--option") {|x| @flag = x} 24 | end 25 | end 26 | 27 | def test_short 28 | assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-xq")} 29 | assert_equal(%w"", no_error {@opt.parse!(%w"-x")}) 30 | assert_equal(true, @flag) 31 | @flag = nil 32 | assert_equal(%w"foo", no_error {@opt.parse!(%w"-x foo")}) 33 | assert_equal(true, @flag) 34 | end 35 | 36 | def test_abbrev 37 | assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-oq")} 38 | assert_equal(%w"", no_error {@opt.parse!(%w"-o")}) 39 | assert_equal(true, @flag) 40 | @flag = nil 41 | assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-O")} 42 | assert_nil(@flag) 43 | @flag = nil 44 | assert_equal(%w"foo", no_error {@opt.parse!(%w"-o foo")}) 45 | assert_equal(true, @flag) 46 | end 47 | 48 | def test_long 49 | assert_raise(OptionParser::NeedlessArgument) {@opt.parse!(%w"--option=x")} 50 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt")}) 51 | assert_equal(true, @flag) 52 | @flag = nil 53 | assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt foo")}) 54 | assert_equal(true, @flag) 55 | end 56 | 57 | def test_ambiguous 58 | @opt.def_option("--open") {|x|} 59 | assert_raise(OptionParser::AmbiguousOption) {@opt.parse!(%w"--op")} 60 | assert_raise(OptionParser::AmbiguousOption) {@opt.parse!(%w"-o")} 61 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt")}) 62 | assert_equal(true, @flag) 63 | end 64 | 65 | def test_hyphenize 66 | @flag = nil 67 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_underscore")}) 68 | assert_equal(true, @flag) 69 | @flag = nil 70 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-underscore")}) 71 | assert_equal(true, @flag) 72 | @flag = nil 73 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-hyphen")}) 74 | assert_equal(true, @flag) 75 | @flag = nil 76 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_hyphen")}) 77 | assert_equal(true, @flag) 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /test/optparse/test_optarg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | class TestOptionParserOptArg < TestOptionParser 5 | def setup 6 | super 7 | @opt.def_option("-x[VAL]") {|x| @flag = x} 8 | @opt.def_option("--option[=VAL]") {|x| @flag = x} 9 | @opt.def_option("--regexp[=REGEXP]", Regexp) {|x| @reopt = x} 10 | @opt.def_option "--with_underscore[=VAL]" do |x| @flag = x end 11 | @opt.def_option "--with-hyphen[=VAL]" do |x| @flag = x end 12 | @opt.def_option("--fallback[=VAL]") do |x = "fallback"| @flag = x end 13 | @opt.def_option("--lambda[=VAL]", &->(x) {@flag = x}) 14 | @reopt = nil 15 | end 16 | 17 | def test_short 18 | assert_equal(%w"", no_error {@opt.parse!(%w"-x")}) 19 | assert_equal(nil, @flag) 20 | @flag = false 21 | assert_equal(%w"foo", no_error {@opt.parse!(%w"-x foo")}) 22 | assert_equal(nil, @flag) 23 | assert_equal(%w"", no_error {@opt.parse!(%w"-xfoo")}) 24 | assert_equal("foo", @flag) 25 | assert_equal(%w"", no_error {@opt.parse!(%w"-x=")}) 26 | assert_equal("=", @flag) 27 | end 28 | 29 | def test_abbrev 30 | assert_equal(%w"", no_error {@opt.parse!(%w"-o")}) 31 | assert_equal(nil, @flag) 32 | @flag = false 33 | assert_equal(%w"foo", no_error {@opt.parse!(%w"-o foo")}) 34 | assert_equal(nil, @flag) 35 | assert_equal(%w"", no_error {@opt.parse!(%w"-ofoo")}) 36 | assert_equal("foo", @flag) 37 | assert_equal(%w"", no_error {@opt.parse!(%w"-o=")}) 38 | assert_equal("=", @flag) 39 | end 40 | 41 | def test_long 42 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt")}) 43 | assert_equal(nil, @flag) 44 | assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")}) 45 | assert_equal("", @flag) 46 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")}) 47 | assert_equal("foo", @flag) 48 | assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt foo")}) 49 | assert_equal(nil, @flag) 50 | end 51 | 52 | def test_hyphenize 53 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_underscore=foo1")}) 54 | assert_equal("foo1", @flag) 55 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-underscore=foo2")}) 56 | assert_equal("foo2", @flag) 57 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-hyphen=foo3")}) 58 | assert_equal("foo3", @flag) 59 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_hyphen=foo4")}) 60 | assert_equal("foo4", @flag) 61 | end 62 | 63 | def test_default_argument 64 | assert_equal(%w"", no_error {@opt.parse!(%w"--fallback=val1")}) 65 | assert_equal("val1", @flag) 66 | assert_equal(%w"", no_error {@opt.parse!(%w"--fallback")}) 67 | assert_equal("fallback", @flag) 68 | end 69 | 70 | def test_lambda 71 | assert_equal(%w"", no_error {@opt.parse!(%w"--lambda=lambda1")}) 72 | assert_equal("lambda1", @flag) 73 | assert_equal(%w"", no_error {@opt.parse!(%w"--lambda")}) 74 | assert_equal(nil, @flag) 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /test/optparse/test_optparse.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse' 4 | 5 | class TestOptionParser < Test::Unit::TestCase 6 | def setup 7 | @opt = OptionParser.new 8 | @flag = self.class # cannot set by option 9 | end 10 | 11 | class DummyOutput < String 12 | alias write concat 13 | end 14 | def assert_no_error(*args) 15 | $stderr, stderr = DummyOutput.new, $stderr 16 | assert_nothing_raised(*args) {return yield} 17 | ensure 18 | stderr, $stderr = $stderr, stderr 19 | $!.backtrace.delete_if {|e| /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}/o =~ e} if $! 20 | assert_empty(stderr) 21 | end 22 | alias no_error assert_no_error 23 | 24 | def test_permute 25 | assert_equal(%w"", no_error {@opt.permute!(%w"")}) 26 | assert_equal(self.class, @flag) 27 | assert_equal(%w"foo bar", no_error {@opt.permute!(%w"foo bar")}) 28 | assert_equal(self.class, @flag) 29 | assert_equal(%w"- foo bar", no_error {@opt.permute!(%w"- foo bar")}) 30 | assert_equal(self.class, @flag) 31 | assert_equal(%w"foo bar", no_error {@opt.permute!(%w"-- foo bar")}) 32 | assert_equal(self.class, @flag) 33 | assert_equal(%w"foo - bar", no_error {@opt.permute!(%w"foo - bar")}) 34 | assert_equal(self.class, @flag) 35 | assert_equal(%w"foo bar", no_error {@opt.permute!(%w"foo -- bar")}) 36 | assert_equal(self.class, @flag) 37 | assert_equal(%w"foo --help bar", no_error {@opt.permute!(%w"foo -- --help bar")}) 38 | assert_equal(self.class, @flag) 39 | end 40 | 41 | def test_order 42 | assert_equal(%w"", no_error {@opt.order!(%w"")}) 43 | assert_equal(self.class, @flag) 44 | assert_equal(%w"foo bar", no_error {@opt.order!(%w"foo bar")}) 45 | assert_equal(self.class, @flag) 46 | assert_equal(%w"- foo bar", no_error {@opt.order!(%w"- foo bar")}) 47 | assert_equal(self.class, @flag) 48 | assert_equal(%w"foo bar", no_error {@opt.permute!(%w"-- foo bar")}) 49 | assert_equal(self.class, @flag) 50 | assert_equal(%w"foo - bar", no_error {@opt.order!(%w"foo - bar")}) 51 | assert_equal(self.class, @flag) 52 | assert_equal(%w"foo -- bar", no_error {@opt.order!(%w"foo -- bar")}) 53 | assert_equal(self.class, @flag) 54 | assert_equal(%w"foo -- --help bar", no_error {@opt.order!(%w"foo -- --help bar")}) 55 | assert_equal(self.class, @flag) 56 | end 57 | 58 | def test_regexp 59 | return unless defined?(@reopt) 60 | assert_equal(%w"", no_error {@opt.parse!(%w"--regexp=/foo/")}) 61 | assert_equal(/foo/, @reopt) 62 | assert_equal(%w"", no_error {@opt.parse!(%w"--regexp=/foo/i")}) 63 | assert_equal(/foo/i, @reopt) 64 | assert_equal(%w"", no_error {@opt.parse!(%w"--regexp=/foo/n")}) 65 | assert_equal(/foo/n, @reopt) 66 | assert_equal(%w"", no_error {@opt.parse!(%W"--regexp=/\u{3042}/s")}) 67 | assert_equal(Encoding::Windows_31J, @reopt.encoding) 68 | assert_equal("\x82\xa0".force_encoding(Encoding::Windows_31J), @reopt.source) 69 | end 70 | 71 | def test_into 72 | @opt.def_option "-h", "--host=HOST", "hostname" 73 | @opt.def_option "-p", "--port=PORT", "port", Integer 74 | @opt.def_option "-v", "--verbose" do @verbose = true end 75 | @opt.def_option "-q", "--quiet" do @quiet = true end 76 | @opt.def_option "-o", "--option [OPT]" do |opt| @option = opt end 77 | @opt.def_option "-a", "--array [VAL]", Array do |val| val end 78 | result = {} 79 | @opt.parse %w(--host localhost --port 8000 -v), into: result 80 | assert_equal({host: "localhost", port: 8000, verbose: true}, result) 81 | assert_equal(true, @verbose) 82 | result = {} 83 | @opt.parse %w(--option -q), into: result 84 | assert_equal({quiet: true, option: nil}, result) 85 | result = {} 86 | @opt.parse %w(--option OPTION -v), into: result 87 | assert_equal({verbose: true, option: "OPTION"}, result) 88 | result = {} 89 | @opt.parse %w(-a b,c,d), into: result 90 | assert_equal({array: %w(b c d)}, result) 91 | result = {} 92 | @opt.parse %w(--array b,c,d), into: result 93 | assert_equal({array: %w(b c d)}, result) 94 | result = {} 95 | @opt.parse %w(-a b), into: result 96 | assert_equal({array: %w(b)}, result) 97 | result = {} 98 | @opt.parse %w(--array b), into: result 99 | assert_equal({array: %w(b)}, result) 100 | end 101 | 102 | def test_require_exact 103 | @opt.def_option('-F', '--zrs=IRS', 'zrs') 104 | %w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg| 105 | result = {} 106 | @opt.parse([arg, 'foo'], into: result) 107 | assert_equal({zrs: 'foo'}, result) 108 | end 109 | 110 | @opt.require_exact = true 111 | [%w(--zrs foo), %w(--zrs=foo), %w(-F foo), %w(-Ffoo)].each do |args| 112 | result = {} 113 | @opt.parse(args, into: result) 114 | assert_equal({zrs: 'foo'}, result) 115 | end 116 | 117 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo))} 118 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo))} 119 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo))} 120 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo))} 121 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo))} 122 | 123 | @opt.def_option('-f', '--[no-]foo', 'foo') {|arg| @foo = arg} 124 | @opt.parse(%w[-f]) 125 | assert_equal(true, @foo) 126 | @opt.parse(%w[--foo]) 127 | assert_equal(true, @foo) 128 | @opt.parse(%w[--no-foo]) 129 | assert_equal(false, @foo) 130 | end 131 | 132 | def test_exact_option 133 | @opt.def_option('-F', '--zrs=IRS', 'zrs') 134 | %w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg| 135 | result = {} 136 | @opt.parse([arg, 'foo'], into: result) 137 | assert_equal({zrs: 'foo'}, result) 138 | end 139 | 140 | [%w(--zrs foo), %w(--zrs=foo), %w(-F foo), %w(-Ffoo)].each do |args| 141 | result = {} 142 | @opt.parse(args, into: result, exact: true) 143 | assert_equal({zrs: 'foo'}, result) 144 | end 145 | 146 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo), exact: true)} 147 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo), exact: true)} 148 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo), exact: true)} 149 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo), exact: true)} 150 | assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo), exact: true)} 151 | 152 | @opt.def_option('-f', '--[no-]foo', 'foo') {|arg| @foo = arg} 153 | @opt.parse(%w[-f], exact: true) 154 | assert_equal(true, @foo) 155 | @opt.parse(%w[--foo], exact: true) 156 | assert_equal(true, @foo) 157 | @opt.parse(%w[--no-foo], exact: true) 158 | assert_equal(false, @foo) 159 | end 160 | 161 | def test_raise_unknown 162 | @opt.def_option('--my-foo [ARG]') {|arg| @foo = arg} 163 | assert @opt.raise_unknown 164 | 165 | @opt.raise_unknown = false 166 | assert_equal(%w[--my-bar], @opt.parse(%w[--my-foo --my-bar])) 167 | assert_nil(@foo) 168 | 169 | assert_equal(%w[--my-bar], @opt.parse(%w[--my-foo x --my-bar])) 170 | assert_equal("x", @foo) 171 | end 172 | 173 | def test_nonopt_pattern 174 | @opt.def_option(/^[^-]/) do |arg| 175 | assert(false, "Never gets called") 176 | end 177 | e = assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-t))} 178 | assert_equal(["-t"], e.args) 179 | end 180 | 181 | def test_help_pager 182 | require 'tmpdir' 183 | Dir.mktmpdir do |dir| 184 | File.open(File.join(dir, "options.rb"), "w") do |f| 185 | f.puts "#{<<~"begin;"}\n#{<<~'end;'}" 186 | begin; 187 | stdout = $stdout.dup 188 | def stdout.tty?; true; end 189 | $stdout = stdout 190 | ARGV.options do |opt| 191 | end; 192 | 100.times {|i| f.puts " opt.on('--opt-#{i}') {}"} 193 | f.puts "#{<<~"begin;"}\n#{<<~'end;'}" 194 | begin; 195 | opt.parse! 196 | end 197 | end; 198 | end 199 | 200 | optparse = $".find {|path| path.end_with?("/optparse.rb")} 201 | args = ["-r#{optparse}", "options.rb", "--help"] 202 | cmd = File.join(dir, "pager.cmd") 203 | if RbConfig::CONFIG["EXECUTABLE_EXTS"]&.include?(".cmd") 204 | command = "@echo off" 205 | else # if File.executable?("/bin/sh") 206 | # TruffleRuby just calls `posix_spawnp` and no fallback to `/bin/sh`. 207 | command = "#!/bin/sh\n" 208 | end 209 | 210 | [ 211 | [{"RUBY_PAGER"=>cmd, "PAGER"=>"echo ng"}, "Executing RUBY_PAGER"], 212 | [{"RUBY_PAGER"=>nil, "PAGER"=>cmd}, "Executing PAGER"], 213 | ].each do |env, expected| 214 | File.write(cmd, "#{command}\n" "echo #{expected}\n", perm: 0o700) 215 | assert_in_out_err([env, *args], "", [expected], chdir: dir) 216 | end 217 | end 218 | end 219 | end 220 | -------------------------------------------------------------------------------- /test/optparse/test_placearg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | class TestOptionParserPlaceArg < TestOptionParser 5 | def setup 6 | super 7 | @opt.def_option("-x [VAL]") {|x| @flag = x} 8 | @opt.def_option("--option [VAL]") {|x| @flag = x} 9 | @opt.def_option("-T [level]", /^[0-4]$/, Integer) {|x| @topt = x} 10 | @opt.def_option("--enum [VAL]", [:Alpha, :Bravo, :Charlie]) {|x| @enum = x} 11 | @opt.def_option("--enumval [VAL]", [[:Alpha, 1], [:Bravo, 2], [:Charlie, 3]]) {|x| @enum = x} 12 | @opt.def_option("--integer [VAL]", Integer, [1, 2, 3]) {|x| @integer = x} 13 | @opt.def_option("--range [VAL]", Integer, 1..3) {|x| @range = x} 14 | @topt = nil 15 | @opt.def_option("-n") {} 16 | @opt.def_option("--regexp [REGEXP]", Regexp) {|x| @reopt = x} 17 | @reopt = nil 18 | @opt.def_option "--with_underscore=VAL" do |x| @flag = x end 19 | @opt.def_option "--with-hyphen=VAL" do |x| @flag = x end 20 | @opt.def_option("--fallback [VAL]") do |x = "fallback"| @flag = x end 21 | @opt.def_option("--lambda [VAL]", &->(x) {@flag = x}) 22 | end 23 | 24 | def test_short 25 | assert_equal(%w"", no_error {@opt.parse!(%w"-x -n")}) 26 | assert_equal(nil, @flag) 27 | assert_equal(%w"", no_error {@opt.parse!(%w"-x -")}) 28 | assert_equal("-", @flag) 29 | @flag = false 30 | assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")}) 31 | assert_equal("foo", @flag) 32 | assert_equal(%w"", no_error {@opt.parse!(%w"-xbar")}) 33 | assert_equal("bar", @flag) 34 | assert_equal(%w"", no_error {@opt.parse!(%w"-x=")}) 35 | assert_equal("=", @flag) 36 | end 37 | 38 | def test_abbrev 39 | assert_equal(%w"", no_error {@opt.parse!(%w"-o -n")}) 40 | assert_equal(nil, @flag) 41 | assert_equal(%w"", no_error {@opt.parse!(%w"-o -")}) 42 | assert_equal("-", @flag) 43 | @flag = false 44 | assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")}) 45 | assert_equal("foo", @flag) 46 | assert_equal(%w"", no_error {@opt.parse!(%w"-obar")}) 47 | assert_equal("bar", @flag) 48 | assert_equal(%w"", no_error {@opt.parse!(%w"-o=")}) 49 | assert_equal("=", @flag) 50 | end 51 | 52 | def test_long 53 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt -n")}) 54 | assert_equal(nil, @flag) 55 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt -")}) 56 | assert_equal("-", @flag) 57 | assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")}) 58 | assert_equal("", @flag) 59 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")}) 60 | assert_equal("foo", @flag) 61 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt bar")}) 62 | assert_equal("bar", @flag) 63 | end 64 | 65 | def test_hyphenize 66 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_underscore=foo1")}) 67 | assert_equal("foo1", @flag) 68 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-underscore=foo2")}) 69 | assert_equal("foo2", @flag) 70 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-hyphen=foo3")}) 71 | assert_equal("foo3", @flag) 72 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_hyphen=foo4")}) 73 | assert_equal("foo4", @flag) 74 | end 75 | 76 | def test_conv 77 | assert_equal(%w"te.rb", no_error('[ruby-dev:38333]') {@opt.parse!(%w"-T te.rb")}) 78 | assert_nil(@topt) 79 | assert_equal(%w"te.rb", no_error('[ruby-dev:38333]') {@opt.parse!(%w"-T1 te.rb")}) 80 | assert_equal(1, @topt) 81 | end 82 | 83 | def test_default_argument 84 | assert_equal(%w"", no_error {@opt.parse!(%w"--fallback=val1")}) 85 | assert_equal("val1", @flag) 86 | assert_equal(%w"", no_error {@opt.parse!(%w"--fallback val2")}) 87 | assert_equal("val2", @flag) 88 | assert_equal(%w"", no_error {@opt.parse!(%w"--fallback")}) 89 | assert_equal("fallback", @flag) 90 | end 91 | 92 | def test_lambda 93 | assert_equal(%w"", no_error {@opt.parse!(%w"--lambda=lambda1")}) 94 | assert_equal("lambda1", @flag) 95 | assert_equal(%w"", no_error {@opt.parse!(%w"--lambda lambda2")}) 96 | assert_equal("lambda2", @flag) 97 | assert_equal(%w"", no_error {@opt.parse!(%w"--lambda")}) 98 | assert_equal(nil, @flag) 99 | end 100 | 101 | def test_enum 102 | assert_equal([], no_error {@opt.parse!(%w"--enum=A")}) 103 | assert_equal(:Alpha, @enum) 104 | end 105 | 106 | def test_enum_pair 107 | assert_equal([], no_error {@opt.parse!(%w"--enumval=A")}) 108 | assert_equal(1, @enum) 109 | end 110 | 111 | def test_enum_conversion 112 | assert_equal([], no_error {@opt.parse!(%w"--integer=1")}) 113 | assert_equal(1, @integer) 114 | end 115 | 116 | def test_enum_range 117 | assert_equal([], no_error {@opt.parse!(%w"--range=1")}) 118 | assert_equal(1, @range) 119 | assert_raise(OptionParser::InvalidArgument) {@opt.parse!(%w"--range=4")} 120 | end 121 | end 122 | -------------------------------------------------------------------------------- /test/optparse/test_reqarg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | module TestOptionParserReqArg 5 | def setup 6 | super 7 | @opt.def_option "--with_underscore=VAL" do |x| @flag = x end 8 | @opt.def_option "--with-hyphen=VAL" do |x| @flag = x end 9 | @opt.def_option("--lambda=VAL", &->(x) {@flag = x}) 10 | end 11 | 12 | class Def1 < TestOptionParser 13 | include TestOptionParserReqArg 14 | def setup 15 | super 16 | @opt.def_option("-xVAL") {|x| @flag = x} 17 | @opt.def_option("--option=VAL") {|x| @flag = x} 18 | @opt.def_option("--regexp=REGEXP", Regexp) {|x| @reopt = x} 19 | @reopt = nil 20 | end 21 | end 22 | class Def2 < TestOptionParser 23 | include TestOptionParserReqArg 24 | def setup 25 | super 26 | @opt.def_option("-x", "--option=VAL") {|x| @flag = x} 27 | end 28 | end 29 | class Def3 < TestOptionParser 30 | include TestOptionParserReqArg 31 | def setup 32 | super 33 | @opt.def_option("--option=VAL", "-x") {|x| @flag = x} 34 | end 35 | end 36 | class Def4 < TestOptionParser 37 | include TestOptionParserReqArg 38 | def setup 39 | super 40 | @opt.def_option("-xVAL", "--option=VAL") {|x| @flag = x} 41 | end 42 | end 43 | 44 | def test_short 45 | assert_raise(OptionParser::MissingArgument) {@opt.parse!(%w"-x")} 46 | assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")}) 47 | assert_equal("foo", @flag) 48 | assert_equal(%w"", no_error {@opt.parse!(%w"-xbar")}) 49 | assert_equal("bar", @flag) 50 | assert_equal(%w"", no_error {@opt.parse!(%w"-x=")}) 51 | assert_equal("=", @flag) 52 | end 53 | 54 | def test_abbrev 55 | assert_raise(OptionParser::MissingArgument) {@opt.parse!(%w"-o")} 56 | assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")}) 57 | assert_equal("foo", @flag) 58 | assert_equal(%w"", no_error {@opt.parse!(%w"-obar")}) 59 | assert_equal("bar", @flag) 60 | assert_equal(%w"", no_error {@opt.parse!(%w"-o=")}) 61 | assert_equal("=", @flag) 62 | end 63 | 64 | def test_long 65 | assert_raise(OptionParser::MissingArgument) {@opt.parse!(%w"--opt")} 66 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt foo")}) 67 | assert_equal("foo", @flag) 68 | assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")}) 69 | assert_equal("", @flag) 70 | assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")}) 71 | assert_equal("foo", @flag) 72 | end 73 | 74 | def test_hyphenize 75 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_underscore foo1")}) 76 | assert_equal("foo1", @flag) 77 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-underscore foo2")}) 78 | assert_equal("foo2", @flag) 79 | assert_equal(%w"", no_error {@opt.parse!(%w"--with-hyphen foo3")}) 80 | assert_equal("foo3", @flag) 81 | assert_equal(%w"", no_error {@opt.parse!(%w"--with_hyphen foo4")}) 82 | assert_equal("foo4", @flag) 83 | end 84 | 85 | def test_lambda 86 | assert_equal(%w"", no_error {@opt.parse!(%w"--lambda=lambda1")}) 87 | assert_equal("lambda1", @flag) 88 | end 89 | 90 | class TestOptionParser::WithPattern < TestOptionParser 91 | def test_pattern 92 | pat = num = nil 93 | @opt.def_option("--pattern=VAL", /(\w+)(?:\s*:\s*(\w+))?/) {|x, y, z| pat = [x, y, z]} 94 | @opt.def_option("-T NUM", /\A[1-4]\z/) {|n| num = n} 95 | no_error {@opt.parse!(%w"--pattern=key:val")} 96 | assert_equal(%w"key:val key val", pat, '[ruby-list:45645]') 97 | no_error {@opt.parse!(%w"-T 4")} 98 | assert_equal("4", num, '[ruby-dev:37514]') 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /test/optparse/test_summary.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require_relative 'test_optparse' 3 | 4 | class TestOptionParserSummaryTest < TestOptionParser 5 | def test_short_clash 6 | r = nil 7 | o = OptionParser.new do |opts| 8 | opts.on("-f", "--first-option", "description 1", "description 2"){r = "first-option"} 9 | opts.on("-t", "--test-option"){r = "test-option"} 10 | opts.on("-t", "--another-test-option"){r = "another-test-option"} 11 | opts.separator "this is\nseparator" 12 | opts.on("-l", "--last-option"){r = "last-option"} 13 | end 14 | s = o.summarize 15 | o.parse("-t") 16 | assert_match(/--#{r}/, s.grep(/^\s*-t,/)[0]) 17 | assert_match(/first-option/, s[0]) 18 | assert_match(/description 1/, s[0]) 19 | assert_match(/description 2/, s[1]) 20 | assert_match(/last-option/, s[-1]) 21 | end 22 | 23 | def test_banner 24 | o = OptionParser.new("foo bar") 25 | assert_equal("foo bar", o.banner) 26 | end 27 | 28 | def test_banner_from_progname 29 | o = OptionParser.new 30 | o.program_name = "foobar" 31 | assert_equal("Usage: foobar [options]\n", o.help) 32 | end 33 | 34 | def test_summary 35 | o = OptionParser.new("foo\nbar") 36 | assert_equal("foo\nbar\n", o.to_s) 37 | assert_equal(["foo\n", "bar"], o.to_a) 38 | end 39 | 40 | def test_summary_containing_space 41 | # test for r35467. OptionParser#to_a shouldn't split str by spaces. 42 | bug6348 = '[ruby-dev:45568]' 43 | o = OptionParser.new("foo bar") 44 | assert_equal("foo bar\n", o.to_s, bug6348) 45 | assert_equal(["foo bar"], o.to_a, bug6348) 46 | end 47 | 48 | def test_ver 49 | o = OptionParser.new("foo bar") 50 | o.program_name = "foo" 51 | assert_warning('') {assert_nil(o.version)} 52 | assert_warning('') {assert_nil(o.release)} 53 | o.version = [0, 1] 54 | assert_equal "foo 0.1", o.ver 55 | o.release = "rel" 56 | assert_equal "foo 0.1 (rel)", o.ver 57 | end 58 | 59 | # https://github.com/ruby/optparse/issues/37 60 | def test_very_long_without_short 61 | o = OptionParser.new do |opts| 62 | # This causes TypeError 63 | opts.on('', '--long-long-option-param-without-short', "Error desc") { options[:long_long_option_param_without_short] = true } 64 | opts.on('', '--long-option-param', "Long desc") { options[:long_option_param_without_short] = true } 65 | opts.on('-a', '--long-long-option-param-with-short', "Normal description") { options[:long_long_option_param_with_short] = true } 66 | 67 | opts.on('', '--long-long-option-param-without-short-but-with-desc', 'Description of the long long param') { options[:long_long_option_param_without_short_but_with_desc] = true } 68 | end 69 | 70 | s = o.summarize 71 | 72 | assert_match(/^\s*--long-long-option-param-without-short$/, s[0]) 73 | assert_match(/^\s*Error desc$/, s[1]) 74 | assert_match(/^\s*--long-option-param\s+Long desc$/, s[2]) 75 | assert_match(/^\s*-a\s+Normal description$/, s[3]) 76 | assert_match(/^\s*--long-long-option-param-with-short$/, s[4]) 77 | 78 | assert_match(/^\s*--long-long-option-param-without-short-but-with-desc$/, s[5]) 79 | assert_match(/^\s*Description of the long long param$/, s[6]) 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /test/optparse/test_zsh_completion.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'optparse' 4 | 5 | class TestOptionParserZshCompletion < Test::Unit::TestCase 6 | def setup 7 | @opt = OptionParser.new 8 | @opt.define("-z", "zzz") {} 9 | @opt.define("--foo") {} 10 | @opt.define("--bar=BAR") {} 11 | @opt.define("--for=TYPE", [:hello, :help, :zot]) {} 12 | end 13 | 14 | def test_compsys 15 | compsys = @opt.compsys("", "zshcompsys") 16 | assert_match(/\"-z\[zzz\]\"/, compsys) 17 | assert_match(/\"--foo\[\]\"/, compsys) 18 | assert_match(/\"--bar\[\]\"/, compsys) 19 | assert_match(/\"--for\[\]\"/, compsys) 20 | end 21 | end 22 | --------------------------------------------------------------------------------