# Tab completion module

# The length of the last completion, e.g. dest<tab>roy will have $LastLen=3
# so another TAB after that means that we should go that long back
# to look for a word
$LastCompletionLen = 0;
$PrevIndex = 0;  # Which completion did we pick the last time?
$CompletionRecursing = 0;
%Completions = ( "complete" => 1);

sub tab_complete {
    my ($word,$complete,$n);
    if ($Key eq $keyTab) {
        # Try tab completion
        ($word) = /(\w*).{$LastCompletionLen}$/;
        foreach $complete (keys %Completions) {
            if ($complete =~ /^$word/i and $n++ == $PrevIndex) {
                # Automatically stick in a space here ?
                s/\w*.{$LastCompletionLen}$/$complete /;
                $LastCompletionLen = (1+length($complete)) - length($word);
                $Key = 0;
                $PrevIndex = $n;
                return;
            }
        }

        # End of list but we have completed something before? Try recursing
        # But don't recurse if we only have one possible item
        if ($LastCompletionLen and !$CompletionRecursing and $PrevIndex > 1) {
            $CompletionRecursing = 1;
            $PrevIndex = 0;
            tab_complete();
            $CompletionRecursing = 0;
        } else {
            mcl_bell();
            $Key = 0;
        }
    } elsif ($Key eq $keyBackspace and $LastCompletionLen) { # Backspace deletes completed word
        s/\w*.{$LastCompletionLen}\s*$//;
        $LastCompletionLen = 0;
        $PrevIndex = 0;
        $Key = 0;
    }
    else {
        $LastCompletionLen = 0;
        $PrevIndex = 0;
    }
}

sub cmd_complete {
    my ($count);

    s/\n//g;
    if (/^(\d+)$/) {
        $cout = 0;
        foreach (keys %Completions) {
            if (++$count == $1) {
                print "Deleted completion #$1: $_\n";
                delete $Completions{$_};
                return;
            }
        }
        print "There are only $count completions. Type completions to see.\n";
    }
    elsif (length > 2) {
        # Add completion
        if (exists $Completions{$_}) {
            print "Completion $_ already exists.\n" unless $Loading;
        } else {
            $Completions{$_}++;
            print "Added completion for '$_'\n" unless $Loading;
        }
    } elsif (length == 0) {
        print "Completions:\n";
        $count = 1;
        foreach (keys %Completions) {
            printf "%3d) $_\n", $count++;
        }
    } else {
        print "A completion must be at least 2 characters long. Type completions to list existing ones.\n";
    }
}

sub load_completions {
    foreach(split (',', $_)) {
        &cmd_complete;
    }
}

sub save_completions {
    local (*FH) = $_[0];
    if (scalar(keys %Completions)) {
        print FH "Completions ", join(',', keys %Completions), "\n";
    }
}

save_add(\&save_completions);
load_add("completions", \&load_completions);
keypress_add(\&tab_complete);
1;
