Code Monkey home page Code Monkey logo

bales's Introduction

Ruby on Bales

bales

What is it?

It's a framework for writing command-line applications.

What does it look like?

Why, like this!

#!/usr/bin/env ruby
# /usr/local/bin/simple-app
require 'bales'

module SimpleApp
  class Application < Bales::Application
    version "0.0.1"
    description "Sample app"
    
    # Default action
    option :recipient,
           long_form: '--to',
           short_form: '-2',
           type: String
           
    action do |recipient: "world"|
      puts "Hello, #{recipient}!"
    end
    
    # Subcommand
    command "smack" do
      option :weapon,
             type: String,
             description: "Thing to smack with",
             short_form: '-w',
             long_form: '--with'
             
      action do |*victims, weapon: nil|
        suffix = weapon ? " with a #{weapon}" : ""
        
        if victims.none?
          puts "You have been smacked#{suffix}."
        else
          victims.each {|v| puts "#{v} has been smacked#{suffix}."}
        end
      end
    end
    
    # Specify subcommand's parent class
    command "help", parent: Bales::Command::Help
    
    # Subsubcommands!
    command "smack with" do
      action do |weapon, *victims|
        SimpleApp::Command::Smack.run(*victims, weapon: weapon)
      end
    end
    
    # This is what makes the app actually run!
    parse_and_run
  end
end

SimpleApp::Application.parse_and_run

And like this (assuming the above script lives in /usr/local/bin/simple-app)!

$ simple-app
Hello, world!
$ simple-app -2 Bruce
Hello, Bruce!
$ simple-app --to Bruce
Hello, Bruce!
$ simple-app smack
You have been smacked.
$ simple-app smack Bruce
Bruce has been smacked.
$ simple-app smack Bruce Bruce
Bruce has been smacked.
Bruce has been smacked.
$ simple-app smack Bruce --with fish
Bruce has been smacked with a fish.
$ simple-app smack with fish Bruce
Bruce has been smacked with a fish.

So how does it work?

  • Come up with a name for your app, like MyApp

  • Create an Application class under that namespace which inherits from Bales::Application

  • Use the DSL (or define classes manually, if that's your thing)

Basically, a Bales app is just a bunch of classes with some fairy dust that turns them into runnable commands. Bales will check the namespace that your subclass of Bales::Application lives in for a Command namespace, then search there for available commands.

The application has a few available DSL-ish functions for you to play with.

  • version: sets your app's version number. If you use semantic versioning, you can query this with the major_version, minor_version, and patch_level class methods.

  • command "foo" { ... }: defines a subcommand called "foo", which turns into a class called MyApp::Command::Foo (if you picked the name MyApp above). If you provide a block, said block will be evaluated in the class' context (see below for things you can do in said context).

Meanwhile, commands also have some DSL-ish functions to play around with.

  • option: defines a command-line option, like --verbose or -f or something. It takes the name of the option (which becomes a key in your command's options hash) and some named parameters:

    • :type: a valid Ruby class, like String. For a boolean, you should provide either TrueClass or FalseClass, which - when set - will set the option in question to true or false (respectively).

    • :short_form: a short flag, like '-v'. You must specify this if you want a short flag.

    • :long_form: a long flag, like '--verbose'. This will be created from the option's name if you don't override it here.

    • :description: a quick description of the option, like "Whether or not to be verbose".

  • action: defines what the command should do when it's called. This is provided in the form of a block. Said block should accept two arguments (an array of arguments and a hash of options), though you don't have to name them with pipes and stuff if you know that your command won't take any arguments or options.

  • description: sets a long description of what your command does. Should be a string.

  • summary: sets a short description of what your command does. Should be a string. Should also be shorter than :description, though this isn't strictly necessary.

Some of the command functions (option, action, description, summary) can also be used from within the application class; doing so will define and configure a "root command", which is what is run if you run your app without any arguments.

What can this thing already do?

  • Create a working command-line app

  • Automatically produce subcommands (recursively, in fact) based on the namespaces of the corresponding Bales::Command subclasses

  • Provide a DSL defining commands and options

What might this thing someday do in the future?

  • Provide some helpers to wrap things like HighLine, curses, etc.

  • Provide some additional flexibility in how options are specified without requiring users to completely reimplement a command's option parsing functions

What kind of a silly name is "Bales", anyway?

It's shamelessly stolen^H^H^H^H^H^Hborrowed from Jason R. Clark's "Testing the Multiverse" talk at Ruby on Ales 2015 (which, if you haven't watched, you totally should). Sorry, Jason. Hope you don't mind.

Ironically enough, despite ripping off the name from a talk about Ruby testing, Bales currently lacks any formal test suite. Hm...

What's the license?

MIT License; see COPYING for details.

bales's People

Contributors

yellowapple avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

wfschmitt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.