Changes in / [85fa6e4:460fbe8]
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
perl/lib/BarnOwl/Complete/Client.pm
rdc8f6e0 rdab89e28 6 6 package BarnOwl::Complete::Client; 7 7 8 use BarnOwl::Completion::Util qw(complete_flags complete_file);8 use BarnOwl::Completion::Util qw(complete_flags); 9 9 use BarnOwl::Complete::Filter qw(complete_filter_name complete_filter_expr); 10 10 … … 167 167 } 168 168 169 sub complete_bindkey {170 my $ctx = shift;171 # bindkey KEYMAP KEYSEQ command COMMAND172 # 0 1 2 3 4173 if ($ctx->word == 1) {174 return complete_keymap();175 } elsif ($ctx->word == 2) {176 return;177 } elsif ($ctx->word == 3) {178 return ('command');179 } else {180 my $new_ctx = $ctx->shift_words(4);181 return BarnOwl::Completion::get_completions($new_ctx);182 }183 }184 185 sub complete_print {186 my $ctx = shift;187 return unless $ctx->word == 1;188 return complete_variable();189 }190 191 sub complete_one_file_arg {192 my $ctx = shift;193 return unless $ctx->word == 1;194 return complete_file($ctx->words->[1]);195 }196 197 169 BarnOwl::Completion::register_completer(help => \&complete_help); 198 170 BarnOwl::Completion::register_completer(filter => \&complete_filter); … … 206 178 BarnOwl::Completion::register_completer(unset => \&complete_set); 207 179 BarnOwl::Completion::register_completer(startup => \&complete_startup); 208 BarnOwl::Completion::register_completer(bindkey => \&complete_bindkey);209 BarnOwl::Completion::register_completer(print => \&complete_print);210 211 BarnOwl::Completion::register_completer(source => \&complete_one_file_arg);212 BarnOwl::Completion::register_completer('load-subs' => \&complete_one_file_arg);213 BarnOwl::Completion::register_completer(loadsubs => \&complete_one_file_arg);214 BarnOwl::Completion::register_completer(loadloginsubs => \&complete_one_file_arg);215 BarnOwl::Completion::register_completer(dump => \&complete_one_file_arg);216 180 217 181 1; -
perl/lib/BarnOwl/Completion.pm
r880311d r48d130b 31 31 my @words = get_completions($ctx); 32 32 return unless @words; 33 my $prefix = common_prefix( map {completion_value($_)}@words);33 my $prefix = common_prefix(@words); 34 34 35 35 if($prefix) { 36 insert_completion($ctx, $prefix, 37 scalar @words == 1 && completion_done($words[0])); 36 insert_completion($ctx, $prefix, scalar @words == 1); 38 37 } 39 38 … … 45 44 } 46 45 47 =head1 COMPLETIONS48 49 A COMPLETION is either a simple string, or a reference to an array50 containing two or more values.51 52 In the former case, the string use used for both the text to display,53 as well as the result of the completion, and is assumed to be a full54 completion.55 56 An arrayref completion consists of57 58 [$display_text, $replacement_value[, $completion_done] ].59 60 $display_text will be printed in the case of ambiguous completions,61 $replacement_value will be used to substitute the value in. If there62 is only a single completion for a given word, a space will be appended63 after the completion iff $completion_done is true (or missing).64 65 =cut66 67 sub completion_text {68 my $c = shift;69 return $c unless ref($c) eq 'ARRAY';70 return $c->[0];71 }72 73 sub completion_value {74 my $c = shift;75 return $c unless ref($c) eq 'ARRAY';76 return $c->[1];77 }78 79 sub completion_done {80 my $c = shift;81 return 1 if ref($c) ne 'ARRAY' or @$c < 3;82 return $c->[2];83 }84 85 46 sub insert_completion { 86 47 my $ctx = shift; 87 my $completion = BarnOwl::quote( completion_value(shift));88 my $ done = shift;48 my $completion = BarnOwl::quote(shift); 49 my $unique = shift; 89 50 90 if($ done) {51 if($unique) { 91 52 $completion .= " "; 92 53 } … … 105 66 sub show_completions { 106 67 my @words = @_; 107 my $all = BarnOwl::quote( map {completion_text($_)}@words);68 my $all = BarnOwl::quote(@words); 108 69 my $width = BarnOwl::getnumcols(); 109 70 if (length($all) > $width-1) { … … 137 98 my $word = $ctx->words->[$ctx->word]; 138 99 if(exists($completers{$cmd})) { 139 return grep { completion_value($_)=~ m{^\Q$word\E}} $completers{$cmd}->($ctx);100 return grep {$_ =~ m{^\Q$word\E}} $completers{$cmd}->($ctx); 140 101 } 141 102 return; -
perl/lib/BarnOwl/Completion/Util.pm
re6cec01 r69c27e6 5 5 6 6 use base qw(Exporter); 7 our @EXPORT_OK = qw(complete_flags complete_file);7 our @EXPORT_OK = qw(complete_flags); 8 8 9 9 use Getopt::Long; 10 use Cwd qw(abs_path);11 use File::Basename qw(dirname basename);12 13 10 14 11 sub complete_flags { … … 70 67 } 71 68 } 72 73 sub expand_tilde {74 # Taken from The Perl Cookbook, recipe 7.375 my $path = shift;76 $path =~ s{ ^ ~ ( [^/]* ) }77 { $178 ? (getpwnam($1))[7]79 : ( $ENV{HOME} || $ENV{LOGDIR}80 || (getpwuid($>))[7]81 )82 }ex;83 return $path;84 }85 86 sub splitfile {87 my $path = shift;88 if ($path =~ m{^(.*/)([^/]*)$}) {89 return ($1, $2);90 } else {91 return ('', $path);92 }93 }94 95 sub complete_file {96 my $string = shift;97 98 return ['~/', '~/', 0] if $string eq '~';99 100 my $path = abs_path(expand_tilde($string));101 my $dir;102 if ($string =~ m{/$} || $string eq '' || basename($string) eq '.') {103 $dir = $path;104 } else {105 $dir = dirname($path);106 }107 return unless -d $dir;108 109 my ($pfx, $base) = splitfile($string);110 111 opendir(my $dh, $dir) or return;112 my @dirs = readdir($dh);113 close($dh);114 115 my @out;116 for my $d (@dirs) {117 # Skip dotfiles unless explicitly requested118 if($d =~ m{^[.]} && $base !~ m{^[.]}) {119 next;120 }121 122 my ($text, $value, $done) = ($d, "${pfx}${d}", 1);123 124 if (-d "$dir/$d") {125 $text .= "/";126 $value .= "/";127 $done = 0;128 }129 push @out, [$text, $value, $done];130 }131 return @out;132 } -
perl/modules/IRC/lib/BarnOwl/Module/IRC.pm
r416241f r618a980 137 137 } 138 138 139 =head2 mk_irc_command SUB FLAGS 140 141 Return a subroutine that can be bound as a an IRC command. The 142 subroutine will be called with arguments (COMMAND-NAME, 143 IRC-CONNECTION, [CHANNEL], ARGV...). 144 145 C<IRC-CONNECTION> and C<CHANNEL> will be inferred from arguments to 146 the command and the current message if appropriate. 147 148 The bitwise C<or> of zero or more C<FLAGS> can be passed in as a 149 second argument to alter the behavior of the returned commands: 150 151 =over 4 152 153 =item C<CHANNEL_ARG> 154 155 This command accepts the name of a channel. Pass in the C<CHANNEL> 156 argument listed above, and die if no channel argument can be found. 157 158 =item C<CHANNEL_OPTIONAL> 159 160 Pass the channel argument, but don't die if not present. Only relevant 161 with C<CHANNEL_ARG>. 162 163 =item C<ALLOW_DISCONNECTED> 164 165 C<IRC-CONNECTION> may be a disconnected connection object that is 166 currently pending a reconnect. 167 168 =back 169 170 =cut 171 172 use constant CHANNEL_ARG => 1; 173 use constant CHANNEL_OPTIONAL => 2; 174 175 use constant ALLOW_DISCONNECTED => 4; 139 use constant OPTIONAL_CHANNEL => 1; 140 use constant REQUIRE_CHANNEL => 2; 176 141 177 142 sub register_commands { … … 202 167 203 168 BarnOwl::new_command( 204 'irc-disconnect' => mk_irc_command( \&cmd_disconnect, ALLOW_DISCONNECTED ),169 'irc-disconnect' => \&cmd_disconnect, 205 170 { 206 171 summary => 'Disconnect from an IRC server', … … 227 192 228 193 BarnOwl::new_command( 229 'irc-mode' => mk_irc_command( \&cmd_mode, CHANNEL_OPTIONAL|CHANNEL_ARG),194 'irc-mode' => mk_irc_command( \&cmd_mode, OPTIONAL_CHANNEL ), 230 195 { 231 196 summary => 'Change an IRC channel or user mode', … … 251 216 252 217 BarnOwl::new_command( 253 'irc-part' => mk_irc_command( \&cmd_part, CHANNEL_ARG),218 'irc-part' => mk_irc_command( \&cmd_part, REQUIRE_CHANNEL ), 254 219 { 255 220 summary => 'Leave an IRC channel', … … 276 241 277 242 BarnOwl::new_command( 278 'irc-names' => mk_irc_command( \&cmd_names, CHANNEL_ARG),243 'irc-names' => mk_irc_command( \&cmd_names, REQUIRE_CHANNEL ), 279 244 { 280 245 summary => 'View the list of users in a channel', … … 329 294 330 295 BarnOwl::new_command( 331 'irc-topic' => mk_irc_command( \&cmd_topic, CHANNEL_ARG),296 'irc-topic' => mk_irc_command( \&cmd_topic, REQUIRE_CHANNEL ), 332 297 { 333 298 summary => 'View or change the topic of an IRC channel', … … 426 391 427 392 sub cmd_disconnect { 428 my $cmd = shift; 429 my $conn = shift; 430 if ($conn->conn->connected) { 431 $conn->conn->disconnect; 432 } elsif ($reconnect{$conn->alias}) { 433 BarnOwl::admin_message('IRC', 434 "[" . $conn->alias . "] Reconnect cancelled"); 435 $conn->cancel_reconnect; 436 } 393 # Such a hack 394 local *get_connection_by_alias = sub { 395 my $key = shift; 396 return $ircnets{$key} if exists $ircnets{$key}; 397 return $reconnect{$key}{conn} if exists $reconnect{$key}; 398 die("No such ircnet: $key\n"); 399 }; 400 401 mk_irc_command( 402 sub { 403 my $cmd = shift; 404 my $conn = shift; 405 if ($conn->conn->connected) { 406 $conn->conn->disconnect; 407 } elsif ($reconnect{$conn->alias}) { 408 BarnOwl::admin_message('IRC', 409 "[" . $conn->alias . "] Reconnect cancelled"); 410 delete $reconnect{$conn->alias}; 411 } 412 } 413 )->(@_); 437 414 } 438 415 … … 587 564 sub mk_irc_command { 588 565 my $sub = shift; 589 my $ flags= shift || 0;566 my $use_channel = shift || 0; 590 567 return sub { 591 568 my $cmd = shift; … … 601 578 602 579 if(defined($alias)) { 603 $conn = get_connection_by_alias($alias, 604 $flags & ALLOW_DISCONNECTED); 605 } 606 if($flags & CHANNEL_ARG) { 580 $conn = get_connection_by_alias($alias); 581 } 582 if($use_channel) { 607 583 $channel = $ARGV[0]; 608 584 if(defined($channel) && $channel =~ /^#/) { … … 618 594 } 619 595 620 if(!$channel && 621 ($flags & CHANNEL_ARG) && 622 !($flags & CHANNEL_OPTIONAL)) { 596 if(!$channel && $use_channel == REQUIRE_CHANNEL) { 623 597 die("Usage: $cmd <channel>\n"); 624 598 } 625 599 if(!$conn) { 626 600 if($m && $m->type eq 'IRC') { 627 $conn = get_connection_by_alias($m->network, 628 $flags & ALLOW_DISCONNECTED); 601 $conn = get_connection_by_alias($m->network); 629 602 } 630 603 } … … 635 608 die("You must specify an IRC network using -a.\n"); 636 609 } 637 if($ flags & CHANNEL_ARG) {610 if($use_channel) { 638 611 $sub->($cmd, $conn, $channel, @ARGV); 639 612 } else { … … 645 618 sub get_connection_by_alias { 646 619 my $key = shift; 647 my $allow_disconnected = shift; 648 649 return $ircnets{$key} if exists $ircnets{$key}; 650 return $reconnect{$key} if $allow_disconnected && exists $reconnect{$key}; 651 die("No such ircnet: $key\n") 620 die("No such ircnet: $key\n") unless exists $ircnets{$key}; 621 return $ircnets{$key}; 652 622 } 653 623 -
perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm
r416241f r618a980 23 23 24 24 use BarnOwl; 25 use Scalar::Util qw(weaken);26 25 27 26 BEGIN { … … 316 315 my $interval = shift || 5; 317 316 delete $BarnOwl::Module::IRC::ircnets{$self->alias}; 318 $BarnOwl::Module::IRC::reconnect{$self->alias} = $self; 319 my $weak = $self; 320 weaken($weak); 321 $self->{reconnect_timer} = 317 $BarnOwl::Module::IRC::reconnect{$self->alias} = 322 318 BarnOwl::Timer->new( { 323 319 after => $interval, 324 320 cb => sub { 325 $ weak->reconnect( $interval ) if $weak;321 $self->reconnect( $interval ); 326 322 }, 327 323 } ); 328 } 329 330 sub cancel_reconnect { 331 my $self = shift; 332 delete $BarnOwl::Module::IRC::reconnect{$self->alias}; 333 delete $self->{reconnect_timer}; 324 $BarnOwl::Module::IRC::reconnect{$self->alias}{conn} = $self; 334 325 } 335 326 … … 338 329 my $msg = shift; 339 330 BarnOwl::admin_message("IRC", $msg); 340 $self->cancel_reconnect;331 delete $BarnOwl::Module::IRC::reconnect{$self->alias}; 341 332 $BarnOwl::Module::IRC::ircnets{$self->alias} = $self; 342 333 my $fd = $self->getSocket()->fileno(); -
scripts/do-release
rd771d1b r01846ce 31 31 if [ ! "$force" ] && [ "$VERS" != "$(head -1 ChangeLog)" ]; then 32 32 die "No ChangeLog entry for version $VERS, aborting." 33 fi34 35 head=$(git symbolic-ref HEAD)36 head=${head#refs/heads/}37 38 git rev-parse --verify -q $head >/dev/null 2>&139 git rev-parse --verify -q origin/$head >/dev/null 2>&140 if [ -n "$(git rev-list $head..origin/$head)" ]; then41 die "$head is not up to date. Aborting."42 33 fi 43 34 -
t/completion.t
re6cec01 r1167bf1 289 289 \&complete_filter_expr); 290 290 291 # Test complete_files292 use BarnOwl::Completion::Util qw(complete_file);293 use File::Temp;294 use File::Path qw(mkpath);295 296 my $tmpdir = File::Temp::tempdir(CLEANUP => 1);297 298 # Make sure $tmpdir does not have a trailing /299 $tmpdir =~ s{/$}{};300 $ENV{HOME} = $tmpdir;301 302 sub touch {303 my $path = shift;304 system("touch", "$path");305 }306 307 mkpath("$tmpdir/.owl/",308 "$tmpdir/.owl/modules/",309 "$tmpdir/Public/",310 "$tmpdir/Private/",311 "$tmpdir/.ours",312 "$tmpdir/www");313 touch("$tmpdir/.zephyr.subs");314 touch("$tmpdir/wheee");315 touch("$tmpdir/.owl/startup");316 317 sub completion_value {318 my $c = shift;319 return $c unless ref($c) eq 'ARRAY';320 return $c->[1];321 }322 323 sub test_file {324 my $spec = shift;325 my $pfx = shift;326 my $dirs = shift;327 my $files = shift;328 329 my $expect = [ sort {$a->[1] cmp $b->[1]}330 ((map {["$_/", defined($pfx)?"$pfx/$_/":"$_/", 0]} @$dirs),331 (map {["$_", defined($pfx)?"$pfx/$_" :$_ , 1]} @$files))332 ];333 334 local $Test::Builder::Level = $Test::Builder::Level + 1;335 336 my @got = complete_file($spec);337 338 @got = grep {completion_value($_) =~ m{^\Q$spec\E}} @got;339 @got = sort {completion_value($a) cmp completion_value($b)} @got;340 341 use Data::Dumper;342 is_deeply(\@got, $expect);343 }344 345 is_deeply([complete_file("~")], [["~/", "~/", 0]]);346 347 chdir($tmpdir);348 test_file("$tmpdir/", $tmpdir,349 [qw(Public Private www)],350 [qw(wheee)]);351 352 test_file("./", ".",353 [qw(Public Private www)],354 [qw(wheee)]);355 356 test_file("", undef, [qw(Public Private www)], [qw(wheee)]);357 358 test_file("./.owl/", "./.owl",359 [qw(modules)],360 [qw(startup)]);361 362 test_file("~/", "~",363 [qw(Public Private www)],364 [qw(wheee)]);365 366 test_file("P", undef, [qw(Public Private)], []);367 368 test_file("$tmpdir/.", $tmpdir,369 [qw(. .. .owl .ours)],370 [qw(.zephyr.subs)]);371 291 1; 372 292
Note: See TracChangeset
for help on using the changeset viewer.