Coder Social home page Coder Social logo

clap's Introduction

CLAP: A Kick-Ass .NET Command-Line Parser

Full Documentation and Samples

http://adrianaisemberg.github.com/CLAP

Basic example: One verb, Some parameters

class Program
{
    public static void Main(string[] args)
    {
        Parser.Run<MyApp>(args);
    }
}

class MyApp
{
    [Verb]
    public static void Print(string text, int count)
    {
        for (int i = 0; i < count; i++)
        {
            Console.WriteLine(text);
        }
    }
}
>myexe print -text:"Hello World" -count:10

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World

Complex sample: Various verbs, global handlers, help handler, validation, default values, switches, arrays

class MyApp
{
    [Global(Aliases = "d", Description = "Launch a debugger")]
    public static void Debug()
    {
        // this is a global parameter handler.
        // it works for any verb.

        Debugger.Launch();
    }

    [Empty, Help]
    public static void Help(string help)
    {
        // this is an empty handler that prints
        // the automatic help string to the console.

        Console.WriteLine(help);
    }

    [Verb]
    public static void Print(string text, int count)
    {
        for (int i = 0; i < count; i++)
        {
            Console.WriteLine(text);
        }
    }

    [Verb]
    public static void Foo(
        [Parameter(Aliases = "t", Description = "A string parameter with an additional alias")]
        string text,

        [Parameter(Default = 5, Description = "An int parameter with a default")]
        int number,

        [MoreThan(10)]
        [LessThan(100)]
        [Parameter(Default = 42.3, Description = "A double parameter with validation and a default value")]
        double percent,

        [Parameter(Description = "A bool parameter, which can be used as a switch")]
        bool verbose,

        [Parameter(Description = "An enum parameter")]
        OptionEnum option,

        [Parameter(Description = "An array of strings")]
        string[] array)
    {
        Console.WriteLine("text = {0}", text);
        Console.WriteLine("number = {0}", number);
        Console.WriteLine("percent = {0}", percent);
        Console.WriteLine("verbose = {0}", verbose);
        Console.WriteLine("option = {0}", option);
        Console.WriteLine("array = [{0}]", string.Join(",", array));
    }
}
>myexe foo -t:hello -number:88 -percent:12.446 -verbose -option:Option2 -array:a,b,c,d

text = hello
number = 88
percent = 12.446
verbose = True
option = Option2
array = [a,b,c,d]

No arguments, help is printed:

>myexe

Print:
 -text:  [String]
 -count:  [Int32]

Foo:
 -text/t: A string parameter with an additional alias [String]
 -number: An int parameter with a default [Int32, Default = 5]
 -percent: A double parameter with validation and a default value [Double, Default = 42.3, More than 10, Less than 100]
 -verbose: A bool parameter, which can be used as a switch [Boolean]
 -option: An enum parameter [OptionEnum]
 -array: An array of strings [String[]]

Global parameters:
 -Debug/d: Launch a debugger [Boolean]

clap's People

Contributors

adrianaisemberg avatar appakz avatar brutaldev avatar invizory avatar mikalai-kardash avatar wernight 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

clap's Issues

.pdb file is included in nuget package

Hi, it appears maybe you published the debug version of the code, because the .pdb debug database is included in the referenced files when I add this package from nuget.
This quadruples the file size and while I can manually remove the file, it creates additional maintenance I don't want.

Writing RunConsole Errors to Console.Error instead of Console.Out

Seems like CLAP writes the message of an exception to the Console.Out stream when using RunConsole. So when you redirect the output to a file the error message will end up in that file. It would be nicer if you would write the message to Console.Error instead.

Anyway: I great library! LOVE IT!

r

Multiple apps and help - how to call?

I have multiple apps and in each app a help attribute. How to call the help from the command line?

  • Empty cmd -> nothing
  • domain. -> exception
  • domain.help -> exeption
  • help -> exception

Exceptions exceptions exception, and the docu says nothing about mupltiple apps and how to call the help.


Domain domain = new Domain();
User user = new User();
Parser.Run(args, domain, user);

public class User
{
[Empty, Help]
void ShowHelp(string help)
{
Console.WriteLine(help);
}
}

public class Domain
{
[Empty, Help]
void ShowHelp(string help)
{
Console.WriteLine(help);
}
}

Feature Request: Interactive REPL shell support

Some command line tools, such as NETSH and NSLOOKUP allow you to provide command line parameters and receive an immediate response, but they also support an interactive mode, where you call the command without parameters, and it then displays an interactive shell. It seems to me that adding this capability to CLAP would be fairly straightforward. Is this something you would be interested in doing, or should I look at doing it as a fork? It seems that extending the Parser.Run method to support an interactive mode would do the trick.

Assembly contains references to .NET 3.5 where it should only reference .NET 2.0

The download available from https://github.com/downloads/adrianaisemberg/CLAP/CLAP.FW2.v3.2.zip contains references to .NET 3.5 assemblies and therefore does not compile in a project that targets .NET 2.0.

When using NuGet for fetching CLAP the following problem is reported (most likely the reason is similar):

Successfully installed 'CLAP 3.3'. Successfully uninstalled 'CLAP 3.3'. Install failed. Rolling back... Could not install package 'CLAP 3.3'. You are trying to install this package into a project that targets '.NETFramework,Version=v2.0', but the package does not contain any assembly references that are compatible with that framework. For more information, contact the package author.

Create base exception class for all CLAP exceptions

Currently the only way to distinguish CLAP exceptions from the exceptions thrown by user code in the [Error] handling method is to test for every type like:

if(context.Exception is CommandLineParserException){ /* ... */ }
else if (context.Exception is VerbNotFoundException){ /* ... */ }
/* ... test every CLAP.*Exception ... */
else { /* Handle user code exception */}

It would be a lot easier to just check the base class:

if(context.Exception is CLAPBaseExeption){ /* Handle CLAP exceptions */ }
else { /* Handle user exception */}

Yes you can wrap every verb method code inside a try-catch instead but that is not nearly as convenient.

Localizing description strings

I really want to be able to use a resource key instead of having the language specific string for Description directly in the attribute. I would normally just use a trick similar to this example: http://stackoverflow.com/a/17381168/564726

Unfortunately the Global and Verb attributes are sealed and description is not virtual so you cannot inherit from it and dynamically return a description string.

Could I please request that the attributes that contain properties that could be localized (Description in both VerbAttribute and GlobalAttribute) be unsealed and the localizable properties be made virtual so that developers can customize how the string is retrieved?

Default verb is ignored

Hi. Verb(IsDefault=true) doesn't work. When I run my program without args, I still get the help message

$ ExampleProject.exe

  exercise|e (Default): Build a tree 
          /labelname        : target variable (String)

Correctly bubbling exit-codes

It looks like CLAP methods often return integers, which I can only assume represent exit codes, and yet any integers returned by the verb handlers will seemingly be ignored (with the process always returning (0)).

I see that there was an issue for this in 2012: #12. Is there support yet for the user-defined handlers to return non-zero rather than either conceding just (0) or (1) to represent error state or just doing an Environment.Exit(x) manually?

Thanks.

Handling of Nullables (int?)

Hello there,

I have a [Verb] with two int? / nullable parameters but CLAP throws an exception in case they are actually present:

CLAP.TypeConvertionException: '1' cannot be converted to System.Nullable1[System.Int32] ---> CLAP.TypeConvertionException: '1' cannot be converted to System.Nullable1[System.Int32]
at CLAP.ValuesFactory.ConvertParameterValue(String inputKey, String stringValue, Type parameterType, Exception deserializationException)
at CLAP.ValuesFactory.GetValueForParameter(Type parameterType, String inputKey, String stringValue)
--- End of inner exception stack trace ---
at CLAP.ValuesFactory.ConvertParameterValue(String inputKey, String stringValue, Type parameterType, Exception deserializationException)
at CLAP.ValuesFactory.GetValueForParameter(Type parameterType, String inputKey, String stringValue)
at CLAP.ValuesFactory.CreateParameterValues(String verb, Dictionary2 inputArgs, IEnumerable1 list)
at CLAP.ParserRunner.RunInternal(String[] args, Object obj)
at CLAP.ParserRunner.TryRunInternal(String[] args, Object obj)
at CLAP.MultiParser.RunTargets(String[] args, Object[] targets)
at CLAP.Parser.Run[T](String[] args)

.. the static method looks like this:

[Verb(IsDefault = true, Description = "Extracts the raw html stored in the CaliberRM database")]
public static void ExtractHtml(
[Parameter(Required = true)] string hostname,
[MoreThan(0)] [Parameter(Default = 20000, Required = false)]int port,
[Parameter(Required = true)] string username,
[Parameter(Required = true)] string password,
[Parameter(Required = true)] int requirementId,
[MoreThan(0)] [Parameter(Required = false)] int? majorVersion = null,
[MoreThan(0)] [Parameter(Required = false)] int? minorVersion = null)
{
// ...
}

Is there any way to use nullables or write my own type converter for CLAP?

Cheers and thanks for this awesome little library!
-J

Parameter attributes aren't working

I'm probably doing something wrong, but it seems like the Parameter attribute doesn't work. I made a test app with a Description property on some parameters, but the help text doesn't show the descriptions, it just shows the parameter Type. Also, I set a default on one of the parameters (int savedSearchId should default to 1), but the value comes in as zero.

This is what I get at the command line:
C:\projects\gbwork\CampaignEngine\src\hydra\bin\Debug>hydra

foo|f: Foo() description...

deletefromsavedsearch|d
/savedsearchid : (Int32)
/savedsearchname : (String)

Here is the code I'm using, it's in a .NET 4.5 Console App, and I added CLAP from nuget:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CLAP;

namespace hydra {
public class hydraConsole {
public static void Main(string[] args) {
Parser.Run(args);
}
}

public class hydraVerbs {

    [Verb(Description="Foo() description...")]
    public static void Foo() {
        Console.WriteLine("Foo!"); 
    }

    [Verb]
    public static void DeleteFromSavedSearch(
        [CLAP.Parameter(Description="Name of saved search with the users to delete")] 
        string savedSearchName

        , [CLAP.Parameter(Default = 1, Description = "Id of the saved search with the users to delete")] 
        int savedSearchId
    ) {
        Console.WriteLine("DeleteFromSavedSearch(savedSearchName: {0}, savedSearchId: {1}) !", savedSearchName, savedSearchId);
    }


    [Empty, Help]
    public static void Help(string help) {
        // this is an empty handler that prints
        // the automatic help string to the console.

        Console.WriteLine(help);
    }
}

}

auto-complete cannot work with arguments

CLAP enforces that argument values immediately follow the colon. This prevents auto-completion (from the command window) from working, because the auto-complete engine parses on whitespace, and starts the word from the switch and not from the colon.

Support unnamed arguments

You usually would like to support something like:

copy source dest

or

myapp copy source dest

Currently it seems you can only support:

myapp copy -src source -dst dest

Error attribute is ignored when RunConsole is used

CLAP registers it's own default error handler in RunConsole that overrides the one defined by the ErrorAttribute.

Probably the handler specified by the user should have priority. Currently RunConsole gives the user no possibility to control error handling.

couldn't make it work

code and documentation seems to be different, I couldn't find a working example and it's not self explanatory, had to move to another library

[PreVerbExecution] method not called for [Empty] verb

This issue can be reproduced always with CLAP version 4.6.0 NuGet package in a .NET FW 4.8 console app.

The docs for [Empty] read: Marks a method to be executed when there is no input. The method must not accept any parameter except if marked along with [Help].
I expect [PreVerbExecution] handler to be called for all the verbs and there is no indication that this is not the case.

Steps to reproduce

  1. Create a new console project and add CLAP 4.6.0 from NuGet. I called mine MyConsole.
  2. Add this code to Program.cs:
static void Main(string[] args) {
    Parser.Run(args, new Program());
}

[Empty]
[Verb]
private void MyVerb() {
    Console.WriteLine("MyVerb");
}

[PreVerbExecution]
private void MyPreVerb() {
    Console.WriteLine("MyPreVerb");
}
  1. Run MyConsole MyVerb and the output is like this:
MyPreVerb
MyVerb
  1. Now run it without arguments MyConsole and the output is like this:
MyVerb

Workaround

Change MyVerb() like so:

//[Empty]
[Verb(IsDefault = true)]
private void MyVerb() {
    Console.WriteLine("MyVerb");
}

Possible solutions

  1. Call [PreVerbExecution] when the method is annotated with both [Empty] and [Verb] but not when it is annotated with [Help]
  2. Call [PreVerbExecution] for all verbs regardless of [Empty]. This is less flexible than # 1.
  3. Add a parameter to control the behavior of [Empty]:
[Empty(IgnorePreVerb = false)]
[Verb]
private void MyVerb() {
    Console.WriteLine("MyVerb");
}

IMO this is the best choice.
4. Clearly document the current behabior.

Help text of parameters not displayed

The help text of parameters is not being displayed ..
eg for [Parameter(Description = "A bool parameter, which can be used as a switch")]
bool verbose,

when we type abc.exe help on command line It displays text of description from methods only and not the ones from the parameter.

Support for Enum Flags?

First I want to thank you for your great work!

Is there a way to provide enum parameters which are defined as flags and or'ed together?

[Flags]
enum FileType {
    Csv,
    Excel
}

[Verb]
void CreateFiles([Parameter] FileType fileType) { ... }

How to call the method with Csv and Excel enabled?

MySuperApp createfiles -filetype=Csv|Excel

Thanks in advance
Thomas

Required property on ParameterAttribute not working

I'm trying to validate the parameters I'm given using the Required property on my Parameter attributes, but it doesn't seem to do anything.

    private static void Start (
        [Parameter(Required = true, Description = "The defect number.")] int? n,
        [Parameter(Required = true, Description = "The workspace folder parent.")] string dir)
    {
        Console.WriteLine("{0}, {1}", n, dir);
    }

Invoking this application with no arguments just results in , being logged (no errors). Am I misunderstanding how Required is supposed to work?

Add support for Argument Models

please add support for arguments models ,
most CLI frameworks are supporting this via Property attributes,
this increases code reuse and makes the code look much cleaner
i like everything about his framework except this aspect
some of the applications i create are quite large CLI programs for development and deployment tooling this is the only thing stopping me from using this for our larger projects , as the verb method signatures quickly get very messy and unruly with more then a few verb arguments

Remove Windows.Forms Dependency

Hi,
I noticed this pretty handy tool and I'm wondering if it is still maintained? I want to get rid of the System.Windows.Forms dependency (followed by System.Data). I would recommend a separate project that could be published as NuGet package as well. So if you need a UI component, you can add this to your project as additional package. As I see, that is not a big effort since the architecture is pretty nice. If you're okay with that, I could work something out! In that case I would also update all included NuGet packages as well.

Maybe we can also get rid of Newtonsoft and System.Data so that the main program gets a little more slighter.

Merge #24 break when an exception is not serializable

Hi,
in the latest version (3.5.2) of autofac, to support the PCL the author(Nicholas Blumhardt) removed the SerializableAttribute(and the associated constructor) from the DependecyResolutionException class.
(autofac/Autofac@1db4ee4, file Core/Source/Autofac/Core/DependencyResolutionException.cs)
The merge [https://github.com//pull/24] will cause Clap to fail when trying to serialize such exception.
There should be some conditional checking and maybe a fallback on the old behavior if the exception is not serializable.

Thanks,
MrJingle

Allow [DirectoryExists], [FileExists], [PathExists] to be applied to global parameters

I'd like to expose a global parameter that is essentially a data directory.

I'm trying to do something like:

[Global("d")]
[DirectoryExists]
public void DataDir(string dir)
{
    this.dataDir = dir;
}

But, of course I can't because the DirectoryExistsAttribute is marked with [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter)]

It would be very helpful to allow these validation attributes on global parameters

Parameter Help format

Could we update the parameter help text that is output, currently

/i /id : (String) (Required)

will be displayed but we can use -i or -id as well as the separators -i= -id= or -i: -id:

/i /id -i -id (valid separators are : or =) : (String) (Required)

Also I have no verb for debug yet /debug shows in the help text output, I love this library and it is Kick-Ass!

Return 1

I like how CLAP applications given a bad command give back a useful message. They ought to fail in the Unix sense, ie. give a non-zero return code

$ git party ; echo  $?
git: 'party' is not a git command. See 'git --help'.
1

Whereas with a CLAP app:

 Verb 'party' was not found
 0

Nasty exception on `program.exe .`

program.exe . gives the nasty exception

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at CLAP.MultiParser.GetSingleTypeParser(String[] args, Object obj, ParserRegistration registration) in C:\Projects\CLAP\master\CLAP\MultiParser.cs:line 148
   at CLAP.MultiParser.RunTargets(String[] args, Object[] targets) in C:\Projects\CLAP\master\CLAP\MultiParser.cs:line 199

Whereas program.exe - is nicely handled.

Simpler scenarios support

Hi,
This looks cool but seems to require the developer perceive their app as being invoked:

application.exe <verb> <args>

Is it possible to use CLAP in a minimal way allowing simple:

application.exe <args>

The flexibility and generality is excellent but forcing that pattern for simple app's seems overkill.

Allow sequence of Verbs

For my specific application, I'll need to be able to issue a sequence of verbs to configure the application before the final verb executes the application action.

For instance:

app.exe verb1 /option1=value /option2=value verb2 /option1=value /option2=value ...

This would require that each verb method could be executed multiple times as well. For instance:

app.exe verb1 /option1=value1 verb1 /option1=value2 verb1 /option1=value3 ...

Now to get really specific, a real example of how it will be used:

mp.exe template /file="template.xml" data /file="data.json" compiler /engine="mustache#" output /file="render.xml"

And:

mp.exe template /file="template.xml" data /file="author.json" /as="Author" data /file="book.json" /as="Book" compiler /engine="mustache#" output /file="render.xml"

Is executing a verb sequence currently supported? Can it be done easily? When I try it is throwing CLAP.MissingArgumentPrefixException, saying it should be prefixed with one of "/" or "-".

I'm also with the crowd that would probably rather see the GNU-style parameters supported, especially with Microsoft moving towards an open-source .NET. Something like:

mp.exe template --file="template.xml" data --file="data.json" compiler --engine="mustache#" output --file="render.xml"

A single dash has been used in the past to either indicate the presence of a single-character parameter with or without a value or a sequence of single-character switches that do not have values. E.g. -a -b=123 -defgh

Great work so far. I would be interested in implementing both of these features if you would like.

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.