Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: document cloud-core #9

Merged
merged 30 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d83ef9a
chore: port over the existing docs
Citymonstret Nov 28, 2023
28dad53
provide snippets for maven & gradle
Citymonstret Nov 28, 2023
ae498f9
disable instant :)
Citymonstret Nov 28, 2023
0b484a3
fix the navigation names
Citymonstret Nov 28, 2023
e2b7404
stuff x
Citymonstret Nov 28, 2023
b1011e0
more scaffolding
Citymonstret Nov 28, 2023
5e87fe9
some parser docs
Citymonstret Nov 28, 2023
5100660
Update docs/core/index.md
Citymonstret Nov 28, 2023
5aaa0cf
explain parsing
Citymonstret Nov 29, 2023
bac12a8
Update docs/core/index.md
Citymonstret Nov 29, 2023
92769be
explain execution coordinators & exception handling
Citymonstret Nov 29, 2023
5d64c03
explain processing
Citymonstret Nov 29, 2023
220eb98
some improvements & disable cookie consent form for now
Citymonstret Nov 29, 2023
02feed1
test out social
Citymonstret Nov 29, 2023
2a9cd06
Revert "test out social"
Citymonstret Nov 29, 2023
4755698
document the new exception handling api
Citymonstret Dec 3, 2023
936086b
document the parser registry
Citymonstret Dec 3, 2023
6d2050d
start documenting commands
Citymonstret Dec 3, 2023
d0408b2
document permissions
Citymonstret Dec 3, 2023
411db0a
document sender types
Citymonstret Dec 3, 2023
fc56983
document literals
Citymonstret Dec 3, 2023
0ddc9e9
explain the new caption system
Citymonstret Dec 9, 2023
170fca2
hlep
Citymonstret Dec 10, 2023
20dfed4
we now support spring bby
Citymonstret Dec 17, 2023
cc57b4b
explain how to produce suggestions
Citymonstret Dec 17, 2023
4e275ca
document meta
Citymonstret Dec 21, 2023
b67cdda
disable the nav footer
Citymonstret Dec 21, 2023
b7bcb51
very extensive component documentation
Citymonstret Dec 21, 2023
15c965d
ok docs finished idc anymore bye
Citymonstret Dec 21, 2023
cccfbdb
restore cookie consent modal
Citymonstret Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
326 changes: 317 additions & 9 deletions docs/core/index.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,328 @@
# cloud-core

Version: xCLOUD_BASE_VERSIONx
`cloud-core` contains the main cloud API.
Generally you'll want to depend on a platform module which implements Cloud for your specific platform, as
`cloud-core` does not have any platform-specific code.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Auctor elit sed vulputate mi sit amet mauris. Sollicitudin ac orci phasellus egestas tellus. Habitasse platea dictumst quisque sagittis purus. Gravida neque convallis a cras semper auctor. Sed libero enim sed faucibus. Consequat id porta nibh venenatis cras sed felis eget velit. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse. Eu turpis egestas pretium aenean pharetra magna ac placerat. Leo duis ut diam quam nulla porttitor massa. Faucibus et molestie ac feugiat sed lectus vestibulum mattis. Non nisi est sit amet facilisis magna etiam tempor orci.
## Installation

## Aliquam
Cloud is available through [Maven Central](https://search.maven.org/search?q=cloud.commandframework).

Aliquam nulla facilisi cras fermentum odio eu. Auctor urna nunc id cursus metus aliquam eleifend. Scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis. Commodo nulla facilisi nullam vehicula ipsum a. Ultricies lacus sed turpis tincidunt. Montes nascetur ridiculus mus mauris vitae. Ultrices mi tempus imperdiet nulla malesuada. Lacus sed viverra tellus in hac habitasse. Consectetur a erat nam at. Blandit cursus risus at ultrices mi tempus. Gravida in fermentum et sollicitudin ac. Diam maecenas ultricies mi eget mauris pharetra et ultrices neque. Proin libero nunc consequat interdum varius. Montes nascetur ridiculus mus mauris vitae ultricies leo integer. Tellus id interdum velit laoreet id donec ultrices. Mi sit amet mauris commodo quis imperdiet massa tincidunt nunc. Eget nullam non nisi est sit amet facilisis magna. Nunc sed velit dignissim sodales. Sapien faucibus et molestie ac. Diam in arcu cursus euismod quis viverra nibh cras.
<!-- prettier-ignore -->
=== "Maven"
```xml
<dependency>
<groupId>cloud.commandframework</groupId>
<artifactId>cloud-core</artifactId>
<version>dCLOUD_BASE_VERSIONd</version>
</dependency>
```
=== "Gradle (Kotlin)"
```kotlin
implementation("cloud.commandframework:cloud-core:dCLOUD_BASE_VERSIONd")
```
=== "Gradle (Groovy)"
```groovy
implementation 'cloud.commandframework:cloud-core:dCLOUD_BASE_VERSIONd'
```

## Fermentum
## Command

Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Nulla aliquet enim tortor at auctor urna. Dui id ornare arcu odio ut sem nulla pharetra. Nibh praesent tristique magna sit amet purus gravida quis. Curabitur vitae nunc sed velit dignissim sodales ut eu. Interdum velit laoreet id donec ultrices tincidunt. Id nibh tortor id aliquet lectus proin nibh nisl condimentum. Mi eget mauris pharetra et ultrices neque. Cursus risus at ultrices mi tempus imperdiet nulla malesuada. Tellus orci ac auctor augue mauris augue neque. Velit scelerisque in dictum non consectetur a erat nam at. Montes nascetur ridiculus mus mauris vitae ultricies. Consequat id porta nibh venenatis cras sed felis eget. Amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae tempus quam pellentesque nec nam aliquam sem et tortor. Malesuada fames ac turpis egestas. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus mattis. Sit amet nulla facilisi morbi tempus iaculis urna. Pharetra pharetra massa massa ultricies mi.
A command is a chain of components. Each unique chain makes up a unique command.
A command can have some properties associated with it, such as a permission, description, etc.

## Pharetra
<!-- prettier-ignore -->
!!! example
All of these are examples of unique commands:
```
/foo bar one
/foo bar two <arg1> -- Command with a required variable
/bar [arg] -- Command with an optional variable
```

### Components

There are four different types of components:

1. Literals: A string literal with optional aliases.
2. Required variables: A variable component which gets parsed by a parser, that must be present.
3. Optional variables: A variable component which gets parsed by a parser, that must not necessarily be present.
An optional component may have a default value.
4. Flags: Named components that are always optional. They may have an associated variable component.
Examples: `--flag value`, `-abc`.

Cloud requires that the command chains are unambiguous.
This means that you may not have a required component following an optional component.
You may also not have two conflicting variable components on the same level, as it would not be clear
which of them gets to parse the input.
You may have _one_ variable component alongside literals, where the literals always get priority.

### Variable Components

A variable component is associated with an output type.
It takes the incoming input and attempts to parse it into the output type using a parser.
See the section on [parsers](#parsers) for more information.

#### Suggestions

Cloud can generate suggestions for values which, depending on the platform, can be displayed
to the player to help them complete the command input.
Most standard parsers generate suggestions, and by default Cloud will ask the parser for suggestions.
You may provide your own suggestions using a suggestion provider.

## Command Manager

### Creating a command manager

#### Execution coordinators

### Building a command

#### Descriptions

#### Permissions

#### Sender types

#### Components

#### Literals

#### Variable

##### Required

##### Optional

### Executing a command

### Customizing the command manager

#### Pre-processing

#### Post-processing

#### Exception handling

## Parsers

### Parser Registry

### Standard Parsers

Cloud ships with parsers for all Java primitives as well as strings, enums, UUIDs and durations.

#### String

Cloud has four different string "modes":

- **Single**: A single space-delimited string.
- **Quoted**: Either a single space-delimited string, or multiple space-delimited
strings surrounded by a pair of single or double quotes.
- **Greedy**: All remaining input.
- **Greedy flag yielding**: All remaining input until a [flag](#flags) is encountered.

The string parsers do not produce suggestions by default.

The string parsers can be created using the static factory methods found in [StringParser](TODO).

#### String Array

Cloud can parse string arrays, in which case it captures all remaining input.
A string array parser may also be flag yielding, in which case it will only capture input until
it encounters a [flag](#flags).

The string array parser does not produce suggestions by default.

The string array parser can be created using the static factory methods found in [StringArrayParser](TODO).

#### Character

This parses a single space-delimited character.
The character parser does not produce suggestions by default.

The character parser can be created using the static factory methods found in [CharacterParser](TODO).

#### Numbers

Cloud has parsers for bytes, shorts, integers, longs, doubles and floats.
The numerical values may have min- and max-values set.

All numerical parsers except for `FloatParser` and `DoubleParser` will produce suggestions.

Pharetra magna ac placerat vestibulum. Enim praesent elementum facilisis leo vel fringilla. Sapien et ligula ullamcorper malesuada proin. Id aliquet risus feugiat in ante metus dictum at. Mattis pellentesque id nibh tortor. Cras ornare arcu dui vivamus arcu felis bibendum ut tristique. Cras fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus. Mus mauris vitae ultricies leo integer. Leo vel fringilla est ullamcorper eget. Mattis enim ut tellus elementum sagittis vitae et. Leo urna molestie at elementum eu facilisis sed odio morbi. Nunc congue nisi vitae suscipit tellus mauris a diam maecenas. Lectus vestibulum mattis ullamcorper velit sed ullamcorper. Aliquam etiam erat velit scelerisque in dictum non. Risus in hendrerit gravida rutrum.
The numerical parsers can be created using the static factory methods found in:

- [ByteParser](TODO)
- [ShortParser](TODO)
- [IntegerParser](TODO)
- [LongParser](TODO)
- [DoubleParser](TODO)
- [FloatParser](TODO)

#### Boolean

The boolean parser can either be strict or liberal.
A strict boolean parser only accepts (independent of the case) `true` and `false`.
A liberal boolean parser also accepts `yes`, `no`, `on` and `off`.

The boolean parser can be created using the static factory methods found in [BooleanParser](TODO).

#### Enum

The enum parser matches the input (independent of the case) to the names of an enum. The parser will return
the enum values as suggestions.

The enum parser can be created using the static factory methods found in [EnumParser](TODO).

#### Duration

Durations can be parsed.

#### UUID

The UUID parser parses dash-separated UUIDs.

The UUID parser can be created using the static factory methods found in [UUIDParser](TODO).

### Flags

Flags are named optional values that can either have an associated value (value flags),
or have their value be determined by whether the flag is present (presence flags).

Flags are always optional.
You cannot have required flags.
If you want required values, then they should be part of a deterministic command chain.
Flags are parsed at the tail of a command chain.

Flags can have aliases alongside their full names.
When referring to the full name of a flag, you use `--name` whereas an alias uses the syntax `-a`.
You can chain the aliases of multiple presence flags together, such that `-a -b -c` is equivalent to `-abc`.

The flag values are contained in `FlagContext` which can be retrieved using `CommandContext.flags()`.

<!-- prettier-ignore -->
!!! example
Example of a command with a presence flag.
```java
manager.commandBuilder("command")
.flag(manager.flagBuilder("flag").withAliases("f"))
.handler(context -> {
boolean present = context.flags().isPresent("flag");
));
```

### Aggregate Parsers

Aggregate parsers are a new concept as of Cloud v2, and they supersede the old compound argument concept.
An aggregate parser is a combination of multiple parsers that maps the intermediate results into an output
type using a mapper.

You may either implement the `AggregateCommandParser` interface, or using construct the parser by using a builder
that you create by calling `AggregateCommandParser.builder()`.

<!-- prettier-ignore -->
!!! example
Sit amet volutpat consequat mauris nunc congue nisi vitae. Volutpat sed cras ornare arcu dui vivamus arcu felis bibendum. At consectetur lorem donec massa sapien faucibus. Ut faucibus pulvinar elementum integer enim neque volutpat. Nunc congue nisi vitae suscipit tellus. Viverra aliquet eget sit amet tellus cras adipiscing enim. Praesent tristique magna sit amet purus gravida quis. Sed blandit libero volutpat sed cras ornare. Lectus quam id leo in vitae turpis massa sed elementum. Nunc aliquet bibendum enim facilisis gravida neque convallis a cras. Molestie ac feugiat sed lectus vestibulum. Proin fermentum leo vel orci porta. Vitae elementum curabitur vitae nunc sed velit. Sit amet consectetur adipiscing elit duis tristique sollicitudin nibh. Ac tortor dignissim convallis aenean et tortor. Nunc sed velit dignissim sodales ut eu sem integer. Euismod nisi porta lorem mollis aliquam.
```java
final AggregateCommandParser<CommandSender, Location> locationParser = AggregateCommandParser.<CommandSender>builder()
.withComponent("world", worldParser())
.withComponent("x", integerParser())
.withComponent("y", integerParser())
.withComponent("z", integerParser())
.withMapper(Location.class, (commandContext, aggregateCommandContext) -> {
final World world = aggregateCommandContext.get("world");
final int x = aggregateCommandContext.get("x");
final int y = aggregateCommandContext.get("y");
final int z = aggregateCommandContext.get("z");
return CompletableFuture.completedFuture(new Location(world, x, y, z));
}).build();
```

### Custom Parsers

Cloud allows you to create your own parsers.
A parser accepts a command context and a command input,
and produces a result (or a future that completes with a result).

The context allows the parser to accept parsed results from other command components, which can be useful when
the result of the parser depends on other parsed components.
The command input is a structure that allows you to consume the input supplied by the command sender by peeking &
then reading primitive values and strings.

A parser can fail when the input does not match the expectations.
The command manager will turn the failure into a command syntax exception which can then be displayed to the
sender, informing them about what went wrong.

The recommended way of parsing an argument is to:

1. Peek the command input.
2. Attempt to parse the object.
- If the object cannot be parsed, a failure is returned.
3. Pop from the command input.
4. Return the parsed value.
5. <!-- prettier-ignore -->
!!! warning
If the read values are not popped from the command input the command engine will assume that the syntax is wrong
and an error message is sent to the command sender.

The parser has two different choices when it comes to which method to implement.
If the parser implements `ArgumentParser` then the signature looks like

```java
public ArgumentParseResult<OutputType> parse(
CommandContext<SenderType> context,
CommandInput input) { ... }
```

where the `ArgumentParseResult` can either be a `ArgumentParseResult.success(OutputType)` or
`ArgumentParseResult.failure(Exception)`.

The parser may also implement `ArgumentParser.FutureParser` in which case the signature looks like

```java
public CompletableFuture<OutputType> parseFuture(
CommandContext<SenderType> context,
CommandInput input) { ... }
```

in which case, a successful result is returned as a completed future, and a failure is instead returned as an
exceptionally completed future.
Returning a future is useful when the parsing needs to take place on a specific thread.

<!-- prettier-ignore -->
!!! example
```java
public class UUIDParser<C> implements ArgumentParser<C, UUID> {

@Override
public ArgumentParseResult<UUID> parse(
CommandContext<C> context,
CommandInput input
) {
final String input = input.peekString(); // Does not the remove the string!
Citymonstret marked this conversation as resolved.
Show resolved Hide resolved
try {
final UUID uuid = UUID.fromString(input);
input.readString(); // Removes the string from the input.
return ArgumentParseResult.success(uuid);
} catch(final IllegalArgumentException e) {
return ArgumentParseResult.failure(new UUIDParseException(input, commandContext));
}
}
}
```

#### Exceptions

It is recommended to make use of `ParserException` when returning a failed result.
This allows for integration with the caption system, see [exception handling](#exception-handling) for more information.

#### Suggestions

The parser may implement the `suggestions` method to produce suggestions.
These suggestions will be used to provide suggestions for the component using the parser,
unless the component is created using a custom suggestion provider.

## Extra

### Confirmations

### Help generation
58 changes: 57 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,59 @@
# Cloud

Hello :)
Cloud is a JVM framework for creating user commands.
A command is a chain of parsed arguments and a handler that gets invoked with the parsed values.
Cloud is not made to be used in any specific software, but it has modules with support for Minecraft
(Bukkit/Paper, BungeeCord, Velocity, Fabric, CloudBurst, Sponge & NeoForge), Discord (JavaCord & JDA)
and IRC (PIrcBotX).

Cloud allows you to write commands either using builders or annotated methods, and has special support for Kotlin.
Cloud allows you to customize the command execution pipeline by injecting custom behavior along the entire
execution path.

This document does not aim to cover every single detail of Cloud, but will instead introduce you to various different
concepts and explain how they can be used in your software
For technical details, we ask you to look at the [JavaDoc](https://javadocs.dev/cloud.commandframework).

We have a set of examples that introduce some useful Cloud concepts.
They are written for the Bukkit Minecraft API but the examples are not specific to Minecraft:
[example-bukkit](https://github.com/Incendo/cloud/tree/iCLOUD_BASE_BRANCHi/examples/example-bukkit).

## Structure

The documentation is split into different sections for the different Cloud modules.
It is highly recommended that you get started with the [cloud-core](./core/index.md) docs before you delve into the
platform-specific docs.
If you want to use annotated command methods, then you should start out with [cloud-core](./core/index.md) and then
move over to [cloud-annotations](./annotations/index.md).

## Development Builds

Development builds of Cloud are available on the Sonatype Snapshots Repository:

<!-- prettier-ignore -->
=== "Maven"
```xml
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
```
=== "Gradle (Kotlin)"
```kotlin
maven("https://oss.sonatype.org/content/repositories/snapshots/") {
name = "sonatype-snapshots"
mavenContent {
snapshotsOnly()
}
}
```
=== "Gradle (Groovy)"
```groovy
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
name "sonatype-snapshots"
mavenContent {
snapshotsOnly()
}
}
```
Loading
Loading