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=(${COMPCWORDS[@]}) # 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-Completion.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.