{"id":15406770,"url":"https://github.com/dannyben/mister_bin","last_synced_at":"2025-04-14T13:12:20.935Z","repository":{"id":31851442,"uuid":"129512123","full_name":"DannyBen/mister_bin","owner":"DannyBen","description":"Build modular command line tools","archived":false,"fork":false,"pushed_at":"2025-02-06T10:27:31.000Z","size":1455,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T09:54:56.345Z","etag":null,"topics":["cli","cli-framework","docopt","gem","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/DannyBen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/demo/.gitignore","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-14T11:48:45.000Z","updated_at":"2025-02-06T10:27:34.000Z","dependencies_parsed_at":"2024-01-08T18:32:38.601Z","dependency_job_id":"101f7e5a-c660-4658-8f5f-01f17b8b5bb7","html_url":"https://github.com/DannyBen/mister_bin","commit_stats":{"total_commits":158,"total_committers":2,"mean_commits":79.0,"dds":"0.37341772151898733","last_synced_commit":"35a19df2c1c3536ae54d5f149d6f169f348f5f5d"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DannyBen%2Fmister_bin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DannyBen%2Fmister_bin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DannyBen%2Fmister_bin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DannyBen%2Fmister_bin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DannyBen","download_url":"https://codeload.github.com/DannyBen/mister_bin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248886325,"owners_count":21177644,"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":["cli","cli-framework","docopt","gem","ruby"],"created_at":"2024-10-01T16:25:18.596Z","updated_at":"2025-04-14T13:12:20.868Z","avatar_url":"https://github.com/DannyBen.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mister Bin\n\n[![Gem Version](https://badge.fury.io/rb/mister_bin.svg)](https://badge.fury.io/rb/mister_bin)\n[![Build Status](https://github.com/DannyBen/mister_bin/workflows/Test/badge.svg)](https://github.com/DannyBen/mister_bin/actions?query=workflow%3ATest)\n[![Maintainability](https://api.codeclimate.com/v1/badges/ae82443a99c2839d8ba8/maintainability)](https://codeclimate.com/github/DannyBen/mister_bin/maintainability)\n\n---\n\nMister Bin lets you develop rich, scalable and testable command line \ninterfaces for your gem or other Ruby application.\n\n---\n\n## Installation\n\n```\n$ gem install mister_bin\n```\n\n## Feature Highlights\n\n- Easy to use and minimalistic DSL for describing your command line actions.\n- Each command is defined with a separate class for maximum testability and \n  scalability.\n- Commands can have subcommands.\n- Commands can have aliases.\n- Designed primarily for gem developers.\n\n## Examples\n\nThis screencast shows the command line output of several Ruby gems that were\ncreated with Mister Bin:\n\n![Demo](support/demo/cast.gif)\n\n- See the [examples](/examples) folder for several example use cases.\n- For real world examples, see the [In the Wild](#in-the-wild) section.\n\n## Usage\n\nCreating a command line utility with Mister Bin involves at least two files:\n\n1. The main \"bin\" file. This is the actual executable, and if you are \n   developing a gem, this will be in the `bin` directory of your folder.\n2. One or more subcommand files. These files use the DSL, and will usually be\n   placed in your `lib/\u003cyour gem\u003e/commands` folder.\n\nWhen executing the commands, you can use only the first letters of the \ncommand name. Mister Bin will search for the command that starts with your \ninput, and if it finds one and one only, it will execute it. For example, \nif you have a `server` command, you can execute it with `yourapp s` if it\nis the only command that starts with an `s`.\n\n## Creating the Main Executable\n\nThe main executable is usually simple and only serves to initialize Mister \nBin with options.\n\nThis is the minimal code:\n\n```ruby\n#!/usr/bin/env ruby\nrunner = MisterBin::Runner.new\n\nrunner.route 'dir',   to: DirCommand\nrunner.route 'greet', to: GreetCommand\n\nexit runner.run ARGV\n```\n\n### Runner Options\n\nThe `Runner` object accepts an optional hash of options:\n\n```ruby\nrunner = MisterBin::Runner.new version: '1.2.3',\n  header: 'My command line app'\n  footer: 'Use --help for additional info',\n```\n\n#### `version`\n\nVersion number to display when running the main executable with `--version`.\n\n#### `header`\n\nText to display before the list of commands.\n\n#### `footer`\n\nText to display after the list of commands.\n\n#### `commands`\n\nA hash of `{ 'command_name' =\u003e ClassName }` to serve as command routes.\nThis is equivalent to adding routes later with \n`runner.route 'command_name', to: ClassName`.\n\n\n#### `handler`\n\nProvide a single handler to all commands. When this is provided, `commands`\nare ignored.\nThis is equivalent to using `runner.route_all to: ClassName`.\n\n\n### Runner Routes\n\nThe `Runner` object needs to be told how to route commands that are executed\nin the command line.\n\nUse the `#route` method as follows:\n\n```ruby\nrunner = MisterBin::Runner.new\nrunner.route \u003ccommand_name\u003e, to: \u003cClass Name\u003e\n```\n\nfor example:\n\n```ruby\nrunner = MisterBin::Runner.new\nrunner.route 'dir', to: DirCommand\nrunner.route 'greet', to: GreetCommand\nrunner.route 'config', to: ConfigCommand\n```\n\nThe first argument to the `route` method can be an array. In this case, the\nfirst element of the array will be considered the primary command name, and the\nother elements will be considered aliases.\n\n```ruby\nrunner = MisterBin::Runner.new\nrunner.route %w[dir ls list], to: DirCommand\n```\n\nIf you wish to route all commands to the same class, you can use:\n\n```ruby\nrunner = MisterBin::Runner.new\nrunner.route_all to: \u003cClass Name\u003e\n```\n\nfor example:\n\n```ruby\nrunner = MisterBin::Runner.new\nrunner.route_all to: GlobalCommand\n```\n\n## Creating Commands\n\nCreate command classes by inheriting from `MisterBin::Command`, for example:\n\n```ruby\nrequire 'mister_bin'\n\nclass GreetCommand \u003c MisterBin::Command\n  summary \"Say hi\"\n  usage \"app greet [NAME]\"\n  param \"NAME\", \"The recipient of the greeting\"\n\n  def run\n    # args hash is available everywhere in the class\n    name = args['NAME'] || 'Luke'\n    puts \"#{name}... I am your father...\"\n  end\nend\n```\n\nThese classes can use any of the below DSL commands, and must define a\n`def run(args)` method.\n\n\n### Command DSL\n\nThe DSL is designed to create a [docopt] document. Most commands are \noptional.\n\nThe below example outlines all available DSL commands.\n\n\n```ruby\n# Optional summary string\nsummary \"A short sentence or paragraph describing the command\"\n\n# Optional help string\nhelp \"A longer explanation can go here\"\n\n# Optional version string for the command\nversion \"0.1.1\"\n\n# Usage patterns. You can use either a compact docopt notation, or provide\n# multiple usage calls.\nusage \"app ls\"\nusage \"app ls [--all]\"\nusage \"app new NAME\"\n\n# Describe any subcommands\n# Note that this has an additional important use:\n# - For each command defined with the `command` directive, we will search \n#   for a method with the same name and a `_command` suffix.\n# - If no such method is found, we will call the generic `run` method.\ncommand \"ls\", \"Show list of files\"\ncommand \"new\", \"Pretend to create a new application\"\n\n# Describe any flags\noption \"--all\", \"Also show hidden files\"\noption \"-f --force\", \"Force delete\"\n\n# Describe any parameters\nparam \"NAME\", \"The name of the repository\"\n\n# Describe any environment variables that your app cares about\nenvironment \"SECRET\", \"There is no spoon\"\n\n# Provide examples\nexample \"app ls\"\nexample \"app ls --all\"\n```\n\n## Interactive Terminal\n\nMister Bin comes with an interactive terminal that allows you to set up a\nconsole that sends all commands to your runner.\n\n![Demo](support/demo/terminal.gif)\n\nSee the [terminal example](/examples/06-terminal) folder.\n\nIn order to start a terminal, you need to provide it with a \n`MisterBin::Runner` object:\n\n```ruby\nrunner = MisterBin::Runner.new \nrunner.route 'greet', to: GreetCommand\nterminal = MisterBin::Terminal.new runner\nterminal.start\n```\n\n### Terminal features\n\n- All commands will be routed to the runner.\n- Customizable autocomplete.\n- Command history (up/down arrows).\n- Start a command with a `/` in order to run a system (shell) command.\n- Type `exit` to quit (or Ctrl+D or Ctrl+C).\n- Customizable header, exit message, exit command and prompt.\n\n\n### Terminal options\n\nThe `MisterBin::Terminal.new` command accepts an optional second argument. If \nprovided, it should be a options hash:\n\n```ruby\nterminal = MisterBin::Terminal.new runner, {\n  header: \"Welcome\",\n  autocomplete: %w[--help greet]\n}\n```\n\nIn addition, you may wish to provide your own code blocks for handling some\ncommands that are not handled by your runner. For example, this piece of code\nwill capture the `/cd ...` command from the terminal and pass it to your \nblock:\n\n```ruby\nterminal = MisterBin::Terminal.new runner\nterminal.on '/cd' do |args|\n  Dir.chdir args[0] if args[0]\n  puts Dir.pwd\nend\n```\n\nThese are the available options. All string options are displayed with \nthe [Colsole] `say` command so they support color markers.\n\n#### `header`\n\nMessage to show when starting the terminal.\nDefault: blank.\n\n#### `show_usage`\n\nIf true, the runner will be executed on startup to show its usage patterns.\nDefault: `false`.\n\n#### `prompt`\n\nThe string for the prompt. Default: `\"\\n\u003e \"`.\n\n#### `autocomplete`\n\nAn array of words to autocomplete by pressing Tab.\nDefault: none.\n\n#### `exit_message`\n\nThe message to show on exit.\nDefault: blank.\n\n#### `exit_commands`\n\nAn array of commands that if typed, will exit the terminal.\nDefault: `[\"exit\", \"q\"]`.\n\n#### `system_character`\n\nThe prefix character that if typed at the beginning of a command, will avoid\nexecuting the runner, and instead execute a system (shell) command. \nDefault: `\"/\"`.\n\n#### `disable_system_shell`\n\nIf true, commands that start with `/` will *not* be delegated to the stsrem.\nDefault: `false`.\n\n\n## In the Wild\n\nSeveral examples of real world use of Mister Bin in the wild (well, \n\"In the Back Yard\" really...).\n\n- [AudioAddict] - Command line utility for the AudioAddict radio network\n- [Bashly] - Bash command line framework and CLI Generator\n- [Jobly] - Compact job server with API, CLI and Web UI\n- [Kojo] - Command line utility for generating config files from templates and definition files\n- [Madman] - The Markdown Swiss Army Knife\n- [Madness] - Instant Markdown Server\n- [Slacktail] - Command line utility for following your Slack chat from the terminal\n- [Site Link Analyzer] - Command line utility for finding broken links in a site\n\n\n[AudioAddict]: https://github.com/DannyBen/audio_addict\n[Bashly]: https://github.com/DannyBen/bashly\n[Colsole]: https://github.com/dannyben/colsole\n[docopt]: http://docopt.org/\n[Jobly]: https://github.com/dannyben/jobly\n[Kojo]: https://github.com/DannyBen/kojo\n[Madman]: https://github.com/DannyBen/madman\n[Madness]: https://github.com/DannyBen/madness\n[Site Link Analyzer]: https://github.com/dannyben/sla\n[Slacktail]: https://github.com/dannyben/slacktail\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdannyben%2Fmister_bin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdannyben%2Fmister_bin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdannyben%2Fmister_bin/lists"}