Skip to content

Commit

Permalink
Update documentation and README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
yakovypg committed Aug 6, 2024
1 parent 31bf4c1 commit 95436a7
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Docs/CustomConverters.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Custom converters allow you to easily work with options whose values are non-sta
## Converter Types
There are three converter types: value converter, multiple value converter and enum value converter. They are used in value options, multiple value options and enum value options. However, in the vast majority of situations it is sufficient to use only the value converter.

Furthermore, you can create your own converters. To do this you need to inherit your class from the `IValueConverter` interface. You can also use an existing option class as a base class. See examples of this kind of inheritance, for example, by looking at the implementation of the `MultipleValueConverter` and `EnumValueConverter` classes.
Furthermore, you can create your own converters. To do this you need to inherit your class from the `IValueConverter` interface and implement it. You can also use an existing option class as a base class. See examples of this kind of inheritance, for example, by looking at the implementation of the `MultipleValueConverter` and `EnumValueConverter` classes. Next, you can use this class in the same way as the standard ones.

### Value Converter
To create a value converter for type T, you need a function that takes a string and returns T. Pass this function to the constructor of the appropriate class as shown in the example below.
Expand Down
2 changes: 1 addition & 1 deletion Docs/OptionalArguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ parser.Parse(new string[] { "--split-option", "TrimEntries" });
```

## Custom Options
You can create your own options. To do this you need to inherit your class from the `ICommonOption` interface. You can also use an existing option class as a base class. See examples of this kind of inheritance, for example, by looking at the implementation of the `FlagOption` and `EnumValueOption` classes.
You can create your own options. To do this you need to inherit your class from the `ICommonOption` interface and implement it. You can also use an existing option class as a base class. See examples of this kind of inheritance, for example, by looking at the implementation of the `FlagOption` and `EnumValueOption` classes. Next, you can use this class in the same way as the standard ones.

## Option Groups
Options can be divided into groups. This division may be useful when there are a lot of options.
Expand Down
122 changes: 113 additions & 9 deletions Docs/PrintingHelp.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ Argument parser uses description generator to geterate command-line help. If you
* [Change Headers](#change-headers)
* [Change usage header](#change-usage-header)
* [Change default option group header](#change-default-option-group-header)
* [Change subcommands header](#change-subcommands-header)
* [Change Delimiters](#change-delimiters)
* [Change option example delimiters](#change-option-example-delimiters)
* [Change subcommand name delimiters](#change-subcommand-name-delimiters)
* [Configure Printing Space](#configure-printing-space)
* [Configure window width](#configure-window-width)
* [Configure maximum space for option example](#configure-maximum-space-for-option-example)
* [Custom Description Generator](#custom-description-generator)
* [Change Output Stream](#change-output-stream)
* [Custom Description Generators](#custom-description-generators)
* [Custom Application Description Generator](#custom-application-description-generator)
* [Custom Subcommand Description Generator](#custom-subcommand-description-generator)

## Add Program Information
You can specify name, version, description and epilog of your program. To do this, you need to set values in the corresponding properties, as shown in the example below.
Expand Down Expand Up @@ -43,17 +49,20 @@ Text at the bottom
**NetArgumentParser** allows you to customize the generating of command-line help. You can configure an existing generator or [create](#custom-description-generator) your own.

### Change Headers
You can change a header of the `usage` section and a default option group header.
You can change header of the `usage` section, header of the `subcommands` section and a default option group header.

#### Change usage header
To change a header of the `usage` section you need to create description generator and specify corresponding property in it. You can do this the same way as in the following example.

```cs
var parser = new ArgumentParser();
var generator = new DescriptionGenerator(parser)

var generator = new ApplicationDescriptionGenerator(parser)
{
UsageHeader = "My Usage: "
};

parser.DescriptionGenerator = generator;
```

The output will be like the following:
Expand Down Expand Up @@ -82,16 +91,50 @@ Default group:
...
```

#### Change subcommands header
To change a header of the `subcommands` section you need to create description generator and specify corresponding property in it. You can do this the same way as in the following example.

```cs
var parser = new ArgumentParser();

var generator = new ApplicationDescriptionGenerator(parser)
{
SubcommandsHeader = "My Subcommands:"
};

parser.DescriptionGenerator = generator;
```

The output will be like the following:

```
Usage: ...
Options:
...
My Subcommands: ...
...
```

### Change Delimiters
You can change a delimiters before and after option example. You can do this the same way as in the following example.
You can change the following delimiters:
- Before and after option example.
- Before and after subcommand name.

#### Change option example delimiters
You can change delimiters before and after option example. You can do this the same way as in the following example.

```cs
var parser = new ArgumentParser();
var generator = new DescriptionGenerator(parser)

var generator = new ApplicationDescriptionGenerator(parser)
{
OptionExamplePrefix = "@@",
DelimiterAfterOptionExample = " -> "
};

parser.DescriptionGenerator = generator;
```

The output will be like the following:
Expand All @@ -104,6 +147,33 @@ Options:
@@--version -> show version information
```

#### Change subcommand name delimiters
You can change delimiters before and after subcommand name. You can do this the same way as in the following example.

```cs
var parser = new ArgumentParser();

var generator = new ApplicationDescriptionGenerator(parser)
{
SubcommandNamePrefix = "@@",
DelimiterAfterSubcommandName = " -> "
};

parser.DescriptionGenerator = generator;
```

The output will be like the following:

```
Usage: ...
Options:
...
Subcommands:
@@resize -> resize the image
```

### Configure Printing Space
You can specify window width and maximum space for option example.

Expand All @@ -112,22 +182,56 @@ The width of the window is set in order to correctly wrap the components of the

```cs
var parser = new ArgumentParser();
var generator = new DescriptionGenerator(parser)

var generator = new ApplicationDescriptionGenerator(parser)
{
WindowWidth = Console.WindowWidth
};

parser.DescriptionGenerator = generator;
```

#### Configure maximum space for option example
You can specify a character limit for the option examples. This is useful for small windows to prevent running out of space to describe options. The default value for this limit is 30, but you can change it as follows:

```cs
var parser = new ArgumentParser();
var generator = new DescriptionGenerator(parser)

var generator = new ApplicationDescriptionGenerator(parser)
{
OptionExampleCharsLimit = 25
};

parser.DescriptionGenerator = generator;
```

## Custom Description Generator
You can create your own description generator. To do this you need to inherit your class from the `IDescriptionGenerator` interface. You can also use an existing description generator class as a base class. See example of this kind of inheritance, for example, by looking at the implementation of the `DescriptionGenerator` class.
## Change Output Stream
You can change output stream in which all information and messages are written. To do this you need to create a custom class inherited from the `ITextWriter` interface and pass it to the `ChangeOutputWriter()` method. You can also use an existing text writer class as a base class. See example of this kind of inheritance, for example, by looking at the implementation of the `ConsoleTextWriter` class.

```cs
var parser = new ArgumentParser();
parser.ChangeOutputWriter(new ConsoleTextWriter());
```

## Custom Description Generators
You can create your own application description generator and subcommand description generator. This can be useful if you want to implement your own command-line help generation system.

### Custom Application Description Generator
You can create your own application description generator. To do this you need to inherit your class from the `IDescriptionGenerator` interface and implement it. You can also use an existing `ParserQuantumDescriptionGenerator` class as a base class. See example of this kind of inheritance, for example, by looking at the implementation of the `ApplicationDescriptionGenerator` class. Next, you can use this class in the same way as the standard ones.

```cs
var parser = new ArgumentParser();
var generator = new ApplicationDescriptionGenerator(parser);

parser.DescriptionGenerator = generator;
```

### Custom Subcommand Description Generator
You can create your own subcommand description generator. To do this you need to inherit your class from the `IDescriptionGenerator` interface and implement it. You can also use an existing `ParserQuantumDescriptionGenerator` class as a base class. See example of this kind of inheritance, for example, by looking at the implementation of the `SubcommandDescriptionGenerator` class. Next, you can use this class in the same way as the standard ones.

```cs
var parser = new ArgumentParser()
{
SubcommandDescriptionGeneratorCreator = t => new SubcommandDescriptionGenerator(t)
};
```
68 changes: 68 additions & 0 deletions Docs/Subcommands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Subcommands
Many programs split up their functionality into a number of subcommands. For example, `dotnet` can invoke subcommands like `dotnet new`, `dotnet add`, and `dotnet build`. Splitting up functionality this way can be an extremely good idea when a program performs several different functions which require different kinds of command-line arguments.

outputweiret
descriptiongeneratorcreator

## Table of Contents
* [Basics](#basics)
* [Create Subcommand](#create-subcommand)
* [Configure Subcommand](#configure-subcommand)
* [Default Help Option](#default-help-option)
* [Nested Subcommands](#nested-subcommands)

## Basics
You can create and configure any number of subcommands and nested subcommands. Please note that subcommand names must be unique within each subcommand. Furthermore, subcommands have its own option namespace, which allows you to have options with the same name in different subcommands.

### Create Subcommand
`ArgumentParser` supports the creation of subcommands with the `AddSubcommand()` method.

```cs
var parser = new ArgumentParser();
Subcommand subcommand = parser.AddSubcommand("name", "description");
```

### Configure Subcommand
Subcommands have the same properties and methods for working with options and converters as the parser. For example, you can add options to the subcommand using `AddOptions()` method, add converters using `AddConverters()` method and add option group using `AddOptionGroup()` method.

```cs
bool verbose = false;
bool debug = false;

var parser = new ArgumentParser();
Subcommand subcommand = parser.AddSubcommand("name", "description");

subcommand.AddOptions(new FlagOption("verbose", afterHandlingAction: () => verbose = true));
subcommand.AddConverters(new ValueConverter<int>(Convert.ToInt32));

OptionGroup<ICommonOption> subcommandGroup = subcommand.AddOptionGroup("group");
subcommandGroup.AddOptions(new FlagOption("debug", afterHandlingAction: () => debug = true));
```

### Default Help Option
By default, subcommands are supplied with standard help option. However, you can specify that help option isn't needed. To do this, you can set the appropriate value for property `UseDefaultHelpOption` or add your own help option.

```cs
var parser = new ArgumentParser();

Subcommand subcommand = parser.AddSubcommand("name", "description");
resizeSubcommand.UseDefaultHelpOption = false;
```

```cs
var parser = new ArgumentParser();

Subcommand subcommand = parser.AddSubcommand("name", "description");
subcommand.AddOptions(new HelpOption());
```

## Nested Subcommands
You can create nested subcommands. It means that each subcommand can have its own subcommands. For example, `dotnet` program has `dotnet add` subcommand, which has a `dotnet add reference` subcommand.

```cs
var parser = new ArgumentParser();

Subcommand subcommand = parser.AddSubcommand("name1", "description1");
Subcommand subsubcommand = subcommand.AddSubcommand("name2", "description2");
Subcommand subsubsubcommand = subsubcommand.AddSubcommand("name3", "description3");
```
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</p>

## About
**NetArgumentParser** is a cross-platform, free and open source library for parsing command-line options and arguments.
**NetArgumentParser** is a cross-platform, free and open source library for parsing command-line options, arguments and sub-commands.

[![Contributors](https://img.shields.io/github/contributors/yakovypg/NetArgumentParser)](https://github.com/yakovypg/NetArgumentParser/graphs/contributors)
[![Build Status](https://img.shields.io/github/actions/workflow/status/yakovypg/NetArgumentParser/dotnet.yml?branch=main)](https://github.com/yakovypg/NetArgumentParser/actions/workflows/dotnet.yml?query=branch%3Amain)
Expand All @@ -31,26 +31,29 @@

## Main Features
This library supports the following main features:
- Parse options starting with a minus (such as `-v`).
- Parse options starting with a double minus (such as `--version`).
- Parse options starting with a slash (such as `/v` or `/version`).
- Parse short-named options (such as `-v`).
- Parse long-named options (such as `--version` or `-version`).
- Parse windows-based options (such as `/v` or `/version`).
- Parse compound options (such as `-lah`).
- Parse long name options starting with a minus (such as `-version`).
- Parse nested subcommands (such as `app subcommand subsubcommand`).
- Extract extra arguments.
- Support custom converters.
- Configure command-line help generation.
- Provide a lot of default option types.
- Support custom options and converters.
- Configure command-line help generation and output stream.

Many other features you can find in [documentation](#documentation).

## Quick Start
To start working with the library you need to build it and then connect it to your project.
To start working with the library you need to [connect](#connect-project) it to your project. If you are going to connect a library cloned from a repository, you may want to [build](#build-project) and [test](#test-project) it before doing so.

### Build Project
You can [build](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-build) the library with the following command, which should be run from the root of the library.
You can [build](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-build) the library with the following command, which should be run from the root of the library project.
```
dotnet build
```

### Test Project
You can [test](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test) the library with the following command, which should be run from the root of the library.
You can [test](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test) the library with the following command, which should be run from the root of the library project.
```
dotnet test
```
Expand All @@ -60,7 +63,6 @@ You can find instructions for connecting **NetArgumentParser** to your project [

## Project Status And TODO List
**NetArgumentParser** is currently under development. There are some features that need to be added to the project:
- Add support of subcommands.
- Add support of reflection-based configuring option set using special attributes.
- Add support of import and export JSON configuration.
- Add support of parent parsers.
Expand All @@ -73,6 +75,7 @@ The main topics are:
- [Optional arguments](Docs/OptionalArguments.md)
- [Optional arguments config](Docs/OptionalArgumentsConfig.md)
- [Custom converters](Docs/CustomConverters.md)
- [Subcommands](Docs/Subcommands.md)
- [Printing help](Docs/PrintingHelp.md)
- [Additional features](Docs/AdditionalFeatures.md)

Expand All @@ -83,4 +86,4 @@ The project is developed on the .NET 8.0 platform. To continue development you w
Contributions are welcome, have a look at the [CONTRIBUTING.md](CONTRIBUTING.md) document for more information.

## License
The project is available under the [GPL-3.0](LICENSE) license.
The project is available under the [GPLv3](LICENSE) license.

0 comments on commit 95436a7

Please sign in to comment.