source: perl/lib/BarnOwl/Completion.pm @ 5368d75

release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 5368d75 was 5368d75, checked in by Nelson Elhage <nelhage@mit.edu>, 12 years ago
Implement tab completion by replacing the entire word. Replace the entire word, instead of just appending the new text. Among other things, this lets us deal with expansions that need to be quoted much better.
  • Property mode set to 100644
File size: 2.3 KB
Line 
1use warnings;
2use strict;
3
4=head1 NAME
5
6BarnOwl::Completion
7
8=head1 DESCRIPTION
9
10Hooks for tab-completion support in BarnOwl.
11
12=cut
13
14package BarnOwl::Completion;
15
16use BarnOwl::Completion::Context;
17use BarnOwl::Editwin qw(save_excursion text_before_point text_after_point
18                        point_move replace_region);
19
20use List::Util qw(max first);
21
22sub do_complete {
23    my $cmd = shift;
24    my $before = text_before_point();
25    my $after  = text_after_point();
26    BarnOwl::debug("Completing: $before-|-$after");
27    my $ctx = BarnOwl::Completion::Context->new($before, $after);
28
29    my @words = get_completions($ctx);
30    return unless @words;
31    my $prefix = common_prefix(@words);
32
33    my $word = $ctx->words->[$ctx->word];
34
35    if($prefix) {
36        insert_completion($ctx, $prefix, scalar @words == 1);
37    }
38
39    if(scalar @words > 1) {
40        show_completions(@words);
41    } else {
42        BarnOwl::message('');
43    }
44}
45
46sub insert_completion {
47    my $ctx = shift;
48    my $completion = shift;
49    my $unique = shift;
50
51    save_excursion {
52        point_move($ctx->word_start - $ctx->point);
53        BarnOwl::Editwin::set_mark();
54        point_move($ctx->word_end - $ctx->word_start);
55        replace_region(BarnOwl::quote($completion));
56    };
57    if($unique && $ctx->word == (scalar @{$ctx->words} - 1)) {
58        save_excursion {
59            BarnOwl::Editwin::set_mark();
60            replace_region(' ');
61        };
62        point_move(1);
63    }
64}
65
66sub get_completions {
67    my $ctx = shift;
68    if($ctx->word == 0) {
69        return complete_command($ctx->words->[0]);
70    } else {
71        return;
72    }
73}
74
75sub complete_command {
76    my $cmd = shift;
77    return grep {$_ =~ m{^\Q$cmd\E}} @BarnOwl::all_commands;
78}
79
80sub show_completions {
81    my @words = @_;
82    my $all = join(" ", map {BarnOwl::quote($_)} @words);
83    my $width = BarnOwl::getnumcols();
84    if (length($all) > $width-1) {
85        $all = substr($all, 0, $width-4) . "...";
86    }
87    BarnOwl::message($all);
88}
89
90sub common_prefix {
91    my @words = @_;
92    my $len   = max(map {length($_)} @words);
93    my $pfx = '';
94    for my $i (1..$len) {
95        $pfx = substr($words[0], 0, $i);
96        if(first {substr($_, 0, $i) ne $pfx} @words) {
97            $pfx = substr($pfx, 0, $i-1);
98            last;
99        }
100    }
101
102    return $pfx;
103}
104
1051;
Note: See TracBrowser for help on using the repository browser.