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, default0)-
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
$optionslist when the user typesall.A subset derived from the comma/space-separated numbers the user entered.
$defaultswhen 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>
COPYRIGHT AND LICENSE
Copyright 2025-2026 Nigel Horne.
Usage is subject to the GPL2 licence terms. If you use it, please let me know.