The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

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

VERSION

version 0.04008

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> ',
    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) and Term::ReadLine::Gnu(3p).

First-time users may want to read Term::CLI::Tutorial and Term::CLI::Intro 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.

commands => ArrayRef

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

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 => Str

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.

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.

callback ( [ CodeRef ] )

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

Others

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, [ ArrayRef[Str] ] )

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

The first Str should be the original command line string.

By default, execute will split the command line into words using Text::ParseWords::parse_line, and then parse and execute the result accordingly. If parse_line fails, then a parse error is generated.

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).

  • 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

In case of INT, HUP, TERM, or TSTP signals, the current input line is always discarded.

If the application has not set its own handlers, the readline method will set signal handlers for the INT and QUIT signals in such a way that they do not cause the application to terminate.

It also makes sure that after a keyboard suspend (TSTP) and subsequent continue (CONT), the command prompt is redrawn:

    bash$ perl tutorial/term_cli.pl
    > foo
    > ^Z
    [1]+  Stopped                 perl tutorial/term_cli.pl
    bash$ fg
    perl tutorial/term_cli.pl
    > _

SEE ALSO

FindBin(3p), Getopt::Long(3p), Term::CLI(3p), Term::CLI::Argument(3p), Term::CLI::Command(3p), Term::CLI::Intro(3p), Term::CLI::Role::CommandSet(3p), Term::CLI::Tutorial(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.