[ANN] cmd 0.7.0: Library for Line-Oriented Command Interpreters (initial release)

Discussion in 'Ruby' started by Marcel Molina Jr., Apr 10, 2005.

  1. = Cmd 0.7.0 (initial release)

    I am very pleased to announce the initial public release of Cmd (version 0.7.0).

    http://cmd.rubyforge.org/

    == What is Cmd?

    cmd is a library for building line-oriented command interpreters in Ruby.
    Simply inherit from cmd's Cmd class, and methods whose names start with do_
    become interactive commands. cmd is inspired by the Python library [1] of the
    same name, but offers a distinctive Ruby feel and several additional features.

    Documentation, examples, a mini tutorial and more can be found at:

    http://code.vernix.org/cmd/

    Take a look at the README:

    http://code.vernix.org/cmd/rdoc/

    == Download and Install

    http://code.vernix.org/cmd/#download for various packaging formats.

    With RubyGems:

    $ [sudo] gem i cmd -r

    From archive:

    $ wget http://code.vernix.org/cmd/download/cmd-0.7.0.tar.gz
    $ tar -zxvvf cmd-0.7.0.tar.gz
    $ cd cmd*
    $ [sudo] ruby setup.rb

    == Examples

    There are a few examples of Cmd in action here:

    http://svn.vernix.org/main/library/cmd/trunk/example/

    == Todo

    Cmd is more usable than not at the moment, but I do have a lot of ideas for
    where I'd like it to go. You can see these here.

    http://svn.vernix.org/main/library/cmd/trunk/TODO

    == License

    MIT

    == Thanks

    A special thanks goes to Sam Stephenson (http://conio.net/).

    More elaborate gushing at http://svn.vernix.org/main/library/cmd/trunk/THANKS

    marcel
    --
    Marcel Molina Jr. <>


    [1] http://docs.python.org/lib/module-cmd.html
    Marcel Molina Jr., Apr 10, 2005
    #1
    1. Advertising

  2. On Apr 10, 2005, at 3:26 PM, Marcel Molina Jr. wrote:

    > = Cmd 0.7.0 (initial release)
    >
    > I am very pleased to announce the initial public release of Cmd
    > (version 0.7.0).
    >
    > http://cmd.rubyforge.org/


    I've only had a few short minutes to play around with this, but this is
    pretty darn nifty. I'll look into it more when I have some time, but
    thanks for sharing!

    James Edward Gray II
    James Edward Gray II, Apr 11, 2005
    #2
    1. Advertising

  3. On Mon, Apr 11, 2005 at 11:04:37PM +0900, itsme213 wrote:
    > "Marcel Molina Jr." <> wrote in message
    > news:...
    > > = Cmd 0.7.0 (initial release)

    >
    > Cool!


    Thanks!

    > Any plans to go towards interactive commands e.g. some commands valid only
    > within scope of other commands?


    By interactive commands do you mean something like?

    > foo

    # now you are in a context within 'foo' that opens you up to a whole other
    # set of things

    If so then I don't believe there are any plans for something like that but
    please do provide a bit more information if you are inclined and I would very
    gladly take some time to think about it.

    FYI: you can take a peek at things that are planned by checking out the todo.

    Browse on over to: http://svn.vernix.org/main/library/cmd/trunk/TODO

    marcel
    --
    Marcel Molina Jr. <>
    Marcel Molina Jr., Apr 11, 2005
    #3
  4. [ANN] cmd 0.7.1 (Minor bug fix)

    Jim Weirich was gracious enough to inform me that there was a subtle semantic
    error in the way my Readline detection was performed in cmd. As a result I've
    pushed a minor bug fix release, 0.7.1. The same information below applies:

    == Download and Install

    http://code.vernix.org/cmd/#download for various packaging formats.

    With RubyGems:

    $ [sudo] gem i cmd -r

    From archive:

    $ wget http://code.vernix.org/cmd/download/cmd-0.7.0.tar.gz
    $ tar -zxvvf cmd-0.7.0.tar.gz
    $ cd cmd*
    $ [sudo] ruby setup.rb

    Thanks,
    marcel
    --
    Marcel Molina Jr. <>
    Marcel Molina Jr., Apr 11, 2005
    #4
  5. Marcel Molina Jr.

    Luke Graham Guest

    On Apr 12, 2005 12:04 AM, itsme213 <> wrote:
    >
    > "Marcel Molina Jr." <> wrote in message
    > news:...
    > > = Cmd 0.7.0 (initial release)

    >
    > Cool!
    >
    > Any plans to go towards interactive commands e.g. some commands valid only
    > within scope of other commands?


    Wouldnt the best way to do this be to open another, specialised Cmd?

    --
    spooq
    Luke Graham, Apr 12, 2005
    #5
  6. On Tue, Apr 12, 2005 at 12:29:38PM +0900, itsme213 wrote:
    > "Marcel Molina Jr." <> wrote in message
    > news:...
    > > = Cmd 0.7.0 (initial release)

    >
    > Gem install, Windows XP, Ruby 1.8.2, trying out phonebook.rb, I get:
    >
    > [C:\ruby\lib\ruby\gems\1.8\gems\cmd-0.7.2\example]ruby phonebook.rb
    > phonebook.rb:11:in `expand_path': couldn't find HOME environment --
    > expanding `~/.pho
    > nebook' (ArgumentError)
    > from phonebook.rb:11


    Yes, I was fairly certain when I wrote that that it would not work on
    Windows. The phonebook.rb example is meant to be simple and illustrative so
    I passed over my recognition that I was more than likely imposing a platform
    dependency. A bit insensitive, sorry 'bout that :)

    Thanks for reporting this. Just for kicks I've made phonebook.rb a bit more
    platform agnostic. Mind you I don't have access to a Windows machine to test
    this but it *seems* like it ought to cover most cases.

    PHONEBOOK_FILE = begin
    File.expand_path('~/.phonebook')
    rescue
    File.join((ENV['HOME'] || ENV['USERPROFILE']), '_phonebook')
    end

    Windows users that I asked knew many ways in which this could be made more
    rigorous or "accurate" or what have you but for the purposes of the
    phonebook example I'm assuming this will work well enough.

    Thanks again. Please let me know if you implement something with cmd and
    thanks for the interest.

    marcel
    --
    Marcel Molina Jr. <>
    Marcel Molina Jr., Apr 12, 2005
    #6
  7. On Tue, Apr 12, 2005 at 01:09:39PM +0900, itsme213 wrote:
    > "Marcel Molina Jr." <> wrote
    > > > Any plans to go towards interactive commands e.g. some commands valid

    > only
    > > > within scope of other commands?

    > >
    > > By interactive commands do you mean something like?
    > >
    > > > foo

    > > # now you are in a context within 'foo' that opens you up to a whole

    > other
    > > # set of things

    >
    > Sort-of ... lousy description on my part. I can see the command interpreter
    > as a state machine consisting of a current object + the available commands
    > on the current object. I'll start with the latter.
    >
    > The available commands on the current object could change as you do things
    > to it. Suppose each of its commands has some declared pre-condition. A
    > command is disabled if its precondition is false. Here is one of many ways
    > to do this.
    >
    > class PhoneBook < Cmd
    > # ... define commands & docs
    > pre :add { |pb| pb.condition_on_phonebook_add }
    > pre :remove { |pb| pb.condition_on_phonebook_remove }
    > end
    >
    > All commands whose pre is true are 'enabled', all others are 'greyed-out'.
    > Preconditions could have a descriptive string for help purposes.


    Perhaps the already existent precmd and postcmd methods could be extracted
    into something that was a bit more aware and versatile. Like above where
    rather than having precmd be a hook that is called before all commands, the
    pre macro here would set up a pre condition for the specified command. But
    the example above is about what commands you are then afforded, which sort of
    translates to what commands the completion proc will display you and not much
    else that I can think of. I imagine the notion of setting pre condition hooks
    on a per command basis could be generalized to offer more than just what
    subcommands you are then afforded, like 'input actions' in FSM. Sort of seems
    to get into the realm of Design by Contract.

    > Secondly the current object itself could be switched. e.g If you add some
    > special commands to "cd", "pushd", and "popd" to any command-able object, to
    > start working in a new command context.
    >
    > PBook> pushd `find Sam`
    > - execute command "find Sam" in current context
    > - perhaps check return (e.g. a Person) is command-able
    > - make that the new command context, so ...
    > Sam> first Sammy
    > last Brown
    > popd
    > PBook>


    This idea seems quite similar to irb's job management where you can create a
    subirb which lets you essentially "enter" the object that you invoke the
    subirb session onto. Perhaps rather than having to fall back on some exiting
    convention like popd, something sort of like what Luke Graham was suggesting
    could happen. A thread with a specialized Cmd. Or perhaps there could be come
    simple protocol where by Cmd instances could interact with one another. It
    all gets a bit sophisticated after a certain point. I don't know whether this
    kind of stuff is better suited built into Cmd or on top of it. But I do
    welcome the ideas and look forward to see what bubbles up as I take the time
    to think about them.

    > And, lastly, every command has arguments. Each argument has a range of valid
    > values that can depend on current state. If you store an array of blocks
    > that computes the possible values for each argument given the current
    > context object (when applicable), you can even provide completion for
    > arguments to commands.
    >
    > class PhoneBook < Cmd
    > # can only delete X if X currently in phonebook
    > command :delete do
    > args [ {|pb| pb.people.collect { |p| p.name }}
    > # even better if returned objects, not strings
    > # using to_s or some protocol to get strings for completion
    > # command intereter keeps map of string->object
    > # refuse to execute if no valid completion
    > # inner code just deals with objects
    > ]
    > end
    > end
    >
    > PBook> delete <TAB>
    > #--> Sammy Mary
    > PBook> delete S<TAB>
    > #--> delete Sammy


    More DbC sort of stuff kind of. More simply, this functionality is actually
    sort of already implemented. Or at least the blue print is there and a I've
    commented on the hypothetical API in the TODO. Customized completion per
    command should be as easy as providing a proc or block or method reference or
    hard-coded array or whatever that provides a collection of things to complete
    against. This can be set for commands, subcommands, etc.

    > btw: have you considered adding a Command class to keep all info about one
    > command?


    Yes actually. Here is the branch at the point where I abandoned it for the
    time being:

    http://svn.vernix.org/main/library/cmd/branches/custom-classes-for-commands/lib/cmd.rb

    I set out to make cmd way more compositional. There was a Command class, a
    Commands container, Shortcut, SubCommand and I was thinking of Documentation.
    It would be really useful to be able to have a command object and just ask it
    if it has subcommands and get a list of them or ask it for its documentation.
    That's what I was aiming for. It ended up just adding way more complexity
    (which I was aiming to diminish by taking that approach). It was kludgy and
    sucked. This was largely just because I did a bad job of it. I have the
    feeling there could be a nice balance, where the composition of objects
    approach is succinct and elegant and simple. I just had to back out and
    approach it again from a different angle at the time. So after hanging out on
    that branch for a few days I just moved back to the original approach. Now
    the plan, enumerated in the TODO file, is to have Cmd be a module that you
    mix in. When you mix it in you define methods with whatever name you want and
    then you a 'command' class method to designate something a command. For
    example:

    command :foo
    def foo
    # ...
    end

    This makes it easy to take code that was developed previously or without Cmd
    in mind and stick a Cmd type interface onto it.

    Alternatively, there would be some Cmd::Base class that has the Cmd module
    mixed in. You could instead inherit from this and rather than use the
    'command' class method or have some naming system, work off the convention
    that all public methods of the subclass are implicitly commands. After doing
    that I think I would tackle wrapping command and subcommand discovery into
    specialized instances of stuff like a Command class.

    Thanks for the suggestions! Glad you're interested,
    marcel
    --
    Marcel Molina Jr. <>
    Marcel Molina Jr., Apr 12, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charles Fox
    Replies:
    3
    Views:
    1,714
    Charles Fox
    Apr 15, 2005
  2. Gianni Mariani
    Replies:
    0
    Views:
    351
    Gianni Mariani
    Jun 1, 2004
  3. christopher diggins
    Replies:
    2
    Views:
    346
    christopher diggins
    Mar 2, 2005
  4. ghorner
    Replies:
    4
    Views:
    84
    Ryan Davis
    Apr 26, 2009
  5. Zhan Deaux
    Replies:
    7
    Views:
    158
    Zhan Deaux
    Dec 9, 2010
Loading...

Share This Page