NAME
Complete::Util - General completion routine
VERSION
This document describes version 0.619 of Complete::Util (from Perl distribution Complete-Util), released on 2023-12-26.
DESCRIPTION
This package provides some generic completion routines that follow the Complete convention. (If you are looking for bash/shell tab completion routines, take a look at the See Also section.) The main routine is complete_array_elem
which tries to complete a word using choices from elements of supplied array. For example:
complete_array_elem(word => "a", array => ["apple", "apricot", "banana"]);
The routine will first try a simple substring prefix matching. If that fails, will try some other methods like word-mode, character-mode, or fuzzy matching. These methods can be disabled using settings.
There are other utility routines e.g. for converting completion answer structure from hash to array/array to hash, combine or modify answer, etc. These routines are usually used by the other more specific or higher-level completion modules.
FUNCTIONS
answer_has_entries
Usage:
answer_has_entries($answer) -> int
Check if answer has entries.
It is equivalent to:
ref $answer eq 'ARRAY' ? (@$answer ? 1:0) : (@{$answer->{words}} ? 1:0);
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answer* => array|hash
Completion answer structure.
Return value: (int)
answer_num_entries
Usage:
answer_num_entries($answer) -> int
Get the number of entries in an answer.
It is equivalent to:
ref $answer eq 'ARRAY' ? (@$answer // 0) : (@{$answer->{words}} // 0);
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answer* => array|hash
Completion answer structure.
Return value: (int)
arrayify_answer
Usage:
arrayify_answer($answer) -> array
Make sure we return completion answer in array form.
This is the reverse of hashify_answer
. It accepts a hash or an array. If it receives a hash, will return its words
key.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answer* => array|hash
Completion answer structure.
Return value: (array)
combine_answers
Usage:
combine_answers($answers, ...) -> hash
Given two or more answers, combine them into one.
This function is useful if you want to provide a completion answer that is gathered from multiple sources. For example, say you are providing completion for the Perl tool cpanm, which accepts a filename (a tarball like *.tar.gz
), a directory, or a module name. You can do something like this:
combine_answers(
complete_file(word=>$word),
complete_module(word=>$word),
);
But if a completion answer has a metadata final
set to true, then that answer is used as the final answer without any combining with the other answers.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answers* => array[hash|array]
(No description)
Return value: (hash)
Return a combined completion answer. Words from each input answer will be combined, order preserved and duplicates removed. The other keys from each answer will be merged.
complete_array_elem
Usage:
complete_array_elem(%args) -> array
Complete from array.
Try to find completion from an array of strings. Will attempt several methods, from the cheapest and most discriminating to the most expensive and least discriminating.
First method is normal/exact string prefix matching (either case-sensitive or insensitive depending on the $Complete::Common::OPT_CI
variable or the COMPLETE_OPT_CI
environment variable). If at least one match is found, return result. Else, proceed to the next method.
Word-mode matching (can be disabled by setting $Complete::Common::OPT_WORD_MODE
or COMPLETE_OPT_WORD_MODE
environment varialbe to false). Word-mode matching is described in Complete::Common. If at least one match is found, return result. Else, proceed to the next method.
Prefix char-mode matching (can be disabled by settings $Complete::Common::OPT_CHAR_MODE
or COMPLETE_OPT_CHAR_MODE
environment variable to false). Prefix char-mode matching is just like char-mode matching (see next paragraph) except the first character must match. If at least one match is found, return result. Else, proceed to the next method.
Char-mode matching (can be disabled by settings $Complete::Common::OPT_CHAR_MODE
or COMPLETE_OPT_CHAR_MODE
environment variable to false). Char-mode matching is described in Complete::Common. If at least one match is found, return result. Else, proceed to the next method.
Fuzzy matching (can be disabled by setting $Complete::Common::OPT_FUZZY
or COMPLETE_OPT_FUZZY
to false). Fuzzy matching is described in Complete::Common. If at least one match is found, return result. Else, return empty string.
Will sort the resulting completion list, so you don't have to presort the array.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
array* => array[str]
(No description)
exclude => array
(No description)
replace_map => hash
You can supply correction entries in this option. An example is when array if
['mount','unmount']
andumount
is a popular "typo" forunmount
. When someone already typesum
it cannot be completed into anything (even the current fuzzy mode will return both so it cannot complete immediately).One solution is to add replace_map
{'unmount'=>['umount']}
. This way,umount
will be regarded the same asunmount
and when user typesum
it can be completed unambiguously intounmount
.summaries => array[str]
(No description)
word* => str (default: "")
Word to complete.
Return value: (array)
complete_comma_sep
Usage:
complete_comma_sep(%args) -> array
Complete a comma-separated list string.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
elems* => array[str]
(No description)
exclude => array
(No description)
remaining => code
What elements should remain for completion.
This is a more general mechanism if the
uniq
option does not suffice. Suppose you are offering completion for sorting fields. The elements are field names as well as field names prefixed with dash (-
) to mean sorting with a reverse order. So for exampleelems
is["name","-name","age","-age"]
. When current word isname
, it doesn't make sense to offername
nor-name
again as the next sorting field. So we can setremaining
to this code:sub { my ($seen_elems, $elems) = @_; my %seen; for (@$seen_elems) { (my $nodash = $_) =~ s/^-//; $seen{$nodash}++; } my @remaining; for (@$elems) { (my $nodash = $_) =~ s/^-//; push @remaining, $_ unless $seen{$nodash}; } \@remaining; }
As you can see above, the code is given
$seen_elems
and$elems
as arguments and is expected to return remaining elements to offer.replace_map => hash
You can supply correction entries in this option. An example is when array if
['mount','unmount']
andumount
is a popular "typo" forunmount
. When someone already typesum
it cannot be completed into anything (even the current fuzzy mode will return both so it cannot complete immediately).One solution is to add replace_map
{'unmount'=>['umount']}
. This way,umount
will be regarded the same asunmount
and when user typesum
it can be completed unambiguously intounmount
.sep => str (default: ",")
(No description)
summaries => array[str]
(No description)
uniq => bool
Whether list should contain unique elements.
When this option is set to true, if the formed list in the current word already contains an element, the element will not be offered again as completion answer. For example, if
elems
is[1,2,3,4]
andword
is2,3,
then withoutuniq
set to true the completion answer is:2,3,1 2,3,2 2,3,3 2,3,4
but with
uniq
set to true, the completion answer becomes:2,3,1 2,3,4
See also the
remaining
option for a more general mechanism of offering fewer elements.word* => str (default: "")
Word to complete.
Return value: (array)
complete_comma_sep_pair
Usage:
complete_comma_sep_pair(%args) -> array
Complete a comma-separated list of key-value pairs.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
complete_value => code
Code to supply possible values for a key.
Code should accept hash arguments and will be given the arguments
word
(word that is part of the value), andkey
(the key being evaluated) and is expected to return a completion answer.keys* => array[str]
(No description)
keys_summaries => array[str]
Summary for each key.
remaining_keys => code
What keys should remain for completion.
This is a more general mechanism if the
uniq
option does not suffice. Suppose you are offering completion for arguments. Possible arguments arefoo
,bar
,baz
but thebar
andbaz
arguments are mutually exclusive. We can setremaining_keys
to this code:my %possible_args = {foo=>1, bar=>1, baz=>1}; sub { my ($seen_elems, $elems) = @_; my %remaining = %possible_args; for (@$seen_elems) { delete $remaining{$_}; delete $remaining{baz} if $_ eq 'bar'; delete $remaining{bar} if $_ eq 'baz'; } [keys %remaining]; }
As you can see above, the code is given
$seen_elems
and$elems
as arguments and is expected to return remaining elements to offer.uniq => bool (default: 1)
(No description)
word* => str (default: "")
Word to complete.
Return value: (array)
complete_hash_key
Usage:
complete_hash_key(%args) -> array
Complete from hash keys.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
hash* => hash
(No description)
summaries => hash
(No description)
summaries_from_hash_values => true
(No description)
word* => str (default: "")
Word to complete.
Return value: (array)
complete_hash_value
Usage:
complete_hash_value(%args) -> array
Complete from hash values.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
hash* => hash
(No description)
summaries => hash
(No description)
summaries_from_hash_keys => true
(No description)
word* => str (default: "")
Word to complete.
Return value: (array)
get_answer_summaries
Usage:
get_answer_summaries($answer) -> array
Extract just the entry summaries from answer structure.
This routine accepts a hash or an array answer structure. It then returns an arrayref containing just the summaries from each answer entry. If the answer is undef, it returns an empty arrayref.
See also: get_answer_words()
.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answer* => array|hash
Completion answer structure.
Return value: (array)
get_answer_words
Usage:
get_answer_words($answer) -> array
Extract just the words from answer structure.
This routine accepts a hash or an array answer structure. It then returns an arrayref containing just the words from each answer entry. If the answer is undef, it returns an empty arrayref.
See also: get_answer_summaries()
.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answer* => array|hash
Completion answer structure.
Return value: (array)
hashify_answer
Usage:
hashify_answer($answer, $meta) -> hash
Make sure we return completion answer in hash form.
This function accepts a hash or an array. If it receives an array, will convert the array into `{words=>$ary}' first to make sure the completion answer is in hash form.
Then will add keys from meta
to the hash.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
$answer* => array|hash
Completion answer structure.
$meta => hash
Metadata (extra keys) for the hash.
Return value: (hash)
modify_answer
Usage:
modify_answer(%args) -> undef
Modify answer (add prefix/suffix, etc).
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
answer* => hash|array
(No description)
prefix => str
(No description)
suffix => str
(No description)
Return value: (undef)
FAQ
Why is fuzzy matching slow?
Example:
use Benchmark qw(timethis);
use Complete::Util qw(complete_array_elem);
# turn off the other non-exact matching methods
$Complete::Common::OPT_CI = 0;
$Complete::Common::OPT_WORD_MODE = 0;
$Complete::Common::OPT_CHAR_MODE = 0;
my @ary = ("aaa".."zzy"); # 17575 elems
timethis(20, sub { complete_array_elem(array=>\@ary, word=>"zzz") });
results in:
timethis 20: 7 wallclock secs ( 6.82 usr + 0.00 sys = 6.82 CPU) @ 2.93/s (n=20)
Answer: fuzzy matching is slower than exact matching due to having to calculate Levenshtein distance. But if you find fuzzy matching too slow using the default pure-perl implementation, you might want to install Text::Levenshtein::Flexible (an optional prereq) to speed up fuzzy matching. After Text::Levenshtein::Flexible is installed:
timethis 20: 1 wallclock secs ( 1.04 usr + 0.00 sys = 1.04 CPU) @ 19.23/s (n=20)
ENVIRONMENT
COMPLETE_UTIL_TRACE
Bool. If set to true, will generate more log statements for debugging (at the trace level).
COMPLETE_UTIL_LEVENSHTEIN => str ('pp'|'xs'|'flexible')
Can be used to force which Levenshtein distance implementation to use. pp
means the included PP implementation, which is the slowest (1-2 orders of magnitude slower than XS implementations), xs
which means Text::Levenshtein::XS, or flexible
which means Text::Levenshtein::Flexible (performs best).
If this is not set, the default is to use Text::Levenshtein::Flexible when it's available, then fallback to the included PP implementation.
HOMEPAGE
Please visit the project's homepage at https://metacpan.org/release/Complete-Util.
SOURCE
Source repository is at https://github.com/perlancar/perl-Complete-Util.
SEE ALSO
If you want to do bash tab completion with Perl, take a look at Complete::Bash or Getopt::Long::Complete or Perinci::CmdLine.
Other Complete::*
modules.
Bencher::Scenarios::CompleteUtil
AUTHOR
perlancar <perlancar@cpan.org>
CONTRIBUTORS
A. Sinan Unur <nanis@cpan.org>
Steven Haryanto <stevenharyanto@gmail.com>
CONTRIBUTING
To contribute, you can send patches by email/via RT, or send pull requests on GitHub.
Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via:
% prove -l
If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond that are considered a bug and can be reported to me.
COPYRIGHT AND LICENSE
This software is copyright (c) 2023, 2022, 2020, 2019, 2017, 2016, 2015, 2014, 2013 by perlancar <perlancar@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
BUGS
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Complete-Util
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.