Giter VIP home page Giter VIP logo

app-spec-p5's Introduction

App::Spec

Writing command line apps made easy

Status

The structure of the spec will probably change.

I wait for your suggestions, wishes, bug reports.

Purpose

Write a specification for your command line application (currently in YAML) and get:

  • Subcommands (nested), options, parameters
  • a Perl 5 (and possibly other) framework that
  • automatically calls the specified method for the subcommand
  • validates options and parameters
  • outputs help
  • Automatic creation of pod, man pages
  • Automatic creation of zsh and bash completion scripts. Completion includes:
  • Subcommands, parameter values, option names and option values.
  • Description for completion items are shown, in zsh builtin, in bash with a cute little trick.
  • Generating dynamic completion. When completing a parameter or option, you can call an external command returning possible completion values
  • Possibly even creating a specification for your favourite app which lacks shell completion

Writing the specification in YAML takes advantage of YAML aliases, for example when you have options or parameters which are not global, but are used in more than one place. Alternatively the spec could allow to create definitions which you can just link to, kind of like Swagger does it.

Documentation

For now just an example in the examples directory called "myapp". Just play with it and use your tab key! Also try zsh if you haven't yet.

For authors

There is a command line tool called appspec https://github.com/perlpunk/App-AppSpec-p5 which is useful for you as an author of an app. You can use it to create completion and pod from a spec file.

Example

For a first overview, here is how an app looks like:

use strict;
use warnings;
use 5.010;
# your app class
# you could even go without an extra class and simply use the "main" namespace
package App::Spec::Example::MyApp;
use base 'App::Spec::Run';

# the method for the subcommand frobnicate
sub frobnicate {
    my ($self) = @_;
    my $options = $self->options; # just a hashref
    my $parameters = $self->parameters; # just a hashref
    say "frobnicate";
}

package main;
use App::Spec;

# read YAML from __DATA__ section
my $spec = App::Spec->read("myapp-spec.yaml");
my $run = App::Spec::Example::MyApp->new({ spec => $spec });
# this will check input and call frobnicate
$run->run;

See https://github.com/perlpunk/App-Spec-p5/blob/master/examples/myapp-spec.yaml for the specification of the example app. It's supposed to cover all currently implemented features.

Getting the completion to work

Here is how you get the completion for the example app.

First, add the bin directory to your path:

% PATH=$PWD/examples/bin:$PATH

Locate the modules:

% export PERL5LIB=$PWD/lib:$PERL5LIB

Bash

Simply source the bash completion script:

 $ source examples/bash/myapp.bash
 $ myapp <TAB>

Zsh

When using a new script/completion, you have to do two things:

Add the path to the completion dir to your .zshrc before the compinit call:

fpath=('/path/to/App-Spec-p5/examples/zsh' $fpath)

Then:

% exec zsh

If you change the completion script later, you just need to source it:

% source examples/zsh/_myapp

Note that the completion script must also be executable!

Reinventing the wheel?

Yes, I know MooseX::App::Cmd, MooseX::App::Command, MouseX::App::Cmd, MooX::Cmd. I've written https://github.com/perlpunk/MooseX-App-Plugin-ZshCompletion.

But all are a little bit different and lack things.

My use case which got me into this required automatic creation of the spec, and I would have been forced to dynamically generate a whole bunch of Mo*X classes when I actually just needed one.

I also like the idea of having a language independent specification.

I'm lazy and I didn't want to write a completion for all the other app frameworks and getopt modules. I just want to do it once.

TODO

See https://github.com/perlpunk/App-Spec-p5/issues

  • Write a schema
  • Write tests
  • Complete the help output
  • Generate pod, man pages
  • Allow Getopt::Long, Getopt::Long::Descriptive, ... input as a specification
  • Allow caching of dynamic completion values that take long to compute
  • Options/parameters imply other options
  • Options with multiple values
  • Allow apps without subcommands

app-spec-p5's People

Contributors

eitanschuler avatar manwar avatar perlpunk avatar s-nez 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

Watchers

 avatar  avatar  avatar

app-spec-p5's Issues

Generate POD

Generating a pod file from your spec with the complete usage and descriptions.

It could use more of Moo

Looking at the source code, I notice that in a few places you're not exploiting the facilities that Moo provides (e.g. you've got common and build do more-or-less what BUILDARGS and BUILD are designed to do, you handle lazy attributes by hand, you have no type constraints).
Is there a particular reason for that, or is just general unfamiliarity with Moo?
Would it be appreciated if I sent a pull request making the whole thing more Moo-ish? I'd also like to add some type constraints via Type::Tiny, but that can come later.

Regression: op must now be a string

Before 0.005, a command op could be a coderef, which was nice for those times where you just need to call an existing method with a value from the runner, see https://www.thenautilus.net/cgit/Sietima/tree/lib/Sietima/Role/SubscriberOnly/Moderate.pm?h=v1.0.4-dzilla&id=402b4b8e83babbb453c3caa23fb7e75c0cfbe1c0#n221for example.

With 0.005, I had to add methods just for App::Spec, see
https://www.thenautilus.net/cgit/Sietima/commit/?id=db2394b8c0beba5f4323dffe2d20adad1c5acf2b

Why YAML?

I don't see the need for YAML.
It would be much simpler to write the spec in Perl.

If you had the need to parse the spec from outside the program itself (ex for documentation generators), you could just inject an --export-getopt-spec option that would dump the spec.

Generate man page(s)

Generating a man pages (or several per subcommand) from your spec with the complete usage and descriptions.

Implement global parameters

Right now only parameters for apps with subcommands are possible, and for nested subcommands only for the last subcommand.

Todo:

myapp param [options]
myapp param0 cmd1 param1 cmd2 param2 [options]
  • Implement in App::Spec::Run
  • Pod
  • Usage
  • zsh completion
  • bash completion

Rename App::Spec::Completion::Bash to ...::bash

Rename App::Spec::Completion::Bash to App::Spec::Completion::bash and App::Spec::Completion::Zsh to App::Spec::Completion::zsh.
That will allow extension and simplify App::Spec::generate_completion:

sub generate_completion {
    my ($self, %args) = @_;
    my $shell = delete $args{shell};

    require "App/Spec/Completion/$shell.pm";
    "App::Spec::Completion::$shell"->new({ spec => $self })->generate_completion(%args)
}

Maybe regression: the 'class' slot of the spec is now required

Before 0.005, it was possible to ignore the class slot of the spec, as long as a pre-built object was set in App::Spec::Run::cmd.
Now, op method names are assumed to be fully-qualified, and if not, they're prefixed with the class. I'm not sure why this is.

Howto install?

I don't know how to install this great module, I love the ideas implemented here!

In fact I have the feeling there is nothing like 'perl Makefile.PL; make; make install'. Is the idea for development-time simply to copy lib/App to my current directory und do this:

use lib './lib';
use App::Spec;
...
I wish it would be more fun if I could do it the perl-standard way:

git clone https://github.com/perlpunk/App-Spec-p5.git
cd App-Spec-p5
perl Makefile.PL
make
make install

Thanks for your understanding.
Richard

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.