NAME
Complete::Bash - Completion routines for bash shell
VERSION
This document describes version 0.337 of Complete::Bash (from Perl
distribution Complete-Bash), released on 2022-09-08.
DESCRIPTION
This module provides routines related to tab completion in bash shell.
About programmable completion in bash
Bash allows completion to come from various sources. The simplest is
from a list of words ("-W"):
% complete -W "one two three four" somecmd
% somecmd t<Tab>
two three
Another source is from a bash function ("-F"). The function will receive
input in two variables: "COMP_WORDS" (array, command-line chopped into
words) and "COMP_CWORD" (integer, index to the array of words indicating
the cursor position). It must set an array variable "COMPREPLY" that
contains the list of possible completion:
% _foo()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($( compgen -W '--help --verbose --version' -- $cur ) )
}
% complete -F _foo foo
% foo <Tab>
--help --verbose --version
And yet another source is an external command ("-C") including, from a
Perl script. The command receives two environment variables: "COMP_LINE"
(string, raw command-line) and "COMP_POINT" (integer, cursor location).
Program must split "COMP_LINE" into words, find the word to be
completed, complete that, and return the list of words one per-line to
STDOUT. An example:
% cat foo-complete
#!/usr/bin/perl
use Complete::Bash qw(parse_cmdline format_completion);
use Complete::Util qw(complete_array_elem);
my ($words, $cword) = @{ parse_cmdline() };
my $res = complete_array_elem(array=>[qw/--help --verbose --version/], word=>$words->[$cword]);
print format_completion($res);
% complete -C foo-complete foo
% foo --v<Tab>
--verbose --version
About the routines in this module
First of all, "parse_cmdline()" is the function to parse raw
command-line (such as what you get from bash in "COMP_LINE" environment
variable) into words. This makes it easy for the other functions to
generate completion answer. See the documentation for that function for
more details.
"format_completion()" is what you use to format completion answer
structure for bash.
FUNCTIONS
format_completion
Usage:
format_completion($completion, $opts) -> str|array
Format completion for output (for shell).
Bash accepts completion reply in the form of one entry per line to
STDOUT. Some characters will need to be escaped. This function helps you
do the formatting, with some options.
This function accepts completion answer structure as described in the
"Complete" POD. Aside from "words", this function also recognizes these
keys:
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
* $completion* => *hash|array*
Completion answer structure.
Either an array or hash. See function description for more details.
* $opts => *hash*
Specify options.
Known options:
* as
Either "string" (the default) or "array" (to return array of
lines instead of the lines joined together). Returning array is
useful if you are doing completion inside "Term::ReadLine", for
example, where the library expects an array.
* esc_mode
Escaping mode for entries. Either "default" (most
nonalphanumeric characters will be escaped), "shellvar" (like
"default", but dollar sign "$" will also be escaped, convenient
when completing environment variables for example), "filename"
(currently equals to "default"), "option" (currently equals to
"default"), or "none" (no escaping will be done).
* word
A workaround. String. For now, see source code for more details.
* show_summaries
Whether to show item's summaries. Boolean, default is from
COMPLETE_BASH_SHOW_SUMMARIES environment variable or 1.
An answer item contain summary, which is a short description
about the item, e.g.:
[{word=>"-a" , summary=>"Show hidden files"},
{word=>"-l" , summary=>"Show details"},
{word=>"--sort", summary=>"Specify sort order"}],
When summaries are not shown, user will just be seeing something
like:
-a
-l
--sort
But when summaries are shown, user will see:
-a -- Show hidden files
-l -- Show details
--sort -- Specify sort order
which is quite helpful.
* workaround_with_wordbreaks
Boolean. Default is true. See source code for more details.
Return value: Formatted string (or array, if `as` is set to `array`)
(str|array)
join_wordbreak_words
Usage:
join_wordbreak_words() -> [$status_code, $reason, $payload, \%result_meta]
Post-process parse_cmdline() result by joining some words.
"parse_cmdline()", like bash, splits some characters that are considered
as word-breaking characters:
"'@><=;|&(:
So if command-line is:
command --module=Data::Dump bob@example.org
then they will be parsed as:
["command", "--module", "=", "Data", "::", "Dump", "bob", '@', "example.org"]
Normally in Perl applications, we want ":", "@" to be part of word. So
this routine will convert the above into:
["command", "--module=Data::Dump", 'bob@example.org']
This function is not exported by default, but exportable.
No arguments.
Returns an enveloped result (an array).
First element ($status_code) is an integer containing HTTP-like status
code (200 means OK, 4xx caller error, 5xx function error). Second
element ($reason) is a string containing error message, or something
like "OK" if status is 200. Third element ($payload) is the actual
result, but usually not present when enveloped result is an error
response ($status_code is not 2xx). Fourth element (%result_meta) is
called result metadata and is optional, a hash that contains extra
information, much like how HTTP response headers provide additional
metadata.
Return value: (any)
parse_cmdline
Usage:
parse_cmdline($cmdline, $point, $opts) -> array
Parse shell command-line for processing by completion routines.
This function basically converts "COMP_LINE" (str) and "COMP_POINT"
(int) into something like (but not exactly the same as) "COMP_WORDS"
(array) and "COMP_CWORD" (int) that bash supplies to shell functions.
The differences with bash are (these differences are mostly for parsing
convenience for programs that use this routine; this comparison is made
against bash versions 4.2-4.3):
1) quotes and backslashes are stripped (bash's "COMP_WORDS" contains all
the quotes and backslashes);
2) quoted phrase that contains spaces, or phrase that contains escaped
spaces is parsed as a single word. For example:
command "First argument" Second\ argument
bash would split it as (represented as Perl):
["command", "\"First", "argument\"", "Second\\", "argument"]
which is not very convenient. We parse it into:
["command", "First argument", "Second argument"]
3) variables are substituted with their values from environment
variables except for the current word ("COMP_WORDS[COMP_CWORD]") (bash
does not perform variable substitution for "COMP_WORDS"). However, note
that special shell variables that are not environment variables like $0,
$_, $IFS will not be replaced correctly because bash does not export
those variables for us.
4) tildes ("~") are expanded with user's home directory except for the
current word (bash does not perform tilde expansion for "COMP_WORDS");
Caveats:
* Like bash, we group non-whitespace word-breaking characters into its
own word. By default "COMP_WORDBREAKS" is:
"'@><=;|&(:
So if raw command-line is:
command --foo=bar http://example.com:80 mail@example.org Foo::Bar
then the parse result will be:
["command", "--foo", "=", "bar", "http", ":", "//example.com", ":",
"80", "Foo", "::", "Bar"]
which is annoying sometimes. But we follow bash here so we can more
easily accept input from a joined "COMP_WORDS" if we write
completion bash functions, e.g. (in the example, "foo" is a Perl
script):
*foo () { local words=(${COMP*CWORDS[@]}) # add things to words, etc
local point=... # calculate the new point COMPREPLY=(
"COMP_LINE="foo ${words[@]}" COMP_POINT=$point foo" ) }
To avoid these word-breaking characters to be split/grouped, we can
escape them with backslash or quote them, e.g.:
command "http://example.com:80" Foo\:\:Bar
which bash will parse as:
["command", "\"http://example.com:80\"", "Foo\:\:Bar"]
and we parse as:
["command", "http://example.com:80", "Foo::Bar"]
* Due to the way bash parses the command line (see above), the two
below are equivalent:
% cmd --foo=bar % cmd --foo = bar
Because they both expand to "['--foo', '=', 'bar']". But obviously
Getopt::Long does not regard the two as equivalent.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
* $cmdline => *str*
Command-line, defaults to COMP_LINE environment.
* $opts => *hash*
Options.
Optional. Known options:
* "truncate_current_word" (bool). If set to 1, will truncate
current word to the position of cursor, for example ("^" marks
the position of cursor): "--vers^oo" to "--vers" instead of
"--versoo". This is more convenient when doing tab completion.
* $point => *int*
Point/position to complete in command-line, defaults to COMP_POINT.
Return value: (array)
Return a 2-element array: "[$words, $cword]". $words is array of str,
equivalent to "COMP_WORDS" provided by bash to shell functions. $cword
is an integer, roughly equivalent to "COMP_CWORD" provided by bash to
shell functions. The word to be completed is at "$words->[$cword]".
Note that COMP_LINE includes the command name. If you want the
command-line arguments only (like in @ARGV), you need to strip the first
element from $words and reduce $cword by 1.
point
Usage:
point($cmdline, $marker) -> any
Return line with point marked by a marker.
This is a utility function useful for testing/debugging.
"parse_cmdline()" expects a command-line and a cursor position ($line,
$point). This routine expects $line with a marker character (by default
it's the caret, "^") and return ($line, $point) to feed to
"parse_cmdline()".
Example:
point("^foo") # => ("foo", 0)
point("fo^o") # => ("foo", 2)
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
* $cmdline => *str*
Command-line which contains a marker character.
* $marker => *str* (default: "^")
Marker character.
Return value: (any)
ENVIRONMENT
COMPLETE_BASH_DEFAULT_ESC_MODE
Str. To provide default for the "esc_mode" option in
"format_completion".
COMPLETE_BASH_FZF
Bool. Whether to pass large completion answer to fzf instead of directly
passing it to bash and letting bash page it with a simpler more-like
internal pager. By default, large is defined as having at least 100
items (same bash's "completion-query-items" setting). This can be
configured via "COMPLETE_BASH_FZF_ITEMS".
Will not pass to fzf if inside emacs ("INSIDE_EMACS" environment is
true).
COMPLETE_BASH_FZF_ITEMS
Uint. Default 100. The minimum number of items to trigger passing
completion answer to "fzf".
A special value of -1 means to use terminal height. However, since
terminal height (and width) normally cannot be read during tab
completion anyway, it's better if you do something like this in your
bash startup file:
export COMPLETE_BASH_FZF_ITEMS=$LINES
because without passing to "fzf", as soon as the number of completion
answers exceeds $LINES, "bash" will start paging the answer to its
internal pager, which is limited like "more". If you set the above, then
as soon as the number of completion answers exceeds terminal height, you
will avoid the bash internal pager and use the nicer "fzf".
See also: "COMPLETE_BASH_FZF".
COMPLETE_BASH_MAX_COLUMNS
Uint.
Bash will show completion entries in one or several columns, depending
on the terminal width and the length of the entries (much like a
standard non-long `ls`). If you prefer completion entries to be shown in
a single column no matter how wide your terminal is, or how short the
entries are, you can set the value of this variable to 1. If you prefer
a maximum of two columns, set to 2, and so on. "format_completion" will
pad the entries with sufficient spaces to limit the number of columns.
COMPLETE_BASH_SHOW_SUMMARIES
Bool. Will set the default for "show_summaries" option in
"format_completion".
COMPLETE_BASH_SUMMARY_ALIGN
String. Either "left" (the default) or "right".
The "left" align looks something like this:
--bar Summary about the bar option
--baz Summary about the baz option
--foo Summary about the foo option
--schapen Summary about the schapen option
The "right" align will make the completion answer look like what you see
in the fish shell:
--bar Summary about the bar option
--baz Summary about the baz option
--foo Summary about the foo option
--schapen Summary about the schapen option
COMPLETE_BASH_TRACE
Bool. If set to true, will produce more log statements to Log::ger.
HOMEPAGE
Please visit the project's homepage at
<https://metacpan.org/release/Complete-Bash>.
SOURCE
Source repository is at
<https://github.com/perlancar/perl-Complete-Bash>.
SEE ALSO
Complete, the convention that this module follows.
Some higher-level modules that use this module (so you don't have to use
this module directly): Getopt::Long::Complete (via
Complete::Getopt::Long), Getopt::Long::Subcommand, Perinci::CmdLine (via
Perinci::Sub::Complete).
Other modules related to bash shell tab completion: Bash::Completion,
Getopt::Complete, Term::Bash::Completion::Generator.
Programmable Completion section in Bash manual:
<https://www.gnu.org/software/bash/manual/html_node/Programmable-Complet
ion.html>
AUTHOR
perlancar <perlancar@cpan.org>
CONTRIBUTORS
* Mary Ehlers <regina.verb.ae@gmail.com>
* 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) 2022, 2020, 2019, 2018, 2016, 2015, 2014
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-Bash>
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.