summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorDavid Paleino <dapal@debian.org>2012-01-08 00:19:18 +0100
committerDavid Paleino <dapal@debian.org>2012-01-08 00:19:18 +0100
commitc3d398fcc6e400be546c28eb1fc25abfa5816eac (patch)
tree3266a00f1037eb5522f1f8bf1a73e443ab2c26c4 /doc
parent2c8171c38d87ddef31c92a76547d3fdf773a1337 (diff)
downloadbash-completion-c3d398fcc6e400be546c28eb1fc25abfa5816eac.tar.gz
Imported Upstream version 1.99upstream/1.99
Diffstat (limited to 'doc')
-rw-r--r--doc/Makefile.am8
-rw-r--r--doc/Makefile.in309
-rw-r--r--doc/bash_completion.txt59
-rw-r--r--doc/bashrc41
-rw-r--r--doc/inputrc21
-rw-r--r--doc/main.txt18
-rwxr-xr-xdoc/makeHtml.sh4
-rw-r--r--doc/styleguide.txt111
-rw-r--r--doc/testing.txt573
9 files changed, 1144 insertions, 0 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 00000000..6930b9cb
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,8 @@
+EXTRA_DIST = \
+ bash_completion.txt \
+ bashrc \
+ inputrc \
+ main.txt \
+ makeHtml.sh \
+ styleguide.txt \
+ testing.txt
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 00000000..8e2fe930
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,309 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = doc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+compatdir = @compatdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ bash_completion.txt \
+ bashrc \
+ inputrc \
+ main.txt \
+ makeHtml.sh \
+ styleguide.txt \
+ testing.txt
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/bash_completion.txt b/doc/bash_completion.txt
new file mode 100644
index 00000000..c6e53d4c
--- /dev/null
+++ b/doc/bash_completion.txt
@@ -0,0 +1,59 @@
+Bash completion
+===============
+
+Configuration files
+-------------------
+
+*~/.bash_completion*::
+ Sourced late by bash_completion, pretty much after everything else.
+ Use this file for example to load additional completions, and to remove
+ and override ones installed by bash_completion.
+
+*$XDG_CONFIG_HOME/bash_completion*::
+ Sourced by the bash_completion.sh profile.d script. This file is
+ suitable for definitions of all `COMP_*` environment variables
+ below. If `$XDG_CONFIG_HOME` is unset or null, `~/.config` is
+ used instead of it.
+
+Environment variables
+---------------------
+
+*COMP_CONFIGURE_HINTS*::
+ If set and not null, `configure` completion will return the entire option
+ string (e.g. `--this-option=DESCRIPTION`) so one can see what kind of data
+ is required and then simply delete the descriptive text and add one's own
+ data. If unset or null (default), `configure` completion will strip
+ everything after the '=' when returning completions.
+
+*COMP_CVS_REMOTE*::
+ If set and not null, `cvs commit` completion will try to complete on
+ remotely checked-out files. This requires passwordless access to the
+ remote repository. Default is unset.
+
+*COMP_FILEDIR_FALLBACK*::
+ If set and not null, completions that look for filenames based on their
+ "extensions" will fall back to suggesting all files if there are none
+ matching the sought ones.
+
+*COMP_IWLIST_SCAN*::
+ If set and not null, `iwconfig` completion will try to complete on
+ available wireless networks identifiers. Default is unset.
+
+*COMP_KNOWN_HOSTS_WITH_HOSTFILE*::
+ If set and not null (default), known hosts completion will complement
+ hostnames from ssh's known_hosts files with hostnames taken from the file
+ specified by the HOSTFILE shell variable (compgen -A hostname). If null,
+ known hosts completion will omit hostnames from HOSTFILE. Omitting
+ hostnames from HOSTFILE is useful if HOSTFILE contains many entries for
+ local web development or ad-blocking.
+
+*COMP_KNOWN_HOSTS_WITH_AVAHI*::
+ If set and not null, known hosts completion will try to use `avahi-browse`
+ for additional completions. This may be a slow operation in some setups.
+ Default is unset.
+
+*COMP_TAR_INTERNAL_PATHS*::
+ If set and not null *before* sourcing bash_completion, `tar` completion
+ will do correct path completion for tar file contents. If unset or null,
+ `tar' completion will do correct completion for paths to tar files. See
+ also README.
diff --git a/doc/bashrc b/doc/bashrc
new file mode 100644
index 00000000..fd72b816
--- /dev/null
+++ b/doc/bashrc
@@ -0,0 +1,41 @@
+# bashrc file for DejaGnu testsuite
+
+ # Use emacs key bindings
+set -o emacs
+ # Use bash strict mode
+set -o posix
+ # Unset `command_not_found_handle' as defined on Debian/Ubuntu, because this
+ # troubles and slows down testing
+unset -f command_not_found_handle
+ # Set fixed prompt `/@'
+TESTDIR=$(pwd)
+export PS1='/@'
+export PS2='> '
+ # Configure readline
+export INPUTRC=$SRCDIR/config/inputrc
+ # When not running via cron, avoid escape junk at beginning of line from
+ # readline, see e.g. http://bugs.gentoo.org/246091
+[ "$CRON" ] || export TERM=dummy
+ # Ensure enough columns so expect doesn't have to care about line breaks
+stty columns 150
+ # Also test completions of system administrator commands, which are
+ # installed via the same PATH expansion in `bash_completion.have()'
+export PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
+
+ # Make sure default settings are in effect
+unset -v \
+ COMP_CONFIGURE_HINTS \
+ COMP_CVS_REMOTE \
+ COMP_KNOWN_HOSTS_WITH_HOSTFILE \
+ COMP_TAR_INTERNAL_PATHS
+
+ # Load bash testsuite helper functions
+. $SRCDIR/lib/library.sh
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh
diff --git a/doc/inputrc b/doc/inputrc
new file mode 100644
index 00000000..33134da6
--- /dev/null
+++ b/doc/inputrc
@@ -0,0 +1,21 @@
+# Readline init file for DejaGnu testsuite
+# See: info readline
+
+ # Press TAB once (instead of twice) to auto-complete
+set show-all-if-ambiguous on
+ # No bell. No ^G in output
+set bell-style none
+ # Don't query user about viewing the number of possible completions
+set completion-query-items -1
+ # Display completions sorted horizontally, not vertically
+set print-completions-horizontally on
+ # Don't use pager when showing completions
+set page-completions off
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh
diff --git a/doc/main.txt b/doc/main.txt
new file mode 100644
index 00000000..d8a3076a
--- /dev/null
+++ b/doc/main.txt
@@ -0,0 +1,18 @@
+Bash-completion
+===============
+Freddy Vulto (FVu)
+v1.0, Mar 2009
+
+Preface
+=======
+Bash completion extends bashs standard completion behavior to achieve
+complex command lines with just a few keystrokes. This project was
+conceived to produce programmable completion routines for the most
+common Linux/UNIX commands, reducing the amount of typing sysadmins
+and programmers need to do on a daily basis.
+
+// include::intro.txt[]
+include::bash_completion.txt[]
+
+include::styleguide.txt[]
+include::testing.txt[]
diff --git a/doc/makeHtml.sh b/doc/makeHtml.sh
new file mode 100755
index 00000000..79780eb6
--- /dev/null
+++ b/doc/makeHtml.sh
@@ -0,0 +1,4 @@
+#!/bin/bash -eu
+
+[ -d html~ ] || mkdir html~
+a2x -D html~ -d book -f xhtml --asciidoc-opts="--unsafe" main.txt
diff --git a/doc/styleguide.txt b/doc/styleguide.txt
new file mode 100644
index 00000000..31ad4469
--- /dev/null
+++ b/doc/styleguide.txt
@@ -0,0 +1,111 @@
+Coding Style Guide
+==================
+
+Introduction
+------------
+This document attempts to explain the basic styles and patterns that
+are used in the bash completion. New code should try to conform to
+these standards so that it is as easy to maintain as existing code.
+Of course every rule has an exception, but it's important to know
+the rules nonetheless!
+
+This is particularly directed at people new to the bash completion
+codebase, who are in the process of getting their code reviewed.
+Before getting a review, please read over this document and make
+sure your code conforms to the recommendations here.
+
+Indentation
+-----------
+Indent step should be 4 spaces, no tabs.
+
+Globbing in case labels
+-----------------------
+
+Avoid "fancy" globbing in case labels, just use traditional style when
+possible. For example, do "--foo|--bar)" instead of "--@(foo|bar))".
+Rationale: the former is easier to read, often easier to grep, and
+doesn't confuse editors as bad as the latter, and is concise enough.
+
+&#91;[ ]] vs [ ]
+----------------
+
+Always use [[ ]] instead of [ ]. Rationale: the former is less error
+prone, more featureful, and slightly faster.
+
+Line wrapping
+-------------
+
+Try to wrap lines at 79 characters. Never go past this limit, unless
+you absolutely need to (example: a long sed regular expression, or the
+like). This also holds true for the documentation and the testsuite.
+Other files, like ChangeLog, or COPYING, are exempt from this rule.
+
+$(...) vs \`...`
+----------------
+
+When you need to do some code substitution in your completion script,
+you *MUST* use the $(...) construct, rather than the \`...`. The former
+is preferable because anyone, with any keyboard layout, is able to
+type it. Backticks aren't always available, without doing strange
+key combinations.
+
+-o filenames
+------------
+
+As a rule of thumb, do not use "complete -o filenames". Doing it makes
+it take effect for all completions from the affected function, which
+may break things if some completions from the function must not be
+escaped as filenames. Instead, use "compopt -o filenames" to turn on
+"-o filenames" behavior dynamically when returning completions that
+need that kind of processing (e.g. file and command names). The
+_filedir and _filedir_xspec helpers do this automatically whenever
+they return some completions.
+
+&#91;[ $COMPREPLY == *= ]] && compopt -o nospace
+------------------------------------------------
+
+The above is functionally a shorthand for:
+----
+if [[ ${#COMPREPLY[@]} -eq 1 && ${COMPREPLY[0]} == *= ]]; then
+ compopt -o nospace
+fi
+----
+It is used to ensure that long options' name won't get a space
+appended after the equal sign. Calling compopt -o nospace makes sense
+in case completion actually occurs: when only one completion is
+available in COMPREPLY.
+
+$split && return
+----------------
+
+Should be used in completions using the -s flag of _init_completion,
+or other similar cases where _split_longopt has been invoked, after
+$prev has been managed but before $cur is considered. If $cur of the
+form --foo=bar was split into $prev=--foo and $cur=bar and the $prev
+block did not process the option argument completion, it makes sense
+to return immediately after the $prev block because --foo obviously
+takes an argument and the remainder of the completion function is
+unlikely to provide meaningful results for the required argument.
+Think of this as a catch-all for unknown options requiring an
+argument.
+
+Note that even when using this, options that are known to require an
+argument but for which we don't have argument completion should be
+explicitly handled (non-completed) in the $prev handling block because
+--foo=bar options can often be written without the equals sign, and in
+that case the long option splitting does not occur.
+
+/////////////////////////////////////////
+case/esac vs if
+---------------
+
+quoting
+-------
+
+awk vs cut for simple cases
+---------------------------
+
+variable and function naming
+----------------------------
+
+/////////////////////////////////////////
diff --git a/doc/testing.txt b/doc/testing.txt
new file mode 100644
index 00000000..c4b7cf18
--- /dev/null
+++ b/doc/testing.txt
@@ -0,0 +1,573 @@
+Automated testing
+=================
+
+Introduction
+------------
+The bash-completion package contains an automated test suite. Running the
+tests should help verifying that bash-completion works as expected. The tests
+are also very helpful in uncovering software regressions at an early stage.
+
+The bash-completion test suite is written on top of the
+http://www.gnu.org/software/dejagnu/[DejaGnu] testing framework. DejaGnu is
+written in http://expect.nist.gov[Expect], which in turn uses
+http://tcl.sourceforge.net[Tcl] -- Tool command language.
+
+
+Coding Style Guide
+------------------
+
+The bash-completion test suite tries to adhere to this
+http://wiki.tcl.tk/708[Tcl Style Guide].
+
+
+Installing dependencies
+-----------------------
+
+Installing dependencies should be easy using your local package manager.
+
+
+Debian/Ubuntu
+~~~~~~~~~~~~~
+
+On Debian/Ubuntu you can use `apt-get`:
+-------------
+sudo apt-get install dejagnu tcllib
+-------------
+This should also install the necessary `expect` and `tcl` packages.
+
+Fedora/RHEL/CentOS
+~~~~~~~~~~~~~~~~~~
+
+On Fedora and RHEL/CentOS (with EPEL) you can use `yum`:
+-------------
+sudo yum install dejagnu tcllib
+-------------
+This should also install the necessary `expect` and `tcl` packages.
+
+
+
+Structure
+---------
+
+
+Main areas (DejaGnu tools)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The tests are grouped into different areas, called _tool_ in DejaGnu:
+
+*completion*::
+ Functional tests per completion.
+*install*::
+ Functional tests for installation and caching of the main bash-completion
+ package.
+*unit*::
+ Unit tests for bash-completion helper functions.
+
+Each tool has a slightly different way of loading the test fixtures, see
+<<Test_context,Test context>> below.
+
+
+Completion
+~~~~~~~~~~
+
+Completion tests are spread over two directories: `completion/\*.exp` calls
+completions in `lib/completions/\*.exp`. This two-file system stems from
+bash-completion-lib (http://code.google.com/p/bash-completion-lib/, containing
+dynamic loading of completions) where tests are run twice per completion; once
+before dynamic loading and a second time after to confirm that all dynamic
+loading has gone well.
+
+For example:
+
+----
+set test "Completion via comp_load() should be installed"
+set cmd "complete -p awk"
+send "$cmd\r"
+expect {
+ -re "^$cmd\r\ncomplete -o filenames -F comp_load awk\r\n/@$" { pass "$test" }
+ -re /@ { fail "$test at prompt" }
+}
+
+
+source "lib/completions/awk.exp"
+
+
+set test "Completion via _longopt() should be installed"
+set cmd "complete -p awk"
+send "$cmd\r"
+expect {
+ -re "^$cmd\r\ncomplete -o filenames -F _longopt awk\r\n/@$" { pass "$test" }
+ -re /@ { fail "$test at prompt" }
+}
+
+
+source "lib/completions/awk.exp"
+----
+
+Looking to the completion tests from a broader perspective, every test for a
+command has two stages which are now reflected in the two files:
+
+. Tests concerning the command completions' environment (typically in
+`test/completion/foo`)
+. Tests invoking actual command completion (typically in
+`test/lib/completions/foo`)
+
+
+Running the tests
+-----------------
+
+The tests are run by calling `runtest` command in the test directory:
+-----------------------
+runtest --outdir log --tool completion
+runtest --outdir log --tool install
+runtest --outdir log --tool unit
+-----------------------
+The commands above are already wrapped up in shell scripts within the `test`
+directory:
+-----------------------
+./runCompletion
+./runInstall
+./runUnit
+-----------------------
+To run a particular test, specify file name of your test as an argument to
+`runCompletion` script:
+-----------------------
+./runCompletion ssh.exp
+-----------------------
+That will run `test/completion/ssh.exp`.
+
+
+Running tests via cron
+~~~~~~~~~~~~~~~~~~~~~~
+
+The test suite requires a connected terminal (tty). When invoked via cron, no
+tty is connected and the test suite may respond with this error:
+---------------------------------------------
+can't read "multipass_name": no such variable
+---------------------------------------------
+
+To run the tests successfully via cron, connect a terminal by redirecting
+stdin from a tty, e.g. /dev/tty40. (In Linux, you can press alt-Fx or
+ctrl-alt-Fx to switch the console from /dev/tty1 to tty7. There are many more
+/dev/tty* which are not accessed via function keys. To be safe, use a tty
+greater than tty7)
+
+----------------------
+./runUnit < /dev/tty40
+----------------------
+
+If the process doesn't run as root (recommended), root will have to change the
+owner and permissions of the tty:
+-------------------------
+sudo chmod o+r /dev/tty40
+-------------------------
+
+To make this permission permanent (at least on Debian) - and not revert back on
+reboot - create the file `/etc/udev/rules.d/10-mydejagnu.rules`, containing:
+----------------------------
+KERNEL=="tty40", MODE="0666"
+----------------------------
+
+To start the test at 01:00, set the crontab to this:
+----------------------------
+* 1 * * * cd bash-completion/test && ./cron.sh < /dev/tty40
+----------------------------
+
+Here's an example batch file `cron.sh`, to be put in the bash-completion `test`
+directory. This batch file only e-mails the output of each test-run if the
+test-run fails.
+
+[source,bash]
+---------------------------------------------------------------------
+#!/bin/sh
+
+set -e # Exit if simple command fails
+set -u # Error if variable is undefined
+
+CRON=running
+LOG=/tmp/bash-completion.log~
+
+ # Retrieve latest sources
+git pull
+
+ # Run tests on bash-4
+
+./runUnit --outdir log/bash-4 --tool_exec /opt/bash-4.0/bin/bash > $LOG || cat $LOG
+./runCompletion --outdir log/bash-4 --tool_exec /opt/bash-4.0/bin/bash > $LOG || cat $LOG
+
+ # Clean up log file
+[ -f $LOG ] && rm $LOG
+---------------------------------------------------------------------
+
+Specifying bash binary
+~~~~~~~~~~~~~~~~~~~~~~
+
+The test suite standard uses `bash` as found in the tcl path (/bin/bash).
+Using `--tool_exec` you can specify which bash binary you want to run the test
+suite against, e.g.:
+
+----------------
+./runUnit --tool_exec /opt/bash-4.0/bin/bash
+----------------
+
+
+
+
+Maintenance
+-----------
+
+
+Adding a completion test
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can run `cd test && ./generate cmd` to add a test for the `cmd` command.
+This will add two files with a very basic tests:
+----------------------------------
+test/completion/cmd.exp
+test/lib/completions/cmd.exp
+----------------------------------
+Place any additional tests into `test/lib/completions/cmd.exp`.
+
+
+Fixing a completion test
+~~~~~~~~~~~~~~~~~~~~~~~~
+Let's consider this real-life example where an ssh completion bug is fixed.
+First you're triggered by unsuccessful tests:
+
+----------------------------------
+$ ./runCompletion
+...
+ === completion Summary ===
+
+# of expected passes 283
+# of unexpected failures 8
+# of unresolved testcases 2
+# of unsupported tests 47
+----------------------------------
+
+Take a look in `log/completion.log` to find out which specific command is
+failing.
+
+-----------------------
+$ vi log/completion.log
+-----------------------
+
+Search for `UNRESOLVED` or `FAIL`. From there scroll up to see which `.exp`
+test is failing:
+
+---------------------------------------------------------
+/@Running ./completion/ssh.exp ...
+...
+UNRESOLVED: Tab should complete ssh known-hosts at prompt
+---------------------------------------------------------
+
+In this case it appears `ssh.exp` is causing the problem. Isolate the `ssh`
+tests by specifying just `ssh.exp` to run. Furthermore add the `--debug` flag,
+so output gets logged in `dbg.log`:
+
+----------------------------------
+$ ./runCompletion ssh.exp --debug
+...
+ === completion Summary ===
+
+# of expected passes 1
+# of unresolved testcases 1
+----------------------------------
+
+Now we can have a detailed look in `dbg.log` to find out what's going wrong.
+Open `dbg.log` and search for `UNRESOLVED` (or `FAIL` if that's what you're
+looking for):
+
+---------------------------------------------------------
+UNRESOLVED: Tab should complete ssh known-hosts at prompt
+---------------------------------------------------------
+
+From there, search up for the first line saying:
+
+-------------------------------------------------
+expect: does "..." match regular expression "..."
+-------------------------------------------------
+
+This tells you where the actual output differs from the expected output. In
+this case it looks like the test "ssh -F fixtures/ssh/config <TAB>" is
+expecting just hostnames, whereas the actual completion is containing commands
+- but no hostnames.
+So what should be expected after "ssh -F fixtures/ssh/config <TAB>" are *both*
+commands and hostnames. This means both the test and the completion need
+fixing. Let's start with the test.
+
+----------------------------
+$ vi lib/completions/ssh.exp
+----------------------------
+
+Search for the test "Tab should complete ssh known-hosts". Here you could've
+seen that what was expected were hostnames ($hosts):
+
+-----------------------------------------
+set expected "^$cmd\r\n$hosts\r\n/@$cmd$"
+-----------------------------------------
+
+Adding *all* commands (which could well be over 2000) to 'expected', seems a
+bit overdone so we're gonna change things here. Lets expect the unit test for
+`_known_hosts` assures all hosts are returned. Then all we need to do here is
+expect one host and one command, just to be kind of sure that both hosts and
+commands are completed.
+
+Looking in the fixture for ssh:
+
+-----------------------------
+$ vi fixtures/ssh/known_hosts
+-----------------------------
+
+it looks like we can add an additional host 'ls_known_host'. Now if we would
+perform the test "ssh -F fixtures/ssh/config ls<TAB>" both the command `ls` and
+the host `ls_known_host` should come up. Let's modify the test so:
+
+--------------------------------------------------------
+$ vi lib/completions/ssh.exp
+...
+set expected "^$cmd\r\n.*ls.*ls_known_host.*\r\n/@$cmd$"
+--------------------------------------------------------
+
+Running the test reveals we still have an unresolved test:
+
+----------------------------------
+$ ./runCompletion ssh.exp --debug
+...
+ === completion Summary ===
+
+# of expected passes 1
+# of unresolved testcases 1
+----------------------------------
+
+But if now look into the log file `dbg.log` we can see the completion only
+returns commands starting with 'ls' but fails to match our regular expression
+which also expects the hostname `ls_known_host':
+
+-----------------------
+$ vi dbg.log
+...
+expect: does "ssh -F fixtures/ssh/config ls\r\nls lsattr lsb_release lshal lshw lsmod lsof lspci lspcmcia lspgpot lss16toppm\r\nlsusb\r\n/@ssh -F fixtures/ssh/config ls" (spawn_id exp9) match regular expression "^ssh -F fixtures/ssh/config ls\r\n.*ls.*ls_known_host.*\r\n/@ssh -F fixtures/ssh/config ls$"? no
+-----------------------
+
+Now let's fix ssh completion:
+
+-------------------
+$ vi ../contrib/ssh
+...
+-------------------
+
+until the test shows:
+
+----------------------------------
+$ ./runCompletion ssh.exp
+...
+ === completion Summary ===
+
+# of expected passes 2
+----------------------------------
+
+Fixing a unit test
+~~~~~~~~~~~~~~~~~~
+Now let's consider a unit test failure. First you're triggered by unsuccessful
+tests:
+
+----------------------------------
+$ ./runUnit
+...
+ === unit Summary ===
+
+# of expected passes 1
+# of unexpected failures 1
+----------------------------------
+
+Take a look in `log/unit.log` to find out which specific command is failing.
+
+-----------------
+$ vi log/unit.log
+-----------------
+
+Search for `UNRESOLVED` or `FAIL`. From there scroll up to see which `.exp`
+test is failing:
+
+------------------------------------------
+/@Running ./unit/_known_hosts_real.exp ...
+...
+FAIL: Environment should stay clean
+------------------------------------------
+
+In this case it appears `_known_hosts_real.exp` is causing the problem.
+Isolate the `_known_hosts_real` test by specifying just `_known_hosts_real.exp`
+to run. Furthermore add the `--debug` flag, so output gets logged in
+`dbg.log`:
+
+----------------------------------
+$ ./runUnit _known_hosts_real.exp --debug
+...
+ === completion Summary ===
+
+# of expected passes 1
+# of unexpected failures 1
+----------------------------------
+
+Now, if we haven't already figured out the problem, we can have a detailed look
+in `dbg.log` to find out what's going wrong. Open `dbg.log` and search for
+`UNRESOLVED` (or `FAIL` if that's what you're looking for):
+
+-----------------------------------
+FAIL: Environment should stay clean
+-----------------------------------
+
+From there, search up for the first line saying:
+
+-------------------------------------------------
+expect: does "..." match regular expression "..."
+-------------------------------------------------
+
+This tells you where the actual output differs from the expected output. In
+this case it looks like the the function `_known_hosts_real` is unexpectedly
+modifying global variables `cur` and `flag`. In case you need to modify the
+test:
+
+-----------------------------------
+$ vi lib/unit/_known_hosts_real.exp
+-----------------------------------
+
+Rationale
+---------
+
+
+Naming conventions
+~~~~~~~~~~~~~~~~~~
+
+Test suite or testsuite
+^^^^^^^^^^^^^^^^^^^^^^^
+The primary Wikipedia page is called
+http://en.wikipedia.org/wiki/Test_suite[test suite] and not testsuite, so
+that's what this document sticks to.
+
+script/generate
+^^^^^^^^^^^^^^^
+The name and location of this code generation script come from Ruby on Rails'
+http://en.wikibooks.org/wiki/Ruby_on_Rails/Tools/Generators[script/generate].
+
+
+
+
+== Reference
+
+Within test scripts the following library functions can be used:
+
+[[Test_context]]
+== Test context
+
+The test environment needs to be put to fixed states when testing. For
+instance the bash prompt (PS1) is set to the current test directory, followed
+by an at sign (@). The default settings for `bash` reside in `config/bashrc`
+and `config/inputrc`.
+
+For each tool (completion, install, unit) a slightly different context is in
+effect.
+
+=== What happens when tests are run?
+
+==== completion
+
+When the completions are tested, invoking DejaGnu will result in a call to
+`completion_start()` which in turn will start `bash --rcfile config/bashrc`.
+
+.What happens when completion tests are run?
+----
+ | runtest --tool completion
+ V
+ +----------+-----------+
+ | lib/completion.exp |
+ | lib/library.exp |
+ | config/default.exp |
+ +----------+-----------+
+ :
+ V
+ +----------+-----------+ +---------------+ +----------------+
+ | completion_start() +<---+ config/bashrc +<---| config/inputrc |
+ | (lib/completion.exp) | +---------------+ +----------------+
+ +----------+-----------+
+ | ,+----------------------------+
+ | ,--+-+ "Actual completion tests" |
+ V / +------------------------------+
+ +----------+-----------+ +-----------------------+
+ | completion/*.exp +<---| lib/completions/*.exp |
+ +----------+-----------+ +-----------------------+
+ | \ ,+--------------------------------+
+ | `----------------------+-+ "Completion invocation tests" |
+ V +----------------------------------+
+ +----------+-----------+
+ | completion_exit() |
+ | (lib/completion.exp) |
+ +----------------------+
+----
+Setting up bash once within `completion_start()` has the speed advantage that
+bash - and bash-completion - need only initialize once when testing multiple
+completions, e.g.:
+----
+ runtest --tool completion alias.exp cd.exp
+----
+==== install
+
+.What happens when install tests are run?
+----
+ | runtest --tool install
+ V
+ +----+----+
+ | DejaGnu |
+ +----+----+
+ |
+ V
+ +------------+---------------+
+ | (file: config/default.exp) |
+ +------------+---------------+
+ |
+ V
+ +------------+------------+
+ | (file: lib/install.exp) |
+ +-------------------------+
+----
+
+==== unit
+
+.What happens when unit tests are run?
+----
+ | runtest --tool unit
+ V
+ +----+----+
+ | DejaGnu |
+ +----+----+
+ |
+ V
+ +----------+-----------+
+ | - |
+ | (file: lib/unit.exp) |
+ +----------------------+
+----
+
+=== bashrc
+
+This is the bash configuration file (bashrc) used for testing:
+
+[source,bash]
+---------------------------------------------------------------------
+include::bashrc[]
+---------------------------------------------------------------------
+
+
+=== inputrc
+
+This is the readline configuration file (inputrc) used for testing:
+
+[source,bash]
+---------------------------------------------------------------------
+include::inputrc[]
+---------------------------------------------------------------------
+
+
+Index
+=====