The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Term::CLI - CLI interpreter based on Term::ReadLine

VERSION

version 0.054002

SYNOPSIS

 use Term::CLI;
 use Term::CLI::Command;
 use Term::CLI::Argument::Filename;
 use Data::Dumper;

 my $cli = Term::CLI->new(
    name => 'myapp',
    prompt => 'myapp> ',
    cleanup => sub {
        my ($cli) = @_;
        $cli->write_history;
            or warn "cannot write history: ".$cli->error."\n";
    },
    callback => sub {
        my ($self, %args) = @_;
        print Data::Dumper->Dump([\%args], ['args']);
        return %args;
    },
    commands => [
        Term::CLI::Command->new(
            name => 'copy',
            options => [ 'verbose!' ],
            arguments => [
                Term::CLI::Argument::Filename->new(name => 'src'),
                Term::CLI::Argument::Filename->new(name => 'dst'),
            ],
            callback => sub {
                my ($self, %args) = @_;
                print Data::Dumper->Dump([\%args], ['args']);
                return (%args, status => 0);
            }
        )
    ],
 );

 $cli->read_history;  # Read history from ~/.myapp_history
 $cli->write_history; # Write history to ~/.myapp_history

 $cli->word_delimiters(';,');
 # $cli will now recognise things like: 'copy;--verbose;a,b'

 $cli->word_delimiters(" \t\n");
 # $cli will now recognise things like: 'copy --verbose a b'

 while ( my $input = $cli->readline(skip => qr/^\s*(?:#.*)?$/) ) {
    $cli->execute($input);
 }

DESCRIPTION

Implement an easy-to-use command line interpreter based on Term::ReadLine(3p). Although primarily aimed at use with the Term::ReadLine::Gnu(3p) implementation, it also supports Term::ReadLine::Perl(3p).

First-time users may want to read Term::CLI::Tutorial(3p) and Term::CLI::Intro(3p) first, and peruse the example scripts in the source distribution's examples and tutorial directories.

CLASS STRUCTURE

Inherits from:

Term::CLI::Base(3p).

Consumes:

Term::CLI::Role::CommandSet(3p).

CONSTRUCTORS

new ( attr => VAL ... )

Create a new Term::CLI object and return a reference to it.

Valid attributes:

callback => CodeRef

Reference to a subroutine that should be called when the command is executed, or undef.

cleanup => CodeRef

Reference to a subroutine that should be called when the object is destroyed (i.e. in Moo terminology, when DEMOLISH is called).

commands => ArrayRef

Reference to an array containing Term::CLI::Command object instances that describe the commands that Term::CLI recognises, or undef.

ignore_keyboard_signals => ArrayRef

Specify a list of signals for which the keyboard generation should be turned off during a readline operation.

The list of signals should be a combination of INT, QUIT, or TSTP. See also ignore_keyboard_signals in Term::CLI::ReadLine(3p). If this is not specified, QUIT keyboard generation is turned off by default.

name => Str

The application name. This is used for e.g. the history file and default command prompt.

If not given, defaults to $FindBin::Script (see FindBin(3p)).

prompt => Str

Prompt to display when readline is called. Defaults to the application name with > and a space appended.

skip => RegEx

Set the object's skip attribute, telling the readline method to ignore input lines that match the given RegEx. A common call value is qr{^\s+(?:#.*)$} to skip empty lines, lines with only whitespace, and comments.

history_file => Str

Specify the file to read/write input history to/from. The default is name + _history in the user's HOME directory.

history_lines => Int

Maximum number of lines to keep in the input history. Default is 1000.

INHERITED METHODS

This class inherits all the attributes and accessors of Term::CLI::Role::CommandSet(3p) and Term::CLI::Base(3p), most notably:

Accessors

has_callback

See has_callback in Term::CLI::Role::CommandSet.

callback ( [ CodeRef ] )

See callback in Term::CLI::Role::CommandSet.

has_commands

See has_commands in Term::CLI::Role::CommandSet.

commands ( [ ArrayRef ] )

See commands in Term::CLI::Role::CommandSet.

ArrayRef with Term::CLI::Command object instances.

Others

has_cleanup

Predicate function that returns whether or not the cleanup attribute has been set.

cleanup ( [ CodeRef ] )

Gets or sets a reference to a subroutine that should be called when the object is destroyed (i.e. in Moo terminology, when DEMOLISH is called).

The code is called with one parameter: the object to be destroyed. One typical use of cleanup is to ensure that the history gets saved upon exit:

  my $cli = Term::CLI->new(
    ...
    cleanup => sub {
      my ($cli) = @_;
      $cli->write_history
        or warn "cannot write history: ".$cli->error."\n";
    }
  );
find_command ( Str )

See find_command in Term::CLI::Role::CommandSet.

find_matches ( Str )

See find_matches in Term::CLI::Role::CommandSet.

METHODS

Accessors

name

The application name. See name in Term::CLI::Base.

prompt ( [ Str ] )

Get or set the command line prompt to display to the user.

term

Return a reference to the underlying Term::CLI::ReadLine object. See term in Term::CLI::Base.

quote_characters ( [ Str ] )

Get or set the characters that should considered quote characters for the completion and parsing/execution routines.

Default is '", that is a single quote or a double quote.

It's possible to change this, but this will interfere with the default splitting function, so if you do want custom quote characters, you should also override the split_function.

split_function ( [ CodeRef ] )

Get or set the function that is used to split a (partial) command line into words. The default function uses Text::ParseWords::parse_line. Note that this implies that it can take into account custom delimiters, but not custom quote characters.

The CodeRef is called as:

    ( ERROR, [ WORD, ... ] ) = CodeRef->( CLI_OBJ, TEXT )

The function should return a list of at least one element, an ERROR string. Subsequent elements are the words resulting from the split.

ERROR string should be empty (not undef!) if splitting was successful, otherwise it should contain a relevant error message.

word_delimiters ( [ Str ] )

Get or set the characters that are considered word delimiters in the completion and parsing/execution routines.

Default is \t\n, that is space, tab, and newline.

The first character in the string is also the character that is appended to a completed word at the command line prompt.

History Control

history_lines ( [ Int ] )

Get or set the maximum number of lines to keep in the history. Default is 1000.

history_file ( [ Str ] )

Set the default file to read from/write to.

read_history ( [ Str ] )

Try to read input history from the history_file(). Returns 1 on success. On failure, it will set the error field and return undef.

If Str is given, it will try to read from that file instead. If that is successful, the history_file() attribute will be set to Str.

write_history ( [ Str ] )

Try to write the input history to the history_file(). Returns 1 on success. On failure, it will set the error field and return undef.

If Str is given, it will try to write to that file instead. If that is successful, the history_file() attribute will be set to Str.

Others

complete_line ( TEXT, LINE, START )

Called when the user hits the TAB key for completion.

TEXT is the text to complete, LINE is the input line so far, START is the position in the line where TEXT starts.

The function will split the line in words and delegate the completion to the first Term::CLI::Command sub-command, see Term::CLI::Command.

readline ( [ ATTR => VAL, ... ] )

Read a line from the input connected to term, using the Term::ReadLine interface.

By default, it returns the line read from the input, or an empty value if end of file has been reached (e.g. the user hitting Ctrl-D).

The following ATTR are recognised:

skip => RegEx

Override the object's skip attribute.

Skip lines that match the RegEx parameter. A common call is:

    $text = CLI->readline( skip => qr{^\s+(?:#.*)$} );

This will skip empty lines, lines containing whitespace, and comments.

prompt => Str

Override the prompt given by the prompt method.

Examples:

    # Just read the next input line.
    $line = $cli->readline;
    exit if !defined $line;

    # Skip empty lines and comments.
    $line = $cli->readline( skip => qr{^\s*(?:#.*)?$} );
    exit if !defined $line;
execute ( Str )

Parse and execute the command line consisting of Str (see the return value of readline above).

The command line is split into words using the split_function. If that succeeds, then the resulting list of words is parsed and executed, otherwise a parse error is generated (i.e. the object's callback function is called with a status of -1 and a suitable error field).

For specifying a custom word splitting method, see split_function.

Example:

    while (my $line = $cli->readline(skip => qr/^\s*(?:#.*)?$/)) {
        $cli->execute($line);
    }

The command line is parsed depth-first, and for every Term::CLI::Command(3p) encountered, that object's callback function is executed (see callback in Term::CLI::Role::Command).

The execute function returns the results of the last called callback function.

  • Suppose that the file command has a show sub-command that takes an optional --verbose option and a single file argument.

  • Suppose the input is:

        file show --verbose foo.txt
  • Then the parse tree looks like this:

        (cli-root)
            |
            +--> Command 'file'
                    |
                    +--> Command 'show'
                            |
                            +--> Option '--verbose'
                            |
                            +--> Argument 'foo.txt'
  • Then the callbacks will be called in the following order:

    1. Callback for 'show'

    2. Callback for 'file'

    3. Callback for Term::CLI object.

    The return value from each callback (a hash in list form) is fed into the next callback function in the chain. This allows for adding custom data to the return hash that will be fed back up the parse tree (and eventually to the caller).

SIGNAL HANDLING

The Term::CLI object (through Term::CLI::ReadLine) will make sure that signals are handled "correctly". This especially means that if a signal is not ignored, the terminal is left in a "sane" state before any signal handler is called or the program exits.

See also SIGNAL HANDLING in Term::CLI::ReadLine.

SEE ALSO

FindBin(3p), Moo(3p), Getopt::Long(3p), Term::CLI::Argument(3p), Term::CLI::Base(3p), Term::CLI::Command(3p), Term::CLI::Intro(3p), Term::CLI::ReadLine(3p), Term::CLI::Role::CommandSet(3p), Term::CLI::Tutorial(3p), Term::ReadLine::Gnu(3p), Term::ReadLine::Perl(3p), Term::ReadLine(3p), Text::ParseWords(3p), Types::Standard(3p).

Inspiration for the custom completion came from: https://robots.thoughtbot.com/tab-completion-in-gnu-readline. This is an excellent tutorial into the completion mechanics of the readline library, and, by extension, Term::ReadLine::Gnu(3p).

AUTHOR

Steven Bakker <sbakker@cpan.org>, 2018.

COPYRIGHT AND LICENSE

Copyright (c) 2018 Steven Bakker

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See "perldoc perlartistic."

This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.