source: perl/lib/BarnOwl/Complete/Filter.pm @ ffc4df6

release-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since ffc4df6 was 5fdc562, checked in by David Benjamin <davidben@mit.edu>, 15 years ago
Fix typo in _complete_filter_expr Forgot to fully switch to the new index variable. Signed-off-by: David Benjamin <davidben@mit.edu>
  • Property mode set to 100644
File size: 3.8 KB
Line 
1use strict;
2use warnings;
3
4# Helper completers for filters
5package BarnOwl::Complete::Filter;
6
7use base qw(Exporter);
8our @EXPORT_OK = qw(complete_filter_name complete_filter_expr);
9
10# Completes the name of a filter
11sub complete_filter_name { return @{BarnOwl::all_filters()}; }
12
13# Completes a filter expression
14sub complete_filter_expr {
15    my $ctx = shift;
16
17    my @completions = ();
18    _complete_filter_expr($ctx, 0, \@completions);
19    # Get rid of duplicates and sort
20    my %hash = ();
21    @hash{@completions} = ();
22    @completions = sort keys %hash;
23    return @completions;
24}
25
26### Private
27
28my %filter_cmds = (
29    sender    => \&BarnOwl::Complete::Zephyr::complete_user,
30    recipient => \&BarnOwl::Complete::Zephyr::complete_user,
31    class     => \&BarnOwl::Complete::Zephyr::complete_class,
32    instance  => \&BarnOwl::Complete::Zephyr::complete_instance,
33    opcode    => \&BarnOwl::Complete::Zephyr::complete_opcode,
34    realm     => \&BarnOwl::Complete::Zephyr::complete_realm,
35    body      => undef,
36    hostname  => undef,
37    type      => sub { qw(zephyr aim admin); },
38    direction => sub { qw(in out none); },
39    login     => sub { qw(login logout none); },
40    filter    => \&complete_filter_name,
41    perl      => undef,
42);
43
44# Returns:
45# - where to look next after pulling out an expression
46# - $INCOMPLETE if this cannot form a complete expression (or w/e)
47# - pushes to completion list as it finds valid completions
48
49my $INCOMPLETE = -1;
50sub _complete_filter_expr {
51    # Takes as arguments context and the index into $ctx->words where the
52    # filter expression starts
53    my $ctx = shift;
54    my $start = shift;
55    my $o_comp = shift;
56    my $end = $ctx->word;
57
58    # Grab an expression; we don't allow empty
59    my $i = $start;
60    $i = _complete_filter_primitive_expr($ctx, $start, $o_comp);
61    return $INCOMPLETE if $i == $INCOMPLETE;
62
63    while ($i <= $end) {
64        if ($i == $end) {
65            # We could and/or another clause
66            push @$o_comp, qw(and or);
67            return $end; # Or we could let the parent do his thing
68        }
69
70        if ($ctx->words->[$i] ne 'and' && $ctx->words->[$i] ne 'or') {
71            return $i; # We're done. Let the parent do his thing
72        }
73
74        # Eat the and/or
75        $i++;
76
77        # Grab an expression
78        $i = _complete_filter_primitive_expr($ctx, $i, $o_comp);
79        return $INCOMPLETE if $i == $INCOMPLETE;
80    }
81   
82    return $i; # Well, it looks like we're happy
83    # (Actually, I'm pretty sure this never happens...)
84}
85
86sub _complete_filter_primitive_expr {
87    my $ctx = shift;
88    my $start = shift;
89    my $o_comp = shift;
90    my $end = $ctx->word;
91
92    if ($start >= $end) {
93        push @$o_comp, "(";
94        push @$o_comp, qw(true false not);
95        push @$o_comp, keys %filter_cmds;
96        return $INCOMPLETE;
97    }
98
99    my $word = $ctx->words->[$start];
100    if ($word eq "(") {
101        $start = _complete_filter_expr($ctx, $start+1, $o_comp);
102        return $INCOMPLETE if $start == $INCOMPLETE;
103
104        # Now, we expect a ")"
105        if ($start >= $end) {
106            push @$o_comp, ")";
107            return $INCOMPLETE;
108        }
109        if ($ctx->words->[$start] ne ')') {
110            # User is being confusing. Give up.
111            return $INCOMPLETE;
112        }
113        return $start+1; # Eat the )
114    } elsif ($word eq "not") {
115        # We just want another primitive expression
116        return _complete_filter_primitive_expr($ctx, $start+1, $o_comp);
117    } elsif ($word eq "true" || $word eq "false") {
118        # No arguments
119        return $start+1; # Eat the boolean. Mmmm, tasty.
120    } else {
121        # It's of the form 'CMD ARG'
122        return $start+2 if ($start+1 < $end); # The user supplied the argument
123
124        # complete the argument
125        my $arg_func = $filter_cmds{$word};
126        push @$o_comp, ($arg_func ? ($arg_func->()) : ());
127        return $INCOMPLETE;
128    }
129}
Note: See TracBrowser for help on using the repository browser.