NOUSERMACRO(xd)

includefile(../../release.yo)

htmlbodyopt(text)(#27408B)
htmlbodyopt(bgcolor)(#FFFAF0)
whenhtml(mailto(Frank B. Brokken: f.b.brokken@rug.nl))

DEFINEMACRO(lsoption)(3)(\
    bf(--ARG1)=tt(ARG3) (bf(-ARG2))\
)
DEFINEMACRO(laoption)(2)(\
    bf(--ARG1)=tt(ARG2)\
)
DEFINEMACRO(loption)(1)(\
    bf(--ARG1)\
)
DEFINEMACRO(soption)(1)(\
    bf(-ARG1)\
)


DELETEMACRO(tt)
DEFINEMACRO(tt)(1)(em(ARG1))

COMMENT( man-request, section, date, distribution file, general name)
manpage(xd)(1)(_CurYrs_)(xd._CurVers_.tar.gz)
        (xd - fast directory changes)

COMMENT( man-request, larger title )
manpagename(xd)(eXtra fast Directory changer)

COMMENT( all other: add after () )
manpagesynopsis()
       bf(xd) [OPTIONS] tt(arguments)

manpagedescription()

    The program bf(xd) is used to perform e+bf(X)tra fast bf(D)irectory
changes. Usually to change a directory the user is required to enter a command
like, e.g., tt(cd /usr/local/bin), possibly with the aid of shell
completion. In many cases this is a tedious task: shell completion shows all
entries, including files, when we're only interested in directories and the
full specification of our intented directory may eventually require many
keyboard actions.

    tt(Xd) was designed a long time ago (in the early 90s) to reduce the
effort of changing directories. Often we're well aware to which directory we
want to change, and it's easy to produce the initial directory characters of
that directory. E.g., if the intent is to tt(cd) to tt(/usr/local/bin),
it's quite easy to produce the letters tt(ulb).

    tt(Xd) capitalizes on this capability. By providing the initial directory
characters of directories tt(xd) determines the proper expansion allowing you
to change directories fast. So, entering the command tt(xd ulb) results in the
expansion tt(/usr/local/bin).

    Often life is not that easy. Often there are multiple expansions from a
given set of initial characters. E.g., when entering tt(xd ulb) tt(xd) may
find several alternatives. E.g.,
        verb(
 1: /usr/lib/base-config
 2: /usr/lib/bonobo
 3: /usr/lib/bonobo-activation
 4: /usr/local/bin
        )
    If these are the alternatives, this is exactly what tt(xd) will show
you. Then, by simply pressing the tt(3) key (em(no) tt(Enter) key required)
tt(xd) will produce the required tt(/usr/local/bin).

    Commands to tt(xd) can be specified so as to fine-tune tt(xd)'s behavior:
    itemization(
    it() By default (as specified by the configuration file, see below)
expansions may start at the user's home directory or at the system's root
directory.
    it() Initial character bf(/): If the first character of the command is
tt(/) then all expansions are performed from the system's root
directory. E.g., tt(xd /t) results in tt(/tmp) but not in tt(/home/user/tmp).
    it() Initial character bf(.): If the first character of the command is
tt(.) then by default all expansions are performed from the user's home
directory. E.g., tt(xd .t) results in tt(/home/user/tmp) but not in
tt(/tmp). The home directory recognition character can be altered using the
tt(--homedir-char) option, see below (section bf(OPTIONS)).
    it() Initial character bf(0): If the first character of the command is
tt(0), then all expansions start at the current working directory. In fact,
this is a specialization of the following, more general form:
    it() Initial character bf(1..9): If the first character of the command is
a digit between tt(1) and tt(9) then all expansions start at that parent
directory level of the current working directory (up to the system's root
directory). E.g., if the current working directory is tt(/usr/share/doc) then
tt(xd 2lb) will offer the alternative tt(/usr/local/bin): two steps up, then
look for directories starting with tt(l) and therein directories starting with
tt(b).
    it() Separators (space, and the forward slash (`tt(/)')): sometimes it is
clear that there are many alternatives and the intention is to reduce that
number. By using separators subsequently nested directories must start with
the characters between the separators. E.g., tt(xd u l bi) never produces the
alternative tt(/usr/lib/base-config) anymore, since tt(base-config) does not
start with tt(bi). In this case only tt(/usr/local/bin) is produced. When used
as initial character in a pattern the forward slash always indicates the
root-directory.
    COMMENT(
   Separators may be mixed (tt(xd u/l bi) is identical to tt(xd u l
    bi)). Since the tt(/) can also be used as a root-directory specification,
    a conflict is implied by a command like tt(xd /u l bi). This conflict is
    solved by given the initial character a higher precedence than the
    separator. Using the underscore (_) separator in this case is another way
    to solve the conflict (which in practice hardly ever occurs).
    END)

    it() Search patterns may contain dots (like tt(.s)). In such cases the dot
represents hidden directories. However, tt(xd) usually also finds patterns
containing tt(/./), as the current directory matches the dot. Such patterns
are considered spurious and are not reported.
    )

    If there's only one solution, tt(Xd) writes that directory to its standard
output stream. If there are multiple solutions, then a list of at most 62
alternatives (10 for the numbers 0..9, 26 for the letters a..z and 26 for the
letters A..Z) is written to the standard error stream from which the user
may select an alternative by simply pressing the key associated with the
selection of choice. If no selection is requested any other key may be pressed
(e.g., the space bar or the tt(Enter) key). If there is no solutioon tt(xd)
writes the text tt(No Solutions) to the standard error stream.

    When tt(xd) is given at least one argument, all its output is sent to the
standard error stream, but for the selected directory name which is written to
the standard output stream. If no selection is made or if the selection
process is aborted a single dot is written to the standard output
stream. Usually tt(xd) will be called by a shell alias, providing the
tt(cd) command with tt(xd)'s output (see below at the bf(SHELL SCRIPTS)
section) executing tt(cd `xd $*`). The default dot produced by tt(xd)
prevents an unintended change of directory.

    When tt(xd) is merely given an initial directory specification, like a
single dot (tt(.)) or digit (a digit in the set tt([0..9])) then tt(xd)
returns the implied path. Specifying a parent before the root-directory (E.g.,
entering `tt(xd 5)' when the current working directory is `tt(/tmp)') results
in writing the root directory (`tt(/)') to the standard output stream.

    If tt(xd) is called without arguments then em(usage) information is
written to the standard error stream.

    tt(Xd) may be further configured using options and a configuration file,
discussed in the bf(OPTIONS) and bf(CONFIGURATION FILE) sections below.

manpagesection(GENERALIZED DIRECTORY SEARCH)

    Starting with version 3.10.0 tt(xd) also supports generalized directory
search command processing (GDS). When GDS is requested separators are no
longer required, and tt(xd) will find all possible alternatives resulting from
all possible sequential combinations of the initial search command. GDS is
activated either by specifying the tt(-g) command line flag or by entering
tt(generalized-search) in tt(xd)'s configuration file. Alternatively, when the
latter is specified then the tt(--traditional) command line option will
suppress GDS.

    When using GDS each initial substring of the command to tt(xd) is
considered as the initial characters of a directory. E.g., if the command
tt(xd tmps) is entered using GDS then directories matching the following
search patterns will be found;
    itemization(
    it() tt(/t*/m*/p*/s*/)
    it() tt(/t*/m*/ps*/)
    it() tt(/t*/mp*/s*/)
    it() tt(/t*/mps*/)
    it() tt(/tm*/p*/s*/)
    it() tt(/tm*/ps*/)
    it() tt(/tmp*/s*/)
    it() tt(/tmps*/)
    )
    Using the traditional processing mode only the first one of these
alternative patterns is considered.

    Multiple command line arguments, the slash and the underscore can still be
used with GDS in which case they force a directory change in the considered
patterns. E.g., with the command tt(xd tm/ps) the following patterns will be
considered:
    itemization(
    it() tt(/t*/m*/p*/s*/)
    it() tt(/t*/m*/ps*/)
    it() tt(/tm*/p*/s*/)
    it() tt(/tm*/ps*/)
    )
    In this set all of the previous patterns showing the tt(...mp...)
combination were dropped, as a directory change is forced between the tt(m)
and tt(p) characters.

manpagesection(RETURN VALUE)

    tt(Xd) returns 0 to the operating system unless an error occurs (e.g.,
when a non-existing configuration file is specified), or tt(xd)'s version or
usage info is shown or requested.

manpageoptions()

    If available, single letter options are listed between parentheses
following their associated long-option variants. Single letter options require
arguments if their associated long options require arguments as well.
    itemization(
    it() loption(add-root) tt(condition)nl()
            If the search starts at the user's home directory an additional
search starting at the system's root directory may be performed as well,
depending on the value specified for the tt(add-root) option. Alternatives are
tt(never) (no additional search is performed); tt(if-empty) (an additional
search is performed if the initial search did not yield any directory); or
tt(always) (an additional search is always performed).  There is also a
configuration file directive tt(add-root) (see below).

    it() loption(all) soption(a)nl()
        If the configuration file (see below) contains tt(ignore) directives
then these directives are ignored when computing the alternatives from which
the user may select a directory to change to.

    it() lsoption(config-file)(c)(filename)nl()
           The name of an tt(xd) configuration file. By default tt(xd)
            looks for the file tt(.xdrc) in the user's home directory. The
            existence of the default file is optional.

    it() loption(directories) tt(inclusion)nl()
        Directories may be also be reached via symbolic links. The inclusion
type tt(all) adds these symbolic links to the list of alternatives. The
inclusion type tt(unique) prevents symbolic links from being added to
the list of alternatives. There is also a configuration file directive
tt(directories) (see below).

    it() loption(homedir-char) tt(ch)nl()
        By default an initial dot character (`tt(.)') initiates a search from
the user's home directory. There is a slight disadvantage to using the dot, as
it is also be the initial character of `hidden' directories. Assuming that you
have a directory tt(~/.ssh) then the command to xd to that directory would be
tt(xd ..s), the first dot being the home directory indicator, after which
tt(.s) is used to find tt(.ssh). The option tt(--homedir-char) can be used to
specify another character. Homedir characters cannot be digits or a slash
(`tt(/)') as these are used to specify, respectively, parent directories and
the computer's root directory. Characters like ``tt(, @ % ^)'' or maybe
`tt(H)' (assuming that it doesn't interfere with an existing directory
beginning with tt(H)) could be used as homedir-characters, other than the
default dot character.

Caveat: command shells by default interpret characters like ``tt(~ $ \ ' " ` <
> |)'' etc., which therefore should probably not be specified as
home directory specifiers.

There is also a configuration file directive tt(homedir-char) (see below).

    it() loption(generalized-search) soption(g)nl()
        When this option is specified tt(xd) uses GDS unless the
directive tt(traditional) is specified in the configuration file.

    it() loption(help) (soption(h))nl()
           Basic usage information is written to the standard error stream.

    it() loption(history) tt([filename])nl()
        A history of previously made choices is kept in the file
tt(filename). If tt(--history) is specified, but the filename is
left empty the history file tt($HOME/.xd.his) is used. This file should only
be modified by tt(xd) itself. If you can't resist editing it then use the
following example showing the format of the lines in the history file.
        verb(
    1292596154 1 /home/frank/svn/xd/
        )
    The first field is the time (in seconds since the epoch) the entry was
written, the second field is the number of times the entry has been selected
and the third field is the associated path.

    it() loption(history-lifetime) tt(spec)nl()
    The lifetime of the entries in the history file. The specification
consists of a number followed by tt(D, W, M) or tt(Y), representing,
resp. days, weeks, months, or years. A month is considered a period of 30
days, a year a period of 365 days. If the specification is omitted a lifetime
of tt(1M) (one month) is used. Entries older than tt(history-lifetime) are
disregarded as history-items and are removed from the history file.

    it() loption(history-maxsize) tt(nr)nl()
    The maximum number of entries the history file may contain. By default
there is no limit. When tt(history-maxsize) is specified and more than the
maximum number of history items are found in the history file then the tt(nr)
most popular choices are kept. Usually the cut-off point will be somewhere
within a popularity category. In that case the most recently selected
alternatives within that category are kept.

    it() loption(history-position) tt([top|bottom])nl()
    When this option is specified then previously found alternatives
are displayed either at the top of the list or at the bottom
of the list. If this option is omitted then the elements in the history will
be intermixed with new alternatives. The next option tt(history-separate) is
only used when this option is also specified. By merely specifying
tt(history-position) the history items are shown at the top of the list.

    it() loption(history-separate)nl()
    When specified, a blank line is written between the items in the history
and new alternatives (not previously selected). This option is only
interpreted when the previous option is also specified.

    it() loption(icase) soption(i)nl()
    This option is used to specify case-insensitive pattern matching. E.g.,
specifying tt(xd /ub) returns the directory tt(/usr/bin), but not a directory
like tt(/UnSpecified/Books), which is returned by tt(xd /UB). However, tt(xd
-i /ub) (using any letter casing for the specification) returns both
directories. The option tt(icase) could of course be specified in the
configuration file, which which case case-insensitive matching is used by
default. In the latter case specifying tt(-i) as a command line option reverts
the matching procedure to case-sensitive directory matching. In general, when
an even number of em(icase) specifications is provided tt(xd) uses
case-sensitive directory matching, while an odd number of em(icase)
specifications results in case-insensitive directory matching.

    it() loption(start-at) tt(origin)nl()
        Defines the default start location of directory searches. Origin
tt(home) results in all default searches to start at the user's home
directory. Origin tt(root) results in searches to begin at the disk's root
(tt(/)) directory. There is also a configuration file directive tt(start-at)
(see below).

    it() loption(traditional)nl()
        When this option is specified tt(xd) will not use GDS but will use its
traditional mode. It overrules a tt(generalized-search) directive specified in
the configuration file as well as the tt(-g) option.

    it() loption(verbose) (soption(V))nl()
           More extensive information about the actions taken by the tt(xd)
program is written to the standard error stream.

    it() loption(version) (soption(v))nl()
           tt(Xd)'s version number is written to the standard error stream.
    )


manpagesection(CONFGURATION FILE)

The default configuration file is tt(.xdrc) in the user's home directory. It
may be overruled by the program's tt(--config-file) option.

Empty lines are ignored. Information at and beyond tt(#)-characters is
interpreted as comment and is ignored as well.

All directives in tt(xd) configuration files follow the pattern
    verb(
    directive value
    )
    but for some directives tt(value) is optional.

A line may at most contain one directive, but white space (including
comment at the end of the line) is OK. The same directive may be specified
multiple times, in which case the em(last) directive will be used (with the
exception of the em(ignore) directive, see below). All
directives  are interpreted em(case sensitively).  Non-empty lines
not beginning with a recognized directive are silently ignored.

    The following directives can be used in the
configuration file. Default values are shown between parentheses.
    itemization(
    it() bf(add-root) tt(when) (if-empty)nl()
            If the search starts at the user's home directory an additional
search starting at the system's root directory may be performed as well,
depending on the value specified for the tt(add-root) directive. nl()
    If tt(when) is specified as tt(always) then an additional search is
always performed.nl()
            If it is specified as tt(if-empty) then an additional search is
performed if the initial search (starting at the user's home directory) did
not yield any directory.nl()
            If it is specified as tt(never) no additional search is
performed.

    This directive is overruled by the tt(---add-root) command line option.

    it() bf(directories) tt(which) (all)nl()
        Directories may be also be reached via symbolic links. The
specification tt(all) will add these symbolic links to the list of
alternatives. The specification tt(unique) will prevent the symbolic links
from being added to the list of alternatives.

    This directive is overruled by the tt(---directories) command line option.

    it() bf(homedir-char) tt(ch)nl()
        By default an initial dot character (`tt(.)') initiates a search from
the user's home directory. There is a slight disadvantage to using the dot, as
it is also be the initial character of `hidden' directories. Assuming that you
have a directory tt(~/.ssh) then the command to xd to that directory would be
tt(xd ..s), the first dot being the home directory indicator, after which
tt(.s) is used to find tt(.ssh). The specification tt(homedir-char ch) can be
used to specify another home directory indicating character tt(ch), as in:
    verb(
 homedir-char ,
    )
    Homedir characters cannot be digits or a
slash (`tt(/)') as these are used to specify, respectively, parent directories
and the computer's root directory. Characters like ``tt(, @ % ^)'' or maybe
`tt(H)' (assuming that it doesn't interfere with an existing directory
beginning with tt(H)) could be used as homedir-characters, other than the
default dot character.

Caveat: command shells by default interpret characters like ``tt(~ $ \ ' " ` <
> |)'' etc., which therefore should probably not be specified as
home directory specifiers.

This directive is overruled by the tt(---homedir-char) command line option.

    it() bf(generalized-search) nl()
        When this directive is specified tt(xd) will use GDS by default.

    it() bf(history) tt([filename])nl()
        A history of previously made choices is kept in the file
tt(filename). If tt(history) is specified, but the filename is
left empty the history file tt($HOME/.xd.his) is used. This file should only
be modified by tt(xd) itself. If you can't resist editing it then use the
following example showing the format of the lines in the history file.
        verb(
    1292596154 1 /home/frank/svn/xd/
        )
    The first field is the time (in seconds since the epoch) the entry was
written, the second field is the number of times the entry has been selected
and the third field is the associated path.

    it() bf(history-lifetime) tt(spec)nl()
    The lifetime of the entries in the history file. The specification
consists of a number followed by tt(D, W, M) or tt(Y), representing,
resp. days, weeks, months, or years. A month is considered a period of 30
days, a year a period of 365 days. If the specification is omitted a lifetime
of tt(1M) (one month) is used. Entries older than tt(history-lifetime) are
disregarded as history-items and are removed from the history file.

    it() bf(history-maxsize) tt(nr)nl()
    The maximum number of entries the history file may contain. By default
there is no limit. When tt(history-maxsize) is specified and more than the
maximum number of history items are found in the history file then the tt(nr)
latest choices are kept. Each previously made selection counts as one.  If a
new alternative is selected it always becomes an element in the history list.

    it() bf(history-position) tt([top|bottom])nl()
    When specified alternatives found in the history will be displayed either
at the top of the list or at the bottom of the list. If this option is omitted
then the elements in the history will be intermixed with new alternatives. The
next directive tt(history-separate) is only used when this directive is also
specified. By merely specifying tt(history-position) the history items are
shown at the top of the list.

    it() bf(history-separate)nl()
    When specified, a blank line is written between the items in the history
and new alternatives (not previously selected). This directive is only
interpreted when the previous directive is also specified.

    it() loption(icase) soption(i)nl()
    This specification is used to request case-insensitive pattern
matching. If this option is entered in the configuration file then specifying
tt(xd /ub) returns the directory tt(/usr/bin) as welll as a directory like
(assuming it exists) tt(/UnSpecified/Books). When specified in the
configuration file, the command-line option tt(-i) reverts the matching
procedure back to case-sensitive directory matching. In general, when an even
number of em(icase) specifications is provided tt(xd) uses case-sensitive
directory matching, while an odd number of em(icase) specifications results in
case-insensitive directory matching.

    it() bf(ignore) tt(path) nl()
        The configuration file may contain multiple tt(ignore) directives
which are --different from the way other directives are handled-- all
interpreted. Each tt(ignore) directive is followed by a path specification as
shown in a list of alternatives produced by tt(xd) or an initial substring of
such a path terminating in a tt(*) character. When tt(xd) encounters a path
matching any of the tt(ignore) directives (with the tt(*) interpreted as `any
further directory name' specification) it will not display that path in its
list of alternatives.

    This directive is overruled by the tt(---all) command line option.

    it() bf(start-at) tt(value) (home) nl()
           Defines the default start location of directory searches. Values
are tt(home) and tt(root). When tt(home) is specified all searches start at
the user's home directory. When tt(root) is specified searches start at the
disk's root (tt(/)) directory. If the directory is omitted or if another value
is specified then the default is used, which is tt(home).

This directive is overruled by the tt(---start-at) command line option.

    it() bf(traditional) nl()
        This directive may be used to request the use of tt(xd)'s traditional
mode. It overrules the tt(-g) command line option and the
tt(generalized-search) directive.
    )


manpagesection(SHELL SCRIPTS)

    Assuming tt(xd) is installed in tt(/usr/bin) scripts can be defined around
tt(xd) for various shell programs. This allows the shell to change directories
under control of tt(xd).

    To use tt(xd) with the bf(bash)(1)-shell, the following function
can be used (which could be added to, e.g., tt(.bash_login)):
        verb(
  xd()                    # function to do `cd` using `xd`
  {
      cd "`/usr/bin/xd $*`"
  }
        )

    To use tt(xd) with the bf(tcsh)(1)-shell, the following alias
can be added to, e.g., the tt(~/.alias) file:
        verb(
  alias  xd  'cd `\xd \!*`'
        )
    If your system uses blanks in directory names, the above tcsh-alias cannot
be used as the blanks are interpreted as argument-separaters. In that case the
following alias can be defined:
        verb(
  alias  xd  'setenv XD "`\xd \!*`";cd "$XD"'
        )

    Having defined the tt(xd) alias or script tt(xd ...) commands results
in the automatic (or optional) change of the current working directory


manpagesection(EXAMPLES)

    verb(
    xd ulb      - all directories starting subsequently,
                  with u, l and b origin is default, or
                  specified in .xdrc as  home or root

    xd 0t       - all directories starting with t below the cwd

    xd 2t       - all directories starting at the `grandparent'
                  (2 steps up) of the cwd

    xd --start-at root t
                - all directories at the root starting with t

    xd ..       - all directories starting with a dot in the cwd

    xd .        - the user's home directory

    xd 0        - the current working directory

    xd 1        - the current directory's parent directory
    )
    Assuming the following directories exist:
    verb(
  /usr/lib/bonobo
  /usr/lib/bonobo-activation
  /usr/local/bin
    )
    then the following two tt(ignore) specifications in tt(xd)'s configuration
file will result in ignoring the tt(bonobo) directory alternatives:

    First specification:
    verb(
  ignore /usr/lib/bonobo
  ignore /usr/lib/bonobo-activation
    )
    Second specification:
    verb(
  ignore /usr/lib/bonobo*
    )

manpagefiles()
    itemization(
    it() bf($HOME/.xdrc): Default location of the configuration file
    it() tt(https://fbb-git.gitlab.io/xd/): Home directory
    )

manpagebugs()

    None reported

manpagesection(ABOUT xd)

    The program tt(xd) was initially (before 1994) written for the MS-DOS
platform. In 1994 it was redesigned to work under Unix (Linux, AIX) and it was
converted to bf(C++). The original bf(C++) code is still available from tag
tt(start) (tt(https://gitlab.com/fbb-git/xd/tags), find the tt(start) tag and
download) and is funny to look at as it is a remarkable illustration of
bf(C++) code written by bf(C) programmers who had just learned about
bf(C++). Versions tt(2.x) were used until 2008, and in late August 2008 I
rewrote tt(xd) completely, reflecting my then views about bf(C++), eventually
resulting in versions tt(3.x.y) and beyond. The tt(3.x.y) and later versions
extensively use the facilities offered by the bf(bobcat)(7) library.

manpagesection(ACKNOWLEDGEMENTS)

    GDS was added to tt(xd) following a suggestion by Bram Neijt (bram at
neijt dot nl).

manpageauthor()

Frank B. Brokken (f.b.brokken@rug.nl).
