Contributions to the bash completion project are more than welcome. Fixes, clean-ups and improvements of existing code are much appreciated, as are completion functions for new commands.
If you wish to contribute code, please bare the following coding guidelines in mind:
For example, if you were writing completion code for perldoc(1), the use of Perl to achieve your goal would be acceptable. irb(1) completion would similarly make the use of Ruby acceptable.
Even so, please consider alternatives to these large and slow to start interpreters. Use lightweight programs such as grep(1), awk(1) and sed(1).
For example, extended globs often enable you to avoid the use of external programs, which are expensive to fork and execute, so do make full use of those:
?(pattern-list)
- match zero or one occurrences of patterns
*(pattern-list)
- match zero or more occurrences of patterns
+(pattern-list)
- match one or more occurrences of patterns
@(pattern-list)
- match exactly one of the given patterns
!(pattern-list)
- match anything except one of the given patterns
For example, judicious use of sed(1) can save you from having to call grep(1) and pipe the output to cut(1), which saves a fork(2) and exec(3).
Sometimes you don't even need sed(1) or other external programs at
all, though. Use of constructs such as ${parameter#word}
,
${parameter%word}
and ${parameter/pattern/string}
can provide
you a lot of power without having to leave the shell.
For example, if $foo
contains the path to an executable,
${foo##*/}
will give you the basename of the program, without
having to call basename(1). Similarly, ${foo%/*}
will give you the
dirname, without having to call dirname(1).
As another example,
shell
bar=$( echo $foo | sed -e 's/bar/baz/g' )
can be replaced by:
shell
bar=${foo//bar/baz}
These forms of parameter substitutions can also be used on arrays, which makes them very powerful (if a little slow).
Prefer compgen -W '...' -- $cur
over embedding $cur
in external
command arguments (often e.g. sed, grep etc) unless there's a good
reason to embed it. Embedding user input in command lines can result
in syntax errors and other undesired behavior, or messy quoting
requirements when the input contains unusual characters. Good
reasons for embedding include functionality (if the thing does not
sanely work otherwise) or performance (if it makes a big difference
in speed), but all embedding cases should be documented with
rationale in comments in the code.
When completing available options, offer only the most descriptive
ones as completion results if there are multiple options that do the
same thing. Usually this means that long options should be preferred
over the corresponding short ones. This way the user is more likely
to find what she's looking for and there's not too much noise to
choose from, and there are less situations where user choice would
be needed in the first place. Note that this concerns only display
of available completions; argument processing/completion for options
that take an argument should be made to work with all known variants
for the functionality at hand. For example if -s
, -S
, and
--something
do the same thing and require an argument, offer only
--something
as a completion when completing option names starting
with a dash, but do implement required argument processing for all
-s
, -S
, and --something
. Note that GNU versions of various
standard commands tend to have long options while other userland
implementations of the same commands may not have them, and it would
be good to have the completions work for as many userlands as
possible so things aren't always that simple.
Do not write to the file-system under any circumstances. This can create race conditions, is inefficient, violates the principle of least surprise and lacks robustness.
Use printf(1) instead of echo(1) for portability reasons, and be
sure to invoke commands that are often found aliased (such as ls
or grep
etc) using the command
(or builtin
) command as
appropriate.
Make small, incremental commits that do one thing. Don't cram unrelated changes into a single commit.
If your code was written for a particular platform, try to make it portable to other platforms, so that everyone may enjoy it. If your code works only with the version of a binary on a particular platform, ensure that it will not be loaded on other platforms that have a command with the same name.
In particular, do not use GNU extensions to commands like sed and awk if you can write your code another way. If you really, REALLY must use them, do so if there's no other sane way to do what you're doing. The "Shell and Utilities" volume of the POSIX specification is a good starting reference for portable use of various utilities, see http://pubs.opengroup.org/onlinepubs/9699919799/
Use an editor that supports EditorConfig, see http://editorconfig.org/, and format source code according to our settings.
Read the existing source code for examples of how to solve particular problems. Read the bash man page for details of all the programming tools available to you within the shell.
Please test your code thoroughly before sending it to us. We don't have access to all the commands for which we are sent completion functions, so we are unable to test them all personally. If your code is accepted into the distribution, a lot of people will try it out, so try to do a thorough job of eradicating all the bugs before you send it to us. If at all practical, add test cases to our test suite (in the test/ dir) that verify that the code does what it is intended to do, fixes issues it intends to fix, etc.
File bugs, enhancement, and pull requests at GitHub,
https://github.com/scop/bash-completion
Sending them to the developers might work too, but is really
discouraged as bits are more likely to fall through the cracks that
way compared to the tracker. Just use GitHub. If that's not an
option for some reason and you want to use email to send patches,
send them as attachments formatted by git format-patch
or directly
with git send-email
.