… | |
… | |
846 | my $text = $self->{entry}->get_text; |
846 | my $text = $self->{entry}->get_text; |
847 | |
847 | |
848 | length $text |
848 | length $text |
849 | or return $self->hide; |
849 | or return $self->hide; |
850 | |
850 | |
851 | my ($cmd, $arg) = $text =~ /^\s*([^[:space:]]*)(.*)$/; |
|
|
852 | |
|
|
853 | if ($text ne $self->{last_search}) { |
851 | if ($text ne $self->{last_search}) { |
854 | my @match; |
852 | my @match; |
855 | |
853 | |
856 | if ($text =~ /^(.*?)\s+$/) { |
854 | if ($text =~ /^(.*?)\s+$/) { |
|
|
855 | my ($cmd, $arg) = $text =~ /^\s*([^[:space:]]*)(.*)$/; |
857 | @match = [$cmd, "(appended whitespace suppresses completion)"]; |
856 | @match = ([[$cmd,'(appended whitespace suppresses completion)'],$text]); |
858 | } else { |
857 | } else { |
|
|
858 | # @match is [command, penalty, command with arguments] until sort |
|
|
859 | |
|
|
860 | my ($cmd, $arg) = $text =~ /^\s*([^[:space:]]*)(.*)$/; |
|
|
861 | |
859 | my $regexp = do { |
862 | my $regexp_abbrev = do { |
860 | my ($beg, @chr) = split //, lc $cmd; |
863 | my ($beg, @chr) = split //, lc $cmd; |
861 | |
864 | |
862 | # the following regex is used to match our "completion entry" |
865 | # the following regex is used to match our "completion entry" |
863 | # to an actual command - the parentheses match kind of "overhead" |
866 | # to an actual command - the parentheses match kind of "overhead" |
864 | # - the more characters the parentheses match, the less attractive |
867 | # - the more characters the parentheses match, the less attractive |
… | |
… | |
866 | my $regexp = "^\Q$beg\E" |
869 | my $regexp = "^\Q$beg\E" |
867 | . join "", map "(?:.*?[ \\\\]\Q$_\E|(.*?)\Q$_\E)", @chr; |
870 | . join "", map "(?:.*?[ \\\\]\Q$_\E|(.*?)\Q$_\E)", @chr; |
868 | qr<$regexp> |
871 | qr<$regexp> |
869 | }; |
872 | }; |
870 | |
873 | |
871 | my @penalty; |
874 | my $regexp_partial = do { |
|
|
875 | my $regexp = "^\Q$text\E(.*)"; |
|
|
876 | qr<$regexp> |
|
|
877 | }; |
872 | |
878 | |
873 | for (keys %{$self->{command}}) { |
879 | for (keys %{$self->{command}}) { |
874 | if (@penalty = $_ =~ $regexp) { |
880 | my @scores; |
875 | push @match, [$_, length join "", map "::$_", grep defined, @penalty]; |
881 | |
|
|
882 | # 1. Complete command [with args] |
|
|
883 | # command is a prefix of the text |
|
|
884 | # score is length of complete command matched |
|
|
885 | # e.g. "invoke summon pet monster bat" |
|
|
886 | # "invoke" "summon pet monster bat" = 6 |
|
|
887 | # "invoke summon pet monster" "bat" = 25 |
|
|
888 | if ($text =~ /^\Q$_\E(.*)/) { |
|
|
889 | push @scores, [$_, length $_, $text]; |
876 | } |
890 | } |
|
|
891 | |
|
|
892 | # 2. Partial command |
|
|
893 | # text is a prefix of the full command |
|
|
894 | # score is the length of the input text |
|
|
895 | # e.g. "invoke s" |
|
|
896 | # "invoke small fireball" = 8 |
|
|
897 | # "invoke summon pet monster" = 8 |
|
|
898 | |
|
|
899 | if ($_ =~ $regexp_partial) { |
|
|
900 | push @scores, [$_, length $text, $_]; |
|
|
901 | } |
|
|
902 | |
|
|
903 | # 3. Abbreviation match |
|
|
904 | # attempts to use first word of text as an abbreviated command |
|
|
905 | # score is length of word + 1 - 3 per non-word-initial character |
|
|
906 | |
|
|
907 | if (my @penalty = $_ =~ $regexp_abbrev) { |
|
|
908 | push @scores, [$_, (length $cmd) + 1 - (length join "", map "::$_", grep defined, @penalty), "$_$arg"]; |
|
|
909 | } |
|
|
910 | |
|
|
911 | # Pick the best option for this command |
|
|
912 | push @match, (sort { |
|
|
913 | $b->[1] <=> $a->[1] |
|
|
914 | } @scores)[0]; |
877 | } |
915 | } |
878 | |
916 | |
|
|
917 | # @match is now [command object, command with arguments] |
879 | @match = map $self->{command}{$_->[0]}, |
918 | @match = map [$self->{command}{$_->[0]}, $_->[2]], |
880 | sort { |
919 | sort { |
881 | $a->[1] <=> $b->[1] |
920 | $b->[1] <=> $a->[1] |
882 | or $self->{command}{$a->[0]}[4] <=> $self->{command}{$b->[0]}[4] |
921 | or $self->{command}{$a->[0]}[4] <=> $self->{command}{$b->[0]}[4] |
883 | or (length $b->[0]) <=> (length $a->[0]) |
922 | or (length $b->[0]) <=> (length $a->[0]) |
884 | } @match; |
923 | } @match; |
885 | } |
924 | } |
886 | |
925 | |
… | |
… | |
905 | $label->{fg} = [1, 1, 1, 1]; |
944 | $label->{fg} = [1, 1, 1, 1]; |
906 | $label->{bg} = [0, 0, 0, 0]; |
945 | $label->{bg} = [0, 0, 0, 0]; |
907 | } |
946 | } |
908 | |
947 | |
909 | if (@matches) { |
948 | if (@matches) { |
910 | $self->{select} = "$matches[0][0]$arg"; |
949 | $self->{select} = "$matches[0][1]"; |
911 | |
950 | |
912 | $labels[0]->{fg} = [0, 0, 0, 1]; |
951 | $labels[0]->{fg} = [0, 0, 0, 1]; |
913 | $labels[0]->{bg} = [1, 1, 1, 0.8]; |
952 | $labels[0]->{bg} = [1, 1, 1, 0.8]; |
914 | } else { |
953 | } else { |
915 | $self->{select} = "$cmd$arg"; |
954 | $self->{select} = "$text"; |
916 | } |
955 | } |
917 | |
956 | |
918 | for my $match (@matches) { |
957 | for my $match (@matches) { |
919 | my $label = shift @labels; |
958 | my $label = shift @labels; |
920 | |
959 | |
921 | if (@labels) { |
960 | if (@labels) { |
922 | $label->set_text ("$match->[0]$arg"); |
961 | $label->set_text ("$match->[1]"); |
923 | $label->set_tooltip ($match->[1]); |
962 | $label->set_tooltip ("$match->[0][1]"); |
924 | } else { |
963 | } else { |
925 | $label->set_text ("..."); |
964 | $label->set_text ("..."); |
926 | $label->set_tooltip ("Use Cursor-Down to view more matches"); |
965 | $label->set_tooltip ("Use Cursor-Down to view more matches"); |
927 | last; |
966 | last; |
928 | } |
967 | } |