/usr/share/barnowl/lib/BarnOwl/Completion.pm is in barnowl 1.9-4build2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | use warnings;
use strict;
=head1 NAME
BarnOwl::Completion
=head1 DESCRIPTION
Hooks for tab-completion support in BarnOwl.
=cut
package BarnOwl::Completion;
use BarnOwl::Completion::Context;
use BarnOwl::Editwin qw(save_excursion text_before_point text_after_point
point_move replace_region);
use List::Util qw(min first);
our %completers = ();
sub do_complete {
my $cmd = shift;
my $before = text_before_point();
my $after = text_after_point();
BarnOwl::debug("Completing: $before-|-$after");
my $ctx = BarnOwl::Completion::Context->new($before, $after);
my @words = get_completions($ctx);
return unless @words;
my $prefix = common_prefix(map {completion_value($_)} @words);
if($prefix) {
insert_completion($ctx, $prefix,
scalar @words == 1 && completion_done($words[0]));
}
if(scalar @words > 1) {
show_completions(@words);
} else {
BarnOwl::message('');
}
}
=head1 COMPLETIONS
A COMPLETION is either a simple string, or a reference to an array
containing two or more values.
In the former case, the string use used for both the text to display,
as well as the result of the completion, and is assumed to be a full
completion.
An arrayref completion consists of
[$display_text, $replacement_value[, $completion_done] ].
$display_text will be printed in the case of ambiguous completions,
$replacement_value will be used to substitute the value in. If there
is only a single completion for a given word, a space will be appended
after the completion iff $completion_done is true (or missing).
=cut
sub completion_text {
my $c = shift;
return $c unless ref($c) eq 'ARRAY';
return $c->[0];
}
sub completion_value {
my $c = shift;
return $c unless ref($c) eq 'ARRAY';
return $c->[1];
}
sub completion_done {
my $c = shift;
return 1 if ref($c) ne 'ARRAY' or @$c < 3;
return $c->[2];
}
sub insert_completion {
my $ctx = shift;
my $completion = BarnOwl::quote(completion_value(shift));
my $done = shift;
if($done) {
$completion .= " ";
}
save_excursion {
point_move($ctx->word_start - $ctx->point);
BarnOwl::Editwin::set_mark();
point_move($ctx->word_end - $ctx->word_start);
replace_region($completion);
};
if(!length($ctx->words->[$ctx->word])) {
point_move(length($completion));
}
}
sub show_completions {
my @words = @_;
my $all = BarnOwl::quote(map {completion_text($_)} @words);
my $width = BarnOwl::getnumcols();
if (length($all) > $width-1) {
$all = substr($all, 0, $width-4) . "...";
}
BarnOwl::message($all);
}
sub common_prefix {
my @words = @_;
my $len = min(map {length($_)} @words);
my $pfx = '';
for my $i (1..$len) {
$pfx = substr($words[0], 0, $i);
if(first {substr($_, 0, $i) ne $pfx} @words) {
$pfx = substr($pfx, 0, $i-1);
last;
}
}
return $pfx;
}
sub get_completions {
my $ctx = shift;
if($ctx->word == 0) {
return complete_command($ctx->words->[0]);
} else {
my $cmd = $ctx->words->[0];
my $word = $ctx->words->[$ctx->word];
if(exists($completers{$cmd})) {
return grep {completion_value($_) =~ m{^\Q$word\E}} $completers{$cmd}->($ctx);
}
return;
}
}
sub complete_command {
my $cmd = shift;
$cmd = "" unless defined($cmd);
return grep {$_ =~ m{^\Q$cmd\E}} @BarnOwl::all_commands;
}
sub register_completer {
my $cmd = shift;
my $completer = shift;
$completers{$cmd} = $completer;
}
sub load_completers {
opendir(my $dh, BarnOwl::get_data_dir() . "/" . "lib/BarnOwl/Complete/") or return;
while(my $name = readdir($dh)) {
next if $name =~ m{^\.};
next unless $name =~ m{[.]pm$};
$name =~ s{[.]pm$}{};
eval "use BarnOwl::Complete::$name";
if($@) {
BarnOwl::error("Loading completion module $name:\n$@\n");
}
}
}
$BarnOwl::Hooks::startup->add("BarnOwl::Completion::load_completers");
1;
|