Option.java

/*
 * Copyright 2022 Terminal Utils Authors
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package net.morimekta.terminal.args;

import net.morimekta.terminal.args.impl.OptionImpl;

import java.util.List;
import java.util.function.Consumer;

import static java.util.Objects.requireNonNull;
import static net.morimekta.terminal.args.impl.OptionUtils.requireValidLongName;
import static net.morimekta.terminal.args.impl.OptionUtils.requireValidShortNames;
import static net.morimekta.terminal.args.impl.OptionUtils.requireValidUsage;

/**
 * Named option that for each invocation takes a single argument value,
 * either the next argument, or from the same argument after a '='
 * delimiter.
 */
public interface Option extends Arg {
    /**
     * Each character of the shortNames string is handled as a short option
     * that is parsed with the -[short] style. If the string is empty or null,
     * no short options are provided.
     *
     * @return The short names
     */
    String getShortNames();

    /**
     * Meta variable to show in usage printout.
     *
     * @return The meta variable.
     */
    String getMetaVar();

    /**
     * When handling a list of short options.
     * <ul>
     *     <li>
     *         If 0 is returned from this method, it should be handled as the
     *         short option char was the only thing being consumed.
     *     </li>
     *     <li>
     *         If 1 is returned from this method, it should be handled as the
     *         remainder of the short options string is consumed.
     *     </li>
     *     <li>
     *         If any higher number is returned, it will consume of the
     *         following arguments from the args list.
     *     </li>
     * </ul>
     *
     * @param opts The remaining characters of the short opt list, including
     *             the triggering char.
     * @param args The list of arguments including the short opt list.
     * @return The number of arguments consumed.
     */
    int applyShort(String opts, List<String> args);

    /**
     * Option builder.
     */
    interface Builder extends Arg.Builder<Option> {
        /**
         * @param metaVar The meta var name.
         * @return The builder.
         */
        Builder metaVar(String metaVar);

        /**
         * @param object Default value.
         * @return The builder.
         */
        Builder defaultValue(Object object);

        /**
         * Set the option as repeated.
         *
         * @return The builder.
         */
        Builder repeated();

        /**
         * Set the option as required.
         *
         * @return The builder.
         */
        Builder required();

        /**
         * Set the option as hidden.
         *
         * @return The builder.
         */
        Builder hidden();
    }


    /**
     * Build an option argument.
     *
     * @param name     Long name for option.
     * @param usage    Usage string.
     * @param consumer Option value consumer.
     * @return The builder.
     */
    static Builder optionLong(String name,
                              String usage,
                              Consumer<String> consumer) {
        return new OptionImpl.BuilderImpl(
                requireValidLongName(name),
                null,
                requireValidUsage(usage),
                requireNonNull(consumer, "consumer == null"));
    }

    /**
     * Build an option argument.
     *
     * @param shortNames Characters for short name options.
     * @param usage      Usage string.
     * @param consumer   Option value consumer.
     * @return The builder.
     */
    static Builder optionShort(String shortNames,
                               String usage,
                               Consumer<String> consumer) {
        return new OptionImpl.BuilderImpl(
                null,
                requireValidShortNames(shortNames),
                requireValidUsage(usage),
                requireNonNull(consumer, "consumer == null"));
    }

    /**
     * Build an option argument.
     *
     * @param name       Long name for option.
     * @param shortNames Characters for short name options.
     * @param usage      Usage string.
     * @param consumer   Option value consumer.
     * @return The builder.
     */
    static Builder option(String name,
                          String shortNames,
                          String usage,
                          Consumer<String> consumer) {
        return new OptionImpl.BuilderImpl(
                requireValidLongName(name),
                requireValidShortNames(shortNames),
                requireValidUsage(usage),
                requireNonNull(consumer, "consumer == null"));
    }
}