Giter Club home page Giter Club logo

gli's Introduction

GLI, the Git-Like Interface Command Line Parser

GLI allows you to create command-line app in Ruby that behaves like git in that it takes subcommands to perform a series of complex action, e.g. git remote add.

<img src=“https://secure.travis-ci.org/davetron5000/gli.svg?branch=gli-2” alt=“Build Status” />

What Problem does GLI Solve?

Creating a command-line app that uses subcommands, each of which might accept different command-line options, is somewhat difficult with Ruby’s built-in OptionParser. GLI provides an API that wraps OptionParser so that you can create a subcommand-based command-line app with minimal boilerplate. This API also produces complete documentation for your command-line app.

Why is GLI’s solution different from others?

There are other RubyGems that allow you to create a command-line app that takes subcommands. These solutions are often quite limited (e.g. they don’t allow deeply nested subcommand structures or sophisticated command-line options per subcommand), or require more code that we think is needed. Some solutions make it difficult or impossible to properly document your command-line app.

What you need to know to use GLI

You should know Ruby, and have a basic understanding of how the UNIX command line works: standard input, standard output, standard error, and exit codes.

Use

Install if you need to:

gem install gli

You can validate you have installed it correctly by running gli help. You should see formatted help output.

If you are using GLI in another application, add it to your Gemfile:

gem "gli"

You can test your install via Bundler by running bundle exec gli help. This should produce formatted help output from GLI.

Getting Started

The simplest way to get started is to create a scaffold project

gli init todo list add complete

(note if you installed via Bundler you will need to execute bundle exec gli init todo list add complete)

This will create a basic scaffold project in ./todo with:

  • executable in ./todo/bin/todo. This file demonstrates most of what you need to describe your command line interface.

  • an empty test in ./todo/test/default_test.rb that can bootstrap your tests

  • a gemspec shell

  • a README shell

  • Rakefile that can generate RDoc, package your Gem and run tests

  • A Gemfile suitable for use with Bundler to manage development-time dependencies

Now, you are ready to go:

> cd todo
> bundle exec bin/todo help
NAME
    todo - Describe your application here

SYNOPSIS
    todo [global options] command [command options] [arguments...]

VERSION
    0.0.1

GLOBAL OPTIONS
    -f, --flagname=The name of the argument - Describe some flag here (default: the default)
    --help                                  - Show this message
    -s, --[no-]switch                       - Describe some switch here

COMMANDS
    add      - Describe add here
    complete - Describe complete here
    help     - Shows a list of commands or help for one command
    list     - Describe list here

> bundle exec bin/todo help list
NAME
    list - Describe list here

SYNOPSIS
    todo [global options] list [command options] Describe arguments to list here

COMMAND OPTIONS
    -f arg - Describe a flag to list (default: default)
    -s     - Describe a switch to list

All you need to do is fill in the documentation and your code; the help system, command-line parsing and many other awesome features are all handled for you.

Get a more detailed walkthrough on the main site

Supported Platforms

See ‘.circleci/config.yml` for the supported rubies, but general we’re running tests on the all MRI rubies receiving support, which tends to be the most recent four versions.

GLI should work on older Rubies and JRuby, but it’s too much work to keep tests passing for those.

Documentation

Extensive documentation is available at the wiki.

API Documentation is available here. Recommend starting with GLI::DSL or GLI::App.

Credits

Author

Dave Copeland (davetron5000 at g mail dot com)

Copyright

Copyright © 2010 by Dave Copeland

License

Distributes under the Apache License, see LICENSE.txt in the source distro

gli CLI documentation

:include:gli.rdoc

gli's People

Contributors

apiology avatar aterris avatar aussielunix avatar babysnakes avatar bemurphy avatar blackjid avatar blindgaenger avatar bluewind avatar calestar avatar camertron avatar carlesjove avatar chrisarcand avatar d1 avatar davetron5000 avatar dblock avatar dividedmind avatar edusantana avatar gnufied avatar haegin avatar jacobevelyn avatar jesseherrick avatar johnl avatar kale avatar kiela avatar mattbrictson avatar pengwynn avatar specious avatar spone avatar tokengeek avatar zeropointenergy 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gli's Issues

Find a way to test the CLI better

The CLI of GLI has pretty much no test coverage. Need to find a way to test it to prevent future cockups like 1.2.0 being nigh-unusable

1.8.7 Path Issue?

On a fresh install of gli using Ruby 1.8.7 & REE (RVM install) i'm getting the following error from GLI.

ruby-1.8.7-p352@test  ~/documents/projects/test   
→ gli init my_proj command_name
Creating dir ./my_proj/lib...
Creating dir ./my_proj/bin...
Creating dir ./my_proj/test...
Created ./my_proj/bin/my_proj
Created ./my_proj/README.rdoc
Created ./my_proj/my_proj.rdoc
Created ./my_proj/my_proj.gemspec
Created ./my_proj/test/tc_nothing.rb
Created ./my_proj/Rakefile
Created ./my_proj/Gemfile
Created ./my_proj/lib/my_proj_version.rb
ruby-1.8.7-p352@test  ~/documents/projects/test

→ my_proj/bin/my_proj help
/Users/schneems/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require': no such file to load -- my_proj_version (LoadError)
    from /Users/schneems/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
    from my_proj/bin/my_proj:4

Any thoughts? Congrats on the book btw.

Provide long option names in the options map as well

It would be handy to have the long option names in the options map in addition to the short names. e.g.

switch [:c,:clean]

options[:c] == options[:clean]

This would allow for more readable access to the options hash

Do some basic type conversions

Probably would be handy to be able to do something like

type Float
flag :cost

and have options[:cost] return a Float of the value.

type [:foo,:bar,:baz]
flag :selection

and have the app a) check that --selection is one of the options and b) set it.

Probably would be pretty easy to do Int, Float, Enum, and List initially.

Also, this would probably be available for free if using OptionParser, per #32

help screen makes no distincting between global and command-specific options

Given this

> todo
usage: todo command [options]

Version: 0.0.1

Options:
    -f, --filename=full path to file - Specify the location of the todo txt file
                                       (default: /Users/davec/.todo.txt)

Commands:
    done - Complete one or more items
    help - Shows list of commands or help for one command
    list - List all items to do
    new  - Create a new item to do

the usage line should really read

usage: todo [global_options] command [command_options]

Global Options:
    -f #etc

And for todo help list we should see

list [command_options] 
    List all items to do
Command Options:
    --foo - 

Allow for subcommands to main commands

  • myapp help should show the commands defined in global space
  • myapp command1 help should show the sub-commands of command1
  • myapp command1 subcommand help should show the commands under subcommand, etc

strange error in map(&:to_sym) on ruby 1.8.7 it seems

on latest, it seems the map(&:to_sym) is not working somehow, even though I test on 1.8.7. Weird.

/usr/lib/ruby/gems/1.8/gems/gli-1.2.1/lib/gli/command_line_token.rb:38:in `parse_names':     wrong argument type Symbol (expected Proc) (TypeError)
    from /usr/lib/ruby/gems/1.8/gems/gli-1.2.1/lib/gli/command_line_token.rb:13:in `initialize'
    from /usr/lib/ruby/gems/1.8/gems/gli-1.2.1/lib/gli/command.rb:15:in `initialize'
    from /usr/lib/ruby/gems/1.8/gems/gli-1.2.1/lib/gli.rb:83:in `new'
    from /usr/lib/ruby/gems/1.8/gems/gli-1.2.1/lib/gli.rb:83:in `command'
    from ./rr:16

Ruby version:

$ ruby --version
ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]

Generated test file requires a non-existent class for 1.9.2

The tc_nothing.rb that is generated by the scaffold requires the file test/unit/ui/console/testrunner for some reason (most likely I thought it was needed). This file exists on 1.8.7, but not on 1.9.2. It's not needed for 1.8.7 tests to work, so it should be removed from the scaffold test file.

multiple flags without equals are sometimes ignored

when using more than one flag, the order seems to sometimes matter. For example:

"-i 5 -z a" I get :z but :i is the default, not 5.

"-z a -i 5" gives me both as expected

"-i=5 -z=a" gives me both as expected

Parsing error, possibly related to numbers

Given this:

desc 'Create a day''s worth of data for a particular service point'
arg_name 'service point ids'
command :data do |c|

  c.desc 'Type of data'
  c.arg_name 'either bill, day, or halfhour'
  c.flag [:t,:type]

  c.desc 'Date for the reads (start date for billing)'
  c.arg_name 'date (in yyyy-mm-dd format)'
  c.default_value '2010-04-01'
  c.flag [:d,:date]

  c.desc 'Number of reads, for billing'
  c.arg_name 'number'
  c.default_value '1'
  c.flag :n

  c.desc 'Make like gas data'
  c.switch :g

  c.action do |global_options,options,args|
    raise "at least one service point id required" if args.nil? || args.empty?
    Generate::Data.new(options[:t],options[:d],options[:n].to_i,options[:g],args).go
  end
end

Using this command line:

generate data -t bill -n 10 1234

The -n 10 doesn't get picked up. If we do this, instead:

generate data -n 10 -t bill 1234

it does work. Not sure why

Create GLI website

Would be cool to have a real website for GLI and not just the giant README

Allow a .rc file to provide default values

Would be nice if gli would generate the code to deal with a .rc file in a user's home directory that could provide user-configured default values for all options:

--- 
:globals: 
  :v: :very
  :h: 
:ls: 
  :x: foo
  :l: true

Provide new command to generate README markdown from DSL

It would be cool if there were a way to generate the README or part of the README from the DSL used to create the commands; you could run this every so often as you developed your command line application:

gli readme bin/my_command

Could even add a few new bits of meta-data:

desc 'Lists all files in directory'
long_desc 'This will show all the files, optionally with details, in the entire directory where you run this command.  The most useful options are `-l` and `-x`'
command :ls do
  # whatever defines the ls command
end

The long_desc wouldn't show up in help, but might show up in the help command and would certainly show up in the README

Provide means of detecting the "special" commands inside the pre block

I end up writing a lot of

if command.nil? || command.name == :help
  # not creating a trac instance
else 
  # do normal pre checks and init
end

and it would be nice to have a way to detect "special" commands like help, initconfig and rdoc (and whatever other ones get added) in a more generic way

Allow flag detection after arguments

Given this example:

#!/usr/bin/ruby
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
require 'rubygems'
require 'gli'

include GLI

desc 'deploys a script to a server'
arg_name 'Describe arguments to deploy here'
command :deploy do |c|
  c.desc 'Forces generation'
  c.default_value 'localhost'
  c.flag [:server,:s]
  c.action do |global_options,options,args|
    p global_options
    p options
    p args
  end
end

GLI.run(ARGV)

When you pass the server before the first argument it works:

$ ruby ./gli-bug.rb deploy --server=internetz here
{}
{:server=>"internetz"}
["here"]

However when you pass it after the argument, it fails:

$ ruby ./gli-bug.rb deploy here --server=internetz
{}
{:server=>"localhost"}
["here", "--server=internetz"]

Am I doing something wrong?

Use bundler (or whatever it uses) to bootstrap common gem stuff

Currently, most of the files are hacked out from the scaffold.rb file. Should use Bundler or its internals to bootstrap the GLI-powered apps. Only issue is that bundler is very married to a git-based repo; not sure that's the best thing to do, so this might could be an option?

Load path problem

I installed gli to follow along with David Copeland's "Command-Line Apps" book. The example fails with "no such file to load -- todo_version.rb". It works when I change line 4 of bin/todo to...

require File.expand_path(File.join(File.dirname(__FILE__),'/../lib/todo_version.rb'))

I verified this behavior on ruby 1.9.2p290 and 1.8.7. I also cloned the repo and did a hard reset to Oct. 5, "updated dep on simplecov", before the load path change and it worked without modification.

Thanks for the great library. I wanted to share in case this is useful.

Completely rdoc the public methods

A lot of the public methods are not rdoc'ed and mentioned only in the wiki documentation. That's not very nice, so I should probably document all the public methods and DSL methods.

Provide better way of documenting non-flag/switch arguments

Currently, you can document a command's arguments via arg_name. This is OK for simple commands, but for commands that have and ordering of arguments, it's difficult. A syntax might be:

arg_name 1,"the filename"
arg_name 2,:optional,"output file (stdout if omitted)"

default_value isn't getting reset

c.flag :c
default_value 'foo'

c.flag :d
# note that no default_value specified

pre do |global,command,options,args|
  # globa[:d] is 'foo'!

Better integrate version numbers

It would be nice if there was a canonical way that GLI could look for the version of an app. It could then include this in the help automatically. It would also be nice to allow

gli_generated_app --version

to simply output the version without requiring a subcommand (or it could just show the help, I suppose)

Allow strings for command and option names

If you want to us a '-' in an option name or command name, you have do this:

flag [:n,:'dry-run']

which is pretty annoying. Should be easy to allow strings, and just sanity check for spaces:

flag [:n,'dry-run']

Barf if a switch/flag is used more than once

I mistakenly used this code in a talk, and it brought up an interesting question:

switch [:f,:force]

flag [:f,:file]

What would happen? I believe that the flag would "win", but I'm not sure of the fate of :force, and overall I think this should be treated as an erroneous interface.

Thus, I think this is a bug in GLI and it should complain if you do this, as it's clearly wrong.

Generate a Rakefile

Generate a canonical Rakefile (optionally) that could:

  • Run tests
  • Set up your github pages page with grancher
  • Generate rdoc
  • Create coverage with rcov

Change how the version is stored to be more canonical

Currently, GLI writes the version file in lib/app_version.rb This probably won't cause any conflicts, but is not the best-practice; it should write the file to lib/app/version.rb (or just anywhere in lib/app).

No way to exit nonzero

All GLI apps exit with a status of zero. This is fairly lame, as you cannot script GLI-powered apps. It's doubly lame because I make fun of maven for not doing this.

A few options:

  • If error, exit -1, otherwise exit 0
  • Provide the user a way to indicate exit code

In either case, this change won't fix any existing GLI apps; they will probably have to add code to exit explicitly themselves

Provide means to specify global command-scoped options

As opposed to a global option to the command, it would be nice to be able to specify a command-scoped option that applies to all commands and then have some commands opt-out of it. For example, suppose several commands create an output file. Instead of

command :foo do |c|
  c.flag [:o,:output_file]
end
command :bar do |c|
  c.flag [:o,:output_file]
end
command :baz do |c|
end

It could look like:

all_commands.flag [:o,:output_file]
command :foo do |c|
end
command :bar do |c|
end
command :baz do |c|
  c.except_flag :o
end

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.