• Stars
    star
    12
  • Rank 1,597,165 (Top 32 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 7 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Object-oriented OptionParser based CLI support for rapid CLI development

Cl Build Status Code Climate Code Coverage Gem Version Rubydocs

OptionParser based CLI support for rapid CLI development in an object-oriented context.

This library wraps Ruby's OptionParser for parsing your options under the hood, so you get all the goodness that the Ruby standard library provides.

On top of that it adds a rich and powerful DSL for defining, validating, and normalizing options, as well as automatic and gorgeous help output (modeled after gem --help).

Further documentation is available on rubydoc.info

Examples in this README are included from examples/readme. More examples can be found in examples. All examples are guaranteed to be up to date by the way of being verified on CI.

Table of Contents

Basic Usage

module Owners
  class Add < Cl::Cmd
    register :add

    summary 'Add one or more owners to an existing owner group'

    description <<~str
      Use this command to add one or more owners to an existing
      owner group.

      [...]
    str

    args :owner

    opt '-t', '--to TO', 'An existing owner group'

    def run
      # implement adding the owner as given in `owner` (as well as `args`)
      # to the group given in `to` (as well as `opts[:to]`).
      p owner: owner, to: to, to?: to?, args: args, opts: opts
    end
  end
end

# Running this, e.g. using `bin/owners add one,two --to group` will instantiate the
# class `Owners::Add`, and call the method `run` on it.

# e.g. bin/owners
#
# args normally would be ARGV
args = %w(add one --to group)

Cl.new('owners').run(args)

# Output:
#
#   {:owner=>"one", :to=>"group", :to?=>true, :args=>["one"], :opts=>{:to=>"group"}}

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [owner] [options]
#
#   Summary:
#
#     Add one or more owners to an existing owner group
#
#   Description:
#
#     Use this command to add one or more owners to an existing
#     owner group.
#
#     [...]
#
#   Arguments:
#
#     owner           type: string
#
#   Options:
#
#     -t --to TO      An existing owner group (type: string)
#        --help       Get help on this command

Command Registry

Commands are Ruby classes that extend the class Cl::Cmd.

They register to a Ruby class registry in order to decouple looking up command classes from their Ruby namespace.

For example:

module Cmd
  class One < Cl::Cmd
    register :one
  end

  class Two < Cl::Cmd
    register :two
  end
end

p Cl::Cmd[:one] # => Cmd::One
p Cl::Cmd[:two] # => Cmd::Two

Commands can be registered like so:

module One
  class Cmd < Cl::Cmd
    register :'cmd:one'
  end
end

By default commands auto register themselves with the underscored name of the last part of their class name (as seen in the example above). It is possible to turn this off using:

Cl::Cmd.auto_register = false

Command auto-registration can cause name clashes when namespaced commands have the same demodulized class name. For example:

class Git < Cl::Cmd
  # auto-registers as :git
end

module Heroku
  class Git < Cl::Cmd
    # also auto-registers as :git
  end
end

It is recommended to turn auto-registration off when using such module structures.

Runners

Runners lookup the command to execute from the registry, by checking the arguments given by the user for registered command keys.

With the two command classes One and Two from the example above (and assuming that the executable that calls Cl is bin/run) the default runner would recognize and run the following commands:

$ bin/run one something else
# instantiates One, passing the args array `["something", "else"]`, and calls the instance method `run`

$ bin/run two
# instantiates Two, passing an empty args arry `[]`, and calls the instance method `run`

The default runner also supports nested namespaces, and checks for command classes with keys separated by colons. For instance:

module Git
  class Pull < Cl::Cmd
    register :'git:pull'

    arg :branch

    def run
      p cmd: registry_key, args: args
    end
  end
end

# With this class registered (and assuming the executable that calls `Cl` is
# `bin/run`) the default runner would recognize and run it:
#
# $ bin/run git:pull master # instantiates Git::Pull, and passes ["master"] as args
# $ bin/run git pull master # does the same

Cl.new('run').run(%w(git:pull master))
# Output:
#
#   {:cmd=>:"git:pull", :args=>["master"]}

Cl.new('run').run(%w(git pull master))
# Output:
#
#   {:cmd=>:"git:pull", :args=>["master"]}

Runners are registered on the module Cl::Runner. It is possible to register custom runners, and use them by passing the option runner to Cl.new:

module Git
  class Pull < Cl::Cmd
    register :'git:pull'

    arg :branch

    def run
      p cmd: registry_key, args: args
    end
  end
end

# With this class registered (and assuming the executable that calls `Cl` is
# `bin/run`) the default runner would recognize and run it:
#
# $ bin/run git:pull master # instantiates Git::Pull, and passes ["master"] as args
# $ bin/run git pull master # does the same

Cl.new('run').run(%w(git:pull master))
# Output:
#
#   {:cmd=>:"git:pull", :args=>["master"]}

Cl.new('run').run(%w(git pull master))
# Output:
#
#   {:cmd=>:"git:pull", :args=>["master"]}

See Cl::Runner::Default for more details.

There also is an experimental runner :multi, which supports rake-style execution of multiple commands at once, like so:

bin/rake db:drop production -f db:create db:migrate production -v 1

See the example rakeish for more details.

Command DSL

The DSL is defined on the class body.

Commands

Commands are classes that are derived from the base class Cl::Cmd.

Description, Summary, Examples

The description, summary, and examples are used in the help output.

module Owners
  class Add < Cl::Cmd
    register :add

    summary 'Add one or more owners to an existing owner group'

    description <<~str
      Use this command to add one or more owners to an existing
      owner group.
    str

    examples <<~str
      Adding a single user to the group admins:

        owners add user --to admins

      Adding a several users at once:

        owners add one two three --to admins
    str
  end
end

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [options]
#
#   Summary:
#
#     Add one or more owners to an existing owner group
#
#   Description:
#
#     Use this command to add one or more owners to an existing
#     owner group.
#
#   Options:
#
#     --help      Get help on this command
#
#   Examples:
#
#     Adding a single user to the group admins:
#
#       owners add user --to admins
#
#     Adding a several users at once:
#
#       owners add one two three --to admins

Abstract

Command base classes can be declared abstract in order to prevent them from being identified as a runnable command and to omit them from help output.

This is only relevant if a command base class is registered. See Command Registry for details.

class Base < Cl::Cmd
  abstract
end

class Add < Base
  register :add

  def run
    puts 'Success'
  end
end

Cl.new('owners').run(%w(add))

# Output:
#
#   Success

Cl.new('owners').run(%w(base))

# Output:
#
#   Unknown command: base

Arguments

Arguments can be declared like so:

arg :arg_name, description: 'arg description', type: :[array|string|integer|float|boolean]

This will define an attr_accessor on the Cmd class. I.e. in the following example the method ownsers will be available on the Cmd instance:

class Add < Cl::Cmd
  register :add

  arg :owner

  def run
    p owner: owner
  end
end

Cl.new('owners').run(%w(add one))

# Output:
#
#   {:owner=>"one"}

Types

Arguments can have a type. Known types are: :array, :string, :integer, :float, :boolean.

The type :array makes sure the argument accessible on the Cmd instance is a Ruby Array. (This currently only supports arrays of strings).

If the option sep is given on the argument, then the argument value is split using this separator.

class Add < Cl::Cmd
  register :add

  arg :owners, type: :array, sep: ','

  def run
    p owners: owners
  end
end

Cl.new('owners').run(%w(add one,two))

# Output:
#
#   {:owners=>["one", "two"]}

Other types cast the given argument to the expected Ruby type.

class Cmd < Cl::Cmd
  register :cmd

  arg :one, type: :integer
  arg :two, type: :float
  arg :three, type: :boolean

  def run
    p [one.class, two.class, three.class]
  end
end

Cl.new('owners').run(%w(cmd 1 2.1 yes))

# Output:
#
#   [Integer, Float, TrueClass]

Splat

Array arguments support splats, modeled after Ruby argument splats.

For example:

class Lft < Cl::Cmd
  register :lft

  arg :a, type: :array, splat: true
  arg :b
  arg :c

  def run
    p [a, b, c]
  end
end

class Mid < Cl::Cmd
  register :mid

  arg :a
  arg :b, type: :array, splat: true
  arg :c

  def run
    p [a, b, c]
  end
end

class Rgt < Cl::Cmd
  register :rgt

  arg :a
  arg :b
  arg :c, type: :array, splat: true

  def run
    p [a, b, c]
  end
end

Cl.new('splat').run(%w(lft 1 2 3 4 5))

# Output:
#
#   [["1", "2", "3"], "4", "5"]

Cl.new('splat').run(%w(mid 1 2 3 4 5))

# Output:
#
#   ["1", ["2", "3", "4"], "5"]

Cl.new('splat').run(%w(rgt 1 2 3 4 5))

# Output:
#
#   ["1", "2", ["3", "4", "5"]]

Options

Declaring options can be done by calling the method opt on the class body.

This will add the option, if given by the user, to the hash opts on the Cmd instance. It also defines a reader method that returns the respective value from the opts hash, and a predicate that will be true if the option has been given.

For example:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', 'Target group to add owners to'

  def run
    p opts: opts, to: to, to?: to?
  end
end

Cl.new('owners').run(%w(add --to one))

# Output:
#
#   {:opts=>{:to=>"one"}, :to=>"one", :to?=>true}

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      Target group to add owners to (type: string)
#     --help          Get help on this command

Options optionally accept a block in case custom normalization is needed.

Depending on the block's arity the following arguments are passed to the block: option value, option name, option type, collection of all options defined on the command.

class Add < Cl::Cmd
  register :add

  # depending on its arity the block can receive:
  #
  # * value
  # * value, name
  # * value, name, type
  # * value, name, type, opts
  opt '--to GROUP' do |value|
    opts[:to] = "group-#{value}"
  end

  def run
    p to: to
  end
end

Cl.new('owners').run(%w(add --to one))

# Output:
#
#   {:to=>"group-one"}

Aliases

Options can have one or many alias names, given as a Symbol or Array of Symbols:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', alias: :group

  def run
    # p opts: opts, to: to, to?: to?, group: group, group?: group?
    p opts: opts, to: to, to?: to?
  end
end

Cl.new('owners').run(%w(add --group one))

# Output:
#
#   {:opts=>{:to=>"one", :group=>"one"}, :to=>"one", :to?=>true}

Defaults

Options can have a default value.

I.e. this value is going to be used if the user does not provide the option:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', default: 'default'

  def run
    p to: to
  end
end

Cl.new('owners').run(%w(add))

# Output:
#
#   {:to=>"default"}

Deprecations

Options, and option alias name can be deprecated.

For a deprecated option:

class Add < Cl::Cmd
  register :add

  opt '--target GROUP', deprecated: 'Deprecated.'

  def run
    p target: target, deprecations: deprecations
  end
end

Cl.new('owners').run(%w(add --target one))

# Output:
#
#   {:target=>"one", :deprecations=>{:target=>"Deprecated."}}

For a deprecated option alias name:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', alias: :target, deprecated: :target

  def run
    p to: to, deprecations: deprecations
  end
end

Cl.new('owners').run(%w(add --target one))

# Output:
#
#   {:to=>"one", :deprecations=>{:target=>:to}}

Downcase

Options can be declared to be downcased.

For example:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', downcase: true

  def run
    p to: to
  end
end

Cl.new('owners').run(%w(add --to ONE))

# Output:
#
#   {:to=>"one"}

Enum

Options can be enums (i.e. have known values).

If an unknown values is given by the user the parser will reject the option, and print the help output for this command.

For example:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', enum: %w(one two)

  def run
    p to: to
  end
end

Cl.new('owners').run(%w(add --to one))

# Output:
#
#   {:to=>"one"}

Cl.new('owners').run(%w(add --to unknown))

# Output:
#
#   Unknown value: to=unknown (known values: one, two)
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string, known values: one, two
#     --help          Get help on this command

Example

Options can have examples that will be printed in the help output.

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', example: 'group-one'
end

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string, e.g.: group-one
#     --help          Get help on this command

Format

Options can have a required format.

If a value is given by the user that does not match the format then the parser will reject the option, and print the help output for this command.

For example:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', format: /^\w+$/

  def run
    p to: to
  end
end

Cl.new('owners').run(%w(add --to one))

# Output:
#
#   {:to=>"one"}

Cl.new('owners').run(['add', '--to', 'does not match!'])

# Output:
#
#   Invalid format: to (format: /^\w+$/)
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string, format: /^\w+$/
#     --help          Get help on this command

Internal

Options can be declared to be internal, hiding the option from the help output.

For example:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP'
  opt '--hidden', internal: true
end

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string
#     --help          Get help on this command

Min and Max

Options can have mininum and/or maximum values.

If a value is given by the user that does not match the required min and/or max values then the parser will reject the option, and print the help output for this command.

For example:

class Add < Cl::Cmd
  register :add

  opt '--retries COUNT', type: :integer, min: 1, max: 5

  def run
    p retries: retries
  end
end

Cl.new('owners').run(%w(add --retries 1))

# Output:
#
#   {:retries=>1}

Cl.new('owners').run(%w(add --retries 10))

# Output:
#
#   Out of range: retries (min: 1, max: 5)
#
#   Usage: owners add [options]
#
#   Options:
#
#     --retries COUNT      type: integer, min: 1, max: 5
#     --help               Get help on this command

Negations

Flags (boolean options) automatically allow negation using --no-* and --no_* using OptionParser's support for these. However, sometimes it can be convenient to allow other terms for negating an option. Flags therefore accept an option negate like so:

class Add < Cl::Cmd
  register :add

  opt '--notifications', 'Send out notifications to the team', negate: %w(skip)

  def run
    p notifications?
  end
end

Cl.new('owners').run(%w(add --notifications))

# Output:
#
#   true

Cl.new('owners').run(%w(add --no_notifications))

# Output:
#
#   false

Cl.new('owners').run(%w(add --no-notifications))

# Output:
#
#   false

Cl.new('owners').run(%w(add --skip_notifications))

# Output:
#
#   false

Cl.new('owners').run(%w(add --skip-notifications))

# Output:
#
#   false

Note

Options can have a note that will be printed in the help output.

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', note: 'needs to be a group'
end

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string, note: needs to be a group
#     --help          Get help on this command

Secret

Options can be declared as secret.

This makes it possible for client code to inspect if a given option is secret. Also, option values given by the user will be tainted, so client code can rely on this in order to, for example, obfuscate values from log output.

class Add < Cl::Cmd
  register :add

  opt '--pass PASS', secret: true

  def run
    p(
      secret?: self.class.opts[:pass].secret?,
      tainted?: pass.tainted?
    )
  end
end

Cl.new('owners').run(%w(add --pass pass))

# Output:
#
#   {:secret?=>true, :tainted?=>true}

See Also

Options can refer to documentation using the see option. This will be printed in the help output.

For example:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', see: 'https://docs.io/cli/owners/add'
end

Cl.new('owners').run(%w(add --help))

# Output:
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string, see: https://docs.io/cli/owners/add
#     --help          Get help on this command

Types

Options can have a type. Known types are: :array, :string, :integer, :float, :boolean.

The type :array allows an option to be given multiple times, and makes sure the value accessible on the Cmd instance is a Ruby Array. (This currently only supports arrays of strings).

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', type: :array

  def run
    p to
  end
end

Cl.new('owners').run(%w(add --to one --to two))

# Output:
#
#   ["one", "two"]

Other types cast the given value to the expected Ruby type.

class Add < Cl::Cmd
  register :add

  opt '--active BOOL', type: :boolean
  opt '--retries INT', type: :integer
  opt '--sleep FLOAT', type: :float

  def run
    p active: active.class, retries: retries.class, sleep: sleep.class
  end
end

Cl.new('owners').run(%w(add --active yes --retries 1 --sleep 0.1))

# Output:
#
#   {:active=>TrueClass, :retries=>Integer, :sleep=>Float}

Required Options

There are three ways options can be required:

  • using required: true on the option: the option itself is required to be given
  • using requires: :otheron the option: the option requires another option to be given
  • using required :one, [:two, :three] on the class: either one or both two and three must be given

For example, this simply requires the option --to:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP', required: true

  def run
    p to: to
  end
end

Cl.new('owners').run(%w(add --to one))

# Output:
#
#   {:to=>"one"}

Cl.new('owners').run(%w(add))

# Output:
#
#   Missing required option: to
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP      type: string, required
#     --help          Get help on this command

This will make the option --retries depend on the option --to:

class Add < Cl::Cmd
  register :add

  opt '--to GROUP'
  opt '--other GROUP', requires: :to

  def run
    p to: to, other: other
  end
end

Cl.new('owners').run(%w(add --to one --other two))

# Output:
#
#   {:to=>"one", :other=>"two"}

Cl.new('owners').run(%w(add --other two))

# Output:
#
#   Missing option: to (required by other)
#
#   Usage: owners add [options]
#
#   Options:
#
#     --to GROUP         type: string
#     --other GROUP      type: string, requires: to
#     --help             Get help on this command

This requires either the option --api_key or both options --username and --password to be given:

class Add < Cl::Cmd
  register :add

  # read DNF, i.e. "token OR user AND pass
  required :token, [:user, :pass]

  opt '--token TOKEN'
  opt '--user NAME'
  opt '--pass PASS'

  def run
    p token: token, user: user, pass: pass
  end
end

Cl.new('owners').run(%w(add --token token))

# Output:
#
#   {:token=>"token", :user=>nil, :pass=>nil}

Cl.new('owners').run(%w(add --user user --pass pass))

# Output:
#
#   {:token=>nil, :user=>"user", :pass=>"pass"}

Cl.new('owners').run(%w(add))

# Output:
#
#   Missing options: token, or user and pass
#
#   Usage: owners add [options]
#
#   Options:
#
#     Either token, or user and pass are required.
#
#     --token TOKEN      type: string
#     --user NAME        type: string
#     --pass PASS        type: string
#     --help             Get help on this command

Config Files

Cl automatically reads config files that match the given executable name (inspired by gem-release), stored either in the user directory or the current working directory.

For example:

module Api
  class Login < Cl::Cmd
    opt '--username USER'
    opt '--password PASS'
  end
end

# bin/api
CL.new('api').run(ARGV)

# ~/api.yml
login:
  username: 'someone'
  password: 'password'

# ./api.yml
login:
  username: 'someone else'

then running

$ bin/api login

instantiates Api::Login, and passes the hash

{ username: 'someone else', password: 'password' }

as opts.

Options passed by the user take precedence over defaults defined in config files.

Environment Variables

Cl automatically defaults options to environment variables that are prefixed with the given executable name (inspired by gem-release).

module Api
  class Login < Cl::Cmd
    opt '--username USER'
    opt '--password PASS'
  end
end

# bin/api
CL.new('api').run(ARGV)

then running

$ API_USERNAME=someone API_PASSWORD=password bin/api login

instantiates Api::Login, and passes the hash

{ username: 'someone', password: 'password' }

Options passed by the user take precedence over defaults given as environment variables, and environment variables take precedence over defaults defined in config files.

More Repositories

1

rails-i18n

Repository for collecting Locale data for Ruby on Rails I18n as well as other interesting, Rails related I18n stuff
Ruby
3,979
star
2

gem-release

Release your ruby gems with ease.
Ruby
512
star
3

adva_cms

cutting edge cms, blog, wiki, forum ...
JavaScript
489
star
4

routing-filter

routing-filter wraps around the complex beast that the Rails routing system is, allowing for unseen flexibility and power in Rails URL recognition and generation.
Ruby
463
star
5

i18n-active_record

I18n ActiveRecord backend
Ruby
281
star
6

adva-cms2

Cutting edge Rails 3 CMS framework
Ruby
115
star
7

hashr

Simple Hash extension to make working with nested hashes (e.g. for configuration) easier and less error-prone.
Ruby
109
star
8

simple_states

A super-slim statemachine-like support library
Ruby
95
star
9

steam

Headless integration testing w/ HtmlUnit: enables testing JavaScript-driven web sites
JavaScript
51
star
10

ripper2ruby

Similar to ruby2ruby this library allows to parse Ruby code, modify and recompile it back to Ruby.
Ruby
41
star
11

simple_opts.sh

Simple Bash option parser
Shell
31
star
12

i18n-missing_translations

Find missing translations in your code more easily.
Ruby
31
star
13

scriptaculous-sortabletree

Implements a sortable tree for scriptacolous
JavaScript
29
star
14

minimal

Minimal templating engine inspired by Markaby & Erector but much smaller and targeting Rails 3
Ruby
26
star
15

rdom

experimental browser implementation in ruby using nokogiri and johnson
Ruby
25
star
16

simple_nested_set

Ruby
22
star
17

space

multi-repository monitoring and shell helper tool to ease development across multiple dependent repositories
Ruby
17
star
18

activesupport-slices

Lazy loaded vertical code slices based on ActiveSupport Dependencies
Ruby
14
star
19

capture_stdout

Adds Kernel.capture_stdout(&block). Useful e.g. for testing command line tools
Ruby
14
star
20

data_migrations

Ruby
14
star
21

vim-tree

vim filesystem tree plugin in ruby
Ruby
13
star
22

rack-cache-purge

Support for purging rack-cache
Ruby
13
star
23

i18n-tools

Tools for working with ruby/rails i18n
Ruby
10
star
24

vim-todo

Provides a simple todo list similar to Textmate’s todo.bundle
Ruby
10
star
25

reference_tracking

Ruby
10
star
26

locator

Generic html element locators for testing tools
Ruby
9
star
27

taskmate

Simplistic TextMate bundle for getting more done with your favorite missing text editor.
Ruby
9
star
28

scrumtious

toying with a remote scrum tool pulling from lighthouse for
Ruby
7
star
29

mephisto_paged_article_list

Mephisto doesn't page article lists out of the box. This plugin adds that.
Ruby
6
star
30

stubby

lightweight and fast stubbing framework
Ruby
6
star
31

with

highly experimental, lightweight and flexible contexts for test/unit
Ruby
6
star
32

resque-heartbeat

Ruby
6
star
33

activemodel-error

I18n support for validation error messages in ActiveModel
Ruby
6
star
34

vim-layout

Ruby
5
star
35

simple_slugs

Ruby
5
star
36

micro_migrations

Minimal ActiveRecord standalone migrations
Ruby
5
star
37

inherited_resources_helpers

Ruby
5
star
38

google_analytics

This plugin is primarily targeted at being used with Mephisto but should be useful with other Rails based CMS or blogging plattforms, too.
Ruby
5
star
39

test_server

Playing around with a test server for Rails that keeps the environment loaded (just like spec_server)
Ruby
5
star
40

will_paginate_liquidized

This plugin allows you to use will_paginate with Liquid templates. That's it.
Ruby
4
star
41

ruby-i18n.tmbundle

Ruby
4
star
42

middleman-toc

Ruby
4
star
43

rjb-require

Adds the ability to import and map Java packages to nested Ruby modules/classes to RJB.
Ruby
4
star
44

globalize-rails.org

Ruby
3
star
45

resque-tagged_queues

Ruby
3
star
46

sh_vars

Shell variable parser
Ruby
3
star
47

em-stdout

Ruby
3
star
48

rack-cache-tags

Support for tagging rack-cache entries
Ruby
3
star
49

rbac

Ruby
3
star
50

with-sugar

Test macros for being used with With
Ruby
3
star
51

treetop_css

Treetop CSS grammar/parser
Ruby
3
star
52

i18n-message

Object-oriented abstraction for looking up translations from I18n.translate
Ruby
3
star
53

adva-cms.org

Ruby
3
star
54

mephisto_tag_cloud

Most complete, sophisticated, standard-conform and allover-awesome implementation of a tag cloud plugin for Mephisto :)
Ruby
3
star
55

mephisto_full_archives

simple plugin that adds a full archives view to Mephisto's own archives
Ruby
2
star
56

bash_opts

SImple Bash options parser
Shell
2
star
57

test_declarative

Simply adds a declarative test method syntax to test/unit
Ruby
2
star
58

simple_taggable

Ruby
2
star
59

dotfiles

Vim Script
2
star
60

mephisto_inverse_captcha

Mephisto anti-comment-spam plugin that adds an "outer floodgate" to the existing (Akismet) spam-protection
Ruby
2
star
61

trsh

Experimental Travis CI Shell using API v3 in Go
Go
2
star
62

uki_reader

Experimental Google Reader UI based on Uki
JavaScript
2
star
63

travis

2
star
64

travis-lxc

Ruby
2
star
65

vim-deliminator

Balancing brackets and quotes
Ruby
1
star
66

database_recorder

Ruby
1
star
67

identity

Ruby
1
star
68

gmail_filters

Ruby
1
star
69

ruby-i18n.org

ruby-i18n.org - static html export, see the source branch for sources
Ruby
1
star
70

command

Ruby
1
star
71

registry

Ruby Class Registry
Ruby
1
star
72

travis-worker

Ruby
1
star
73

pathname_local

Ruby
1
star
74

dom-test

Ruby export of Level 1 and 2 W3C DOM tests
Ruby
1
star
75

led-go

A line editor in Go. Inspired by linenoise, but written with extensibility and separation of concerns in mind.
Go
1
star
76

svenfuchs.github.com

jo
HTML
1
star
77

rails-i18n-chart

Ruby
1
star
78

box

C++
1
star
79

statics

Ruby
1
star
80

silence_log_tailer

Silence rails/server log tailing to console
Ruby
1
star