Add Javadoc examples to CLIHelper, Menu, Parser, and all option types (FileOption, StringOption, IntegerOption, etc.). Include code samples showing fluent API usage, command-line invocation examples, and error handling scenarios. Fix HTML formatting issues (misplaced </p> tags).
* an empty line.</li>
* </ul>
*
- * <h3>Usage example</h3>
+ * <h3>Usage examples</h3>
* <pre>{@code
+ * // Simple boolean prompt with default
* Boolean proceed = CLIHelper.askBoolean("Continue?", true);
- * Integer betweenFiveAndTen = CLIHelper.askInteger("Pick 5‑10", 7, 5, 10, false);
+ * // Console: "Continue? [true]: "
+ *
+ * // Integer with range validation
+ * Integer port = CLIHelper.askInteger("Port number", 8080, 1, 65535, false);
+ * // Console: "Port number [8080]: " - user must enter 1-65535
+ *
+ * // String with length constraints
* String name = CLIHelper.askString("Your name", "Anonymous", 2, 20, false);
+ * // Console: "Your name [Anonymous]: " - must be 2-20 characters
+ *
+ * // File that must exist and be readable
+ * File input = CLIHelper.askFile("Input file", null, true, true, null, null, false);
+ * // Console: "Input file: " - validates file exists and is readable
+ *
+ * // Directory selection
+ * File outputDir = CLIHelper.askDirectory("Output directory", new File("."));
+ * // Console: "Output directory [.]: "
+ *
+ * // Building a simple interactive CLI
+ * public static void main(String[] args) {
+ * System.out.println("Welcome to the installer!");
+ *
+ * if (!CLIHelper.askBoolean("Proceed with installation?", true)) {
+ * System.out.println("Installation cancelled.");
+ * return;
+ * }
+ *
+ * File targetDir = CLIHelper.askDirectory(
+ * "Installation directory",
+ * new File("/opt/myapp"),
+ * false, // doesn't need to exist yet
+ * null, null, null, false
+ * );
+ *
+ * int threads = CLIHelper.askInteger("Number of threads", 4, 1, 16, false);
+ *
+ * System.out.println("Installing to: " + targetDir);
+ * System.out.println("Using " + threads + " threads");
+ * }
* }</pre>
*/
public final class CLIHelper {
* </p>
* <p>
* Behavior for empty input:
+ * </p>
* <ul>
* <li>If a {@code defaultValue} is provided, returns it.</li>
* <li>If {@code allowEmpty} is {@code true}, returns {@code null}.</li>
* <li>Otherwise, continues prompting until valid input is provided.</li>
* </ul>
- * </p>
* @param prompt The prompt message to display (without trailing colon).
* @param defaultValue The default value to return if the user enters an empty line; may be {@code null}.
* @param allowEmpty If {@code true}, allows empty input to return {@code null}; otherwise, continues prompting.
* Prompts the user for a {@code float} value within optional bounds.
* <p>
* Behavior for empty input:
+ * </p>
* <ul>
* <li>If a {@code defaultValue} is provided, returns it.</li>
* <li>If {@code allowEmpty} is {@code true}, returns {@code null}.</li>
* <li>Otherwise, continues prompting until valid input is provided.</li>
* </ul>
- * </p>
* <p>
* Bounds are inclusive. If {@code min} or {@code max} is {@code null}, no check is applied.
* </p>
* Prompts the user for an {@code int} value within optional bounds.
* <p>
* Behavior for empty input:
+ * </p>
* <ul>
* <li>If a {@code defaultValue} is provided, returns it.</li>
* <li>If {@code allowEmpty} is {@code true}, returns {@code null}.</li>
* <li>Otherwise, continues prompting until valid input is provided.</li>
* </ul>
- * </p>
* <p>
* Bounds are inclusive. If {@code min} or {@code max} is {@code null}, no check is applied.
* </p>
* Prompts the user for a string value with optional length constraints.
* <p>
* Behavior for empty input:
+ * </p>
* <ul>
* <li>If a {@code defaultValue} is provided, returns it.</li>
* <li>If {@code allowEmpty} is {@code true}, returns {@code null}.</li>
* <li>Otherwise, continues prompting until valid input is provided.</li>
* </ul>
- * </p>
* <p>
* Length constraints are inclusive. If {@code minLength} or {@code maxLength} is {@code null}, no check is applied.
* </p>
* </p>
* <p>
* Behavior for empty input:
+ * </p>
* <ul>
* <li>If a {@code defaultValue} is provided, returns it.</li>
* <li>If {@code allowEmpty} is {@code true}, returns {@code null}.</li>
* <li>Otherwise, continues prompting until valid input is provided.</li>
* </ul>
- * </p>
* <p>
* Attribute checks:
+ * </p>
* <ul>
* <li>{@code mustExist}: if non-null, {@code true} requires file to exist, {@code false} requires it not to exist.</li>
* <li>{@code mustReadable}: if non-null, requires {@link File#canRead()} to match the value.</li>
* <li>{@code mustWritable}: if non-null, requires {@link File#canWrite()} to match the value.</li>
* <li>{@code mustExecutable}: if non-null, requires {@link File#canExecute()} to match the value.</li>
* </ul>
- * </p>
* @param prompt The prompt message to display.
* @param defaultValue The default file to return if the user enters an empty line; may be {@code null}.
* @param mustExist Whether the file must exist ({@code true}), must not exist ({@code false}), or no check ({@code null}).
import static java.lang.Math.min;
/**
+ * <h2>Menu</h2>
+ * <p>
* Prompts the user to select an option from a list using fuzzy matching and cursor keys with scrolling support.
+ * </p>
* <p>
* <strong>Important: This functionality requires the terminal to be in raw mode for proper operation.</strong>
* On Unix-like systems, this is automatically handled by setting terminal modes.
* or Escape to cancel the selection. For long lists, the menu automatically scrolls to keep the
* selection visible within the terminal's vertical limits.
* </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * import eu.svjatoslav.commons.cli_helper.Menu;
+ * import java.io.IOException;
+ * import java.util.Arrays;
+ * import java.util.List;
+ *
+ * public class MenuExample {
+ * public static void main(String[] args) throws IOException {
+ * List<String> fruits = Arrays.asList(
+ * "Apple", "Banana", "Cherry", "Date", "Elderberry",
+ * "Fig", "Grape", "Honeydew", "Kiwi", "Lemon"
+ * );
+ *
+ * String selected = Menu.askSelection("Select a fruit", fruits);
+ *
+ * if (selected != null) {
+ * System.out.println("You selected: " + selected);
+ * } else {
+ * System.out.println("Selection cancelled.");
+ * }
+ * }
+ * }
+ * }</pre>
+ *
+ * <h3>Fuzzy matching example</h3>
+ * <p>
+ * If the list contains {@code ["Apple", "Banana", "Cherry"]} and the user types "ap",
+ * only "Apple" will be shown (fuzzy match). If they type "a", both "Apple" and "Banana"
+ * will be shown (both contain 'a').
+ * </p>
+ *
+ * <h3>Terminal interaction</h3>
+ * <ul>
+ * <li><strong>Up/Down arrows:</strong> Navigate through options</li>
+ * <li><strong>Type text:</strong> Filter options using fuzzy matching</li>
+ * <li><strong>Backspace:</strong> Remove last character from filter</li>
+ * <li><strong>Enter:</strong> Select the highlighted option</li>
+ * <li><strong>Escape:</strong> Cancel and return {@code null}</li>
+ * </ul>
*/
public class Menu {
import static java.util.Collections.addAll;
/**
+ * <h2>Option</h2>
+ * <p>
* Represents a command-line option (a flag or switch), which can be configured with:
+ * </p>
* <ul>
* <li>whether it's mandatory</li>
* <li>the number of parameters accepted</li>
* <li>aliases (the actual CLI flags, e.g., "--help" or "-h")</li>
* </ul>
*
+ * <h3>Available option types</h3>
+ * <ul>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.NullOption NullOption} - Boolean flag (no parameters)</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.StringOption StringOption} - Single string value</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.StringOptions StringOptions} - Multiple string values</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.IntegerOption IntegerOption} - Single integer value</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FloatOption FloatOption} - Single floating-point value</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOption FileOption} - Single file path</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOptions FileOptions} - Multiple file paths</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.DirectoryOption DirectoryOption} - Single directory path</li>
+ * <li>{@link eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.DirectoryOptions DirectoryOptions} - Multiple directory paths</li>
+ * </ul>
+ *
+ * <h3>Fluent API example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * // All option types support fluent configuration
+ * FileOption input = parser.add(
+ * new FileOption("Input file")
+ * .addAliases("-i", "--input") // add multiple aliases
+ * .mustExist() // file must exist on disk
+ * .setMandatory() // option is required
+ * );
+ *
+ * // Options can be created with aliases in constructor too
+ * StringOption name = parser.add(
+ * new StringOption("User name", "defaultName")
+ * .addAliases("-n", "--name")
+ * );
+ * // name.getValue() returns "defaultName" if not specified on CLI
+ *
+ * // Check if an option was present
+ * if (input.isPresent()) {
+ * System.out.println("Input: " + input.getValue());
+ * }
+ * }</pre>
+ *
* @param <T> the type of object returned by {@link #getValue()}
* @param <I> the actual subclass type, used to enable fluent method chaining
*/
package eu.svjatoslav.commons.cli_helper.parameter_parser;
/**
+ * <h2>ParameterCount</h2>
+ * <p>
* Defines how many parameters a command-line option can accept.
+ * </p>
+ *
+ * <h3>Usage context</h3>
+ * <pre>{@code
+ * // NONE - for boolean flags
+ * new NullOption("Enable debug mode") // uses ParameterCount.NONE
+ *
+ * // ONE - for single-value options
+ * new StringOption("Output file") // uses ParameterCount.ONE
+ * new IntegerOption("Port number") // uses ParameterCount.ONE
+ * new FileOption("Input file") // uses ParameterCount.ONE
+ *
+ * // ONE_OR_MORE - for multi-value options
+ * new StringOptions("List of names") // uses ParameterCount.ONE_OR_MORE
+ * new FileOptions("Input files") // uses ParameterCount.ONE_OR_MORE
+ * }</pre>
*/
public enum ParameterCount {
/** Option has no parameters. */
import java.util.List;
/**
- * This class parses command-line arguments against a set of registered {@link Option} objects.
+ * <h2>Parser</h2>
* <p>
- * Usage:
+ * This class parses command-line arguments against a set of registered {@link Option} objects.
+ * The parser supports fluent API for registering options, automatic validation of mandatory
+ * options, and generates help text showing all available options.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * import eu.svjatoslav.commons.cli_helper.parameter_parser.Parser;
+ * import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.*;
+ * import java.io.File;
+ * import java.util.List;
+ *
+ * public class MyApp {
+ * public static void main(String[] args) {
+ * Parser parser = new Parser();
+ *
+ * // Register options with fluent API
+ * FileOption inputOpt = parser.add(
+ * new FileOption("Input file to process")
+ * .addAliases("-i", "--input")
+ * .mustExist()
+ * .setMandatory()
+ * );
+ *
+ * FileOption outputOpt = parser.add(
+ * new FileOption("Output file")
+ * .addAliases("-o", "--output")
+ * .mustNotExist()
+ * );
+ *
+ * IntegerOption verboseOpt = parser.add(
+ * new IntegerOption("Verbosity level (0-3)")
+ * .addAliases("-v", "--verbose")
+ * );
+ *
+ * NullOption helpOpt = parser.add(
+ * new NullOption("Show this help message")
+ * .addAliases("-h", "--help")
+ * );
+ *
+ * StringOptions filesOpt = parser.add(
+ * new StringOptions("Additional files to process")
+ * .addAliases("--files")
+ * );
+ *
+ * // Parse arguments
+ * if (!parser.parse(args) || helpOpt.getValue()) {
+ * parser.showHelp();
+ * System.exit(helpOpt.getValue() ? 0 : 1);
+ * }
+ *
+ * // Use the parsed values
+ * File input = inputOpt.getValue();
+ * File output = outputOpt.getValue(); // may be null if not specified
+ * int verbosity = verboseOpt.getValue(); // may throw if not specified
+ * List<String> extraFiles = filesOpt.getValue();
+ *
+ * System.out.println("Processing: " + input);
+ * }
+ * }
+ * }</pre>
+ *
+ * <h3>Command-line invocation examples</h3>
* <pre>{@code
- * Parser parser = new Parser();
- * FileOption fileOpt = parser.add(new FileOption("Input file").mustExist())
- * .addAliases("-f", "--file")
- * .setMandatory();
- * parser.parse(args);
- * if (!parser.checkSuccess()) {
- * parser.showHelp();
- * System.exit(1);
- * }
- * File inputFile = fileOpt.getValue();
+ * // Basic usage
+ * java MyApp -i input.txt -o output.txt
+ *
+ * // With verbosity
+ * java MyApp -i input.txt -v 2
+ *
+ * // Multiple values for ONE_OR_MORE option
+ * java MyApp -i input.txt --files file1.txt file2.txt file3.txt
+ *
+ * // Show help
+ * java MyApp --help
* }</pre>
*/
public class Parser {
* Parses command-line arguments against registered options and their parameters.
* <p>
* Processes arguments sequentially:
+ * </p>
* <ul>
* <li>Recognizes option aliases to switch between options.</li>
* <li>Adds subsequent arguments as parameters to the current option.</li>
* <li>Checks mandatory options are present at the end.</li>
* </ul>
- * </p>
* @param args Command-line arguments.
* @return {@code true} if parsing succeeded (all mandatory options present and no errors); otherwise {@code false}.
*/
import java.io.File;
/**
+ * <h2>DirectoryOption</h2>
+ * <p>
* Represents a command-line option that accepts exactly one parameter interpreted as a directory path.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * // Source directory must exist
+ * DirectoryOption source = parser.add(
+ * new DirectoryOption("Source directory")
+ * .addAliases("-s", "--source")
+ * .mustExist()
+ * .setMandatory()
+ * );
+ *
+ * // Output directory should not exist
+ * DirectoryOption output = parser.add(
+ * new DirectoryOption("Output directory")
+ * .addAliases("-o", "--output")
+ * .mustNotExist()
+ * );
+ *
+ * // Working directory - existence optional
+ * DirectoryOption workDir = parser.add(
+ * new DirectoryOption("Working directory")
+ * .addAliases("-w", "--workdir")
+ * );
+ *
+ * parser.parse(args);
+ *
+ * File sourceDir = source.getValue(); // guaranteed to exist and be a directory
+ * File outputDir = output.getValue(); // null if not specified
+ * File workingDir = workDir.getValue(); // may or may not exist
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --source /path/to/input --output /path/to/newdir
+ * java MyApp -s ./src -o ./build
+ * java MyApp --source existing_dir
+ * }</pre>
+ *
+ * <h3>Error handling</h3>
+ * <p>
+ * Directory validation happens during parsing:
+ * </p>
+ * <pre>{@code
+ * java MyApp --source nonexistent/
+ * // Output: Error! Invalid parameter "nonexistent/". It should be Existing directory.
+ *
+ * java MyApp --source regular_file.txt
+ * // Output: Error! Invalid parameter "regular_file.txt". It should be Existing directory.
+ * }</pre>
*/
public class DirectoryOption extends Option<File, DirectoryOption> {
import java.util.stream.Collectors;
/**
+ * <h2>DirectoryOptions</h2>
+ * <p>
* Represents a command-line option that accepts one or more directory paths.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * // Multiple source directories that must exist
+ * DirectoryOptions sources = parser.add(
+ * new DirectoryOptions("Source directories to scan")
+ * .addAliases("--sources")
+ * .mustExist()
+ * .setMandatory()
+ * );
+ *
+ * // Multiple output directories that should not exist
+ * DirectoryOptions outputs = parser.add(
+ * new DirectoryOptions("Output directories to create")
+ * .addAliases("--outputs")
+ * .mustNotExist()
+ * );
+ *
+ * parser.parse(args);
+ *
+ * List<File> sourceDirs = sources.getValue(); // at least one directory
+ * List<File> outputDirs = outputs.getValue(); // may be empty
+ *
+ * for (File dir : sourceDirs) {
+ * System.out.println("Scanning: " + dir.getAbsolutePath());
+ * }
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --sources src/main src/test
+ * // sourceDirs = [src/main, src/test]
+ *
+ * java MyApp --sources project1/src project2/src --outputs build/
+ * // Multiple source dirs and one output dir
+ * }</pre>
*/
public class DirectoryOptions extends Option<List<File>, DirectoryOptions> {
package eu.svjatoslav.commons.cli_helper.parameter_parser.parameter;
/**
+ * <h2>ExistenceType</h2>
+ * <p>
* Defines whether a file/directory resource must exist, must not exist, or if it does not matter.
+ * </p>
+ *
+ * <h3>Usage with FileOption</h3>
+ * <pre>{@code
+ * // MUST_EXIST - file must already exist (e.g., input file)
+ * FileOption input = new FileOption("Input file").mustExist();
+ *
+ * // MUST_NOT_EXIST - file must not exist (e.g., output file to avoid overwriting)
+ * FileOption output = new FileOption("Output file").mustNotExist();
+ *
+ * // DOES_NOT_MATTER - default, no existence check (e.g., optional config)
+ * FileOption config = new FileOption("Config file"); // default behavior
+ * }</pre>
+ *
+ * <h3>Usage with DirectoryOption</h3>
+ * <pre>{@code
+ * // MUST_EXIST - directory must exist (e.g., source directory)
+ * DirectoryOption source = new DirectoryOption("Source dir").mustExist();
+ *
+ * // MUST_NOT_EXIST - directory must not exist (e.g., new project directory)
+ * DirectoryOption project = new DirectoryOption("New project dir").mustNotExist();
+ * }</pre>
*/
public enum ExistenceType {
/** Resource shall exist. */
import java.io.File;
/**
+ * <h2>FileOption</h2>
+ * <p>
* Represents a command-line option that accepts exactly one parameter which is interpreted as a file path.
* By default, {@link ExistenceType#DOES_NOT_MATTER} is used (i.e., the file may or may not exist).
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * // Input file must exist
+ * FileOption input = parser.add(
+ * new FileOption("Input file to process")
+ * .addAliases("-i", "--input")
+ * .mustExist()
+ * .setMandatory()
+ * );
+ *
+ * // Output file must NOT exist (don't overwrite)
+ * FileOption output = parser.add(
+ * new FileOption("Output file")
+ * .addAliases("-o", "--output")
+ * .mustNotExist()
+ * );
+ *
+ * // Config file - existence doesn't matter
+ * FileOption config = parser.add(
+ * new FileOption("Configuration file")
+ * .addAliases("-c", "--config")
+ * );
+ *
+ * parser.parse(args);
+ *
+ * File inputFile = input.getValue(); // guaranteed to exist
+ * File outputFile = output.getValue(); // null if not specified
+ * File configFile = config.getValue(); // may or may not exist
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --input data.txt --output result.txt
+ * java MyApp -i /path/to/file.txt
+ * java MyApp --input existing.txt --output newfile.txt
+ * }</pre>
+ *
+ * <h3>Error handling</h3>
+ * <p>
+ * File validation happens during parsing:
+ * </p>
+ * <pre>{@code
+ * java MyApp --input nonexistent.txt
+ * // Output: Error! Invalid parameter "nonexistent.txt". It should be Existing file.
+ *
+ * java MyApp --output existing.txt
+ * // Output: Error! Invalid parameter "existing.txt". It should be Non-existing file.
+ * }</pre>
*/
public class FileOption extends Option<File, FileOption> {
import java.util.stream.Collectors;
/**
+ * <h2>FileOptions</h2>
+ * <p>
* Represents a command-line option that accepts one or more file paths.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * // Multiple input files that must exist
+ * FileOptions inputs = parser.add(
+ * new FileOptions("Input files to process")
+ * .addAliases("--inputs")
+ * .mustExist()
+ * .setMandatory()
+ * );
+ *
+ * // Multiple output files that should not exist
+ * FileOptions outputs = parser.add(
+ * new FileOptions("Output files to create")
+ * .addAliases("--outputs")
+ * .mustNotExist()
+ * );
+ *
+ * parser.parse(args);
+ *
+ * List<File> inputFiles = inputs.getValue(); // at least one file
+ * List<File> outputFiles = outputs.getValue(); // may be empty
+ *
+ * for (File input : inputFiles) {
+ * System.out.println("Processing: " + input.getName());
+ * }
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --inputs file1.txt file2.txt file3.txt
+ * // inputFiles = [file1.txt, file2.txt, file3.txt]
+ *
+ * java MyApp --inputs src/*.java --outputs out/
+ * // Input files matched by shell glob, output directory specified
+ *
+ * java MyApp --inputs a.txt b.txt --outputs x.txt y.txt
+ * // inputs = [a.txt, b.txt], outputs = [x.txt, y.txt]
+ * }</pre>
*/
public class FileOptions extends Option<List<File>, FileOptions> {
import eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount;
/**
+ * <h2>FloatOption</h2>
+ * <p>
* Represents a command-line option that accepts exactly one floating-point parameter.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * FloatOption scale = parser.add(
+ * new FloatOption("Scale factor")
+ * .addAliases("-s", "--scale")
+ * .setMandatory()
+ * );
+ *
+ * FloatOption threshold = parser.add(
+ * new FloatOption("Detection threshold")
+ * .addAliases("--threshold")
+ * );
+ *
+ * FloatOption rate = parser.add(
+ * new FloatOption("Learning rate")
+ * .addAliases("-r", "--rate")
+ * );
+ *
+ * parser.parse(args);
+ *
+ * float scaleFactor = scale.getValue(); // required
+ * Float thresholdValue = threshold.getValue(); // may throw if missing
+ *
+ * System.out.println("Scale: " + scaleFactor);
+ * System.out.println("Threshold: " + thresholdValue);
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --scale 1.5 // scale=1.5
+ * java MyApp -s 2.0 --threshold 0.75 // scale=2.0, threshold=0.75
+ * java MyApp --scale 1.5 -r 0.01 --threshold 0.9
+ * }</pre>
+ *
+ * <h3>Error handling</h3>
+ * <p>
+ * Invalid floats are rejected during parsing:
+ * </p>
+ * <pre>{@code
+ * java MyApp --scale abc
+ * // Output: Error! Invalid parameter "abc". It should be Floating point number. Example: 3.14
+ * }</pre>
*/
public class FloatOption extends Option<Float, FloatOption> {
import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
/**
+ * <h2>IntegerOption</h2>
+ * <p>
* Represents a command-line option that accepts exactly one parameter interpreted as an integer.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * IntegerOption port = parser.add(
+ * new IntegerOption("Server port")
+ * .addAliases("-p", "--port")
+ * .setMandatory()
+ * );
+ *
+ * IntegerOption timeout = parser.add(
+ * new IntegerOption("Timeout in seconds")
+ * .addAliases("-t", "--timeout")
+ * );
+ *
+ * IntegerOption retries = parser.add(
+ * new IntegerOption("Number of retry attempts")
+ * .addAliases("-r", "--retries")
+ * );
+ *
+ * parser.parse(args);
+ *
+ * int portNumber = port.getValue(); // required, will throw if missing
+ * Integer timeoutValue = timeout.getValue(); // may throw if missing
+ * Integer retryCount = retries.getValue(); // may throw if missing
+ *
+ * System.out.println("Connecting to port: " + portNumber);
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --port 8080 // port=8080
+ * java MyApp -p 3000 -t 30 // port=3000, timeout=30
+ * java MyApp --port 8080 --timeout 60 -r 3 // all options specified
+ * }</pre>
+ *
+ * <h3>Error handling</h3>
+ * <p>
+ * Invalid integers are rejected during parsing:
+ * </p>
+ * <pre>{@code
+ * java MyApp --port abc
+ * // Output: Error! Invalid parameter "abc". It should be Integer.
+ * }</pre>
*/
public class IntegerOption extends Option<Integer, IntegerOption> {
import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
/**
+ * <h2>NullOption</h2>
+ * <p>
* Represents a command-line option that accepts exactly zero parameters.
* Often used for flags that are either present or absent.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * NullOption verbose = parser.add(
+ * new NullOption("Enable verbose output")
+ * .addAliases("-v", "--verbose")
+ * );
+ *
+ * NullOption help = parser.add(
+ * new NullOption("Show help message")
+ * .addAliases("-h", "--help")
+ * );
+ *
+ * parser.parse(args);
+ *
+ * // Check if flag was present
+ * if (help.getValue()) {
+ * parser.showHelp();
+ * System.exit(0);
+ * }
+ *
+ * if (verbose.getValue()) {
+ * System.out.println("Verbose mode enabled");
+ * }
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --verbose // verbose.getValue() returns true
+ * java MyApp -v -h // both flags are true
+ * java MyApp // both flags are false
+ * }</pre>
*/
public class NullOption extends Option<Boolean, NullOption> {
import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
/**
+ * <h2>StringOption</h2>
+ * <p>
* Represents a command-line option that accepts exactly one string parameter.
* An optional default value can be provided; if so, this option is considered "present" even without user input.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * // Without default value
+ * StringOption name = parser.add(
+ * new StringOption("User name")
+ * .addAliases("-n", "--name")
+ * .setMandatory()
+ * );
+ *
+ * // With default value
+ * StringOption format = parser.add(
+ * new StringOption("Output format", "json") // defaults to "json"
+ * .addAliases("-f", "--format")
+ * );
+ *
+ * parser.parse(args);
+ *
+ * String userName = name.getValue(); // throws if not specified
+ * String outputFormat = format.getValue(); // returns "json" if not specified
+ *
+ * System.out.println("User: " + userName);
+ * System.out.println("Format: " + outputFormat);
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp -n Alice // name="Alice", format="json"
+ * java MyApp --name Bob --format xml // name="Bob", format="xml"
+ * java MyApp -n Charlie // name="Charlie", format="json" (default)
+ * }</pre>
*/
public class StringOption extends Option<String, StringOption> {
import java.util.List;
/**
+ * <h2>StringOptions</h2>
+ * <p>
* Represents a command-line option that accepts one or more string parameters.
+ * </p>
+ *
+ * <h3>Usage example</h3>
+ * <pre>{@code
+ * Parser parser = new Parser();
+ *
+ * StringOptions tags = parser.add(
+ * new StringOptions("Tags to apply")
+ * .addAliases("--tags")
+ * );
+ *
+ * StringOptions files = parser.add(
+ * new StringOptions("Files to process")
+ * .addAliases("--files")
+ * .setMandatory()
+ * );
+ *
+ * parser.parse(args);
+ *
+ * List<String> tagList = tags.getValue(); // may be empty if not specified
+ * List<String> fileList = files.getValue(); // at least one file required
+ *
+ * System.out.println("Tags: " + tagList);
+ * for (String file : fileList) {
+ * System.out.println("Processing: " + file);
+ * }
+ * }</pre>
+ *
+ * <h3>Command-line invocation</h3>
+ * <pre>{@code
+ * java MyApp --files input1.txt input2.txt
+ * // fileList = ["input1.txt", "input2.txt"], tagList = []
+ *
+ * java MyApp --files data.txt --tags urgent important
+ * // fileList = ["data.txt"], tagList = ["urgent", "important"]
+ *
+ * java MyApp --tags single --files only.txt
+ * // Note: order matters - tags bound to single file in wrong position
+ * }</pre>
*/
public class StringOptions extends Option<List<String>, StringOptions> {