Rand Stats

Prompt

zef:lizmat

Actions Status Actions Status Actions Status

NAME

Prompt - a smarter prompt for user interaction

SYNOPSIS

use Prompt;

my $prompt = Prompt.new(:history<here>);
loop {
    last without my $line = $prompt.readline("> ");
    say $line;
}
$prompt.save-history;

DESCRIPTION

The Prompt module offers a better prompt experience, drawing on the logic of the Raku REPL.

It also optionally provides a replacement for Raku's standard prompt functionality.

ROLES

The Prompt role is what usually gets punned into a class.

The Prompt::Fallback role provides all of the logic if no specific editor has been found. It also serves as a base role for specific editor roles, such as Prompt::Readline, Prompt::LineEditor and Prompt::Linenoise.

Prompt

The Prompt role embodies the information needed to read a line of input from a user, and optionally keep a history of the lines that were entered.

method new

my $prompt = Prompt.new(
  :editor(Any),    # or "Readline", "LineEditor", "Linenoise"
  :history<here>,                       # default: none
  :completions(@completions),           # default: none
  :additional-completions(&one, &two),  # default: none
);
loop {
    last without my $line = $prompt.readline;
    say $line;
}
$prompt.save-history;

The new method is called to instantiate a Prompt object. It takes a number of named arguments described below.

:editor

The editor logic to be used. Can be specified as a string, or as an instantiated object that implements the Prompt::Fallback role.

If the value is not a string, it is expected to be a class that implements to the Prompt::Fallback interface.

Otherwise defaults to Any, which means to search first for unknown roles in the Prompt:: namespace, then to try if there is support installed for Readline, LineEditor, or Linenoise.

If that failed, then the Fallback editor logic will be used, which may cause a cumbersome user experience, unless the process was wrapped with a call to the rlwrap readline wrapper.

Used value available with the .editor method.

:history

String or IO::Path object. Specifies the path to keep any lines that have been previously entered and/or will be entered in the future by any user interactions. Defaults to Any, indicating no history will be kept.

Will load any persistent history already available if the specified path already existed.

Used value available with the .history method.

:completions

A List of strings to be used for tab-completions by the editor. Will only be useful if the .supports-completions method returns True.

:additional-completions

A List of Callables to be called to support additional completion logic. Will only be useful if the .supports-completions method returns True.

method readline

my $line = $prompt.readline("> ");

The readline method takes a single positional argument for the prompt to be shown (defaults to "> ") and returns a line of input from the user.

An undefined value is returned if the user has indicated there is no more input to be obtained.

If the Prompt object was made with a history file, then that history will be available to the user depending on whether the editor used supports that (the Prompt::Fallback editor does not). And in that case, the readline will make sure that any new lines will be added to the history.

Note that to persistently store the history, one must call the save-history, when appropriate (usually when the user is done).

method read

my $line = $prompt.read("> ");

The read method takes a single positional argument for the prompt to be shown and returns a line of input from the user. It does not handle anything history related.

method completions

.say for $prompt.completions;

$prompt.completions(<a b c>);

The completions method returns the current sorted List of completions.

If called with a Positional, will sort that and use that as the list of completions to use.

method additional-completions

The additional-completions method returns an Array of Callables that will be called whenever a completion is requested. Each Callable is expected to accepted two positional arguments: the first is the line that has been entered so far by the user, and the second is the position of the cursor when a completion was requested.

method editor-name

say $prompt.editor-name;

The editor-name method returns the name of the editor support that was activated. It is intended to be purely informatonal.

method history

my $history = $prompt.history;

$prompt.save-history;
$prompt.history("another-file");

Returns the IO::Path object representing the persistent history file.

Can also be called with a positional argument, indicating the file to be used for history keeping from now on. Note that if history was already being kept in another history file, any additions to that will be lost unless a call to save-history was done before that.

method add-history

$prompt.add-history($line);

The add-history method can be called to add a line to the current history. It takes a single positional argument: the line to be added.

Note that calling this method is not needed if the readline method is being used to obtain input from a user.

method load-history

Will (re-)load the history from the file indicated with history.

method save-history

Will save the current history to the file indicated with history.

EDITOR ROLES

An editor role must supply the methods as defined by the Prompt::Fallback role. Its new method should either return an instantiated class, or Nil if the class could not be instantiated (usually because of lack of installed module dependencies).

The other methods are (in alphabetical order):

add-history

Expected to take a single string argument to be added to the (possibly persistent) history. Does not perform any action by default in Prompt::Fallback.

history

If called as an accessor, should return the IO::Path object of the history file.

If called as a mutator with a single positional argument, should set that as the current history file, and load that history.

load-history

Expected to take no arguments and load any persistent history information, as indicated by its history method. Does not perform any action by the default implementation in the Prompt::Fallback role.

read

Expected to take a string argument with the prompt to be shown, and return the next line of input from the user. Expected to return an undefined value to indicate that no further input is to be expected.

Defaults to showing the prompt and taking a line from $*IN in Prompt::Fallback.

save-history

Expected to take no arguments and save any persistent history information, as indicated by its history method. Does not perform any action by the default implementation in the Prompt::Fallback role.

supports-completions

Expected to take no arguments and return a Bool indicating whether this editor supports completions. Defaults to False in the Prompt::Fallback role.

Prompt::Fallback

Apart from the definition of the interface for editors, it provides the default logic for handling the interaction with the user.

Prompt::Readline

The role that implements the user interface using the Readline module.

Prompt::LineEditor

The role that implements the user interface using the Terminal::LineEditor module.

Prompt::Linenoise

The role that implements the user interface using the Linenoise module.

SUBROUTINES

sub prompt

use Prompt :prompt;

say prompt("> ");

If the :prompt named argument is specified with the use Prompt statement, a lexical replacement for the standard prompt functionality will be exported.

$*PROMPT

The $*PROMPT dynamic variable will be used to obtain the Prompt object to be used in the interaction. If none was found, a new Prompt object will be created and stored as $*PROMPT in the PROCESS:: stash (making it automatically available for any subsequent call to the exported prompt subroutine).

use Prompt :prompt;

my $*PROMPT = Prompt.new(...);
say prompt("> ");

If one needs specific initializations with the Prompt object, one can also define ones own $*PROMPT dynamic variable before calling prompt.

AUTHOR

Elizabeth Mattijsen liz@raku.rocks

Source can be located at: https://github.com/lizmat/Prompt . Comments and Pull Requests are welcome.

If you like this module, or what I'm doing more generally, committing to a small sponsorship would mean a great deal to me!

COPYRIGHT AND LICENSE

Copyright 2024 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.