• Stars
    star
    134
  • Rank 270,967 (Top 6 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created almost 11 years ago
  • Updated about 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A framework to build command-line console applications in Java

Build Status

Clamshell-Cli

Clamshell-Cli is a framework for building console-based command-line applications in Java. Clamshell uses a simple plugin architecture (based on the [http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html ServiceLoader API]) that let developers deploy components to build components with control over all aspects of console-based applications including splashscreen display, IO, prompt, input control, and command delegation. Clamshell-Cli comes with a default runtime that implements all of the basic components needed for a fully functioning console-based app. To customize the runtime with your own command, you simply create and deploy your own plugin jars (see example below).

News

Features

  • Easy to get started
  • Small API footprint with low learning curve
  • Ability to build complex CLI tools such as REPL using plugin architecture
  • Simple component model that imposes little constraints on your design
  • The plugin architecture is designed for extensibility and feature-scalability:
    • If you don't like how the default implementation works, you can change it completely
    • Implement the components you want to change and your feature will be included next time the console is restarted
  • Statically-defined extension points provide control over all facets of console-based apps including:
    • A Splashscreen
    • Console IO
    • Prompt
    • Input Controller
    • Command Handlers
  • Each extension point is mapped to a Java type for easy implementation
  • Plugins are deployed as simple jar files
  • Support for input hints (tab-press at the console)
  • Support for input buffer history

Getting Started

It's easy to get started with Clamshell-Cli to build your first console application.

  • First, download the packaged zipped binary distribution from this site. This is a default runtime implementation that you can use for your own CLI tools.
  • Unzip at a location of your choice. The zip file will create a directory named clamshellcli-{version} (will refer to it as {CLI_HOME}).
  • Change directory inside {CLI_HOME} and inspect the files. You will see the followings:
-rw-r--r--@ 1 299   Mar  17 cli.config
-rw-r--r--@ 1 3748  Mar  18 cli.jar
drwxrwxrwx  5 170   Mar  18 clilib
drwxrwxrwx  4 136   Mar  18 lib
drwxrwxrwx  5 170   Mar  18 plugins
* `cli.config` - Clamshell-Cli configuration file 
* `cli.jar` - the launcher jar file
* `clilib` - lib files to boot Clamshell-Cli
* `lib` - place your dependency jars here
* `plugins` - location for Clamshell-Cli plugin jars

From within {CLI_HOME}, start the Clamshell-Cli launcher by typing:

> java -jar cli.jar
 .d8888b.  888                         .d8888b.  888               888 888
d88P  Y88b 888                        d88P  Y88b 888               888 888
888    888 888                        Y88b.      888               888 888
888        888  8888b.  88888b.d88b.   :Y888b.   88888b.   .d88b.  888 888
888        888     :88b 888 :888 :88b     :Y88b. 888 :88b d8P  Y8b 888 888
888    888 888 .d888888 888  888  888       :888 888  888 88888888 888 888
Y88b  d88P 888 888  888 888  888  888 Y88b  d88P 888  888 Y8b.     888 888
 :Y8888P:  888 :Y888888 888  888  888  :Y8888P:  888  888  :Y8888  888 888

                                                  Command-Line Interpreter

Java version: 1.6.0_22
Java Home: /usr/lib/jvm/java-6-openjdk/jre
OS: Linux, Version: 2.6.38-10-generic

prompt> _

Rightaway, you see three plugins in action:

  • Splashscreen Plugin - displays the ASCII text art scree
  • The Prompt - displays the current prompt at the command-line
  • The IOConsole - accepts user input at the command-line

The default runtime does not do too much. It does, however, provide a command/controller implementation. An internal Input Controller (a plugin) parses input from the command-line, then delegates handling of the input to a registered Command plugin (if any).

If you type 'help' at the prompt, for instance, you will be actually invoking the HelpCmd plugin which lists help info for all Command objects that are mapped. Each command is backed by a plugin class installed in the plugins directory.

prompt> help

Available Commands
------------------
      exit       Exits ClamShell.
      help       Displays help information for available commands.
   sysinfo       Displays current JVM runtime information.
      time       Prints current date/time

prompt> _

Adding A Command

As stated above, Clamshell-Cli uses a plugin architecture. All extension points of the framework can be customized by providing your own plugins. This section shows how to add a new Command plugin and deploy it. It examines the implementation of the time command using the TimeCmd plugin (deployed with the runtime).

Here are the simple steps for creating your own Command:

  • Create a new Java project (standard or maven) in your favorite IDE with a class that extends interface org.clamshellcli.api.Command interface (see below).
  • Package your project as a ServiceLoader SPI jar file (say, time-cmd-0.1.jar) and drop it in directory plugins
  • Voila! You just added your first command to Clamshell-Cli

The Code

public class TimeCmd implements Command {
    private static final String NAMESPACE = "syscmd";
    private static final String ACTION_NAME = "time";

    @Override
    public Object execute(Context ctx) {
        IOConsole console = ctx.getIoConsole();
        console.writeOutput(String.format("%n%s%n%n",new Date().toString()));
        return null;
    }

    @Override
    public void plug(Context plug) {
        // no load-time setup needed
    }
    
    @Override
    public Command.Descriptor getDescriptor(){
        return new Command.Descriptor() {
            @Override public String getNamespace() {return NAMESPACE;}
            
            @Override
            public String getName() {
                return ACTION_NAME;
            }

            @Override
            public String getDescription() {
               return "Prints current date/time";
            }

            @Override
            public String getUsage() {
                return "Type 'time'";
            }

            @Override
            public Map<String, String> getArguments() {
                return Collections.emptyMap();
            }
        };
    }
}

A quick explanation of the code is in order:

  • Method execute() - invoked by the input controller instance when it detects the String time from the command-line. The method retrieves the IOConsole from the context object and use it to print the time. It returns null to the controller (indicating the command did not generate a result).
  • Method plug() - a lifecycle method that is invoked by the framework when the command is first initialized. For our example, there nothing to do.
  • Method getDescriptor() - returns an instance of interface Command.Descriptor which is used to describe the features and document the Command. For our example, the Descriptor interface is implemented anonymously with the following methods:
    • Method Descriptor.getNamespace() - returns a string identifying the command's namespace. This value can be used by input controllers to avoid command name collisions.
    • Method Descriptor.getName() - returns the string mapped to this command object. In our implementation, it returns "time".
    • Method Descriptor.getUsage() - intended to provide a descriptive way of using the command.
    • Method Descriptor.getArguments() - returns a Map containing the description for each arguments that may be attached to the command. This example uses none.

Package Your Plugin

Once your class compiles properly, package the project as a standard Java Service provider (SPI). To do this, do the followings:

  • In your source tree, create service descriptor text file META-INF/services/org.clamshellcli.api.Plugin
  • On the first line of that file, put demo.command.TimeCmd (assuming the class is placed in package demo.command).
  • Next, save the text file and package the project as a jar file (it is important that the descriptor text file gets copied into your jar)

Find more information on Java's Service Loader API:

Update File cli.config

Before your command can be made available in the console, you must let Clamshell-cli know about it. cli.config is JSON-formatted configuration file where you declare and configure your input controller components. In order for your controller to respond to your command, you must configure the controller properly to respond to the input pattern corresponding to your command.

The sample code below shows the configuration of the Command Controller (default controller that comes with Clamshell-Cli):

    "controllers":{
        "org.clamshellcli.impl.CmdController":{
            "enabled":"true"
        }
        ...
    }

Deploy and Test the Command

  • Drop the jar file in the plugins/ directory (shown above).
  • Start the Clamshell-Cli runtime.
  • From the command-line type 'help' and you should see your new command listed.

Developing with the API

When creating your own console-based tool, you can integrate the Clamshell-Cli API by directly pointing to the jar files or use Maven.

Direct Setup

From within your Java IDE, add the followings to your classpath

  • {CLI_HOME}/clilib/clamshell-api-{version}.jar
  • {CLI_HOME}/clilib/clamshell-impl-core-{version}.jar

Maven Artifacts

  • Repository:
<repositories>
	<repository>
		<id>clamshellcli.repo</id>
		<name>Clamshell-Cli Repository</name>
		<url>http://s3.amazonaws.com/repo.clamshellcli.org/release</url>
	</repository>        
</repositories>
  • POM dependencies:
<dependency>
	<groupId>org.clamshellcli</groupId>
	<artifactId>clamshell-api</artifactId>
	<version>0.5.2</version>
</dependency>
<dependency>
	<groupId>org.clamshellcli</groupId>
	<artifactId>clamshell-impl-core</artifactId>
	<version>0.5.2</version>
</dependency>

Clamshell-Cli Examples

The best way to learn how to use the Clamshell-Cli API is to download the source code and look at how the Command plugins are implemented. You can also check out:

More Repositories

1

go-cshared-examples

Calling Go Functions from Other Languages using C Shared Libraries
Dart
875
star
2

automi

A stream processing API for Go (alpha)
Go
790
star
3

ktop

A top-like tool for your Kubernetes clusters
Go
728
star
4

gosh

Gosh - a pluggable framework for building command shell programs
Go
530
star
5

go-plugin-example

Playing around with Go 1.8 plugin system
Go
319
star
6

go-grpc

A collection of gRPC and Go examples showcasing features of the framework
Go
241
star
7

go4vl

A Go library for working with the Video for Linux API (V4L2).
C
236
star
8

learning-go

Source code repository for my book "Learning Go Programming"
Go
232
star
9

go-networking

Code sample for Learning Network Programming with Go
Go
226
star
10

gowfs

A Go client binding for Hadoop HDFS using WebHDFS.
Go
134
star
11

k8s-client-examples

Building stuff with the Kubernetes API
Go
118
star
12

gexe

Script-like OS interaction wrapped in the security and type safety of the Go programming language
Go
72
star
13

iot-dev

Example IoT projects
Go
70
star
14

jmx-cli

[Project Inactive] Jmx-Cli is a command-line interface console for JMX
Java
65
star
15

go-ntp-client

A Network Time Protocol client in Go
Go
50
star
16

gomes

Pure Go Framework API for Apache Mesos
Go
33
star
17

workbench

My code collection for testing new ideas, blog examples, etc
Java
32
star
18

go-tar

Examples using archive/tar compress/gz Go packages
Go
17
star
19

go-binary

Examples using encoding/binary package
Go
16
star
20

streaming-runtime-go

Go
11
star
21

docker.io-recipes

Some favorite Docker.Io recipes
9
star
22

dapr-examples

Examples of Dapr distributed services in Go
Go
6
star
23

go-tutorials

A place for quick Go tutorials
Go
5
star
24

startype

Roundtrip automatic conversion of Starlark-Go API types to regular Go types and back🤩
Go
4
star
25

go-algorithms

Classic CS algorithms examples in Go
Go
4
star
26

embedding-starlark

Examples of how to embed Starlark in Go programs using the Starlark-Go project
Go
4
star
27

go-httpmux-example

Example to show use of the new enhanced http.ServeMux router in Go v1.22.0 or later
Go
3
star
28

mesos-http

Example of Mesos HTTP API
Protocol Buffer
3
star
29

jmx-logger

JMX Logger for JUL and Log4J (old project & little support)
Java
3
star
30

kob

kob simplifies the programmatic construction of Kubernetes API object graphs
Go
2
star
31

gophercon2022

GopherCon 2022 - reveal.js presentation
JavaScript
2
star
32

timeapp

A simple application to print time based on configured time layout (perfect Kubernetes sample app)
Go
2
star
33

go-in-10

Go
2
star
34

mqt

MQT = Mesos Query Tool
Go
1
star
35

cloudy-apps

Cloud native application examples
Go
1
star
36

emojiis

Emojiis is a Go module for emoji icon search
Go
1
star
37

knative-workbench

Playing around with knative examples
Go
1
star
38

libstorage-client

Sample code on writing libstorage client code
Go
1
star
39

mango

Playground for an automated build tool in Go
Go
1
star
40

pourover

simple http reverse proxy
Go
1
star
41

vladimirvivien

1
star
42

go-tour

Examples and test code I use to tour the Go language and packages
Go
1
star
43

homebrew-oss-tools

Homebrew repository for distributing OSS binaries.
Ruby
1
star
44

go-workbench

A playground for Go proof of concepts
Go
1
star
45

horizon

Framework for building distributed apps
Go
1
star
46

e2eframework-controller-example

Repository for showing how to test Kubebuilder's Cronjob example controller using the e2e-framework - https://github.com/kubernetes-sigs/e2e-framework
Go
1
star