home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / GDBUI.pm < prev    next >
Encoding:
Perl POD Document  |  2003-12-16  |  49.9 KB  |  1,872 lines

  1. # Term::GDBUI.pm
  2. # Scott Bronson
  3. # 3 Nov 2003
  4.  
  5. # Makes it very easy to implement a GDB-like interface.
  6.  
  7. package Term::GDBUI;
  8.  
  9. use strict;
  10.  
  11. use Term::ReadLine ();
  12.  
  13. use vars qw($VERSION);
  14. $VERSION = '0.61';
  15.  
  16. =head1 NAME
  17.  
  18. Term::GDBUI - A Bash/GDB-like command-line environment with autocompletion.
  19.  
  20. =head1 SYNOPSIS
  21.  
  22.  use Term::GDBUI;
  23.  my $term = new Term::GDBUI(commands => get_commands());
  24.  $term->run();
  25.  
  26. get_commands() returns a L<command set|/"COMMAND SET">, described
  27. below in the L<COMMAND SET> section.
  28.  
  29. =head1 DESCRIPTION
  30.  
  31. This class uses the history and autocompletion features of Term::ReadLine
  32. to present a sophisticated command-line interface.  It supports history,
  33. autocompletion, quoting/escaping, pretty much everything you would expect
  34. of a good shell.
  35.  
  36. To use this class, you just need to create a command set that
  37. fully describes your user interface.  You need to write almost no code!
  38.  
  39.  
  40. =head1 METHODS
  41.  
  42. =over 4
  43.  
  44. =item new Term::GDBUI
  45.  
  46. Creates a new GDBUI object.
  47.  
  48. It accepts the following named parameters:
  49.  
  50. =over 3
  51.  
  52. =item app
  53.  
  54. The name of this application as passed to L<Term::ReadLine::new>.
  55. Defaults to $0, the name of the current executable.
  56.  
  57. =item blank_repeats_cmd
  58.  
  59. GDB re-executes the previous command when you enter a blank line.
  60. Bash simply presents you with another prompt.  Pass 1 to get
  61. Term::GDBUI to emulate GDB's behavior or 0 to enable Bash's,
  62. the default (GDBUI's name notwithstanding).
  63.  
  64. =item commands
  65.  
  66. A hashref containing all the commands that GDBUI will respond to.
  67. The format of this data structure can be found below in the
  68. L<COMMAND SET> section.
  69. If you do not supply any commands to the constructor, you must call
  70. the L<commands> method to provide at least a minimal command set before
  71. using many of the following calls.  You may add or delete commands or
  72. even change the entire command set at any time.
  73.  
  74. =item history_file
  75.  
  76. This tells whether or not we should save the command history to
  77. a file in the user's home directory.  By default history_file is
  78. undef and we don't load or save the command history.
  79.  
  80. To enable history saving, supply a filename with this argument.
  81. Tilde expansion is performed, so something like
  82. "~/.myprog-history" is perfectly acceptable.
  83.  
  84. =item history_max
  85.  
  86. This tells how many items to save to the history file.
  87. The default is 64.
  88.  
  89. Note that this parameter does not affect in-memory history.  This module
  90. makes no attemt to cull history so you're at the mercy
  91. of the default of whatever ReadLine library you are using.  History
  92. may grow without bound (no big deal in this day of 1 gigabyte workstations).
  93. See i.e. Term::ReadLine::Gnu::StifleHistory() for one way to change this.
  94.  
  95. =item keep_quotes
  96.  
  97. If you pass keep_quotes=>1, then quote marks found surrounding the
  98. tokens will not be stripped.  Normally all unescaped, unnecessary
  99. quote marks are removed.
  100.  
  101. =item prompt
  102.  
  103. This is the prompt that should be displayed for every request.
  104. It can be changed at any time using the L<prompt> method.
  105. The default is "$0> " (see "app" above).
  106.  
  107. =item token_chars
  108.  
  109. This argument specifies the characters that should be considered
  110. tokens all by themselves.  For instance, if I pass
  111. token_chars=>'=', then 'ab=123' would be parsed to ('ab', '=', '123'.)
  112. token_chars is simply a string containing all token characters.
  113.  
  114. NOTE: you cannot change token_chars after the constructor has been
  115. called!  The regexps that use it are compiled once (m//o).
  116.  
  117. =back
  118.  
  119. By default, the terminal has ornaments (text trickery to make the
  120. command line stand out) turned off.  You can re-enable ornaments
  121. by calling $gdbui->{term}->ornaments(arg) where arg is described in
  122. L<Term::ReadLine::ornaments>.
  123.  
  124. =cut
  125.  
  126. sub new
  127. {
  128.     my $type = shift;
  129.     my %args = (
  130.         app => $0,
  131.         prompt => "$0> ",
  132.         commands => undef,
  133.         blank_repeats_cmd => 0,
  134.         history_file => undef,
  135.         history_max => 64,
  136.         token_chars => '',
  137.         keep_quotes => 0,
  138.         debug_complete => 0,
  139.         @_
  140.     );
  141.  
  142.     my $self = {};
  143.     bless $self, $type;
  144.  
  145.     $self->{done} = 0;
  146.  
  147.     # expand tildes in the history file
  148.     if($args{history_file}) {
  149.         $args{history_file} =~ s/^~([^\/]*)/$1?(getpwnam($1))[7]:
  150.             $ENV{HOME}||$ENV{LOGDIR}||(getpwuid($>))[7]/e;
  151.     }
  152.  
  153.     for(qw(prompt commands blank_repeats_cmd history_file
  154.         history_max token_chars keep_quotes debug_complete)) {
  155.         $self->{$_} = $args{$_};
  156.     }
  157.  
  158.     # used by join_line, tells how to space single-character tokens
  159.     $self->{space_none} = '(';
  160.     $self->{space_before} = '[{';
  161.     $self->{space_after} = ',)]}';
  162.  
  163.     $self->{term} = new Term::ReadLine $args{'app'};
  164.     $self->{term}->ornaments(0);    # turn off decoration by default
  165.     $self->{term}->Attribs->{completion_function} =
  166.         sub { completion_function($self, @_); };
  167.     $self->{term}->MinLine(0);    # manually call AddHistory
  168.     $self->{OUT} = $self->{term}->OUT || \*STDOUT;
  169.  
  170.     $self->{prevcmd} = "";    # cmd to run again if user hits return
  171.  
  172.     return $self;
  173. }
  174.  
  175.  
  176. # This is a utility function that implements a getter/setter.
  177. # Pass the field to modify for $self, and the new value for that
  178. # field (if any) in $new.
  179.  
  180. sub getset
  181. {
  182.     my $self = shift;
  183.     my $field = shift;
  184.     my $new = shift;  # optional
  185.  
  186.     my $old = $self->{$field};
  187.     $self->{$field} = $new if defined $new;
  188.     return $old;
  189. }
  190.  
  191.  
  192. =item prompt
  193.  
  194. If supplied with an argument, this method sets the command-line prompt.
  195. Returns the old prompt.
  196.  
  197. =cut
  198.  
  199. sub prompt { return shift->getset('prompt', shift); }
  200.  
  201.  
  202. =item commands
  203.  
  204. If supplied with an argument, it sets the current command set.
  205. This can be used to change the command set at any time.
  206. Returns the old command set.
  207.  
  208. =cut
  209.  
  210. sub commands { return shift->getset('commands', shift); }
  211.  
  212.  
  213. =item add_commands
  214.  
  215. Adds all the commands in the supplied command set
  216. to the current command set.
  217. Replaces any commands in the current command set that have the same name.
  218.  
  219. =cut
  220.  
  221. sub add_commands
  222. {
  223.     my $self = shift;
  224.     my $cmds = shift;
  225.  
  226.     my $cset = $self->commands() || {};
  227.     for (keys %$cmds) {
  228.         $cset->{$_} = $cmds->{$_};
  229.     }
  230. }
  231.  
  232. =item exit_requested
  233.  
  234. If supplied with an argument, sets the finished flag
  235. to the argument (1=exit, 0=don't exit).  So, to get the
  236. interpreter to exit at the end of processing the current
  237. command, call $self->exit_requested(1).
  238. Returns the old state of the flag.
  239.  
  240. =cut
  241.  
  242. sub exit_requested { return shift->getset('done', shift); }
  243.  
  244.  
  245. =item blank_line
  246.  
  247. This routine is called when the user inputs a blank line.
  248. It should return a string that is the command to run or
  249. undef if nothing should happen.
  250.  
  251. By default, GDBUI simply presents another command line.  Pass
  252. blank_repeats_cmd=>1 to L<new> to get GDBUI to repeat the previous
  253. command.  Override this method to supply your own behavior.
  254.  
  255. =cut
  256.  
  257. sub blank_line
  258. {
  259.     my $self = shift;
  260.  
  261.     if($self->{blank_repeats_cmd}) {
  262.         my $OUT = $self->{OUT};
  263.         print $OUT $self->{prevcmd}, "\n";
  264.         return $self->{prevcmd};
  265.     }
  266.  
  267.     return undef;
  268. }
  269.  
  270.  
  271. =item error
  272.  
  273. Called when an error occurrs.  By default, the routine simply
  274. prints the msg to stderr.  Override it to change this behavior.
  275.  
  276.      $self->error("Oh no!  That was terrible!\n");
  277.  
  278. =cut
  279.  
  280. sub error
  281. {
  282.     my $self = shift;
  283.     print STDERR @_;
  284. }
  285.  
  286.  
  287. =item get_deep_command
  288.  
  289. Looks up the supplied command line in a command hash.
  290. Follows all synonyms and subcommands.
  291. Returns undef if the command could not be found.
  292.  
  293.     my($cset, $cmd, $cname, $args) =
  294.         $self->get_deep_command($self->commands(), $tokens);
  295.  
  296. This call takes two arguments:
  297.  
  298. =over 3
  299.  
  300. =item cset
  301.  
  302. This is the command set to use.  Pass $self->commands()
  303. unless you know exactly what you're doing.
  304.  
  305. =item tokens
  306.  
  307. This is the command line that the command should be read from.
  308. It is a reference to an array that has already been split
  309. on whitespace using L<parse_line>.
  310.  
  311. =back
  312.  
  313. and it returns a list of 4 values:
  314.  
  315. =over 3
  316.  
  317. =item 1
  318.  
  319. cset: the deepest command set found.  Always returned.
  320.  
  321. =item 2
  322.  
  323. cmd: the command hash for the command.  Undef if no command was found.
  324.  
  325. =item 3
  326.  
  327. cname: the full name of the command.  This is an array of tokens,
  328. i.e. ('show', 'info').  Returns as deep as it could find commands
  329. even if the final command was not found.
  330.  
  331. =item 4
  332.  
  333. args: the command's arguments (all remaining tokens after the
  334. command is found).
  335.  
  336. =back
  337.  
  338. =cut
  339.  
  340. sub get_deep_command
  341. {
  342.     my $self = shift;
  343.     my $cset = shift;
  344.     my $tokens = shift;
  345.     my $curtok = shift || 0;    # points to the command name
  346.  
  347.     #print "get_deep_cmd: $cset $#$tokens(" . join(",", @$tokens) . ") $curtok\n";
  348.  
  349.     my $name = $tokens->[$curtok];
  350.  
  351.     # loop through all synonyms to find the actual command
  352.     while(exists($cset->{$name}) && exists($cset->{$name}->{'syn'})) {
  353.         $name = $cset->{$name}->{'syn'};
  354.     }
  355.  
  356.     my $cmd = $cset->{$name};
  357.  
  358.     # update the tokens with the actual name of this command
  359.     $tokens->[$curtok] = $name;
  360.  
  361.     # should we recurse into subcommands?
  362.     #print "$cmd  " . exists($cmd->{'subcmds'}) . "  (" . join(",", keys %$cmd) . ")   $curtok < $#$tokens\n";
  363.     if($cmd && exists($cmd->{cmds}) && $curtok < $#$tokens) {
  364.         #print "doing subcmd\n";
  365.         my $subname = $tokens->[$curtok+1];
  366.         my $subcmds = $cmd->{cmds};
  367.         return $self->get_deep_command($subcmds, $tokens, $curtok+1);
  368.     }
  369.  
  370.     #print "splitting (" . join(",",@$tokens) . ") at curtok=$curtok\n";
  371.  
  372.     # split deep command name and its arguments into separate lists
  373.     my @cname = @$tokens;
  374.     my @args = ($#cname > $curtok ? splice(@cname, $curtok+1) : ());
  375.  
  376.     #print "tokens (" . join(",",@$tokens) . ")\n";
  377.     #print "cname (" . join(",",@cname) . ")\n";
  378.     #print "args (" . join(",",@args) . ")\n";
  379.  
  380.     return ($cset, $cmd, \@cname, \@args);
  381. }
  382.  
  383.  
  384. =item get_cname
  385.  
  386. This is a tiny utility function that turns the cname (array ref
  387. of names for this command as returned by L<get_deep_command>) into
  388. a human-readable string.
  389. This function exists only to ensure that we do this consistently.
  390.  
  391. =cut
  392.  
  393. sub get_cname
  394. {
  395.     my $self = shift;
  396.     my $cname = shift;
  397.  
  398.     return join(" ", @$cname);
  399. }
  400.  
  401.  
  402. =item get_cset_completions
  403.  
  404. Returns a list of commands from the passed command set that are suitable
  405. for completing.
  406.  
  407. It would be nice if we could return one set of completions
  408. (without synonyms) to be displayed when the user hits tab twice,
  409. and another set (with synonyms) to actually complete on.
  410.  
  411. =cut
  412.  
  413. sub get_cset_completions
  414. {
  415.     my $self = shift;
  416.     my $cset = shift;
  417.  
  418.     # returns all non-synonym command names.  This used to be the
  419.     # default, but it seemed more confusting than the alternative.
  420.     # return grep {!exists($cset->{$_}->{syn}) } keys(%$cset);
  421.  
  422.     return grep {!exists $cset->{$_}->{exclude_from_completion}} keys(%$cset);
  423.  
  424.     #return keys(%$cset);
  425. }
  426.  
  427.  
  428. =item completemsg
  429.  
  430. your completion routine should call this to display text onscreen
  431. without messing up the command line being completed.  If your
  432. completion routine prints text without calling completemsg,
  433. the cursor will no longer be displayed in the correct position.
  434.  
  435.     $self->completemsg("You cannot complete here!\n");
  436.  
  437. =cut
  438.  
  439. sub completemsg
  440. {
  441.     my $self = shift;
  442.     my $msg = shift;
  443.  
  444.     my $OUT = $self->{OUT};
  445.     print $OUT $msg;
  446.     $self->{term}->rl_on_new_line();
  447. }
  448.  
  449.  
  450. =item complete
  451.  
  452. complete performs the default top-level command-line completion.
  453. Note that is not called directly by ReadLine.  Rather, ReadLine calls
  454. L<completion_function> which tokenizes the input and performs some
  455. housekeeping, then completion_function calls this one.
  456.  
  457. You should override this routine if your application has custom
  458. completion needs (like non-trivial tokenizing).  If you override
  459. this routine, you will probably need to override L<call_cmd> as well.
  460.  
  461. The one parameter, cmpl, is a data structure that contains all the
  462. information you need to calculate the completions.
  463. Set $self->{debug_complete}=5 to see the contents of cmpl.
  464. Here are the items in cmpl:
  465.  
  466. =over 3
  467.  
  468. =item str
  469.  
  470. The exact string that needs completion.  Often you don't need anything
  471. more than this.
  472.  
  473. =item cset
  474.  
  475. Command set for the deepest command found (see L<get_deep_command>).
  476. If no command was found then cset is set to the topmost command
  477. set ($self->commands()).
  478.  
  479. =item cmd
  480.  
  481. The command hash for deepest command found or
  482. undef if no command was found (see L<get_deep_command>).
  483. cset is the command set that contains cmd.
  484.  
  485. =item cname
  486.  
  487. The full name of deepest command found as an array of tokens (see L<get_deep_command>).
  488.  
  489. =item args
  490.  
  491. The arguments (as a list of tokens) that should be passed to the command
  492. (see L<get_deep_command>).  Valid only if cmd is non-null.  Undef if no
  493. args were passed.
  494.  
  495. =item argno
  496.  
  497. The index of the argument (in args) containing the cursor.
  498.  
  499. =item tokens
  500.  
  501. The tokenized command-line.
  502.  
  503. =item tokno
  504.  
  505. The index of the token containing the cursor.
  506.  
  507. =item tokoff
  508.  
  509. The character offset of the cursor in the token.
  510.  
  511. For instance, if the cursor is on the first character of the 
  512. third token, tokno will be 2 and tokoff will be 0.
  513.  
  514. =item twice
  515.  
  516. True if user has hit tab twice in a row.  This usually means that you
  517. should print a message explaining the possible completions.
  518.  
  519. If you return your completions as a list, then $twice is handled
  520. for you automatically.  You could use it, for instance, to display
  521. an error message (using L<completemsg>) telling why no completions
  522. could be found.
  523.  
  524. =item rawline
  525.  
  526. The command line as a string, exactly as entered by the user.
  527.  
  528. =item rawstart
  529.  
  530. The character position of the cursor in rawline.
  531.  
  532. =back
  533.  
  534. =cut
  535.  
  536. sub complete
  537. {
  538.     my $self = shift;
  539.     my $cmpl = shift;
  540.  
  541.     my $cset = $cmpl->{cset};
  542.     my $cmd = $cmpl->{cmd};
  543.  
  544.     if($cmpl->{tokno} < @{$cmpl->{cname}}) {
  545.         # if we're still in the command, return possible command completions
  546.         return $self->get_cset_completions($cset);
  547.     }
  548.  
  549.     my @retval = ();
  550.     if(!$cmd) {
  551.         # don't do nuthin'
  552.     } elsif(exists($cmd->{args})) {
  553.         if(ref($cmd->{args}) eq 'CODE') {
  554.             @retval = &{$cmd->{args}}($self, $cmpl);
  555.         } elsif(ref($cmd->{args}) eq 'ARRAY') {
  556.             # each element in array is a string describing corresponding argument
  557.             my $arg = $cmd->{args}->[$cmpl->{argno}];
  558.             if(!defined $arg) {
  559.                 # do nothing
  560.             } elsif(ref($arg) eq 'CODE') {
  561.                 # it's a routine to call for this particular arg
  562.                 @retval = &$arg($self, $cmpl);
  563.             } elsif(ref($arg) eq 'ARRAY') {
  564.                 # it's an array of possible completions
  565.                 @retval = @$arg;
  566.             } else {
  567.                 # it's a string reiminder of what this arg is meant to be
  568.                 $self->completemsg("$arg\n") if $cmpl->{twice};
  569.             }
  570.         } elsif(ref($cmd->{args}) eq 'HASH') {
  571.             # not supported yet!  (if ever...)
  572.         } else {
  573.             # this must be a string describing all arguments.
  574.             $self->completemsg($cmd->{args} . "\n") if $cmpl->{twice};
  575.         }
  576.     }
  577.  
  578.     return @retval;
  579. }
  580.  
  581.  
  582. =item completion_function
  583.  
  584. This is the entrypoint to the ReadLine completion callback.
  585. It sets up a bunch of data, then calls L<complete> to calculate
  586. the actual completion.
  587.  
  588. To watch and debug the completion process, you can set $self->{debug_complete}
  589. to 2 (print tokenizing), 3 (print tokenizing and results) or 4 (print
  590. everything including the cmpl data structure).
  591.  
  592. Youu should never need to call or override this function.  If
  593. you do (but, trust me, you don't), set
  594. $self->{term}->Attribs->{completion_function} to point to your own
  595. routine.
  596.  
  597. See the L<Term::ReadLine> documentation for a description of the arguments.
  598.  
  599. =cut
  600.  
  601. sub completion_function
  602. {
  603.     my $self = shift;
  604.     my $text = shift;    # the word directly to the left of the cursor
  605.     my $line = shift;    # the entire line
  606.     my $start = shift;    # the position in the line of the beginning of $text
  607.  
  608.     my $cursor = $start + length($text);
  609.  
  610.     # Twice is true if the user has hit tab twice on the same string
  611.     my $twice = ($self->{completeline} eq $line);
  612.     $self->{completeline} = $line;
  613.  
  614.     my($tokens, $tokno, $tokoff) = $self->parse_line($line,
  615.         messages=>0, cursorpos=>$cursor, fixclosequote=>1);
  616.     return unless defined($tokens);
  617.  
  618.     # this just prints a whole bunch of completion/parsing debugging info
  619.     if($self->{debug_complete} > 1) {
  620.         print "\ntext='$text', line='$line', start=$start, cursor=$cursor";
  621.  
  622.         print "\ntokens=(", join(", ", @$tokens), ") tokno=" . 
  623.             (defined($tokno) ? $tokno : 'undef') . " tokoff=" .
  624.             (defined($tokoff) ? $tokoff : 'undef');
  625.  
  626.         print "\n";
  627.         my $str = " ";
  628.         print     "<";
  629.         my $i = 0;
  630.         for(@$tokens) {
  631.             my $s = (" " x length($_)) . " ";
  632.             substr($s,$tokoff,1) = '^' if $i eq $tokno;
  633.             $str .= $s;
  634.             print $_;
  635.             print ">";
  636.             $str .= "   ", print ", <" if $i != $#$tokens;
  637.             $i += 1;
  638.         }
  639.         print "\n$str\n";
  640.         $self->{term}->rl_on_new_line();
  641.     }
  642.  
  643.     my $str = substr($tokens->[$tokno], 0, $tokoff);
  644.  
  645.     my($cset, $cmd, $cname, $args) = $self->get_deep_command($self->commands(), $tokens);
  646.  
  647.     # this structure hopefully contains everything you'll ever
  648.     # need to easily compute a match.
  649.     my $cmpl = {
  650.         str => $str,            # the exact string that needs completion
  651.                                 # (usually, you don't need anything more than this)
  652.  
  653.         cset => $cset,            # cset of the deepest command found
  654.         cmd => $cmd,            # the deepest command or undef
  655.         cname => $cname,        # full name of deepest command
  656.         args => $args,            # anything that was determined to be an argument.
  657.         argno => $tokno - @$cname,    # the argument containing the cursor
  658.  
  659.         tokens => $tokens,        # tokenized command-line (arrayref).
  660.         tokno => $tokno,        # the index of the token containing the cursor
  661.         tokoff => $tokoff,        # the character offset of the cursor in $tokno.
  662.         twice => $twice,        # true if user has hit tab twice in a row
  663.  
  664.         rawline => $line,        # pre-tokenized command line
  665.         rawstart => $start,        # position in rawline of the cursor
  666.     };
  667.  
  668.     if($self->{debug_complete} > 3) {
  669.         print "tokens=(" . join(",", @$tokens) . ") tokno=$tokno tokoff=$tokoff str=$str twice=$twice\n";
  670.         print "cset=$cset cmd=" . (defined($cmd) ? $cmd : "(undef)") .
  671.             " cname=(" . join(",", @$cname) . ") args=(" . join(",", @$args) . ") argno=$tokno\n";
  672.     }
  673.  
  674.     my @retval = $self->complete($cmpl);
  675.  
  676.     if($self->{debug_complete} > 2) {
  677.         print "returning (", join(", ", @retval), ")\n";
  678.     }
  679.  
  680.     # escape the completions so they're valid on the command line
  681.     $self->parse_escape(\@retval);
  682.  
  683.     return @retval;
  684. }
  685.  
  686.  
  687. # Converts a field name into a text string.
  688. # All fields can be code, if so, then they're called to return string value.
  689. # You need to ensure that the field exists before calling this routine.
  690.  
  691. sub get_field
  692. {
  693.     my $self = shift;
  694.     my $cmd = shift;
  695.     my $field = shift;
  696.     my $args = shift;
  697.  
  698.     my $val = $cmd->{$field};
  699.  
  700.     if(ref($val) eq 'CODE') {
  701.         return &$val($self, $cmd, @$args);
  702.     }
  703.  
  704.     return $val;
  705. }
  706.  
  707.  
  708. =item get_cmd_summary
  709.  
  710. Prints a one-line summary for the given command.
  711.  
  712. =cut
  713.  
  714. sub get_cmd_summary
  715. {
  716.     my $self = shift;
  717.     my $tokens = shift;
  718.     my $topcset = shift || $self->commands();
  719.  
  720.     # print "print_cmd_summary: cmd=$cmd args=(" . join(", ", @$args), ")\n";
  721.  
  722.     my($cset, $cmd, $cname, $args) = $self->get_deep_command($topcset, $tokens);
  723.     if(!$cmd) {
  724.         return $self->get_cname($cname) . " doesn't exist.\n";
  725.     }
  726.  
  727.     my $desc = $self->get_field($cmd, 'desc', $args) || "(no description)";
  728.     return sprintf("%20s -- $desc\n", $self->get_cname($cname));
  729. }
  730.  
  731.  
  732. =item get_cmd_help
  733.  
  734. Prints the full help text for the given command.
  735.  
  736. =cut
  737.  
  738. sub get_cmd_help
  739. {
  740.     my $self = shift;
  741.     my $tokens = shift;
  742.     my $topcset = shift || $self->commands();
  743.  
  744.     my $str = "";
  745.  
  746.     # print "print_cmd_help: cmd=$cmd args=(" . join(", ", @$args), ")\n";
  747.  
  748.     my($cset, $cmd, $cname, $args) = $self->get_deep_command($topcset, $tokens);
  749.     if(!$cmd) {
  750.         return $self->get_cname($cname) . " doesn't exist.\n";
  751.     }
  752.  
  753.     if(exists($cmd->{desc})) {
  754.         $str .= $self->get_cname($cname).": ".$self->get_field($cmd,'desc',$args)."\n";
  755.     } else {
  756.         $str .= "No description for " . $self->get_cname($cname) . "\n";
  757.     }
  758.  
  759.     if(exists($cmd->{doc})) {
  760.         $str .= $self->get_field($cmd, 'doc', $args);
  761.     } elsif(exists($cmd->{cmds})) {
  762.         $str .= $self->get_all_cmd_summaries($cmd->{cmds});
  763.     } else {
  764.         # no data -- do nothing
  765.     }
  766.  
  767.     return $str;
  768. }
  769.  
  770.  
  771. =item get_category_summary
  772.  
  773. Prints a one-line summary for the catgetory named $name
  774. in the category hash $cat.
  775.  
  776. =cut
  777.  
  778. sub get_category_summary
  779. {
  780.     my $self = shift;
  781.     my $name = shift;
  782.     my $cat = shift;
  783.  
  784.     my $title = $cat->{desc} || "(no description)";
  785.     return sprintf("%20s -- $title\n", $name);
  786. }
  787.  
  788. =item get_category_help
  789.  
  790. Returns a string containing the full help for the catgetory named
  791. $name and passed in $cat.  The full help is a list of one-line
  792. summaries of the commands in this category.
  793.  
  794. =cut
  795.  
  796. sub get_category_help
  797. {
  798.     my $self = shift;
  799.     my $cat = shift;
  800.     my $cset = shift;
  801.  
  802.     my $str .= "\n" . $cat->{desc} . "\n\n";
  803.     for my $name (@{$cat->{cmds}}) {
  804.         my @line = split /\s+/, $name;
  805.         $str .= $self->get_cmd_summary(\@line, $cset);
  806.     }
  807.     $str .= "\n";
  808.  
  809.     return $str;
  810. }
  811.  
  812.  
  813. =item get_all_cmd_summaries
  814.  
  815. Pass it a command set, and it will return a string containing
  816. the summaries for each command in the set.
  817.  
  818. =cut
  819.  
  820. sub get_all_cmd_summaries
  821. {
  822.     my $self = shift;
  823.     my $cset = shift;
  824.  
  825.     my $str = "";
  826.  
  827.     for(keys(%$cset)) {
  828.         next unless exists $cset->{$_}->{desc};
  829.         $str .= $self->get_cmd_summary([$_], $cset);
  830.     }
  831.  
  832.     return $str;
  833. }
  834.  
  835.  
  836.  
  837. =item load_history
  838.  
  839. If $self->{history_file} is set (see L<new>), this will load all
  840. history from that file.  Called by L<run> on startup.  If you
  841. don't use run, you will need to call this command manually.
  842.  
  843. =cut
  844.  
  845. sub load_history
  846. {
  847.     my $self = shift;
  848.  
  849.     return unless $self->{history_file} && $self->{history_max} > 0;
  850.  
  851.     if(open HIST, '<'.$self->{history_file}) {
  852.         while(<HIST>) {
  853.             chomp();
  854.             next unless /\S/;
  855.             $self->{term}->addhistory($_);
  856.         }
  857.         close HIST;
  858.     }
  859. }
  860.  
  861. =item save_history
  862.  
  863. If $self->{history_file} is set (see L<new>), this will save all
  864. history to that file.  Called by L<run> on shutdown.  If you
  865. don't use run, you will need to call this command manually.
  866.  
  867. The history routines don't use ReadHistory and WriteHistory so they
  868. can be used even if other ReadLine libs are being used.  save_history
  869. requires that the ReadLine lib supply a GetHistory call.
  870.  
  871. =cut
  872.  
  873. sub save_history
  874. {
  875.     my $self = shift;
  876.  
  877.     return unless $self->{history_file} && $self->{history_max} > 0;
  878.     return unless $self->{term}->can('GetHistory');
  879.  
  880.     my @list = $self->{term}->GetHistory();
  881.     return unless(@list);
  882.  
  883.     my $max = $#list;
  884.     $max = $self->{history_max}-1 if $self->{history_max}-1 < $max;
  885.  
  886.     if(open HIST, '>'.$self->{history_file}) {
  887.         local $, = "\n";
  888.         print HIST @list[0..$max];
  889.         close HIST;
  890.     } else {
  891.         $self->error("Could not open ".$self->{history_file}." for writing $!\n");
  892.     }
  893. }
  894.  
  895.  
  896. =item call_cmd
  897.  
  898. Executes a command and returns the result.  It takes a single
  899. argument: the parms data structure.
  900.  
  901. parms is a subset of the cmpl data structure (see the L<complete>
  902. routine for more).  Briefly, it contains: 
  903. cset, cmd, cname, args (see L<get_deep_command>),
  904. tokens and rawline (the tokenized and untokenized command lines).
  905. See L<complete> for full descriptions of these fields.
  906.  
  907. This call should be overridden if you have exotic command
  908. processing needs.  If you override this routine, you will probably
  909. need to override the L<complete> routine too.
  910.  
  911. =cut
  912.  
  913. sub call_cmd
  914. {
  915.     my $self = shift;
  916.     my $parms = shift;
  917.  
  918.     my $OUT = $self->{OUT};
  919.     my $retval = undef;
  920.  
  921.     if(!$parms->{cmd}) {
  922.         $self->error( $self->get_cname($parms->{cname}) . " doesn't exist.\n");
  923.         goto bail;
  924.     }
  925.  
  926.     my $cmd = $parms->{cmd};
  927.  
  928.     # check min and max args if they exist
  929.     if(exists($cmd->{minargs}) && @{$parms->{args}} < $cmd->{minargs}) {
  930.         $self->error("Too few args!  " . $cmd->{minargs} . " minimum.\n");
  931.         goto bail;
  932.     }
  933.     if(exists($cmd->{maxargs}) && @{$parms->{args}} > $cmd->{maxargs}) {
  934.         $self->error("Too many args!  " . $cmd->{maxargs} . " maximum.\n");
  935.         goto bail;
  936.     }
  937.  
  938.     if(exists $cmd->{meth}) {
  939.         # if meth is a code ref, call it, else it's a string, print it.
  940.         if(ref($cmd->{meth}) eq 'CODE') {
  941.             $retval = eval { &{$cmd->{meth}}($self, $parms, @{$parms->{args}}) };
  942.             $self->error($@) if $@;
  943.         } else {
  944.             print $OUT $cmd->{meth};
  945.         }
  946.     } elsif(exists $cmd->{proc}) {
  947.         # if proc is a code ref, call it, else it's a string, print it.
  948.         if(ref($cmd->{proc}) eq 'CODE') {
  949.             $retval = eval { &{$cmd->{proc}}(@{$parms->{args}}) };
  950.             $self->error($@) if $@;
  951.         } else {
  952.             print $OUT $cmd->{proc};
  953.         }
  954.     } else {
  955.         if(exists $cmd->{cmds}) {
  956.             # if not, but it has subcommands, then print a summary
  957.             print $OUT $self->get_all_cmd_summaries($cmd->{cmds});
  958.         } else {
  959.             $self->error($self->get_cname($parms->{cname}) . " has nothing to do!\n");
  960.         }
  961.     }
  962.  
  963.     return $retval;
  964. }
  965.  
  966.  
  967. =item process_a_cmd
  968.  
  969. Prompts for and returns the results from a single command.
  970. Returns undef if no command was called.
  971.  
  972. =cut
  973.  
  974. sub process_a_cmd
  975. {
  976.     my $self = shift;
  977.  
  978.     $self->{completeline} = "";
  979.  
  980.     my $rawline = $self->{term}->readline($self->prompt());
  981.  
  982.     my $OUT = $self->{'OUT'};
  983.  
  984.     # EOF exits
  985.     unless(defined $rawline) {
  986.         print $OUT "\n";
  987.         $self->exit_requested(1);
  988.         return undef;
  989.     }
  990.  
  991.     # is it a blank line?
  992.     if($rawline =~ /^\s*$/) {
  993.         $rawline = $self->blank_line();
  994.         return unless defined $rawline && $rawline !~ /^\s*$/;
  995.     }
  996.  
  997.     my $retval = undef;
  998.     my $str = $rawline;
  999.  
  1000.     my ($tokens) = $self->parse_line($rawline, messages=>1);
  1001.     if(defined $tokens) {
  1002.         $str = $self->join_line($tokens);
  1003.         my($cset, $cmd, $cname, $args) = $self->get_deep_command($self->commands(), $tokens);
  1004.  
  1005.         # this is a subset of the cmpl data structure
  1006.         my $parms = {
  1007.             cset => $cset,
  1008.             cmd => $cmd,
  1009.             cname => $cname,
  1010.             args => $args,
  1011.             tokens => $tokens,
  1012.             rawline => $rawline,
  1013.         };
  1014.  
  1015.         $retval = $self->call_cmd($parms);
  1016.     }
  1017.  
  1018. bail:
  1019.     # Add to history unless it's a dupe of the previous command.
  1020.     $self->{term}->addhistory($str) if $str ne $self->{prevcmd};
  1021.     $self->{prevcmd} = $str;
  1022.  
  1023.     return $retval;
  1024. }
  1025.  
  1026.  
  1027. =item run
  1028.  
  1029. The main loop.  Processes all commands until someone calls
  1030. L<exit_requested>(true).
  1031.  
  1032. =cut
  1033.  
  1034. sub run
  1035. {
  1036.     my $self = shift;
  1037.  
  1038.     $self->load_history();
  1039.  
  1040.     while(!$self->{done}) {
  1041.         $self->process_a_cmd();
  1042.     }
  1043.  
  1044.     $self->save_history();
  1045. }
  1046.  
  1047.  
  1048. =back
  1049.  
  1050.  
  1051.  
  1052. =head1 CALLBACKS
  1053.  
  1054. These functions are meant to be called by the commands themselves
  1055. (usually via the 'meth' field).
  1056. They offer some assistance in implementing common functions like 'help'.
  1057.  
  1058. =over 4
  1059.  
  1060.  
  1061.  
  1062. =item help_call
  1063.  
  1064. Help commands can call this routine to print information about
  1065. command sets.
  1066.  
  1067. =over 3
  1068.  
  1069. =item cats
  1070.  
  1071. A hash of available help categories (see L<CATEGORIES> below
  1072. for more).  Pass undef if you don't have any help categories.
  1073.  
  1074. =item topic
  1075.  
  1076. The item upon which help should be printed (the arguments to the
  1077. help command.
  1078.  
  1079. =back
  1080.  
  1081. Here is the most common way to implement a help command:
  1082.  
  1083.   "help" =>   { desc => "Print helpful information",
  1084.                 args => sub { shift->help_args($helpcats, @_); },
  1085.                 meth => sub { shift->help_call($helpcats, @_); } },
  1086.  
  1087. This follows synonyms and subcommands, completing the entire
  1088. way.  It works exactly as you'd expect.
  1089.  
  1090. =cut
  1091.  
  1092. sub help_call
  1093. {
  1094.     my $self = shift;
  1095.     my $cats = shift;        # help categories to use
  1096.     my $parms = shift;        # data block passed to methods
  1097.     my $topic = $_[0];        # topics or commands to get help on
  1098.  
  1099.     my $cset = $parms->{cset};
  1100.     my $OUT = $self->{OUT};
  1101.  
  1102.     if(defined($topic)) {
  1103.         if(exists $cats->{$topic}) {
  1104.             print $OUT $self->get_category_help($cats->{$topic}, $cset);
  1105.         } else {
  1106.             print $OUT $self->get_cmd_help(\@_, $cset);
  1107.         }
  1108.     } elsif(defined($cats)) {
  1109.         # no topic -- print a list of the categories
  1110.         print $OUT "\nHelp categories:\n\n";
  1111.         for(keys(%$cats)) {
  1112.             print $OUT $self->get_category_summary($_, $cats->{$_});
  1113.         }
  1114.     } else {
  1115.         # no categories -- print a summary of all commands
  1116.         print $OUT $self->get_all_cmd_summaries($cset);
  1117.     }
  1118. }
  1119.  
  1120. =item help_args
  1121.  
  1122. This provides argument completion for help commands.
  1123. Call this as shown in the example in L<help_call>.
  1124.  
  1125. =cut
  1126.  
  1127. sub help_args
  1128. {
  1129.     my $self = shift;
  1130.     my $helpcats = shift;
  1131.     my $cmpl = shift;
  1132.  
  1133.     my $args = $cmpl->{'args'};
  1134.     my $argno = $cmpl->{'argno'};
  1135.     my $cset = $cmpl->{'cset'};
  1136.  
  1137.     if($argno == 1) {
  1138.         # return both categories and commands if we're on the first argument
  1139.         return ($self->get_cset_completions($cset), keys(%$helpcats));
  1140.     }
  1141.  
  1142.     my($scset, $scmd, $scname, $sargs) = $self->get_deep_command($cset, $args);
  1143.  
  1144.     # without this we'd complete with $scset for all further args
  1145.     return () if $argno > @$scname;
  1146.  
  1147.     return $self->get_cset_completions($scset);
  1148. }
  1149.  
  1150.  
  1151.  
  1152. =item complete_files
  1153.  
  1154. Allows any command to easily complete on objects from the filesystem.
  1155. Call it using either "args => sub { shift->complete_files(@_)" or
  1156. "args => \&complete_files".  See the "ls" example in the L<COMMAND SET>
  1157. section below.
  1158.  
  1159. =cut
  1160.  
  1161. sub complete_files
  1162. {
  1163.     my $self = shift;
  1164.     my $cmpl = shift;
  1165.     my $dir = shift || '.';
  1166.  
  1167.     # don't complete if user has gone past max # of args
  1168.     return () if exists($cmpl->{cmd}->{maxargs}) && $cmpl->{argno} > $cmpl->{cmd}->{maxargs};
  1169.  
  1170.     my $str = $cmpl->{str};
  1171.     my $len = length($str);
  1172.  
  1173.     my @files = ();
  1174.     if(opendir(DIR, $dir)) {
  1175.         @files = grep { substr($_,0,$len) eq $str } readdir DIR;
  1176.         closedir DIR;
  1177.     }
  1178.  
  1179.     return @files;
  1180. }
  1181.  
  1182.  
  1183. =item complete_onlyfiles
  1184.  
  1185. Like L<complete_files>, but excludes directories, device nodes, etc.
  1186. It returns regular files only.
  1187.  
  1188. =cut
  1189.  
  1190. sub complete_onlyfiles
  1191. {
  1192.     return grep { -f } shift->complete_files(@_);
  1193. }
  1194.  
  1195.  
  1196. =item complete_onlydirs
  1197.  
  1198. Like L<complete_files>, but excludes files, device nodes, etc.
  1199. It returns only directories.  
  1200. It I<does> return the . and .. special directories so you'll need
  1201. to remove those manually if you don't want to see them.
  1202.  
  1203. =cut
  1204.  
  1205. sub complete_onlydirs
  1206. {
  1207.     return grep { -d } shift->complete_files(@_);
  1208. }
  1209.  
  1210.  
  1211. =back
  1212.  
  1213. =head1 TOKEN PARSING
  1214.  
  1215. Term::GDBUI used to use the Text::ParseWords module to
  1216. tokenize the command line.  However, requirements have gotten
  1217. significantly more complex since then, forcing this module
  1218. to do all tokenizing itself. 
  1219.  
  1220. =over 3
  1221.  
  1222. =item parsebail
  1223.  
  1224. If the parsel routine or any of its subroutines runs into a fatal
  1225. error, they call parsebail to present a very descriptive diagnostic.
  1226.  
  1227. =cut
  1228.  
  1229. sub parsebail
  1230. {
  1231.     my $self = shift;
  1232.     my $msg = shift;
  1233.     my $line = "";
  1234.  
  1235.     die "$msg at char " . pos() . ":\n",
  1236.     "    $_\n    " . (' ' x pos()) . '^' . "\n";
  1237.  
  1238. }
  1239.  
  1240.  
  1241. =item parsel
  1242.  
  1243. This is the heinous routine that actually does the parsing.
  1244. You should never need to call it directly.  Call L<parse_line>
  1245. instead.
  1246.  
  1247. =cut
  1248.  
  1249. sub parsel
  1250. {
  1251.     my $self = shift;
  1252.     $_ = shift;
  1253.     my $cursorpos = shift;
  1254.     my $fixclosequote = shift;
  1255.  
  1256.     my $deb = $self->{debug};
  1257.     my $tchrs = $self->{token_chars};
  1258.  
  1259.     my $usingcp = (defined($cursorpos) && $cursorpos ne '');
  1260.     my $tokno = undef;
  1261.     my $tokoff = undef;
  1262.     my $oldpos;
  1263.  
  1264.     my @pieces = ();
  1265.  
  1266.     # Need to special case the empty string.  None of the patterns below
  1267.     # will match it yet we need to return an empty token for the cursor.
  1268.     return ([''], 0, 0) if $usingcp && $_ eq '';
  1269.  
  1270.     /^/gc;  # force scanning to the beginning of the line
  1271.  
  1272.     do {
  1273.         $deb && print "-- top, pos=" . pos() . " cursorpos=$cursorpos\n";
  1274.  
  1275.         # trim whitespace from the beginning
  1276.         if(/\G(\s+)/gc) {
  1277.             $deb && print "trimmed " . length($1) . " whitespace chars, cursorpos=$cursorpos\n";
  1278.             # if pos passed cursorpos, then we know that the cursor was
  1279.             # surrounded by ws and we need to create an empty token for it.
  1280.             if($usingcp && (pos() >= $cursorpos)) {
  1281.                 # if pos == cursorpos and we're not yet at EOL, let next token accept cursor
  1282.                 unless(pos() == $cursorpos && pos() < length($_)) {
  1283.                     # need to special-case at end-of-line as there are no more tokens
  1284.                     # to take care of the cursor so we must create an empty one.
  1285.                     $deb && print "adding bogus token to handle cursor.\n";
  1286.                     push @pieces, '';
  1287.                     $tokno = $#pieces;
  1288.                     $tokoff = 0;
  1289.                     $usingcp = 0;
  1290.                 }
  1291.             }
  1292.         }
  1293.  
  1294.         # if there's a quote, then suck to the close quote
  1295.         $oldpos = pos();
  1296.         if(/\G(['"])/gc) {
  1297.             my $quote = $1;
  1298.             my $adjust = 0;    # keeps track of tokoff bumps due to subs, etc.
  1299.             my $s;
  1300.  
  1301.             $deb && print "Found open quote [$quote]  oldpos=$oldpos\n";
  1302.  
  1303.             # adjust tokoff unless the cursor sits directly on the open quote
  1304.             if($usingcp && pos()-1 < $cursorpos) {
  1305.                 $deb && print "  lead quote increment   pos=".pos()." cursorpos=$cursorpos\n";
  1306.                 $adjust += 1;
  1307.             }
  1308.  
  1309.             if($quote eq '"') {
  1310.                 if(/\G((?:\\.|(?!["])[^\\])*)["]/gc) {
  1311.                     $s = $1;    # string without quotes
  1312.                 } else {
  1313.                     unless($fixclosequote) {
  1314.                         pos() -= 1;
  1315.                         $self->parsebail("need closing quote [\"]");
  1316.                     }
  1317.                     /\G(.*)$/gc;    # if no close quote, just suck to the end of the string
  1318.                     $s = $1;    # string without quotes
  1319.                     if($usingcp && pos() == $cursorpos) { $adjust -= 1; }    # make cursor think cq was there
  1320.                 }
  1321.                 $deb && print "  quoted string is \"$s\"\n";
  1322.                 while($s =~ /\\./g) { 
  1323.                     my $ps = pos($s) - 2;     # points to the start of the sub
  1324.                     $deb && print "  doing substr at $ps on '$s'  oldpos=$oldpos adjust=$adjust\n";
  1325.                     $adjust += 1 if $usingcp && $ps < $cursorpos - $oldpos - $adjust;
  1326.                     substr($s, $ps, 1) = '';
  1327.                     pos($s) = $ps + 1;
  1328.                     $deb && print "  s='$s'  usingcp=$usingcp  pos(s)=" . pos($s) . "  cursorpos=$cursorpos  oldpos=$oldpos adjust=$adjust\n";
  1329.                 }
  1330.             } else {
  1331.                 if(/\G((?:\\.|(?!['])[^\\])*)[']/gc) {
  1332.                     $s = $1;    # string without quotes
  1333.                 } else {
  1334.                     unless($fixclosequote) {
  1335.                         pos() -= 1;
  1336.                         $self->parsebail("need closing quote [']");
  1337.                     }
  1338.                     /\G(.*)$/gc;    # if no close quote, just suck to the end of the string
  1339.                     $s = $1;
  1340.                     if($usingcp && pos() == $cursorpos) { $adjust -= 1; }    # make cursor think cq was there
  1341.                 }
  1342.                 $deb && print "  quoted string is '$s'\n";
  1343.                 while($s =~ /\\[\\']/g) { 
  1344.                     my $ps = pos($s) - 2;     # points to the start of the sub
  1345.                     $deb && print "  doing substr at $ps on '$s'  oldpos=$oldpos adjust=$adjust\n";
  1346.                     $adjust += 1 if $usingcp && $ps < $cursorpos - $oldpos - $adjust;
  1347.                     substr($s, $ps, 1) = '';
  1348.                     pos($s) = $ps + 1;
  1349.                     $deb && print "  s='$s'  usingcp=$usingcp  pos(s)=" . pos($s) . "  cursorpos=$cursorpos  oldpos=$oldpos adjust=$adjust\n";
  1350.                 }
  1351.             }
  1352.  
  1353.             # adjust tokoff if the cursor if it sits directly on the close quote
  1354.             if($usingcp && pos() == $cursorpos) {
  1355.                 $deb && print "  trail quote increment  pos=".pos()." cursorpos=$cursorpos\n";
  1356.                 $adjust += 1;
  1357.             }
  1358.  
  1359.             $deb && print "  Found close, pushing '$s'  oldpos=$oldpos\n";
  1360.             push @pieces, $self->{keep_quotes} ? $quote.$s.$quote : $s;
  1361.  
  1362.             # Set tokno and tokoff if this token contained the cursor
  1363.             if($usingcp && pos() >= $cursorpos) {
  1364.                 # Previous block contains the cursor
  1365.                 $tokno = $#pieces;
  1366.                 $tokoff = $cursorpos - $oldpos - $adjust;
  1367.                 $usingcp = 0;
  1368.             }
  1369.         }
  1370.  
  1371.         # suck up as much unquoted text as we can
  1372.         $oldpos = pos();
  1373.         if(/\G((?:\\.|[^\s\\"'\Q$tchrs\E])+)/gco) {
  1374.             my $s = $1;        # the unquoted string
  1375.             my $adjust = 0;    # keeps track of tokoff bumps due to subs, etc.
  1376.  
  1377.             $deb && print "Found unquoted string '$s'\n";
  1378.             while($s =~ /\\./g) { 
  1379.                 my $ps = pos($s) - 2;    # points to the start of substitution
  1380.                 $deb && print "  doing substr at $ps on '$s'  oldpos=$oldpos adjust=$adjust\n";
  1381.                 $adjust += 1 if $usingcp && $ps < $cursorpos - $oldpos - $adjust;
  1382.                 substr($s, $ps, 1) = '';
  1383.                 pos($s) = $ps + 1;
  1384.                 $deb && print "  s='$s'  usingcp=$usingcp  pos(s)=" . pos($s) . "  cursorpos=$cursorpos  oldpos=$oldpos adjust=$adjust\n";
  1385.             }
  1386.             $deb && print "  pushing '$s'\n";
  1387.             push @pieces, $s;
  1388.  
  1389.             # Set tokno and tokoff if this token contained the cursor
  1390.             if($usingcp && pos() >= $cursorpos) {
  1391.                 # Previous block contains the cursor
  1392.                 $tokno = $#pieces;
  1393.                 $tokoff = $cursorpos - $oldpos - $adjust;
  1394.                 $usingcp = 0;
  1395.             }
  1396.         }
  1397.  
  1398.         if(length($tchrs) && /\G([\Q$tchrs\E])/gco) {
  1399.             my $s = $1;    # the token char
  1400.             $deb && print "  pushing '$s'\n";
  1401.             push @pieces, $s;
  1402.  
  1403.             if($usingcp && pos() == $cursorpos) {
  1404.                 # Previous block contains the cursor
  1405.                 $tokno = $#pieces;
  1406.                 $tokoff = 0;
  1407.                 $usingcp = 0;
  1408.             }
  1409.         }
  1410.     } until(pos() >= length($_));
  1411.  
  1412.     $deb && print "Result: (", join(", ", @pieces), ") " . 
  1413.         (defined($tokno) ? $tokno : 'undef') . " " .
  1414.         (defined($tokoff) ? $tokoff : 'undef') . "\n";
  1415.  
  1416.     return ([@pieces], $tokno, $tokoff);
  1417. }
  1418.  
  1419.  
  1420. =item parse_line($line, $cursorpos)
  1421.  
  1422. This is the entrypoint to this module's parsing functionality.  It converts
  1423. a line into tokens, respecting quoted text, escaped characters,
  1424. etc.  It also keeps track of a cursor position on the input text,
  1425. returning the token number and offset within the token where that position
  1426. can be found in the output.
  1427.  
  1428. This routine originally bore some resemblance to Text::ParseWords.
  1429. It has changed almost completely, however, to support keeping track
  1430. of the cursor position.  It also has nicer failure modes, modular
  1431. quoting, token characters (see token_chars in L<new>), etc.  This
  1432. routine now does much more.
  1433.  
  1434. Arguments:
  1435.  
  1436. =over 3
  1437.  
  1438. =item line
  1439.  
  1440. This is a string containing the command-line to parse.
  1441.  
  1442. =back
  1443.  
  1444. This routine also accepts the following named parameters:
  1445.  
  1446. =over 3
  1447.  
  1448. =item cursorpos
  1449.  
  1450. This is the character position in the line to keep track of.
  1451. Pass undef (by not specifying it) or the empty string to have
  1452. the line processed with cursorpos ignored.
  1453.  
  1454. Note that passing undef is I<not> the same as passing
  1455. some random number and ignoring the result!  For instance, if you
  1456. pass 0 and the line begins with whitespace, you'll get a 0-length token at
  1457. the beginning of the line to represent the cursor in
  1458. the middle of the whitespace.  This allows command completion
  1459. to work even when the cursor is not near any tokens.
  1460. If you pass undef, all whitespace at the beginning and end of
  1461. the line will be trimmed as you would expect.
  1462.  
  1463. If it is ambiguous whether the cursor should belong to the previous
  1464. token or to the following one (i.e. if it's between two quoted
  1465. strings, say "a""b" or a token_char), it always gravitates to
  1466. the previous token.  This makes more sense when completing.
  1467.  
  1468. =item fixclosequote
  1469.  
  1470. Sometimes you want to try to recover from a missing close quote
  1471. (for instance, when calculating completions), but usually you
  1472. want a missing close quote to be a fatal error.  fixclosequote=>1
  1473. will implicitly insert the correct quote if it's missing.
  1474. fixclosequote=>0 is the default.
  1475.  
  1476. =item messages
  1477.  
  1478. parse_line is capable of printing very informative error messages.
  1479. However, sometimes you don't care enough to print a message (like
  1480. when calculating completions).  Messages are printed by default,
  1481. so pass messages=>0 to turn them off.
  1482.  
  1483. =back
  1484.  
  1485. This function returns a reference to an array containing three
  1486. items:
  1487.  
  1488. =over 3
  1489.  
  1490. =item tokens
  1491.  
  1492. A the tokens that the line was separated into (ref to an array of strings).
  1493.  
  1494. =item tokno
  1495.  
  1496. The number of the token (index into the previous array) that contains
  1497. cursorpos.
  1498.  
  1499. =item tokoff
  1500.  
  1501. The character offet into tokno of cursorpos.
  1502.  
  1503. =back
  1504.  
  1505. If the cursor is at the end of the token, tokoff will point to 1
  1506. character past the last character in tokno, a non-existant character.
  1507. If the cursor is between tokens (surrounded by whitespace), a zero-length
  1508. token will be created for it.
  1509.  
  1510. =cut
  1511.  
  1512. sub parse_line
  1513. {
  1514.     my $self = shift;
  1515.     my $line = shift;
  1516.     my %args = (
  1517.         messages => 1,        # true if we should print errors, etc.
  1518.         cursorpos => undef,    # cursor to keep track of, undef to ignore.
  1519.         fixclosequote => 0,
  1520.         @_
  1521.     );
  1522.  
  1523.     my @result = eval { $self->parsel($line,
  1524.         $args{'cursorpos'}, $args{'fixclosequote'}) };
  1525.     if($@) {
  1526.         $self->error($@) if $args{'messages'};
  1527.         @result = (undef, undef, undef);
  1528.     }
  1529.  
  1530.     return @result;
  1531. }
  1532.  
  1533.  
  1534. =item parse_escape
  1535.  
  1536. Escapes characters that would be otherwise interpreted by the parser.
  1537. Will accept either a single string or an arrayref of strings (which
  1538. will be modified in-place).
  1539.  
  1540. =cut
  1541.  
  1542. sub parse_escape
  1543. {
  1544.     my $self = shift;
  1545.     my $arr = shift;    # either a string or an arrayref of strings
  1546.  
  1547.     my $wantstr = 0;
  1548.     if(ref($arr) ne 'ARRAY') {
  1549.         $arr = [$arr];
  1550.         $wantstr = 1;
  1551.     }
  1552.  
  1553.     foreach(@$arr) {
  1554.         my $quote;
  1555.         if($self->{keep_quotes} && /^(['"])(.*)\1$/) {
  1556.             ($quote, $_) = ($1, $2);
  1557.         }
  1558.         s/([ \\"'])/\\$1/g;
  1559.         $_ = $quote.$_.$quote if $quote;
  1560.     }
  1561.  
  1562.     return $wantstr ? $arr->[0] : $arr;
  1563. }
  1564.  
  1565.  
  1566. =item join_line
  1567.  
  1568. This routine does a somewhat intelligent job of joining tokens
  1569. back into a command line.  If token_chars (see L<new>) is empty
  1570. (the default), then it just escapes backslashes and quotes, and
  1571. joins the tokens with spaces.
  1572.  
  1573. However, if token_chars is nonempty, it tries to insert a visually
  1574. pleasing amount of space between the tokens.  For instance, rather
  1575. than 'a ( b , c )', it tries to produce 'a (b, c)'.  It won't reformat
  1576. any tokens that aren't found in $self->{token_chars}, of course.
  1577.  
  1578. To change the formatting, you can redefine the variables
  1579. $self->{space_none}, $self->{space_before}, and $self->{space_after}.
  1580. Each variable is a string containing all characters that should
  1581. not be surrounded by whitespace, should have whitespace before,
  1582. and should have whitespace after, respectively.  Any character
  1583. found in token_chars, but non in any of these space_ variables,
  1584. will have space placed both before and after.
  1585.  
  1586. =cut
  1587.  
  1588. sub join_line
  1589. {
  1590.     my $self = shift;
  1591.     my $intoks = shift;
  1592.  
  1593.     my $tchrs = $self->{token_chars};
  1594.     my $s_none = $self->{space_none};
  1595.     my $s_before = $self->{space_before};
  1596.     my $s_after = $self->{space_after};
  1597.  
  1598.     # copy the input array so we don't modify it
  1599.     my $tokens = $self->parse_escape([@$intoks]);
  1600.  
  1601.     my $str = '';
  1602.     my $sw = '';    # a space if space wanted after token.
  1603.     for(@$tokens) {
  1604.         if(length == 1 && index($tchrs,$_) >= 0) {
  1605.             if(index($s_none,$_) >= 0)   { $str .= $_;     $sw='';  next; }
  1606.             if(index($s_before,$_) >= 0) { $str .= $sw.$_; $sw='';  next; }
  1607.             if(index($s_after,$_) >= 0)  { $str .= $_;     $sw=' '; next; }
  1608.         }
  1609.         $str .= $sw.$_; $sw = ' ';
  1610.     }
  1611.  
  1612.     return $str;
  1613. }
  1614.  
  1615.  
  1616. =back
  1617.  
  1618.  
  1619. =head1 COMMAND SET
  1620.  
  1621. A command set describes your application's entire user interface.
  1622.  It's probably easiest to explain this with a working example.
  1623. Combine the following get_commands() routine with the
  1624. code shown in the L<SYNOPSIS> above, and you'll have a real-life
  1625. shellish thingy that supports the following commands:
  1626.  
  1627. =over 4
  1628.  
  1629. =item h
  1630.  
  1631. This is just a synonym for "help".  It is not listed in the possible
  1632. completions because it just clutters up the list without being useful.
  1633.  
  1634. =item help
  1635.  
  1636. The default implementation for the help command
  1637.  
  1638. =item ls
  1639.  
  1640. This command shows how to perform completion using the L<complete_files>
  1641. routine, how a proc can process its arguments, and how to provide
  1642. more comprehensive help.
  1643.  
  1644. =item show
  1645.  
  1646. This is an example showing how the GDB show command can be
  1647. implemented.  Both "show warranty" and "show args" are valid
  1648. subcommands.
  1649.  
  1650. =item show args
  1651.  
  1652. This is a hypothetical command.  It uses a static completion for the
  1653. first argument (either "create" or "delete") and the standard
  1654. file completion for the second.  When executed, it echoes its own command
  1655. name followed by its arguments.
  1656.  
  1657. =item quit
  1658.  
  1659. How to nicely quit.  Even if no quit command is supplied, Term::GDBUI
  1660. follows Term::ReadLine's default of quitting when Control-D is pressed.
  1661.  
  1662. =back
  1663.  
  1664. This code is rather large because it is intended to be reasonably
  1665. comprehensive and demonstrate most of the features supported by
  1666. Term::GDBUI's command set.  For a more reasonable example, see the
  1667. "fileman-example" file that ships with this module.
  1668.  
  1669.  sub get_commands
  1670.  {
  1671.      return {
  1672.          "h" =>      { syn => "help", exclude_from_completion=>1},
  1673.          "help" => {
  1674.              desc => "Print helpful information",
  1675.              args => sub { shift->help_args(undef, @_); },
  1676.              meth => sub { shift->help_call(undef, @_); }
  1677.          },
  1678.          "ls" => {
  1679.              desc => "List whether files exist",
  1680.              args => sub { shift->complete_files(@_); },
  1681.              proc => sub {
  1682.                  print "exists: " .
  1683.                      join(", ", map {-e($_) ? "<$_>":$_} @_) .
  1684.                      "\n";
  1685.              },
  1686.              doc => <<EOL,
  1687.  Comprehensive documentation for our ls command.
  1688.  If a file exists, it is printed in <angle brackets>.
  1689.  The help can\nspan\nmany\nlines
  1690.  EOL
  1691.          },
  1692.          "show" => {
  1693.              desc => "An example of using subcommands",
  1694.              cmds => {
  1695.                  "warranty" => { proc => "You have no warranty!\n" },
  1696.                  "args" => {
  1697.                      minargs => 2, maxargs => 2,
  1698.                      args => [ sub {qw(create delete)},
  1699.                                \&Term::GDBUI::complete_files ],
  1700.                      desc => "Demonstrate method calling",
  1701.                      meth => sub {
  1702.                          my $self = shift;
  1703.                          my $parms = shift;
  1704.                          print $self->get_cname($parms->{cname}) .
  1705.                              ": " . join(" ",@_), "\n";
  1706.                      },
  1707.                  },
  1708.              },
  1709.          },
  1710.          "quit" => {
  1711.              desc => "Quit using Fileman",
  1712.              maxargs => 0,
  1713.              meth => sub { shift->exit_requested(1); }
  1714.          },
  1715.      };
  1716.  }
  1717.  
  1718.  
  1719. =head1 COMMAND HASH
  1720.  
  1721. A command is described by a relatively small number of fields: desc,
  1722. args, proc, meth, etc.  These fields are collected into a data
  1723. structure called a command hash.  A command set is simply a
  1724. collection of command hashes.
  1725.  
  1726. The following fields may be found in a command hash:
  1727.  
  1728. =over 4
  1729.  
  1730. =item desc
  1731.  
  1732. A short, one-line description for the command.  Normally this is
  1733. a simple string.
  1734.  
  1735. If you store a reference to a subroutine in this field, the routine
  1736. will be called to calculate the description to print.  Your
  1737. subroutine should accept two arguments, $self (the Term::GDBUI object),
  1738. and $cmd (the command hash for the command), and return a string
  1739. containing the command's description.
  1740.  
  1741. =item doc
  1742.  
  1743. A comprehensive, many-line description for the command.  Normally
  1744. this is stored as a simple string.
  1745.  
  1746. If you store a reference to a subroutine in this field, the routine
  1747. will be called to calculate the documentation.  Your
  1748. subroutine should accept two arguments: self (the Term::GDBUI object),
  1749. and cmd (the command hash for the command), and return a string
  1750. containing the command's documentation.
  1751.  
  1752. =item maxargs
  1753.  
  1754. =item minargs
  1755.  
  1756. These set the maximum and minimum number of arguments that this
  1757. command will accept.  By default, the command can accept any
  1758. number of arguments.
  1759.  
  1760. =item proc
  1761.  
  1762. This contains a reference to the subroutine that should be called
  1763. when this command should be executed.  Arguments are
  1764. those passed on the command line, return value is returned by
  1765. call_cmd and process_a_cmd (i.e. it is usually ignored).
  1766.  
  1767. If this field is a string instead of a subroutine ref, the string
  1768. (i.e. "Not implemented yet") is printed when the command is executed. 
  1769. Examples of both subroutine and string procs can be seen in the example
  1770. above.
  1771.  
  1772. proc is similar to meth, but only passes the command's arguments.
  1773.  
  1774. =item meth
  1775.  
  1776. Like proc, but includes more arguments.  Where proc simply passes
  1777. the arguments for the command, meth also passes the Term::GDBUI object
  1778. and the command's parms object (see L<call_cmd> for more on parms).
  1779.  
  1780. Like proc, meth may also be a string.  If a command has both a meth
  1781. and a proc, the meth takes precedence.
  1782.  
  1783. =item args
  1784.  
  1785. This tells how to complete the command's arguments.  It is usually
  1786. a subroutine.  See L<complete_files>) for an reasonably simple
  1787. example, and the L<complete> routine for a description of the
  1788. arguments and cmpl data structure.
  1789.  
  1790. Args can also be an arrayref.  Each position in the array will be
  1791. used as the corresponding argument.  For instance, if a command
  1792. takes two arguments, an operation and a file
  1793.  
  1794. Finally, args can also be a string that is a reminder and is printed
  1795. whenever the user types tab twice.
  1796.  
  1797. =item cmds
  1798.  
  1799. Command sets can be recursive.  This allows a command to implement
  1800. subcommands (like GDB's info and show).  The cmds field specifies
  1801. the command set that this command implements.
  1802.  
  1803. A command with subcommands should only have two fields:
  1804. cmds (of course),
  1805. and desc to briefly describe this collection of subcommands.
  1806. It may also implement doc, but GDBUI's default behavior of printing
  1807. a summary of subcommands for the command is usually sufficient.
  1808. Any other fields (args, meth, maxargs, etc) will be ignored.
  1809.  
  1810. =item exclude_from_completion
  1811.  
  1812. If this field exists, then the command will be excluded from command-line
  1813. completion.  This is useful for one-letter command synonyms, such as
  1814. "h"->"help".  To include "h" in the completions is usually mildly
  1815. confusing, especially when there are a lot of other single-letter synonyms.
  1816. This is usable in all commands, not just synonyms.
  1817.  
  1818. =back
  1819.  
  1820.  
  1821. =head1 CATEGORIES
  1822.  
  1823. Normally, when the user types 'help', she receives a summary of
  1824. every supported command.  
  1825. However, if your application has 30 or more commands, this can
  1826. result in information overload.  To manage this, you can organize
  1827. your commands into help categories
  1828.  
  1829. All help categories are assembled into a hash and passed to the
  1830. the default L<help_call> and L<help_args> methods.  If you don't
  1831. want to use help categories, simply pass undef.
  1832.  
  1833. Here is an example of how to declare a collection of help categories:
  1834.  
  1835.   my $helpcats = {
  1836.       breakpoints => {
  1837.           desc => "Commands to force the program to stop at certain points",
  1838.           cmds => qw(break tbreak delete disable enable),
  1839.       },
  1840.       data => {
  1841.           desc => "Commands to examine data",
  1842.           cmds => ['info', 'show warranty', 'show args'],
  1843.       }
  1844.   };
  1845.  
  1846. "show warranty" and "show args" are examples of how to include
  1847. subcommands in a help category.
  1848.  
  1849. =head1 BUGS
  1850.  
  1851. The Parsing/Tokeniznig should be split off into another
  1852. module, perhaps soemthing like Text::ParseWords::Cursor.
  1853.  
  1854. It would be nice if this module understood some sort of extended
  1855. EBNF so it could automatically
  1856. tokenize and complete commands for very complex input syntaxes.
  1857. Of course, that would be one hell of a big project...
  1858.  
  1859. =head1 LICENSE
  1860.  
  1861. Copyright (c) 2003 Scott Bronson, all rights reserved. 
  1862. This program is free software; you can redistribute it and/or modify 
  1863. it under the same terms as Perl itself.  
  1864.  
  1865. =head1 AUTHOR
  1866.  
  1867. Scott Bronson E<lt>bronson@rinspin.comE<gt>
  1868.  
  1869. =cut
  1870.  
  1871. 1;
  1872.