All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jio.console.Programs Maven / Gradle / Ivy

There is a newer version: 3.0.0-RC2
Show newest version
package jio.console;

import fun.tuple.Pair;
import fun.tuple.Triple;
import jio.*;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;

import static java.util.Objects.requireNonNull;

/**
 * Set of different programs modeled with JIO effects to print out text and interact with the user. These programs
 * include reading lines, integers, booleans, printing text to the console, and interacting with the user to input
 * data.
 */
public final class Programs {

  /**
   * Effect that reads a line from the console.
   */
  public final static IO READ_LINE = IO.effect(() -> {
    try {
      Scanner in = new Scanner(System.in,
                               StandardCharsets.UTF_8
      );
      return CompletableFuture.completedFuture(in.nextLine());
    } catch (Exception exception) {
      return CompletableFuture.failedFuture(exception);
    }
  });
  /**
   * Effect that reads an integer from the console.
   */
  public static IO READ_INT = IO.effect(() -> {
    try {
      Scanner in = new Scanner(System.in,
                               StandardCharsets.UTF_8);
      return CompletableFuture.completedFuture(in.nextInt());
    } catch (Exception exception) {
      return CompletableFuture.failedFuture(exception);
    }
  });
  /**
   * Effect that reads a boolean from the console.
   */
  public static IO READ_BOOLEAN = IO.effect(() -> {
    try {
      Scanner in = new Scanner(System.in,
                               StandardCharsets.UTF_8);
      return CompletableFuture.completedFuture(in.nextBoolean());
    } catch (Exception exception) {
      return CompletableFuture.failedFuture(exception);
    }
  });

  /**
   * Effect that prints out the given line on the console.
   *
   * @param line the line to print
   * @return a JIO effect
   */
  public static IO PRINT_LINE(final String line) {
    return IO.effect(() -> {
      try {
        System.out.print(line);
        return CompletableFuture.completedFuture(null);
      } catch (Exception exception) {
        return CompletableFuture.failedFuture(exception);
      }

    });
  }

  /**
   * Effect that prints out a line on the console, applying the specified control character color.
   *
   * @param line  the line to print
   * @param color the control character color to apply
   * @return a JIO effect
   */
  public static IO PRINT_LINE(final String line,
                                    final ControlChars color
                                   ) {
    requireNonNull(color);
    return IO.effect(() -> {
                       try {
                         System.out.print(color.code + line + ControlChars.RESET);
                         return CompletableFuture.completedFuture(null);
                       } catch (Exception exception) {
                         return CompletableFuture.failedFuture(exception);
                       }
                     }
                    );
  }

  /**
   * Effect that prints out the given new line on the console.
   *
   * @param line the line to print
   * @return a JIO effect
   */
  public static IO PRINT_NEW_LINE(final String line) {
    return IO.effect(() -> {
      try {
        System.out.println(line);
        return CompletableFuture.completedFuture(null);
      } catch (Exception exception) {
        return CompletableFuture.failedFuture(exception);
      }
    });
  }

  /**
   * Effect that prints out a new line on the console, applying the specified control character color.
   *
   * @param line  the line to print
   * @param color the control character color to apply
   * @return a JIO effect
   */
  public static IO PRINT_NEW_LINE(final String line,
                                        final ControlChars color
                                       ) {
    requireNonNull(color);
    return IO.effect(() -> {
      try {
        System.out.println(color.code + line + ControlChars.RESET);
        return CompletableFuture.completedFuture(null);
      } catch (Exception exception) {
        return CompletableFuture.failedFuture(exception);
      }
    });
  }

  /**
   * Creates an effect that prompts the user for input and reads a string from the console.
   *
   * @param params the parameters to specify how to interact with the user
   * @return a JIO effect that reads the user's input
   */
  public static IO ASK_FOR_INPUT(AskForInputParams params) {

    return PRINT_NEW_LINE(params.promptMessage)
        .then($ -> READ_LINE.then(input -> params.inputValidator.test(input) ?
                                           IO.succeed(input) :
                                           IO.fail(new IllegalArgumentException(params.errorMessage)))
             )
        .retry(params.policy);
  }

  /**
   * Creates an effect that prompts the user for input multiple times, collecting a list of strings.
   *
   * @param params the parameters to specify how to interact with the user
   * @param others additional sets of parameters for more input prompts
   * @return a JIO effect that reads multiple lines of user input as a list
   */
  public static IO> ASK_FOR_INPUTS(AskForInputParams params,
                                                AskForInputParams... others
                                               ) {

    var seq = ListExp.seq(ASK_FOR_INPUT(params));

      for (AskForInputParams other : others) {
          seq = seq.append(ASK_FOR_INPUT(other));
      }

    return seq;
  }

  /**
   * Creates an effect that prompts the user for input twice, returning a pair of strings.
   *
   * @param params1 the parameters to specify how to interact with the user for the first input
   * @param params2 the parameters to specify how to interact with the user for the second input
   * @return a JIO effect that reads two lines of user input as a pair
   */
  public static IO> ASK_FOR_PAIR(AskForInputParams params1,
                                                      AskForInputParams params2
                                                     ) {

    return PairExp.seq(ASK_FOR_INPUT(params1),
                       ASK_FOR_INPUT(params2)
                      );
  }

  /**
   * Creates an effect that prompts the user for input three times, returning a triple of strings.
   *
   * @param params1 the parameters to specify how to interact with the user for the first input
   * @param params2 the parameters to specify how to interact with the user for the second input
   * @param params3 the parameters to specify how to interact with the user for the third input
   * @return a JIO effect that reads three lines of user input as a triple
   */
  public static IO> ASK_FOR_TRIPLE(AskForInputParams params1,
                                                                  AskForInputParams params2,
                                                                  AskForInputParams params3
                                                                 ) {

    return
        TripleExp.seq(ASK_FOR_INPUT(params1),
                      ASK_FOR_INPUT(params2),
                      ASK_FOR_INPUT(params3)
                     );


  }


  /**
   * List of parameters to be considered when asking the user for typing in some text
   *
   * @param promptMessage  the message shown to the user
   * @param inputValidator the predicate that is evaluated to true if the user input is valid
   * @param errorMessage   the message error shown to the user in case the inputValidator is evaluated to false
   * @param policy         retry policy to be applied in case of the user input is invalid
   */
  public record AskForInputParams(String promptMessage,
                                  Predicate inputValidator,
                                  String errorMessage,
                                  RetryPolicy policy
  ) {

    /**
     * Constructor that consider all the user input as valid
     *
     * @param promptMessage the message shown to the user
     */
    public AskForInputParams(String promptMessage) {
      this(promptMessage,
           e -> true,
           "",
           RetryPolicies.limitRetries(2)
          );
    }

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy