{"id":13463069,"url":"https://github.com/mdub/clamp","last_synced_at":"2025-05-15T03:06:05.676Z","repository":{"id":1150914,"uuid":"1034672","full_name":"mdub/clamp","owner":"mdub","description":"a Ruby command-line application framework","archived":false,"fork":false,"pushed_at":"2022-09-17T00:13:08.000Z","size":494,"stargazers_count":424,"open_issues_count":3,"forks_count":52,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-13T13:41:25.557Z","etag":null,"topics":["command-line","command-line-parser","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdub.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null}},"created_at":"2010-10-29T11:36:06.000Z","updated_at":"2025-05-12T11:26:01.000Z","dependencies_parsed_at":"2022-08-06T10:15:34.059Z","dependency_job_id":null,"html_url":"https://github.com/mdub/clamp","commit_stats":null,"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fclamp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fclamp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fclamp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fclamp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdub","download_url":"https://codeload.github.com/mdub/clamp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254020638,"owners_count":22000755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line","command-line-parser","ruby"],"created_at":"2024-07-31T13:00:45.429Z","updated_at":"2025-05-15T03:06:05.649Z","avatar_url":"https://github.com/mdub.png","language":"Ruby","readme":"# Clamp\n\n[![Gem Version](https://badge.fury.io/rb/clamp.png)](http://badge.fury.io/rb/clamp)\n[![Build Status](https://secure.travis-ci.org/mdub/clamp.png?branch=master)](http://travis-ci.org/mdub/clamp)\n\n\"Clamp\" is a minimal framework for command-line utilities.\n\nIt handles boring stuff like parsing the command-line, and generating help, so you can get on with making your command actually do stuff.\n\n## Not another one!\n\nYeah, sorry.  There are a bunch of existing command-line parsing libraries out there, and Clamp draws inspiration from a variety of sources, including [Thor], [optparse], and [Clip].  In the end, though, I wanted a slightly rounder wheel.  (Although, Clamp has a _lot_ in common with Ara T. Howard's [main.rb]. Had I been aware of that project at the time, I might not have written Clamp.)\n\n[optparse]: http://ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html\n[Thor]: http://github.com/wycats/thor\n[Clip]: http://clip.rubyforge.org/\n[main.rb]: https://github.com/ahoward/main\n\n## Quick Start\n\nA typical Clamp script looks like this:\n\n```ruby\nrequire 'clamp'\n\nClamp do\n\n  option \"--loud\", :flag, \"say it loud\"\n  option [\"-n\", \"--iterations\"], \"N\", \"say it N times\", default: 1 do |s|\n    Integer(s)\n  end\n\n  parameter \"WORDS ...\", \"the thing to say\", attribute_name: :words\n\n  def execute\n    the_truth = words.join(\" \")\n    the_truth.upcase! if loud?\n    iterations.times do\n      puts the_truth\n    end\n  end\n\nend\n```\n\nInternally, Clamp models a command as a Ruby class (a subclass of `Clamp::Command`), and a command execution as an instance of that class.  The example above is really just syntax-sugar for:\n\n```ruby\nrequire 'clamp'\n\nclass SpeakCommand \u003c Clamp::Command\n\n  option \"--loud\", :flag, \"say it loud\"\n  option [\"-n\", \"--iterations\"], \"N\", \"say it N times\", default: 1 do |s|\n    Integer(s)\n  end\n\n  parameter \"WORDS ...\", \"the thing to say\", attribute_name: :words\n\n  def execute\n    the_truth = words.join(\" \")\n    the_truth.upcase! if loud?\n    iterations.times do\n      puts the_truth\n    end\n  end\n\nend\n\nSpeakCommand.run\n```\n\nClass-level methods like `option` and `parameter` declare attributes, in a similar way to `attr_accessor`, and arrange for them to be populated automatically based on command-line arguments.  They are also used to generate `help` documentation.\n\nThere are more examples demonstrating various features of Clamp [on Github][examples].\n\n[examples]: https://github.com/mdub/clamp/tree/master/examples\n\n## Declaring options\n\nOptions are declared using the `option` method.  The three required arguments are:\n\n  1. the option switch (or switches),\n  2. an option argument name\n  3. a short description\n\nFor example:\n\n```ruby\noption \"--flavour\", \"FLAVOUR\", \"ice-cream flavour\"\n```\n\nIt works a little like `attr_accessor`, defining reader and writer methods on the command class.  The attribute name is inferred from the switch (in this case, \"`flavour`\").  When you pass options to your command, Clamp will populate the attributes, which are then available for use in your `#execute` method.\n\n```ruby\ndef execute\n  puts \"You chose #{flavour}.  Excellent choice!\"\nend\n```\n\nIf you don't like the inferred attribute name, you can override it:\n\n```ruby\noption \"--type\", \"TYPE\", \"type of widget\", attribute_name: :widget_type\n                                           # to avoid clobbering Object#type\n```\n\n### Short/long option switches\n\nThe first argument to `option` can be an array, rather than a single string, in which case all the switches are treated as aliases:\n\n```ruby\noption [\"-s\", \"--subject\"], \"SUBJECT\", \"email subject line\"\n```\n\n### Flag options\n\nSome options are just boolean flags.  Pass \"`:flag`\" as the second parameter to tell Clamp not to expect an option argument:\n\n```ruby\noption \"--verbose\", :flag, \"be chatty\"\n```\n\nFor flag options, Clamp appends \"`?`\" to the generated reader method; ie. you get a method called \"`#verbose?`\", rather than just \"`#verbose`\".\n\nNegatable flags are easy to generate, too:\n\n```ruby\noption \"--[no-]force\", :flag, \"be forceful (or not)\"\n```\n\nClamp will handle both \"`--force`\" and \"`--no-force`\" options, setting the value of \"`#force?`\" appropriately.\n\n### Required options\n\nAlthough \"required option\" is an oxymoron, Clamp lets you mark an option as required, and will verify that a value is provided:\n\n```ruby\noption \"--password\", \"PASSWORD\", \"the secret password\", required: true\n```\n\nNote that it makes no sense to mark a `:flag` option, or one with a `:default`, as `:required`.\n\n### Multivalued options\n\nDeclaring an option \"`:multivalued`\" allows it to be specified multiple times on the command line.\n\n```ruby\noption \"--format\", \"FORMAT\", \"output format\", multivalued: true\n```\n\nThe underlying attribute becomes an Array, and the suffix \"`_list`\" is appended to the default attribute name.  In this case, an attribute called \"`format_list`\" would be generated (unless you override the default by specifying an `:attribute_name`).\n\n### Hidden options\n\nDeclaring an option \"`:hidden`\" will cause it to be hidden from `--help` output.\n\n```ruby\noption \"--some-option\", \"VALUE\", \"Just a little option\", hidden: true\n```\n\n### Version option\n\nA common idiom is to have an option `--version` that outputs the command version and doesn't run any subcommands.  This can be achieved by:\n\n```ruby\noption \"--version\", :flag, \"Show version\" do\n  puts MyGem::VERSION\n  exit(0)\nend\n```\n\n## Declaring parameters\n\nPositional parameters can be declared using `parameter`, specifying\n\n  1. the parameter name, and\n  2. a short description\n\nFor example:\n\n```ruby\nparameter \"SRC\", \"source file\"\n```\n\nLike options, parameters are implemented as attributes of the command, with the default attribute name derived from the parameter name (in this case, \"`src`\"). By convention, parameter names are specified in uppercase, to make them obvious in usage help.\n\n### Optional parameters\n\nWrapping a parameter name in square brackets indicates that it's optional, e.g.\n\n```ruby\nparameter \"[TARGET_DIR]\", \"target directory\"\n```\n\n### Multivalued (aka \"greedy\") parameters\n\nThree dots at the end of a parameter name makes it \"greedy\" - it will consume all remaining command-line arguments.  For example:\n\n```ruby\nparameter \"FILE ...\", \"input files\", attribute_name: :files\n```\n\nLike multivalued options, greedy parameters are backed by an Array attribute (named with a \"`_list`\" suffix, by default).\n\n## Parsing and validation of options and parameters\n\nWhen you `#run` a command, it will first attempt to `#parse` command-line arguments, and map them onto the declared options and parameters, before invoking your `#execute` method.\n\nClamp will verify that all required (ie. non-optional) parameters are present, and signal a error if they aren't.\n\n### Validation\n\nBoth `option` and `parameter` accept an optional block.  If present, the block will be\ncalled with the raw string argument, and is expected to validate it.  The value returned by the block will be assigned to the underlying attribute, so it's also a good place to coerce the String to a different type, if appropriate.\n\nFor example:\n\n```ruby\noption \"--port\", \"PORT\", \"port to listen on\" do |s|\n  Integer(s)\nend\n```\n\nIf the block raises an ArgumentError, Clamp will catch it, and report that the value was bad:\n\n```ruby\n!!!plain\nERROR: option '--port': invalid value for Integer: \"blah\"\n```\n\nFor multivalued options and parameters, the validation block will be called for each value specified.\n\nMore complex validation, e.g. those involving multiple options/parameters, should be performed within the `#execute` method.  Use `#signal_usage_error` to tell the user what they did wrong, e.g.\n\n```ruby\ndef execute\n  if port \u003c 1024 \u0026\u0026 user != 'root'\n    signal_usage_error \"port restricted for non-root users\"\n  end\n  # ... carry on ...\nend\n```\n\n### Advanced option/parameter handling\n\nWhile Clamp provides an attribute-writer method for each declared option or parameter, you always have the option of overriding it to provide custom argument-handling logic, e.g.\n\n```ruby\nparameter \"SERVER\", \"location of server\"\n\ndef server=(server)\n  @server_address, @server_port = server.split(\":\")\nend\n```\n\n### Default values\n\nDefault values can be specified for options, and optional parameters:\n\n```ruby\noption \"--flavour\", \"FLAVOUR\", \"ice-cream flavour\", default: \"chocolate\"\n\nparameter \"[HOST]\", \"server host\", default: \"localhost\"\n```\n\nFor more advanced cases, you can also specify default values by defining a method called \"`default_#{attribute_name}`\":\n\n```ruby\noption \"--http-port\", \"PORT\", \"web-server port\", default:  9000\n\noption \"--admin-port\", \"PORT\", \"admin port\"\n\ndef default_admin_port\n   http_port + 1\nend\n```\n\n### Environment variable support\n\nOptions (and optional parameters) can also be associated with environment variables:\n\n```ruby\noption \"--port\", \"PORT\", \"the port to listen on\", environment_variable: \"MYAPP_PORT\" do |val|\n  val.to_i\nend\n\nparameter \"[HOST]\", \"server address\", environment_variable: \"MYAPP_HOST\"\n```\n\nClamp will check the specified envariables in the absence of values supplied on the command line, before looking for a default value.\n\n### Allowing options after parameters\n\nBy default, Clamp only recognises options _before_ positional parameters.\n\nSome other option-parsing libraries - notably [GNU `getopt(3)`](https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html) - allow option and parameter arguments to appear in any order on the command-line, e.g.\n\n    foobar --foo=bar something --fnord=snuffle another-thing\n\nIf you want Clamp to allow options and parameters to be \"interspersed\" in this way, set:\n\n```ruby\nClamp.allow_options_after_parameters = true\n```\n\n## Declaring Subcommands\n\nSubcommand support helps you wrap a number of related commands into a single script (ala tools like \"`git`\").  Clamp will inspect the first command-line argument (after options are parsed), and delegate to the named subcommand.\n\nUnsuprisingly, subcommands are declared using the `subcommand` method. e.g.\n\n```ruby\nClamp do\n\n  subcommand \"init\", \"Initialize the repository\" do\n\n    def execute\n      # ...\n    end\n\n  end\n\nend\n```\n\nClamp generates an anonymous subclass of the current class, to represent the subcommand.  Alternatively, you can provide an explicit subcommand class:\n\n```ruby\nclass MainCommand \u003c Clamp::Command\n\n  subcommand \"init\", \"Initialize the repository\", InitCommand\n\nend\n\nclass InitCommand \u003c Clamp::Command\n\n  def execute\n    # ...\n  end\n\nend\n```\n\nLike options, subcommands may have aliases:\n\n```ruby\nClamp do\n\n  subcommand [\"initialize\", \"init\"], \"Initialize the repository\" do\n    # ...\n  end\n\nend\n```\n\n### Default subcommand\n\nYou can set a default subcommand, at the class level, as follows:\n\n```ruby\nClamp do\n\n  self.default_subcommand = \"status\"\n\n  subcommand \"status\", \"Display current status\" do\n\n    def execute\n      # ...\n    end\n\n  end\n\nend\n```\n\nThen, if when no SUBCOMMAND argument is provided, the default will be selected.\n\n### Subcommand options and parameters\n\nOptions are inheritable, so any options declared for a command are supported by it's sub-classes (e.g. those created using the block form of `subcommand`).  Parameters, on the other hand, are not inherited - each subcommand must declare it's own parameter list.\n\nNote that, if a subcommand accepts options, they must be specified on the command-line _after_ the subcommand name.\n\nYou can define a `subcommand_missing` method that is called when user tries to run an unknown subcommand:\n\n```ruby\nClamp do\n  def subcommand_missing(name)\n    if name == \"foo\"\n      return Object.const_get(:FooPlugin) if Object.const_defined?(:FooPlugin)\n      abort \"Subcommand 'foo' requires plugin X\"\n    end\n  end\nend\n```\n\n## Getting help\n\nAll Clamp commands support a \"`--help`\" option, which outputs brief usage documentation, based on those seemingly useless extra parameters that you had to pass to `option` and `parameter`.\n\n```sh\n$ speak --help\nUsage:\n    speak [OPTIONS] WORDS ...\n\nArguments:\n    WORDS ...                     the thing to say\n\nOptions:\n    --loud                        say it loud\n    -n, --iterations N            say it N times (default: 1)\n    -h, --help                    print help\n```\n\n## Localization\n\nClamp comes with support for overriding strings with custom translations. You can use localization library of your choice and override the strings at startup.\n\nExample usage:\n\n```ruby\nrequire 'gettext'\n\nClamp.messages = {\n  too_many_arguments:        _(\"too many arguments\"),\n  option_required:           _(\"option '%\u003coption\u003es' is required\"),\n  option_or_env_required:    _(\"option '%\u003coption\u003es' (or env %\u003cenv\u003es) is required\"),\n  option_argument_error:     _(\"option '%\u003cswitch\u003es': %\u003cmessage\u003es\")\n  # ...\n}\n```\n\nSee [messages.rb](https://github.com/mdub/clamp/blob/master/lib/clamp/messages.rb) for full list of available messages.\n\n## License\n\nCopyright (C) 2011 [Mike Williams](mailto:mdub@dogbiscuit.org)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\nTHE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Contributing to Clamp\n\nSource-code for Clamp is [on Github](https://github.com/mdub/clamp).\n","funding_links":[],"categories":["Developer Tools","Ruby","CLI Builder","[Ruby](https://www.ruby-lang.org/)"],"sub_categories":["CLI Option Parsers","Useful awesome list for Go cli"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdub%2Fclamp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdub%2Fclamp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdub%2Fclamp/lists"}