/**
* Repeatedly prompts the user for a Boolean value.
* <p>
- * Accepted affirmative tokens (case‑insensitive): <kbd>y</kbd>, <kbd>yes</kbd>,
- * <kbd>true</kbd>.<br>
- * Accepted negative tokens: <kbd>n</kbd>, <kbd>no</kbd>, <kbd>false</kbd>.
+ * Accepted affirmative tokens (case-insensitive): <code>y</code>, <code>yes</code>, <code>true</code>.
+ * Accepted negative tokens: <code>n</code>, <code>no</code>, <code>false</code>.
* </p>
- *
- * <p>If the user submits an empty line:</p>
+ * <p>
+ * Behavior for empty input:
* <ul>
- * <li>If {@code defaultValue != null} – return that value.</li>
- * <li>Else if {@code allowEmpty == true} – return {@code null}.</li>
- * <li>Otherwise the prompt is displayed again.</li>
+ * <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>
- *
- * @param prompt message shown to the user (without trailing colon)
- * @param defaultValue value returned when the user simply hits {@code Enter}; may be {@code null}
- * @param allowEmpty whether an empty line without a default should yield {@code null}
- * @return {@code Boolean.TRUE}, {@code Boolean.FALSE}, the supplied {@code defaultValue}, or {@code null}
+ * </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.
+ * @return {@code Boolean.TRUE}, {@code Boolean.FALSE}, the {@code defaultValue}, or {@code null} (if allowed).
*/
+
public static Boolean askBoolean(final String prompt, final Boolean defaultValue, final boolean allowEmpty) {
while (true) {
String displayPrompt = prompt + (defaultValue != null ? " [" + defaultValue + "]" : "") + ": ";
/*‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑ Float ‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑*/
/**
- * Prompts the user for a {@code float} value that satisfies optional
- * minimum/maximum bounds.
- *
- * @param prompt message shown to the user
- * @param defaultValue value returned on empty input; may be {@code null}
- * @param min inclusive lower bound, or {@code null} for no check
- * @param max inclusive upper bound, or {@code null} for no check
- * @param allowEmpty whether an empty line without a default should yield {@code null}
- * @return the parsed {@link Float}, {@code defaultValue}, or {@code null}
+ * Prompts the user for a {@code float} value within optional bounds.
+ * <p>
+ * Behavior for empty input:
+ * <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>
+ * @param prompt The prompt message to display.
+ * @param defaultValue The default value to return if the user enters an empty line; may be {@code null}.
+ * @param min Inclusive lower bound for the value, or {@code null} to disable check.
+ * @param max Inclusive upper bound for the value, or {@code null} to disable check.
+ * @param allowEmpty If {@code true}, allows empty input to return {@code null}; otherwise, continues prompting.
+ * @return The parsed {@code float}, the {@code defaultValue}, or {@code null} (if allowed).
*/
+
public static Float askFloat(final String prompt, final Float defaultValue,
final Float min, final Float max, final boolean allowEmpty) {
while (true) {
/*‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑ Long ‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑*/
/**
- * Prompts the user for a {@code long} value that satisfies optional
- * minimum/maximum bounds.
- *
- * @param prompt message shown to the user
- * @param defaultValue value returned on empty input; may be {@code null}
- * @param min inclusive lower bound, or {@code null}
- * @param max inclusive upper bound, or {@code null}
- * @param allowEmpty whether an empty line without a default should yield {@code null}
- * @return the parsed {@link Long}, {@code defaultValue}, or {@code null}
+ * Prompts the user for an {@code int} value within optional bounds.
+ * <p>
+ * Behavior for empty input:
+ * <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>
+ * @param prompt The prompt message to display.
+ * @param defaultValue The default value to return if the user enters an empty line; may be {@code null}.
+ * @param min Inclusive lower bound for the value, or {@code null} to disable check.
+ * @param max Inclusive upper bound for the value, or {@code null} to disable check.
+ * @param allowEmpty If {@code true}, allows empty input to return {@code null}; otherwise, continues prompting.
+ * @return The parsed {@code int}, the {@code defaultValue}, or {@code null} (if allowed).
*/
public static Long askLong(final String prompt, final Long defaultValue,
final Long min, final Long max, final boolean allowEmpty) {
/*‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑ String ‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑*/
/**
- * Prompts the user for a non‑empty {@link String} and validates its length.
- *
- * @param prompt message shown to the user
- * @param defaultValue value returned on empty input; may be {@code null}
- * @param minLength inclusive lower bound; {@code null} means no check
- * @param maxLength inclusive upper bound; {@code null} means no check
- * @param allowEmpty whether an empty line without a default should yield {@code null}
- * @return the typed {@link String}, {@code defaultValue}, or {@code null}
+ * Prompts the user for a string value with optional length constraints.
+ * <p>
+ * Behavior for empty input:
+ * <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>
+ * @param prompt The prompt message to display.
+ * @param defaultValue The default value to return if the user enters an empty line; may be {@code null}.
+ * @param minLength Minimum allowed string length (inclusive), or {@code null} to disable check.
+ * @param maxLength Maximum allowed string length (inclusive), or {@code null} to disable check.
+ * @param allowEmpty If {@code true}, allows empty input to return {@code null}; otherwise, continues prompting.
+ * @return The input string, the {@code defaultValue}, or {@code null} (if allowed).
*/
public static String askString(final String prompt, final String defaultValue,
final Integer minLength, final Integer maxLength, final boolean allowEmpty) {
/*‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑ File / Directory ‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑*/
/**
- * Prompts the user for a <strong>file path</strong> and validates various
- * attributes (existence, readability, writability, executability).
+ * Prompts the user for a file path and validates specified attributes.
* <p>
- * A {@link File} object is <em>returned as‑is</em>; no attempt is made to
- * canonicalise or resolve symlinks.
+ * A {@link File} object is returned as-is; no canonicalization or symlink resolution is performed.
* </p>
- *
- * @param prompt message shown to the user
- * @param defaultValue value returned on empty input; may be {@code null}
- * @param mustExist if non‑{@code null}: {@code true} ⇒ file must exist, {@code false} ⇒ file must <em>not</em> exist
- * @param mustReadable if non‑{@code null}: {@code true} ⇒ {@link File#canRead()} must be {@code true}
- * @param mustWritable if non‑{@code null}: {@code true} ⇒ {@link File#canWrite()} must be {@code true}
- * @param mustExecutable if non‑{@code null}: {@code true} ⇒ {@link File#canExecute()} must be {@code true}
- * @param allowEmpty whether an empty line without a default should yield {@code null}
- * @return a {@link File} satisfying all constraints, {@code defaultValue}, or {@code null}
+ * <p>
+ * Behavior for empty input:
+ * <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:
+ * <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}).
+ * @param mustReadable Whether the file must be readable ({@code true}), not readable ({@code false}), or no check ({@code null}).
+ * @param mustWritable Whether the file must be writable ({@code true}), not writable ({@code false}), or no check ({@code null}).
+ * @param mustExecutable Whether the file must be executable ({@code true}), not executable ({@code false}), or no check ({@code null}).
+ * @param allowEmpty If {@code true}, allows empty input to return {@code null}; otherwise, continues prompting.
+ * @return A {@link File} object satisfying all constraints, the {@code defaultValue}, or {@code null} (if allowed).
*/
public static File askFile(final String prompt,
final File defaultValue,
*/
public class Menu {
+
/**
- * Presents an interactive menu; returns selection or null
+ * Displays an interactive menu for the user to select an option from a list using fuzzy matching and cursor navigation.
+ * <p>
+ * This method requires the terminal to be in raw mode for proper operation. On Unix-like systems, it automatically
+ * sets the terminal to raw mode. This functionality may not work correctly in standard line-buffered terminals or IDE consoles.
+ * </p>
+ * <p>
+ * The user can navigate the list using up/down arrow keys, type to filter options via fuzzy matching (e.g., "abc" matches
+ * "aXbYc" but not "acb"), press Enter to select the current option, or Escape to cancel.
+ * </p>
+ * @param prompt The prompt message to display above the menu.
+ * @param options The list of options to present to the user.
+ * @return The selected option string, or {@code null} if the user canceled with Escape.
+ * @throws IOException If there's an error reading from the terminal or restoring terminal settings.
*/
public static String askSelection(String prompt, List<String> options) throws IOException {
if (options == null || options.isEmpty()) {
}
/**
- * Gets the current terminal settings as a string.
+ * Retrieves the current terminal settings using the {@code stty -g} command.
+ * @return A string representing the current terminal settings.
+ * @throws IOException If the command fails to execute or read the output.
*/
private static String getTerminalSettings() throws IOException {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "stty -g < /dev/tty"});
}
/**
- * Sets the terminal to raw mode with no echo.
- */
+ * Sets the terminal to raw mode with no echo.
+ * @throws IOException If the terminal cannot be set to raw mode.
+ */
private static void setTerminalToRaw() throws IOException {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "stty raw -echo < /dev/tty"});
try {
}
/**
- * Restores the terminal settings.
+ * Restores the terminal to the specified settings.
+ * @param settings The terminal settings string to restore.
+ * @throws IOException If the terminal settings cannot be restored.
*/
private static void restoreTerminalSettings(String settings) throws IOException {
if (settings != null) {
}
/**
- * Filters options based on fuzzy matching.
- *
- * @param options the list of options to filter
- * @param filter the filter string
- * @return filtered list of options that match the fuzzy pattern
+ * Filters the given list of options using a fuzzy matching algorithm.
+ * Characters in the filter must appear in order in the option string (not necessarily consecutively), case-insensitive.
+ * @param options The list of options to filter.
+ * @param filter The filter string (case-insensitive).
+ * @return A new list containing only the options that match the fuzzy pattern.
*/
private static List<String> filterOptions(List<String> options, String filter) {
if (filter == null || filter.isEmpty()) return new ArrayList<>(options);
}
/**
- * Updates the display based on the current state.
- * @return the total number of lines in the display
+ * Updates the terminal display to show the current menu state, including the prompt, filter string, and filtered options.
+ * Handles cursor positioning and clearing previous output to avoid flicker.
+ * @param prompt The prompt message to display at the top.
+ * @param filteredOptions The list of options currently matching the filter.
+ * @param selectedIndex The index of the currently selected option.
+ * @param filterString The current filter string typed by the user.
+ * @param lastTotalLines The total number of lines in the previous display, used for cursor positioning.
+ * @return The total number of lines in the current display (prompt line + menu lines).
*/
private static int updateDisplay(String prompt, List<String> filteredOptions, int selectedIndex, String filterString, int lastTotalLines) {
}
/**
- * Adds a parameter to this option, validating it against {@link #isValid(String)}.
- *
- * @param parameterString the parameter string to add
- * @return {@code true} if the parameter was valid and added, otherwise {@code false}
+ * Adds a parameter to this option after validating it against the configured rules.
+ * <p>
+ * If the option is configured for {@link ParameterCount#NONE}, adding any parameter will fail.
+ * If the option is configured for {@link ParameterCount#ONE}, only one parameter is allowed.
+ * </p>
+ * @param parameterString The parameter string to add.
+ * @return {@code true} if the parameter is valid and added; otherwise {@code false}.
*/
public boolean addParameter(final String parameterString) {
// Check if this option is supposed to have parameters at all
}
/**
- * Returns a help message that includes the aliases, whether the option is mandatory,
- * the format, and a brief description.
- *
- * @return a descriptive help string
+ * Generates a formatted help string for this option, including:
+ * <ul>
+ * <li>Aliases (e.g., "-f", "--file")</li>
+ * <li>Mandatory status</li>
+ * <li>Parameter format description</li>
+ * <li>Brief description of the option's purpose</li>
+ * </ul>
+ * @return A string suitable for console output, describing the option.
*/
public String getHelp() {
StringBuilder result = new StringBuilder();
}
/**
- * Called when no more arguments can be added to this option, giving it a chance
- * to verify correct usage (e.g., check if required parameters are missing).
- *
- * @return {@code true} if the usage so far is valid; otherwise {@code false}.
+ * Finalizes the option's parameters and checks for required constraints.
+ * <p>
+ * For options that require parameters, this method verifies that the required number
+ * of parameters have been provided. If not, it prints an error message to System.out
+ * and returns {@code false}.
+ * </p>
+ * @return {@code true} if the option's parameters are valid; otherwise {@code false}.
*/
public boolean noMoreArguments() {
// If we expect at least one parameter but none were provided