Skip to content

Commit 76c0514

Browse files
committed
Initial commit
0 parents  commit 76c0514

40 files changed

+3184
-0
lines changed

.gitattributes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# https://help.github.com/articles/dealing-with-line-endings/
3+
#
4+
# Linux start script should use lf
5+
/gradlew text eol=lf
6+
7+
# These are Windows script files and should use crlf
8+
*.bat text eol=crlf
9+

.github/workflows/main.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: CI
2+
on:
3+
push:
4+
branches: [ main ]
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- uses: actions/setup-java@v2
11+
with:
12+
java-version: '16'
13+
distribution: 'temurin'
14+
cache: gradle

.gitignore

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
.gradle
2+
build/
3+
!gradle/wrapper/gradle-wrapper.jar
4+
!**/src/main/**/build/
5+
!**/src/test/**/build/
6+
7+
### IntelliJ IDEA ###
8+
.idea/
9+
.idea/modules.xml
10+
.idea/jarRepositories.xml
11+
.idea/compiler.xml
12+
.idea/libraries/
13+
*.iws
14+
*.iml
15+
*.ipr
16+
out/
17+
!**/src/main/**/out/
18+
!**/src/test/**/out/
19+
20+
### Eclipse ###
21+
.apt_generated
22+
.classpath
23+
.factorypath
24+
.project
25+
.settings
26+
.springBeans
27+
.sts4-cache
28+
bin/
29+
!**/src/main/**/bin/
30+
!**/src/test/**/bin/
31+
32+
### NetBeans ###
33+
/nbproject/private/
34+
/nbbuild/
35+
/dist/
36+
/nbdist/
37+
/.nb-gradle/
38+
39+
### VS Code ###
40+
.vscode/
41+
42+
### Mac OS ###
43+
.DS_Store

COPYRIGHT.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Licensing Information
2+
3+
Copyright 2023 Michael Käser
4+
5+
Copyrights in this project are retained by contributors. No copyright assignment
6+
is required to contribute to this project.
7+
8+
Except as otherwise noted (below and/or in individual files), this project is
9+
licensed under the Apache License, Version 2.0
10+
([`LICENSE-APACHE`](LICENSE-APACHE) or
11+
http://www.apache.org/licenses/LICENSE-2.0) or the MIT license,
12+
([`LICENSE-MIT`](LICENSE-MIT) or http://opensource.org/licenses/MIT), at your
13+
option.

LICENSE-APACHE

Lines changed: 403 additions & 0 deletions
Large diffs are not rendered by default.

LICENSE-MIT

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Copyright 2023 Michael Käser
2+
3+
Permission is hereby granted, free of charge, to any
4+
person obtaining a copy of this software and associated
5+
documentation files (the "Software"), to deal in the
6+
Software without restriction, including without
7+
limitation the rights to use, copy, modify, merge,
8+
publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software
10+
is furnished to do so, subject to the following
11+
conditions:
12+
13+
The above copyright notice and this permission notice
14+
shall be included in all copies or substantial portions
15+
of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21+
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24+
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25+
DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# [JCP](https://github.com/mickare/jcp) - Java Command Pipeline
2+
3+
![Build and Publish](https://github.com/mickare/jcp/actions/workflows/main.yml/badge.svg) [![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-informational?style=flat-square)](COPYRIGHT.md)
4+
5+
A Java library for creating custom command line parser and command pipelines.
6+
7+
Do you need a **slim**, **minimalistic**, **easy to use** and **extensible** command line parser?
8+
You want to return more than just an integer?
9+
You want to supply custom context data to the command execution?
10+
Then you may have found the right library.
11+
12+
## Table of Contents
13+
14+
- [Install](#install)
15+
- [Usage](#usage)
16+
- [FAQ](#faq)
17+
- [Contributing](#contributing)
18+
- [License](#license)
19+
20+
21+
## Install
22+
23+
> Placeholders! The project has not yet been released to maven central
24+
25+
**Maven**
26+
27+
```
28+
<dependency>
29+
<groupId>de.mickare.jcp</groupId>
30+
<artifactId>jcp</artifactId>
31+
<version>0.0.1</version>
32+
</dependency>
33+
```
34+
35+
**Gradle (Groovy)**
36+
37+
```
38+
dependencies {
39+
implementation 'de.mickare.jcp:jcp:0.0.1'
40+
}
41+
```
42+
43+
**Gradle (Kotlin)**
44+
45+
```
46+
dependencies {
47+
implementation("de.mickare.jcp:jcp:0.0.1")
48+
}
49+
```
50+
51+
## Usage
52+
53+
Define your commands with a class and declare the command arguments and options as class fields.
54+
Options and arguments must be annotated and are inherited from base classes.
55+
56+
```java
57+
import de.mickare.jcp.*;
58+
59+
public class MyCommand extends AbstractCommand<V, R> {
60+
61+
@Option(names = {"-v", "--value"})
62+
private final String value = false;
63+
64+
@Argument(name = "other", symbol = "N", nargs = 1)
65+
private List<String> other;
66+
67+
public R execute(CommandContext<V> context) throws Exception {
68+
return #...
69+
}
70+
}
71+
```
72+
73+
Build the command pipeline with your commands.
74+
The command pipeline will parse the input arguments, instantiate your command objects and fill the options and
75+
arguments.
76+
77+
```java
78+
public static CommandPipeline<MyCommand, V, R> buildPipeline(){
79+
CommandPipeline.Builder<MyCommand, V, R> builder=CommandPipeline.builder(MyCommand.class,"main");
80+
// Add custom data parser
81+
builder.getParser().register(MyCustomType.class,new MyCustomTypeParser());
82+
83+
// Add subcommands
84+
builder.addSubcommand(MySubCommandA.class,"a");
85+
builder.addSubcommand(MySubCommandB.class,"b");
86+
return builder.build();
87+
}
88+
```
89+
90+
Run the command pipeline with provided arguments and handle possible exceptions.
91+
92+
```java
93+
public static R example(V context,String[]args)throws Exception{
94+
try{
95+
return buildPipeline().execute(context,args);
96+
}catch(IllegalArgumentException ex){
97+
// handle
98+
System.err.println(ex.getMessage());
99+
return null;
100+
}
101+
}
102+
```
103+
104+
###
105+
106+
### Command Line Interface
107+
108+
This example shows how you can use JCP in a classic CLI use-case.
109+
You can find this example in [examples](examples/ExampleCLI.java).
110+
111+
```java
112+
package myapp;
113+
114+
115+
import de.mickare.jcp.*;
116+
117+
import java.time.DayOfWeek;
118+
import java.util.List;
119+
120+
public class Main {
121+
122+
public static void main(String[] args) {
123+
Context ctx = new Context("nice");
124+
try {
125+
Integer exitCode = buildPipeline().execute(ctx, args);
126+
System.exit(exitCode);
127+
} catch (IllegalArgumentException ex) {
128+
System.err.println(ex.getMessage());
129+
System.exit(1);
130+
} catch (Exception ex) {
131+
System.err.println("Unexpected error: " + ex);
132+
ex.printStackTrace();
133+
System.exit(2);
134+
}
135+
}
136+
137+
private static CommandPipeline<MainCommand, Context, Integer> buildPipeline() {
138+
CommandPipeline.Builder<MainCommand, Main.Context, Integer> builder = CommandPipeline.builder(MainCommand.class, "myapp");
139+
return builder.build();
140+
}
141+
142+
public record Context(String text) {
143+
}
144+
145+
public static class MainCommand extends AbstractHelpedCommand<Context, Integer> {
146+
147+
@Option(names = {"-y", "--yes"}, store_true = true, desc = "Flag that stores true")
148+
private final boolean yes = false;
149+
150+
@Option(names = {"--day"}, desc = "Day of the week")
151+
private final DayOfWeek day = DayOfWeek.MONDAY;
152+
153+
@Argument(name = "other", symbol = "N", nargs = -0, desc = "Additional args")
154+
private List<String> other;
155+
156+
public Integer execute2(CommandContext<Context> context) throws Exception {
157+
System.out.printf("text=%s, yes=%s; day=%s; other=%s%n",
158+
context.getData().text, this.yes, this.day, String.join(",", this.other));
159+
return 0;
160+
}
161+
}
162+
}
163+
```
164+
165+
## FAQ
166+
167+
### Why yet another CLI library?
168+
169+
There are many great & advanced CLI libraries for Java, but many are too specialized to be the main entrypoint.
170+
By design those libraries expect an exit code to be returned back to the operating system.
171+
And because it is never expected that a CLI is called more than once, there is no way to pass custom context data to the
172+
command execution.
173+
This makes it near impossible to use in other use-cases, e.g. when your application keeps running and parses new
174+
commands from stdin.
175+
176+
### Is this a CLI library?
177+
178+
Yes and no.
179+
You can use this library to parse and run commands, but you'll have to implement basic plumbing to make this a working
180+
CLI.
181+
182+
## Contributing
183+
184+
Unless you explicitly state otherwise, any contribution intentionally submitted
185+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
186+
dual licensed as below, without any additional terms or conditions.
187+
188+
## License
189+
190+
Copyright 2023 Michael Käser
191+
192+
This project is licensed under either of
193+
194+
- [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([`LICENSE-APACHE`](LICENSE-APACHE))
195+
- [MIT license](https://opensource.org/licenses/MIT) ([`LICENSE-MIT`](LICENSE-MIT))
196+
197+
at your option.

build.gradle.kts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2023 Michael Käser
3+
*
4+
* This file is free software: you can redistribute it and/or modify
5+
* it under the terms of either the Apache License, Version 2.0 or the MIT License.
6+
*
7+
* You may obtain a copy of the Apache License, Version 2.0 and the MIT License at
8+
* <http://www.apache.org/licenses/LICENSE-2.0> and
9+
* <https://opensource.org/licenses/MIT>, respectively.
10+
*/
11+
12+
plugins {
13+
id("java-library")
14+
id("maven-publish")
15+
}
16+
17+
group = "de.mickare.jcp"
18+
version = "0.0.1"
19+
20+
repositories {
21+
mavenCentral()
22+
}
23+
24+
dependencies {
25+
implementation("org.jetbrains:annotations:24.0.0")
26+
compileOnly("org.projectlombok:lombok:1.18.26")
27+
annotationProcessor("org.projectlombok:lombok:1.18.26")
28+
testCompileOnly("org.projectlombok:lombok:1.18.26")
29+
testAnnotationProcessor("org.projectlombok:lombok:1.18.26")
30+
testImplementation("org.junit.jupiter:junit-jupiter:5.9.1")
31+
}
32+
33+
java {
34+
withSourcesJar()
35+
withJavadocJar()
36+
}
37+
38+
tasks.test {
39+
useJUnitPlatform()
40+
}
41+
42+
publishing {
43+
publications {
44+
register<MavenPublication>("jpc") {
45+
from(components["java"])
46+
}
47+
}
48+
repositories {
49+
maven {
50+
name = "GitHubPackages"
51+
url = uri("https://maven.pkg.github.com/mickare/jcp")
52+
credentials {
53+
username = project.findProperty("gpr.user") as String? ?: System.getenv("USERNAME")
54+
password = project.findProperty("gpr.key") as String? ?: System.getenv("TOKEN")
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)