Skip to content

Commit

Permalink
Documentation fixs
Browse files Browse the repository at this point in the history
  • Loading branch information
erdnaxeli committed Apr 11, 2021
1 parent 620cf45 commit 6b6fb2a
Show file tree
Hide file tree
Showing 25 changed files with 454 additions and 428 deletions.
8 changes: 4 additions & 4 deletions docs/alternatives.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
# Alternatives, inspirations and comparisons

**Clip** is not the only library to parse CLI parameters.
**Clip** is not the only library you can use to parse CLI parameters.
Here are some alternatives and inspirations.

## <a href="https://typer.tiangolo.com" class="external-link" target="_blank">Typer</a>

> Typer is a library for building CLI applications that users will love using and developers will love creating.
Typer is actually a Python library and an awesome project!
Typer is actually an awesome Python library.
It inspired a lot **Clip**, whether for the idea of using type restrictions, the general behavior of the lib (what to consider an option or an argument, the help message), or even this documentation.

## <a href="https://crystal-lang.org/api/1.0.0/OptionParser.html" class="external-link" target="_blank">OptionParser</a>

> `OptionParser` is a class for command-line options processing.
It works by using a specific DSL to react to options or arguments during the parsing.
It works by using a specific DSL to execute blocks of code on command, options and arguments during the parsing.

## <a href="https://github.com/jwaldrip/admiral.cr" class="external-link" target="_blank">Admiral.cr</a>

> A robust DSL for writing command line interfaces
Admiral provides an easy way to define command using a user defined type and a DSL.
Admiral provides an easy way to define commands using inheritance and a DSL.

## <a href="https://github.com/mrrooijen/commander" class="external-link" target="_blank">Commander</a>

Expand Down
8 changes: 4 additions & 4 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Contributing

Feel free to contribute to **Clip**.
Feel free to contribute to **Clip**!

If you spot a bug, you can [open a pull request](https://github.com/erdnaxeli/clip/pulls) to fix it.
If you want to contribute but are not sure about how to do it, just [open an issue](https://github.com/erdnaxeli/clip/issues) to talk discuss about it.
If you are not sure how to do it, just [open an issue](https://github.com/erdnaxeli/clip/issues) to discuss about it.

Here are some tips to develop on **Clip**, assuming you have already cloned the repository.

Expand All @@ -24,7 +24,7 @@ Postinstall of ameba: make bin && make run_file

Always remember to commit your modification on a separated branch.

The majority of the **Clip** features are done by macros.
The majority of the **Clip** features are done with macros.
Macros look like Crystal code, but they actually use a different language that is interpreted at compilation time by the compiler.
The code is not easy to read, don't hesitate to ask for help!

Expand Down Expand Up @@ -66,4 +66,4 @@ Finished in 279.16 milliseconds
## Open a pull request

Your code is now done, congrats!
Your can open a pull request, I will try to at it quickly :)
Your can open a pull request, I will try to look at it quickly :)
26 changes: 13 additions & 13 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,43 @@

## Static typing

**Clip** use a user defined type, a struct or a class, to infer what options and arguments should be parsed.
**Clip** uses a user defined type, struct or class, to infer what options and arguments should be parsed.

The object returned by the **Clip** parsing method is just an instance of this type, hence you benefit from the compilation time type validation.
The object returned by the **Clip** parsing method is just an instance of this type, hence you benefit from the type validation at compilation time.

## No DSL to learn

There is no new DSL to learn to build applications with **Clip**.

You want to add a string option? Just add an attribute and restrict its type to `String`.
You want to add a string option? Just add an attribute with a type `String`.

You want to add a default value? Just add a default value to the attribute.
You want the option to have a default value? Just add a default value to the attribute.

You already know how to do it.

## Standard behaviors
## User friendly

**Clip** allows you to build beautiful applications that respect standard behaviors.
**Clip** allows you to build user friendly applications that respect standard behaviors.
Anything you expect from a CLI application should work with **Clip** too: short and long options, flags, arguments, default values, multiple values, standard help messages, and many more.

## Not a CLI application framework

**Clip** is about parsing CLI-like user input, but is not a framework to build CLI applications.

It means that **Clip** does not run your application code for you, does not print anything for you, and can read the user input from any array of strings, not only `ARGV`.
It means that **Clip** does not run your application code for you, does not print anything for you, and can read the user input from any array of strings or just any string, not only `ARGV`.

Not running your code application for you means that you are free to architecture you code as you like.
Your command's code can take the parsed options and arguments as a parameter, and anything else too, because _you_ run by yourself, **Clip** does not.
Not running your application code for you means that you are free to architecture you code as you like.
Your command's code can take the parsed options and arguments as a parameter, and others parameters too, because _you_ run it yourself, **Clip** does not.

Not printing anything for you means that you can send errors and help messages to any medium, being a `STDOUT`, a socket, or anything else.
Not printing anything for you means that you can send errors and help messages to any medium, being `STDOUT`, a socket, or anything else.

Reading the input from any array of strings means that you can use **Clip** to build applications that are not _CLI applications_.
Reading the user input not only from `ARGV` means that you can use **Clip** to build applications that are not _CLI applications_.
You can receive the user input from an HTTP call, an IRC message, a REPL, or whatever you want.

## Efficient

**Clip** uses your type definition to write a parser and build the hel message.
The parser and the help messages are built at compilation time, which enabled **Clip** to have a minimal overhead at runtime.
**Clip** uses your type definition to write a parser and build the help message for each command.
The parsers and the help messages are built at compilation time, which enabled **Clip** to have a minimal overhead at runtime.

## Tested

Expand Down
2 changes: 1 addition & 1 deletion docs/help.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Get help
# Get help — Help Clip

This project use [github Discussions](https://github.com/erdnaxeli/clip/discussions) for community discussions.
Don't hesitate to start a discussion if you need help!
Expand Down
16 changes: 8 additions & 8 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
---

Clip is a library for building CLI or CLI-like [Crystal](https://crystal-lang.org) applications.
By CLI-like applications I mean every application that interacts with the user in a CLI style, like IRC bots.
_A CLI-like application_ means any application that interacts with the user in a CLI style, like IRC bots.

The major features of Clip are:

* **Easy to write**: All you need to write is a type. No new DSL to learn, and compilation time type validation.
* **Easy to use**: Make beautiful applications with standard behaviors and automatic error and help messages.
* **Easy to write**: All you need to write is a class (or struct). No new DSL to learn, and compilation time type validation.
* **Easy to use**: Make user friendly applications with standard behaviors and automatic error and help messages.
* **You are in control**: No code automatically executed for you, no messages printed to stdout. You do what you want, when you want.

## Requirements
Expand Down Expand Up @@ -82,7 +82,7 @@ Hello Alice

## Advanced example

Let's do a more advanced, with some subcommands.
Let's do a more advanced, with some commands.

```Crystal hl_lines="6-9 32 33 35"
require "clip"
Expand All @@ -94,18 +94,17 @@ abstract struct Command
"hello" => HelloCommand,
"goodbye" => GoodbyeCommand,
})
getter name : String
end
struct HelloCommand < Command
include Clip::Mapper
getter name : String
end
struct GoodbyeCommand < Command
include Clip::Mapper
getter name : String
getter sad = false
end
Expand All @@ -130,9 +129,10 @@ when Clip::Mapper::Help
end
```

That add two new subcommands: "hello" and "goodbye".
It adds two commands: "hello" and "goodbye".

```console
$ crystal build command.cr
$ ./command
Error: you need to provide a command.
$ ./command help
Expand Down
78 changes: 39 additions & 39 deletions docs/user guide/arguments/multiple.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

So far we only used one argument, but it is not uncommon for a command to support multiple arguments.

To do that with **Clip** you just have to specify other attributes:
To do that with **Clip** we just have to define other attributes:

```Crystal hl_lines="9"
```Crystal hl_lines="9 10"
require "clip"
module Mycommand
module Myapplication
VERSION = "0.1.0"
struct Command
Expand Down Expand Up @@ -37,25 +37,25 @@ module Mycommand
end
end
Mycommand.run
Myapplication.run
```

Our command now have two arguments, `NAME` and `REPEAT`:
Our command has now two arguments: `NAME` and `REPEAT`.

```console hl_lines="5 8-9 13"
$ shards build
Dependencies are satisfied
Building: mycommand
$ ./bin/mycommand --help
Usage: ./bin/mycommand [OPTIONS] NAME REPEAT
Building: myapplication
$ ./bin/myapplication --help
Usage: ./bin/myapplication [OPTIONS] NAME REPEAT

Arguments:
NAME [required]
REPEAT [required]

Options:
--help Show this message and exit.
$ ./bin/mycommand 2 Alice
$ ./bin/myapplication 2 Alice
Hello Alice
Hello Alice
```
Expand All @@ -66,19 +66,19 @@ You may have noticed something strange in the previous example.
The usage says "NAME REPEAT" but I wrote "2 Alice", so "REPEAT NAME".
Unfortunately, this behavior comes from the Crystal compiler itself.

When we include `Clip::Mapper`, two macros are ran to generate the parser and the help message.
Those macro rely on `TypeNode#instance_vars` to get all the type's attributes.
When we include `Clip::Mapper`, two macros are run to generate the parser and the help message.
Those macros rely on `TypeNode#instance_vars` to get all the type's attributes.
Sadly, this method does not always return the attributes as they were ordered in the type declaration.
Even sadder, multiple calls can return attributes in a different order.
With our example the parser saw `repeat` and then `name`, but the help saw `name` and then `repeat`.

That's why **Clip** provides a way to ensure the arguments ordering.
It is done with the annotation `Clip::Argument`, by using a named parameter `idx`:
It is done with the annotation `Clip::Argument`, with a named parameter `idx`:

```Crystal hl_lines="9 11"
require "clip"
module Mycommand
module Myapplication
VERSION = "0.1.0"
struct Command
Expand Down Expand Up @@ -110,25 +110,25 @@ module Mycommand
end
end
Mycommand.run
Myapplication.run
```

Now the arguments are correctly ordered both in the help message and in the parser:
The arguments are now correctly ordered both in the help message and in the parser:

```console hl_lines="5 13"
$ shards build
Dependencies are satisfied
Building: mycommand
$ ./bin/mycommand --help
Usage: ./bin/mycommand [OPTIONS] REPEAT NAME
Building: myapplication
$ ./bin/myapplication --help
Usage: ./bin/myapplication [OPTIONS] REPEAT NAME

Arguments:
REPEAT [required]
NAME [required]

Options:
--help Show this message and exit.
$ ./bin/mycommand 1 Alice
$ ./bin/myapplication 1 Alice
Hello Alice
```

Expand All @@ -138,29 +138,29 @@ A little note about how the argument are _consummed_ from the user input.
Let's take the following command definition:

```console
Usage: ./bin/mycommand [OPTIONS] REPEAT NAME
Usage: ./bin/myapplication [OPTIONS] REPEAT NAME
```

This command has two required arguments.
**Clip** always consumes arguments from **left to right**.
So if the user input is `./bin/mycommand 2 Alice`, **Clip** will consume `2` and use it as the value for `REPEAT`, then it will consume `Alice` and use it as the value for `NAME`.
So if the user input is `./bin/myapplication 2 Alice`, **Clip** consumes `2` and uses it as the value for `REPEAT`, then it consumes `Alice` and uses it as the value for `NAME`.

So far so good.
But what if we make `REPEAT` an optional argument?
The command definition now looks like this:

```console
Usage: ./bin/mycommand [OPTIONS] [REPEAT] NAME
Usage: ./bin/myapplication [OPTIONS] [REPEAT] NAME
```

When we give the two arguments, **Clip** maps them both, everything is ok.
But if we give only one argument, **Clip** still tries to map it with `REPEAT` as it consume arguments from left to right.
When we give both arguments, **Clip** maps them both, and everything is ok.
But if we give only one argument, **Clip** still maps it with `REPEAT`, as it consumes arguments from left to right.
Then it finds no value for `NAME` and raises an error:

```Crystal hl_lines="10"
require "clip"
module Mycommand
module Myapplication
VERSION = "0.1.0"
struct Command
Expand Down Expand Up @@ -192,37 +192,37 @@ module Mycommand
end
end
Mycommand.run
Myapplication.run
```

```console hl_lines="5 8 16-19"
$ shards build
Dependencies are satisfied
Building: mycommand
$ ./bin/mycommand --help
Usage: ./bin/mycommand [OPTIONS] [REPEAT] NAME
Building: myapplication
$ ./bin/myapplication --help
Usage: ./bin/myapplication [OPTIONS] [REPEAT] NAME

Arguments:
REPEAT [default: 1]
NAME [required]

Options:
--help Show this message and exit.
$ ./bin/mycommand 2 Alice
$ ./bin/myapplication 2 Alice
Hello Alice
Hello Alice
$ ./bin/mycommand Alice
$ ./bin/myapplication Alice
Error:
argument's value is invalid: REPEAT
argument is required: NAME
```

Now let's make `NAME` optional instead:
Let's make `NAME` optional instead:

```Crystal hl_lines="10 12"
require "clip"
module Mycommand
module Myapplication
VERSION = "0.1.0"
struct Command
Expand Down Expand Up @@ -254,28 +254,28 @@ module Mycommand
end
end
Mycommand.run
Myapplication.run
```

If we give only one argument **Clip** maps it to `REPEAT`, and as `NAME` is optional no error is raised:

```console hl_lines="5 8 9 16"
$ shards build
Dependencies are satisfied
Building: mycommand
$ ./bin/mycommand --help
Usage: ./bin/mycommand [OPTIONS] REPEAT [NAME]
Building: myapplication
$ ./bin/myapplication --help
Usage: ./bin/myapplication [OPTIONS] REPEAT [NAME]

Arguments:
REPEAT [required]
NAME [default: Barbara]

Options:
--help Show this message and exit.
$ ./bin/mycommand 2 Alice
$ ./bin/myapplication 2 Alice
Hello Alice
Hello Alice
$ ./bin/mycommand 1
$ ./bin/myapplication 1
Hello Barbara
```

Expand Down
Loading

0 comments on commit 6b6fb2a

Please sign in to comment.