NAME

Term::DBPrompt - Commandline prompt for a database application

NEW INTERFACE

Version 0.03 of Term::DBPrompt has introduced incompatible changes that break the interface. The changes are:

Subroutines page_say and page_print

Subroutines page_say() and page_print() have been removed from version 0.03. Instead, a new function fh() is introduced that returns a filhandle that can be printed to. The replacement is therefore to use that filehandle as follows: say {fh()} ... or print {fh()} ...

Getopt::Std

The use of Getopt::Std, Commandline parameters and STDIN/STDOUT handling has been removed from version 0.03. Consequently, those actions must be performed in the calling program and passed on to Term::DBPrompt with the new methods set_opt() and init_pipe(). (the subroutine init_pipe() must be called after set_opt(), but before get_cmd_line()).

Here is a sample piece of code:

use Term::DBPrompt;

use Getopt::Std;
getopts('f:ipq', \my %opts);
set_opt({ file     => $opts{f},
          argv     => "@ARGV",
          inter    => $opts{i},
          prompt   => $opts{p},
          quiet    => $opts{q},
          tty_in   => -t STDIN,
          tty_out  => -t STDOUT,
        });

init_pipe;

while (my ($rc, $open, $close, $cmd, @params) = get_cmd_line)

Other changes

Subroutines page_msg_say() and page_msg_print() have been removed from version 0.03, the replacement is to use a simple say {fh()} ... or print {fh()} ... as described above. Consequently, there is no equivalent for option "-s" anymore, this case is now covered by option "-q".

SYNOPSIS

use strict;
use warnings;
use 5.010;

use Term::DBPrompt;

use Getopt::Std;
getopts('f:ipq', \my %opts);
set_opt({ file     => $opts{f},
          argv     => "@ARGV",
          inter    => $opts{i},
          prompt   => $opts{p},
          quiet    => $opts{q},
          tty_in   => -t STDIN,
          tty_out  => -t STDOUT,
        });

set_prompt 'dbx> ';

set_banner qq{\n}.
  qq{*******************************************\n}.
  qq{**   The Database Application Ver 0.12   **\n}.
  qq{*******************************************\n}.
  qq{*                                         *\n}.
  qq{* to get a help screen,    enter "h(elp)" *\n}.
  qq{* to exit the application, enter "e(xit)" *\n}.
  qq{*                                         *\n}.
  qq{*******************************************\n};

set_command qw(exit help list);

init_pipe;

while (my ($rc, $open, $close, $cmd, @params) = get_cmd_line) {

    next if $rc eq 'Empty';

    page_open if $open;

    if ($rc eq 'Dup') {
        local $" = "', '";
        say {fh()} "-- Command '$cmd' can not be uniquely identified";
        say {fh()} "-- Possibilities are ('@params')";
        say {fh()} "-- type 'h' for help or 'e' to exit";
    }
    elsif ($rc eq 'Multi') {
        say {fh()} "-- Multiple commands can not be issued in interactive mode";
        say {fh()} "-- type 'h' for help or 'e' to exit";
    }
    else {
        given ($cmd) {
            when ('exit') { last; }
            when ('help') { do_help(@params); }
            when ('list') { do_list(@params); }
            default {
                local $" = "', '";
                if ($rc eq 'Not') {
                    say {fh()} "-- Invalid command '$cmd' ('@params')";
                    say {fh()} "-- type 'h' for help or 'e' to exit";
                }
                else {
                    say {fh()} "-- Function not implemented '$cmd' ('@params')";
                    say {fh()} "-- type 'h' for help or 'e' to exit";
                }
            }
        }
    }

    page_close if $close;
}

sub do_help {
    say {fh()} 'DBX - Database Application';
    say {fh()} '';
    say {fh()} 'Commands:';
    say {fh()} '';
    say {fh()} '  h(elp)   -- shows this screen';
    say {fh()} '  l(ist)   -- list parameters';
    say {fh()} '  e(xit)   -- exit the application';
}

sub do_list {
    say {fh()} '*****************';
    say {fh()} '**  Parameters **';
    say {fh()} '*****************';
    say {fh()} '';

    for (1..100) {
        printf {fh()} "Parameter #%03d...: ZZZ\n", $_;
    }

    say {fh()} '';
    say {fh()} '*****************';
}

DESCRIPTION

Interactive mode

We save the example program from the synopsis in dbx.pl and we run it with a simple 'perl dbx.pl', which creates the following output:

C:\>perl dbx.pl

*******************************************
**   The Database Application Ver 0.12   **
*******************************************
*                                         *
* to get a help screen,    enter "h(elp)" *
* to exit the application, enter "e(xit)" *
*                                         *
*******************************************

dbx>

As you can see, we are greeted by a banner (as defined by the set_banner command in the dbx.pl program) and a command prompt 'dbx>'.

Now we can enter our first interactive command, the 'help' command:

dbx> help

DBX - Database Application

Commands:

  h(elp)   -- shows this screen
  l(ist)   -- list parameters
  e(xit)   -- exit the application


dbx>

Now we can issue another command, the 'list' command. We don't need to spell out the whole command, the first characters that make that command unique is enough, in this case a simple 'l' suffices. (The list of available commands is defined by the 'set_command(...)' instruction).

dbx> l
*****************
**  Parameters **
*****************

Parameter #001...: ZZZ
Parameter #002...: ZZZ
...
Parameter #049...: ZZZ
Parameter #050...: ZZZ
-- Next  --
...
Parameter #099...: ZZZ
Parameter #100...: ZZZ

*****************

dbx>

You will notice that the output waits for a keypress (see the '-- Next --' line) after a page is complete (i.e. it is piped through 'more').

To exit the application, you can either hit the EOF character (that is Ctrl-Z on Windows or Ctrl-D on Linux) or you can enter the exit command.

Batch mode

There are 3 different ways to feed commands in batch mode: as a parameter on the commandline, as a file specified via option '-f' or as a file redirected into STDIN, all of these 3 possibilities can be combined. Multiple commands can be issued on a single line by separating them with a ';' character. You can also use the '#' character to write comments.

Commandline

Here is an example that uses a parameter on the command line to issue the help command:

C:\>perl dbx.pl help

In order to issue multiple commands, you need to enclose the parameter with double quotes (on Windows) or single quotes (on Linux). Here is a Windows example:

C:\>perl dbx.pl "help; list;"
option -f

Here is an example that uses option '-f' to feed a file into dbx.pl. Suppose we have a file 'cmd.txt' that contains many commands. We could feed this file into dbx.pl like so:

C:\>perl dbx.pl -f cmd.txt
Redirection

We can also feed a file into dbx.pl by redirecting STDIN:

C:\>perl dbx.pl < cmd.txt

Commandline interface

Here is an overview of the commandline interface:

perl dbx.pl [-q] [-p] [-f file] [-i] "cmd1; cmd2; ..."
option -q

Option '-q' stands for quiet mode. This option supresses normal output in batch mode (it does not have any effect in interactive mode).

option -p

Option '-p' stands for show prompt. This option shows a prompt and the commands in batch mode. It does not have any effect in interactive mode where the prompt is shown anyway.

option -f

As already described above, we can use option '-f' to feed a file into dbx.pl:

C:\>perl dbx.pl -f cmd.txt
option -i

Option '-i' forces interactive mode where the command would otherwise run in batch mode. Consider the above example "perl dbx.pl -f cmd.txt" which runs in batch mode, i.e. it terminates after the last command in cmd.txt. If, however, you wish to continue in interactive mode after the commands in cmd.txt have been processed, you can use the -i option:

C:\>perl dbx.pl -i -f cmd.txt

EXPORTED FUNCTIONS

The following functions are exported by default:

set_opt

This function sets one (or more) options (which usually have been read in by "Getopt::Std"). The syntax is: set_opt({ opt1 => "val1", opt2 => "val2", ...), where opt1, opt2 can be any of the following: ('file', 'argv', 'inter', prompt' or 'quiet').

set_opt() is usually called like this:

use Term::DBPrompt;

use Getopt::Std;
getopts('f:ipq', \my %opts);

set_opt({ file     => $opts{f},
          argv     => "@ARGV",
          inter    => $opts{i},
          prompt   => $opts{p},
          quiet    => $opts{q},
          tty_in   => -t STDIN,
          tty_out  => -t STDOUT,
        });
init_pipe

This function must be called before the first use of get_cmd_line(). It resets its internal counters to start a new session of commands to be processed.

set_prompt

This functions sets the prompt. Here is an example to set the prompt to 'abc> ':

set_prompt 'abc> ';

The default is '?> '.

set_banner

The banner is one big string which is displayed at the beginning of each interactive session. You can set the banner with the set_banner function:

set_banner qq{\n}.
  qq{*******************************************\n}.
  qq{**   The Database Application Ver 0.12   **\n}.
  qq{*******************************************\n}.
  qq{*                                         *\n}.
  qq{* to get a help screen,    enter "h(elp)" *\n}.
  qq{* to exit the application, enter "e(xit)" *\n}.
  qq{*                                         *\n}.
  qq{*******************************************\n};
set_command

The function set_command is used to register all possible identifiers that can be used to trigger an action. Two common identifiers are 'help' and 'exit', but there can be many more, depending on the particular application, such as 'add', 'remove', 'list', etc. The reason why these identifiers have to be registered is that long commands can be shortened to a prefix, if that prefix is unique. With the help of the function set_command, the program can then automatically compute the smallest prefix which is still unique to identify an action.

To give a concrete example, suppose we have the following list of commands:

set_command qw(help exit init input list);

If we issued a command 'h', the system would automatically choose the identifier 'help' because there is only one identifier that begins with 'h'. However, if we issued a command 'i', the system would not be able to decide if we wanted the identifier 'init' or 'input'. In order to be valid, we would have to enter at least 3 characters (either 'ini' or 'inp').

get_cmd_line

This is the main function to obtain one line from the input (either from STDIN, from a file or from the commandline). The function takes no parameter, but returns 5 elements:

my ($rc, $open, $close, $cmd, @params) = get_cmd_line;

The first parameter is a return code. It can have 4 values: 'Found', 'Not', 'Empty' or 'Dup'.

$rc == 'Found'

indicates that the prefix that has been entered corresponds exactly to one identifier. $cmd contains that identifier in full and @param contains all parameters.

$rc == 'Not'

indicates that the prefix that has been entered does not correspond to any identifier. $cmd contains the prefix and @param contains all parameters.

$rc == 'Empty'

indicates that an empty line has been entered.

$rc == 'Dup'

indicates that the prefix which has been entered corresponds to more than one identifier. In that case $cmd contains the prefix and @param contains all the possible identifiers that match the prefix.

The value $open can be either 0 or 1. It indicates whether or not the page_open() function should be called before the command is executed.

The value $close can be either 0 or 1. It indicates whether or not the page_close() function should be called after the command is executed.

get_candidates

This functions returns all possible candidates for a given word where the prefix of the commands registered in the set_command function matches that word. The returned list can have 0, 1 or more than 1 element.

page_open

This functions opens a temp file to which you can print via the fh() handle.

page_close

This functions closes the temp file and displays its content on the screen. (for interactive session, its content will be piped through "more")

AUTHOR

Klaus Eichner <klaus03@gmail.com>

COPYRIGHT

Copyright (c) 2009 Klaus Eichner. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.