NAME

App::GHGen::Interactive - Interactive workflow customization

SYNOPSIS

use App::GHGen::Interactive qw(customize_workflow);

my $config = customize_workflow('perl');
# Returns hash of user choices

FUNCTIONS

prompt_yes_no($question, $default)

Prompt the user for a yes/no answer and return a boolean.

Purpose

Print $question followed by a bracket hint ([Y/n] or [y/N]), read one line from STDIN, and return 1 for yes or 0 for no. An empty response uses $default.

Arguments

$question (Str, required)

The question text to display.

$default (Str, optional, default 'y')

The default answer when the user presses Enter without typing. Must be 'y' or 'n'.

Returns

1 when the answer is affirmative (y or yes, case-insensitive) or when the empty response maps to a 'y' default.

0 when the answer is negative (n or no, case-insensitive) or when the empty response maps to an 'n' default.

Side Effects

Reads one line from STDIN; prints to STDOUT.

Usage Example

my $ok = prompt_yes_no("Enable coverage?", 'y');

API SPECIFICATION

Input

{
    question => { type => 'scalar', required => 1 },
    default  => { type => 'scalar', default  => 'y' },
}

Output

{ type => 'scalar' }   # 1 or 0

FORMAL SPECIFICATION

prompt_yes_no : ℤ* × {'y','n'} → 𝔹

answer ≔ chomp(readline(STDIN))
result ≔
    answer =~ /^y(es)?$/i → 1
    answer =~ /^n(o)?$/i  → 0
    answer = ""           → default = 'y' → 1  |  default = 'n' → 0

prompt_choice($question, $choices, $default)

Prompt the user to select one item from a numbered list.

Purpose

Display $question followed by a numbered list of $choices, read one line from STDIN, and return the zero-based index of the selected item.

Arguments

$question (Str, required)

The selection prompt text.

$choices (ArrayRef[Str], required)

The available options, displayed numbered from 1.

$default (Int, optional, default 0)

Zero-based index of the pre-selected option shown in the prompt.

Returns

A zero-based integer index. Returns $default when the user presses Enter without input or when the input is out of range (less than 1 or greater than the number of choices).

Side Effects

Reads one line from STDIN; prints to STDOUT.

Usage Example

my $idx = prompt_choice("Package manager?", ['npm','yarn','pnpm'], 0);

API SPECIFICATION

Input

{
    question => { type => 'scalar',  required => 1 },
    choices  => { type => 'arrayref', required => 1 },
    default  => { type => 'scalar',  default  => 0 },
}

Output

{ type => 'scalar' }   # integer 0 .. |choices|-1

FORMAL SPECIFICATION

prompt_choice : ℤ* × seq ℤ* × ℕ → ℕ

answer ≔ chomp(readline(STDIN))
result ≔
    answer = ""                       → default
    answer ∈ ℕ ∧ 1 ≤ answer ≤ |choices| → answer − 1
    otherwise                         → default

prompt_multiselect($question, $options, $defaults)

Prompt the user to select zero or more items from a numbered list.

Purpose

Display $question and a numbered list of $options, accept comma-separated numbers or the keyword all, and return an array reference of the selected option strings.

Arguments

$question (Str, required)

The multi-select prompt text.

$options (ArrayRef[Str], required)

All available options, displayed numbered from 1.

$defaults (ArrayRef[Str], optional, default [])

The pre-selected options (by value, not index).

Returns

An array reference of selected option strings. Possible values:

  • The full $options list when the user types all.

  • A subset derived from the comma/space-separated numbers the user entered.

  • $defaults when the user presses Enter without typing.

Side Effects

Reads one line from STDIN; prints to STDOUT.

Usage Example

my $sel = prompt_multiselect("OS?", ['ubuntu-latest','macos-latest','windows-latest'], []);

API SPECIFICATION

Input

{
    question => { type => 'scalar',  required => 1 },
    options  => { type => 'arrayref', required => 1 },
    defaults => { type => 'arrayref', default  => [] },
}

Output

{ type => 'arrayref' }

FORMAL SPECIFICATION

prompt_multiselect : ℤ* × seq ℤ* × seq ℤ* → seq ℤ*

answer ≔ chomp(readline(STDIN))
result ≔
    answer = ""           → defaults
    answer =~ /^all$/i   → options
    otherwise            → [ options[n−1] ∣ n ∈ split(/[,\s]+/, answer), 1 ≤ n ≤ |options| ]
                               ?? defaults (when result = ∅)

prompt_text($question, $default)

Prompt the user for a free-form text answer.

Purpose

Display $question optionally followed by [$default], read one line from STDIN, and return the user's answer or $default when empty.

Arguments

$question (Str, required)

The prompt text.

$default (Str, optional, default '')

Returned as-is when the user presses Enter without typing anything.

Returns

The trimmed line the user typed, or $default when the input is empty.

Side Effects

Reads one line from STDIN; prints to STDOUT.

Usage Example

my $name = prompt_text("Project name", 'my-project');

API SPECIFICATION

Input

{
    question => { type => 'scalar', required => 1 },
    default  => { type => 'scalar', default  => '' },
}

Output

{ type => 'scalar' }

FORMAL SPECIFICATION

prompt_text : ℤ* × ℤ* → ℤ*

answer ≔ chomp(readline(STDIN))
result ≔ answer = "" → default  |  otherwise → answer

customize_workflow($type)

Drive an interactive customization session for the given workflow type.

Purpose

Display a series of prompts relevant to $type and collect user preferences. Dispatches to a private _customize_* helper; returns an empty hash when the type is not supported.

Arguments

$type (Str, required)

The workflow type to customise. Supported: perl, node, python, rust, go, ruby, docker, static.

Returns

A hash reference of configuration key/value pairs collected from the user. Returns an empty hash reference ({}) when $type is not recognised.

Side Effects

Reads multiple lines from STDIN; prints to STDOUT.

Usage Example

my $config = customize_workflow('perl');
# $config->{enable_critic}, $config->{perl_versions}, etc.

API SPECIFICATION

Input

{ type => { type => 'scalar', required => 1 } }

Output

{ type => 'hashref' }   # empty or populated with type-specific keys

FORMAL SPECIFICATION

SupportedCustomTypes ≔ { perl, node, python, rust, go, ruby, docker, static }

customize_workflow : ℤ* → Config

t ∈ SupportedCustomTypes → _customize_t()
t ¬in; SupportedCustomTypes → {}

AUTHOR

Nigel Horne <njh@nigelhorne.com>

https://github.com/nigelhorne

COPYRIGHT AND LICENSE

Copyright 2025-2026 Nigel Horne.

Usage is subject to the GPL2 licence terms. If you use it, please let me know.