💋 Crystal CLI

Website / Documentation / Report Issue / Source Code    

Crystal CLI is a "KISS" (Keep It Simple Stupid) CLI API for the Crystal programming language. It provides a cli macro for parsing command line options, that proves to do just about anything your really need a commandline interface to do, despite it's simplicity.

Installation

Add this to your application's shard.yml:

dependencies:
  cli:
    gitlab: transfire/crystal-cli

Usage

You can get the cli macro by including the CLI module into your own class, or simply call it at the module level, CLI.cli. Usage is straightforward, although it might look a little odd at first glance.

  require 'cli'

  class MyCLI
    include CLI

    def run(argv=ARGV)
      cli argv, {
        "-f --file" : set_file(String)
        "-d --debug": set_debug
        "-h --help" : show_help
      }
    end

    def set_file(f)
      @file = f
    end

    def set_debug
      @@DEBUG = true
    end

    def show_help
      puts "Usage: mycommand [OPTIONS]"
      puts
      puts "-f --file     choose a file"
      puts "-d --debug    turn on debug mode"
      puts "-h --help     display this help message"
    end
  end

There's very little to it really. The cli command simply maps command line options to procedures which are used to process them. That's it.

In our example, notice that -f and --file are easily defined as synonymous options. Simple. Then notice that the -f/--file option's procedure takes an argument, so the command line option takes an argument as well. Again simple.

The cli method has a few additional niceties. It can handle run-on flags, i.e. -abc is the same as -a -b -c.

NOTE In the Ruby version of this library, cli takes Proc objects, not method names. This makes it a bit more flexible. It would be nice if Crystal could do the same, but it has proved mind-boggling to implement. Maybe in the future ...

Subcommands

Subcommands are just as easy. Simply add them to your cli macro without the flag markers (e.g. - or --) and map them to a method that takes an Array(String), which are the remaining command line arguments.

  require 'cli'

  class MyCLI
    include CLI

    def run(argv=ARGV)
      cli argv, {
        "sub1" : run_sub1(Array(String))
        "sub2" : run_sub2(Array(String))
        "-h --help" : show_help
      }
    end

    def run_sub1(argv : ARRAY(String))
      cli argv, {
        "-o --out"  : set_ouput(String)
        "-h --help" : show_help
      }
    end

    def run_sub2(argv : Array(String))
      cli argv, {
        "-V --verbose" : set_verbose
        "-h --help"    : show_help
      }
    end

You need Help? No, you really don't.

At this point, you might be wondering about help output. Clearly there are no descriptions given in our example. Well, guess what? It's actually easier to just print it out yourself. In fact, if you really want to do it right, create a manpage with a tool like ronn or md2man, and impress your friends. It's a much better approach then jamming all that verbage into the command line options parser.

Ask and you shell receive

In addition to the cli macro, the library also provides an optional #ask method. This is a very simple command line query method. You can use it via include CLI or as a module method.

    require "cli/ask"

    ans = CLI.ask "Are you nice? [Y/n]", "Y"

Or,

    require "cli/ask"

    include CLI

    ans = ask "Are you nice? [Y/n]", "Y"

Other libraries have their own take on the #ask method, and this very simple implementation can just as soon be substititued for another. No biggy. But it's nice to have for simple use cases.

Development

Please feel free to offer up suggestions for improvement on the issues board, or better yet, hack at this macro and contribute a pull request. Thanks!

Contributing

  1. Fork it ( https://github.com/[your-github-name]/crystal-cli/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

Acknowledgments

We have to give credit where credit is due. The general idea of this interface is the great achievement of Michel Martens, who created the original Ruby Clap library from which Crystal CLI evolved. Mr. Martens deserves high praise for this design. It's not easy to realize that this level of simplicity is all one really needs! Thank you, Michel!

Copyrights & License

Crystal CLI is copyrighted open-source software.

Copyright (c) 2018 Thomas Sawyer

See LICENSE.txt for details.