source: perl/lib/BarnOwl/Complete/Filter.pm @ 3001c11

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