tool

Visionary Software Solutions Tool: command-line tools written once and run by name

Write a command-line tool by stating its name, its arguments and its work; a module providing it as a FromCommandLine launches as that tool.

Rationale

Why. A ToolProvider leaves reading arguments, printing help and refusing to each tool. Aenima does them once, so every tool does them alike.

Key Concepts

Aenima

Role. The ToolProvider and FromCommandLine a tool extends, stating name(), arguments(String...) and answer(Invocation).

Pattern. Template Method

ToolProviderToCommand

Role. An ADAPTER from a ToolProvider and its arguments to a commander Command, which throws when the tool exits other than 0, quoting what it said.

Lane

Purpose. Writing a command-line tool, and launching it or running it from Java.

Alternative. The JDK's ToolProvider.findFirst, when the tool's exact name is known and its status is read by hand.

Usage

Write a tool: its arguments, its name, its work

public record Root(List<Path> value) implements Required<List<Path>> {
    public static Root create(final String said) {
        return new Root(Stream.of(said.split("\u001f", -1)).map(Path::of).toList());
    }
}

public final class Arguments extends software.visionary.argumentative.Arguments {
    public Arguments(final String... line) {
        super(line, accepted -> accepted.option(Root.class, Root::create));
    }
}

public final class FindShape extends Aenima {
    @Override
    protected Arguments arguments(final String... line) {
        return new Arguments(line);
    }

    @Override
    public String name() {
        return "find-shape";
    }

    @Override
    protected String answer(final Invocation invocation) {
        final List<Path> roots = invocation.required(Root.class);
        roots.forEach(root -> invocation.emitProgress("censusing " + root));
        return census(roots);
    }
}

Give it help: a bundle beside the class, its package opened to tool

# src/main/resources/com/example/shape/FindShape.properties
help=Censuses source roots for one structural shape.\n\
Example: find-shape --root src/main/java

// module-info.java
opens com.example.shape to software.visionary.tool;

# find-shape --help
#   Censuses source roots for one structural shape.
#   Example: find-shape --root src/main/java

Run it from Java: run it, throw if it fails

new ToolProviderToCommand(new FindShape(), List.of("--root", "src/main/java")).execute();

Launch it: its module provides it as a FromCommandLine, and the whole line is its arguments

// module-info.java
provides software.visionary.cthulu.FromCommandLine with com.example.shape.FindShape;

ServiceLoader.load(FromCommandLine.class).findFirst().orElseThrow()
        .apply(new String[]{"--root", "src/main/java"})
        .execute();

Dependencies

  • software.visionary:cthulu:2026.10.13 at Compile
  • software.visionary.contrax:processor:2026.10.13 at Processor
  • software.visionary:junit-closure:2026.09.17 at Testing

Caveats

  • Progress goes to err as the work runs; the answer goes to out once, at the end, so a refusal leaves no half answer on out.
  • The bundle's help is plain text, not a MessageFormat, and is the tool's whole description.
  • A tool whose non-zero status is still an answer calls complain() and returns the answer; throwing discards it.
  • What arguments(String...) throws escapes run and apply, before any work; a refusal from the work is exit 1, its message on err.

Views

Drawn from the release. A link in a view opens its source at the release tag.

architecture.svg
architecture.svg
classes.software.visionary.tool.svg
classes.software.visionary.tool.svg
packages.svg
packages.svg