---
 texmf/doc/man/man1/texdoc.1        |   25 
 texmf/doc/texdoc/News              |  113 +++
 texmf/doc/texdoc/texdoc.tex        |  756 ++++++++++++-------------
 texmf/scripts/texdoc/alias.tlu     |   95 +++
 texmf/scripts/texdoc/config.tlu    |  533 ++++++++++++++++++
 texmf/scripts/texdoc/constants.tlu |  115 +++
 texmf/scripts/texdoc/functions.tlu |  102 +++
 texmf/scripts/texdoc/main.tlu      |   37 +
 texmf/scripts/texdoc/score.tlu     |  266 ++++++++
 texmf/scripts/texdoc/search.tlu    |  369 ++++++++++++
 texmf/scripts/texdoc/texdoc.tlu    | 1094 +------------------------------------
 texmf/scripts/texdoc/view.tlu      |  176 +++++
 texmf/texdoc/texdoc.cnf            |  160 ++---
 tlpkg/texlive.tlpdb                |   11 
 14 files changed, 2319 insertions(+), 1533 deletions(-)

Index: texlive-base-2009/texmf/doc/man/man1/texdoc.1
===================================================================
--- texlive-base-2009.orig/texmf/doc/man/man1/texdoc.1	2009-10-08 21:57:15.000000000 +0900
+++ texlive-base-2009/texmf/doc/man/man1/texdoc.1	2010-01-03 11:23:46.000000000 +0900
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.36.
-.TH TEXDOC "1" "October 2009" "texdoc 0.47" "User Commands"
+.TH TEXDOC "1" "December 2009" "texdoc 0.61" "User Commands"
 .SH NAME
-texdoc \- finding & viewing TeX documentation
+texdoc \- find & view documentation in TeX Live
 .SH SYNOPSIS
 .B texdoc
 [\fIOPTIONS\fR]... [\fINAME\fR]...
@@ -13,9 +13,6 @@
 \fB\-f\fR, \fB\-\-files\fR
 Print the name of the config files being used.
 .TP
-\fB\-e\fR, \fB\-\-extensions\fR=\fIL\fR
-Require file extensions to be in the list L.
-.TP
 \fB\-w\fR, \fB\-\-view\fR
 Use view mode: start a viewer.
 .TP
@@ -23,13 +20,16 @@
 Use mixed mode (view or list).
 .TP
 \fB\-l\fR, \fB\-\-list\fR
-Use list mode: don't start a viewer.
+Use list mode: show a list of results.
 .TP
-\fB\-s\fR, \fB\-\-search\fR
-Search for name as a substring.
+\fB\-s\fR, \fB\-\-showall\fR
+Use showall mode: show also "bad" results.
 .TP
 \fB\-r\fR, \fB\-\-regex\fR
-Search for name as a lua regex.
+Use regex mode. (Deprecated.)
+.TP
+\fB\-e\fR, \fB\-\-extensions\fR=\fIL\fR
+Set ext_list=L. (Deprecated.)
 .TP
 \fB\-a\fR, \fB\-\-alias\fR
 Use the alias table.
@@ -46,8 +46,11 @@
 \fB\-v\fR, \fB\-\-verbosity\fR=\fIN\fR
 Set verbosity level to N.
 .TP
-\fB\-d\fR, \fB\-\-debug\fR
-Set verbosity level to maximum.
+\fB\-d\fR, \fB\-\-debug\fR[=\fIlist\fR]
+Activate debug for selected items (default all).
+.TP
+\fB\-M\fR, \fB\-\-machine\fR
+Use a more machine\-friendly output format.
 .SS "Environment:"
 .IP
 PAGER, BROWSER, PDFVIEWER, PSVIEWER, DVIVIEWER.
Index: texlive-base-2009/texmf/doc/texdoc/News
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/doc/texdoc/News	2010-01-03 11:23:27.000000000 +0900
@@ -0,0 +1,113 @@
+Version 0.61
+------------
+
+Detect desktop environments (KDE4, KDE, GNOME, XFCE) for viewer selection.
+
+Version 0.60
+------------
+
+Changed the search/alias/score logic. See section 2 of the manual for details,
+but here is a primer:
+- alias now /adds/ patterns to be search, it is no more a substitution
+- new scoring system, partially confugurable, with improved heuristics
+
+The beginning of the manual has been completely rewritten.
+
+Bug have been fixed as usual, and probably some others introduced...
+
+Version 0.50
+------------
+
+- New option for machine-readable output.
+- Bugfixes (esp. for zipped file support (Unix only)).
+- Hopefully more sensible default viewer selection.
+
+Version 0.49
+------------
+
+Major code rewrite. No big user-visible change, except a few bugs fixed and new
+debugging levels.
+
+Version 0.47 (TeX Live 2009)
+----------------------------
+
+Improve support for zipped documentation and comments about it in the default
+configuration file. (Thank Norbert Preining for his help.)
+
+Version 0.46
+------------
+
+Avoid using lfs.currentdir() and lfs.chdir() which are broken on Solaris 10 
+in LuaTeX 0.40
+
+Version 0.45
+------------
+
+Fix possible line ending problems on windows with certain versions of LuaTeX
+
+Version 0.44
+------------
+
+- fixing viewer problems on Windows
+- expanding the list of default viewers on generic Unix
+
+
+Version 0.43
+------------
+
+Various fixes, aliases updates as usual.
+
+Version 0.42
+------------
+
+Improvements to default txt viewer on Windows (thanks to Phil Taylor).
+
+New debugging levels; new names for debugging options.
+
+New configuration file allowing to run the development version more easily.
+
+Changes to the way files are displayed. Results are numbered even when -I is
+used.
+
+Documentation update.  Alias additions and fixes as usual. Various bugfixes.
+
+License switched to GPL.
+
+Version 0.4 (TeX Live 2008)
+---------------------------
+
+Use our own configuration files, not texmf.cnf. Rework the way viewers are
+handled, and add a few configuration options.
+
+Add an 'alias' feature. Filter results in a more restrictive way. Add new search
+modes 'mixed' and 'regex'. Turn result lists into menus.
+
+Add a user manual in pdf.
+
+Development passed from Frank Küster to Manuel Pégourié-Gonnard.
+
+Version 0.3
+-----------
+
+Various changes including:
+- added changelog
+- better OS detection for default viewer settings
+- removed some debugging code
+- -s now works in dirs without ls-R, too
+
+Version 0.2
+-----------
+
+Various changes including:
+- implemented reading of configuration from texmf.cnf
+- fixed "-s" option
+
+Version 0.1
+-----------
+
+Initial public release of the texlua version by Frank Küster.
+
+Earlier versions
+----------------
+
+Shell script by Thomas Esser maintained as part of teTeX.
Index: texlive-base-2009/texmf/doc/texdoc/texdoc.tex
===================================================================
--- texlive-base-2009.orig/texmf/doc/texdoc/texdoc.tex	2009-10-12 07:55:36.000000000 +0900
+++ texlive-base-2009/texmf/doc/texdoc/texdoc.tex	2010-01-03 11:21:01.000000000 +0900
@@ -2,20 +2,24 @@
 % written by Manuel Pgouri-Gonnard in 2008, 2009
 % distributed under the terms of GPL v3 or later
 
+%!TEX encoding=latin1
+%!TEX program=pdflatex
+
+\setlength\overfullrule{5pt}
+
 \documentclass[a4paper, oneside]{scrartcl}
 \usepackage[latin1]{inputenc}
 \usepackage[T1]{fontenc}
 \usepackage{textcomp}
 \usepackage{fixltx2e}
 
-\usepackage{lmodern} \edef\ttmodern{\ttdefault}
-\usepackage[osf]{mathpazo}
-\renewcommand\sfdefault{uop} % optima
-\renewcommand\ttdefault{lmvtt} % lm tt proportional
+\usepackage{tgbonum}
+\usepackage{tgheros}
+\usepackage[scaled=1.10]{inconsolata}
 \renewcommand\familydefault{\sfdefault} \normalfont
 \newcommand\otherfamily{\rmfamily}
-\newcommand\mylangle{\textlangle}
-\newcommand\myrangle{\textrangle}
+\newcommand\mylangle{$\langle$}
+\newcommand\myrangle{$\rangle$}
 
 \usepackage{xargs, xspace, fancyvrb, xcolor, pifont, calc, ifmtarg, mathstyle}
 
@@ -23,7 +27,8 @@
 \titlelabel{\makebox[0pt][r]{\thetitle\kern1pc}}
 \titleformat{\subsubsection}[runin]{\otherfamily\itshape}{%
   \makebox[0pt][r]{\thetitle\kern1pc}}{%
-  0pt}{}[\maybedot\space --- ]
+  0pt}{}[\maybedot\space --- \kern0pt]
+\titlespacing{\subsubsection}{0pt}{0.5\baselineskip}{0pt}
 
 \usepackage{enumitem}
 \newlength\lssep \setlength\lssep{\smallskipamount}
@@ -34,7 +39,7 @@
 \usepackage[bookmarks=true]{hyperref}
 \hypersetup{%
   bookmarksnumbered=true, bookmarksopen=true, bookmarksopenlevel=2,
-  pdftitle=texdoc: finding and viewing TeX documentation,
+  pdftitle=texdoc: find and view documentation in TeX Live,
   pdfauthor=Manuel Pgouri-Gonnard,
   pdfsubject=texdoc's user manual,
   pdfkeywords={texdoc, TeX Live, manual}}
@@ -62,8 +67,6 @@
 \definecolor{input}{rgb}{1.0,0,0}
 \newcommand\inputcolorname{red}
 \hypersetup{colorlinks=true, linkcolor=links, urlcolor=links, citecolor=links}
-\newcommand\textpa[1]{% % noms d'extensions (package)
-  {\normalfont\color{special}\otherfamily #1}}
 \newcommand\cofont{% % code
   \color{code}\normalfont\ttfamily}
 \newcommand\textco[1]{{\cofont#1}}
@@ -78,7 +81,7 @@
 \newcommand\file{\nolinkurl}
 
 % take care of nbsp
-\catcode`\10\relax
+\catcode`\ 10\relax
 
 \newcommand\meta[1]{% % variantes  remplacer
   {\color{special}\mylangle\textme{#1}\myrangle}}
@@ -138,296 +141,286 @@
   }{%
   \endcommandes}
 
+\makeatletter
 \newenvironment{htcode}{% % code en hors-texte
   \SaveVerbatim[samepage, gobble=2]{verbmat}%
   }{%
   \endSaveVerbatim
   \par\medskip\noindent\hspace*{\parindent}%
   \BUseVerbatim{verbmat}%
-  \par\medskip}
+  \par\medskip\@endpetrue}
+\makeatother
 \DefineShortVerb{\}
 
 \setkomafont{title}{}
 \setkomafont{subtitle}{\Large}
 \deffootnote[1.5em]{1.5em}{1em}{\textsuperscript{\thefootnotemark}\thinspace}
 
-\newcommand\texdoc{\textpa{texdoc}\xspace}
+\newcommand\texdoc{texdoc\xspace}
+\newcommand\tdml{\href{mailto:texdoc@tug.org}{texdoc mailing list}\xspace}
 
 \title{\texdoc}
-\subtitle{Finding \& viewing \TeX documentation
-  }
+\subtitle{Find \& view documentation in \TeX\ Live}
 \author{\url{http://tug.org/texdoc/}\\
   Manuel Pgouri-Gonnard}
-\date{v0.47 2009-10-12}
+\date{v0.60 2009-11-24}
 
 \begin{document}
 \VerbatimFootnotes
 
 \maketitle
 
-\section{Basic Usage, Modes}\label{s-basics}
+\section{Quick guide}
 
-\begin{cmdsubsec}{Normal (view) mode}{ss-view}
-  texdoc name
-\end{cmdsubsec}
-
-The simplest way to use \texdoc is just to type\footnote{In a command line.  If
-  you don't know how to open one, look for Start$\to$Execute and type cmd on
-  Windows, or use the ``terminal'' icon on Mac OS X.  If you are using another
-  flavour of Unix, you probably know what to do.} texdoc followed by the
-name of the package whose documentation you want to read.  It usually finds
-the documentation for you and opens it in the appropriate reader.  That's it:
-easy and usually fast.  The rest of this manual describes what to do if
-this doesn't work exactly as you like and you want to customise things, and
-how to do more extensive searchs.
-
-Before the description of \texdoc's different modes, just a word words about
-the typographic conventions in this manual.  Things like name in the above
-title mean that they should be replaced by what you actually want.  For
-example, if you want to read \package{hyperref}'s manual, type
-texdochyperref.  Sometimes there will be complete examples like this:
-
-\begin{htcode}
-   texdoc -s babelbib 
-  1 /usr/local/texlive/2008/texmf-dist/doc/latex/babelbib/babelbib.pdf
-  2 /usr/local/texlive/2008/texmf-dist/doc/latex/babelbib/tugboat-babelbib.pdf
-  3 /usr/local/texlive/2008/texmf-dist/doc/latex/babelbib/ChangeLog
-  4 /usr/local/texlive/2008/texmf-dist/doc/latex/babelbib/README
-  Please enter the number of the file to view, anything else to skip: 2
-\end{htcode}
+\subsection{Basics}
 
-In this case, what you actually type is in \textcolor{input}{\inputcolorname},
-and the funny symbol \textco{\prompt} represents your shell's prompt, which
-can actually be something like C:\> or name@host:~% or funnier.
+Open a command line\footnote{On windows, use ``Execute'' from the Start menu
+  and type cmd.  On Mac OS X, use the ``terminal'' icon on Mac OS X.  If you
+  are using another flavour of Unix, you probably know what to do.} and type
+texdoc name: the documentation of the name package will pop up. Of
+course, replace name with the actual name of the package you want to learn
+about. You can also look for the documentation of more than one package at
+once: just give many names as arguments.
+
+The rest of this section describes the most usual options, like how to
+see all documentation related to a package or use a different viewer.
+
+\subsection{Modes}\label{ss-modes}
+
+\texdoc has different modes that determine how results will be handled. The
+default mode, called ``view'' mode, is to open the first (supposedly the best)
+result in a viewer. It is rather handy when you know what you want to read,
+and want to access it quickly. On the other hand, there may be other relevant
+documents for the given name, which are ignored in view mode.
+
+The so-called ``list mode'' makes \texdoc list all relevant documentation and
+ask you which one you want to view. It is useful when there a other
+interesting sources of information besides the package's main documentation.
+
+There is also a ``mixed'' mode, intended to combine the best of view mode and
+list mode: if there is only one relevant result, then \texdoc opens it in a
+viewer, else it offers you a menu.
+
+Usually, \texdoc shows you only results it considers relevant. If there are no
+``good'' results, it falls back to less relevant results. You can force
+\texdoc to show you also ``bad'' results even when there are good ones by
+using the ``showall'' mode. (This implies using a menu rather than starting a
+viewer.)
+
+You can select with command-line options: use texdoc option name with
+one of the following options: -w or --view for view mode, -m or
+--mixed for mixed mode, -l or --list for list mode, -s or --showall
+for showall mode.
+
+If you always (or mostly) use the same mode, it is probably easier to
+select it in a configuration file than to always use the command-line
+option. For this, see the next section.
+
+\subsection{Configuration files}\label{ss-quick-file}
+
+\texdoc use various configuration files, which you can see using the -f or
+--files options. The second entry in this list is marked with a star (*):
+it is the file you should use for your personal preferences as a user; you may
+need to create it (and the parents directories).
+
+In order to select you favorite mode, just insert a line mode = yourmode
+in this files, where yourmode is one of view, mixed, list or
+showall.
+
+The configuration files can be used to tweak \texdoc in many ways, the most
+useful of which is probably the selection of the viewers for various types of
+documents, explained in the next section.
+
+\subsection{Viewers}
+
+\texdoc's mechanism for choosing a viewer varies according to your platform.
+On Windows and MacOS, it uses your file associations like when you
+double-click files in the Explorer or the Finder (except for the text viewer,
+which is always a pager). On Unix, it tries to find a viewer in the path from
+a list of ``known' viewers.
+
+You may want to select a different viewer for some kind of file. This is
+achieved by the various viewer_ext configuration options, where ext is
+the extension corresponding to the file type. For example, if you want to set
+xpdf as your default PDF viewer, and run it in the background, insert the line
+viewer_pdf = xpdf %s & in your configuration file. Here, %s stands for the
+name of the file to view.
+
+\subsection{Conclusion}
+
+We have now covered the most common needs. The next part explains
+how \texdoc proceeds to find the best results.
+The default configuration file tries hard to set appropriate values so that
+you have a good out-of-the-box experience, but you may want to understand the
+underlying mechanisms and adapt them to your needs. The final part is a full
+reference for configuration options, including points omitted in the present
+part.
+
+Your feedback is very welcome of the \tdml. Feel free to post comments, bug
+reports, suggestions for improvements (inc. new aliases), even without
+subscribing.
+
+\clearpage
+
+\section{File search, aliases, score}
+
+\subsection{An overview of how texdoc works}
+
+When you type texdoc keyword, texdoc browses the trees containing
+documentation (given by the \href{http://www.tug.org/kpathsea/} {kpathsea}
+variable TEXDOCS), lists all files containing keyword in their name
+(including the directory name) and give them a score based on some simple
+heuristics. For example, a file named keyword.pdf, will get a high score,
+keyword-doc will be preferred over keywordwhatever, files in a
+directory named exactly keyword get a bonus, etc.
+
+There is also some filtering based on extensions: only files with known
+extensions are listed, and some extensions get a lesser score. Also, there is
+some score adjustments based on keywords; by default, Makefile's get a very
+bad score since they are almost never documentation.\footnote{They often end
+  up in the doc tree, since the source of documentation is often in the same
+  directory as the documentation itself in \TeX\ Live. Other source files are
+  discriminated by extension.}
+
+Then, depending on the mode, the file with the highest score is opened in a
+viewer, or the list of results is shown. Usually, only results with a positive
+score are displayed, except in showall mode. Result with very bad score (-100
+and below) are never displayed.
+
+\medskip
+
+However, this model works only if the documentation for keyword has
+keyword in its name, which is not always true. The documentation of the
+memoir class is in memman.pdf, for example, but it will be found anyway
+since it is in a directory named memoir. But there are more complicated cases:
+the documentation for mathptmx is in psnfss2e.pdf, which is quite more
+complicated to guess.\footnote{But not totally impossible: using the \TeX\
+  Live database, texdoc can know which documentation files are associated with
+  a given .sty file. Here, it could guess that the documentation is either
+  psfonts.pdf of psnfss2e.pdf. This will probably be done in a future
+  version.}
+
+Here comes the notion of \emph{alias}: in the default configuration file,
+mathptmx is aliased to psnfss2e, so that when you type texdoc mathptmx,
+texdoc knows it has to look also for psnfss2e. Note that texdoc will also look
+for the original name, and that a name can be aliased to more than one new
+name (this is new in texdoc 0.60).
 
-\bigskip
+\medskip
 
-\texdoc's normal mode of operation is to find the more appropriate document
-for your request and open it. But sometimes it has a weird notion of
-``appropriate'', and you'd better look at the list of all results and choose
-to see oen or more of them. For this, \texdoc offers various modes, like the
-``search mode'' illustrated above.
-
-\begin{cmdsubsec}{Search mode}{ss-search}
-  texdoc -s name 
-  texdoc --search name
-\end{cmdsubsec}
-
-With the two (equivalent) commands above, \texdoc also looks for documentation
-for name, but using the \emph{search mode}, which differs from the
-normal mode (called \emph{view mode}) on two points:
-\begin{itemize}
-  \item It doesn't start a viewer and offers you a \emph{menu} instead.
-  \item It always do a \emph{full search}.
-\end{itemize}
-The first point is rather straightforward on the example.  The second deserves
-more explanation. 
+We will soon see how you can configure this, but let's give a few definitions
+about how a file can match keyword first (all matching is case-insensitive):
+\begin{enumerate}
+  \item The keyword is a substring of the file name.
+  \item The keyword is a ``subword'' of the file name; words are defined as a
+    sequence of alphanumeric characters delimited by punctuation characters
+    (there is no space in file names in \TeX\ Live) and a subword is a
+    substring both ends of which are a word boundary.
+  \item The keyword can match ``exactly'' the file name: that is, the file
+    name is the keyword + and extension.
+\end{enumerate}
 
-Usually, \texdoc looks for files named name.pdf or name.html etc. (see
-\ref{cf-ext_list}), where name means what you asked for, in \texlive's
-documentation directories, and if cannot find such a file, it tries a full
-search: it finds all files which have name in their name, or in the
-directory's name.  In search mode, \texdoc always performs a full search.
-
-Now look carefully at the previous example.  The purpose of search mode is to
-allow you to find related documentation, such as the
-\href{http://www.tug.org/TUGboat/}{TUGboat} article on \package{babelbib},
-which you might want to read, whereas in normal mode \texdoc offers you no
-choice and just displays the user manual babelbib.pdf.  On the other hand,
-the view mode is much faster when you know exactly what you want to read.
-
-To try and make you happy, \texdoc offers two other modes, introduced below.
-
-\begin{cmdsubsec}{List mode}{ss-list}
-  texdoc -l name
-  texdoc --list name
-\end{cmdsubsec}
-
-The \emph{list mode} uses a normal search, but forces \texdoc to give you a
-menu instead of choosing itself the documentation to display.  It is usefull
-when there are many files with the same name but different contents, or many
-versions of the same file on your system. 
+\subsection{Alias directives}\label{ss-alias}
 
 \begin{htcode}
-   texdoc -l tex 
-  1 /usr/local/texlive/2008/texmf/doc/man/man1/tex.pdf
-  2 /usr/local/texlive/2008/texmf-doc/doc/english/knuth/tex/tex.pdf
-  Please enter the number of the file to view, anything else to skip: 
+  alias original keyword = name
+  alias(score) original keyword = name
 \end{htcode}
 
-Here the first file is the manual page\footnote{converted in pdf.  To allow
-  texdoc to find and display real man pages in man format,
-  see~\ref{cf-ext_list}.} of the tex command, while the second is \TeX{}'s
-documented source code\dots
-
-\begin{cmdsubsec}{Mixed mode}{ss-mixed}
-  texdoc -m name
-  texdoc --mixed name
-\end{cmdsubsec}
-
-As the name says, \emph{mixed mode} is an attempt to provide you the best of
-the normal (view) and list modes, by mixing them in the following way:  If
-only one file is found, then \texdoc opens it, and if many are found, it
-displays a menu to let you choose.  You may want to make this mode the
-default, see~\ref{cf-mode}.
-
-\begin{cmdsubsec}{What's a <name>?}{ss-name}
-  texdoc name1 name2 ...
-  texdoc name.ext
-\end{cmdsubsec}
-
-To conclude this section on basics, let us just mention two points concerning
-the name in all previous sections.  Is is usually a single name without
-extension, but you can also use many names at once: then, depending on the
-mode, \texdoc will either open all the corresponding documentation or show you
-menus for each of the names you mentioned.  For each name, you can also
-specifiy the file exention\footnote{It should be an allowed extension,
-  see~\ref{cf-ext_list}, and preferably have a associated viewer defined,
-  see~\ref{cf-viewer_*}.} if you want, eg texdoc texlive-en.html lets you
-read the \texlive manual in html rather than in pdf format.
-
-\bigskip
-
-You can now stop reading this manual unless you have special needs.  If you
-want to understand the curious aliased too messages that you will sometimes
-see, and control them, read section~\ref{s-alias}.  If you have problems
-viewing certain type of files or want to choose you preferred reader, look at
-section~\ref{s-viewer}.  Finally, section~\ref{s-ref} is the full
-reference concerning \texdoc configuration: while you probably don't want to
-read it all at once, you can consult~\ref{cf-mode} if you want to select your
-preferred mode and make it the default.
-
-Finally, be aware of the -h or --help option which provides you a quick
-reminder of all available command-line options.
-
-\section{Aliases, or name substitution}\label{s-alias}
-
-\subsection{Basic concept}\label{ss-alias-basics}
-
-The usual search modes of \texdoc assume that the name of the documentation
-file is the name of the package, or contains it (at least in the directory
-name).  However, this is not always true, due either to the author choosing a
-fancy name, or packaging peculiarities.  To try helping the user to find the
-doc even in these cases, \texdoc provides an alias mechanism and comes with a
-list of circa 200 pre-defined aliases.
-
+You can define your own aliases in \texdoc's configuration files
+(see~\ref{ss-quick-file} or \ref{ss-prec}). For example,
+insert\footnote{Actually, you don't need to do this, the default configuration
+  file already includes this directive.}
 \begin{htcode}
-   texdoc -l geometry 
-  texdoc info: geometry aliased to geometry/manual.pdf
-  1 /usr/local/texlive/2008/texmf-dist/doc/latex/geometry/manual.pdf
-  Please enter the number of the file to view, anything else to skip: 0
+  alias mathptmx = psnfss2e
 \end{htcode}
+in order to alias mathptmx to psnfss2e. Precisely, it means that files
+matching exactly psnfss2e will be added to the result list when you look for
+mathptmx, and get a score of 10 (default score for alias results). This is
+greater than the results of heuristic scoring: it means that results found via
+aliases will always rank before results associated to the original keyword.
+
+If you want the results associated to a particular alias to have a custom
+score instead of the default 10, you can use the optional argument to the
+alias directive. This can be usefull if you associate many aliases to
+a keyword and want one of them to show up first.
+
+You can have a look at the configuration file provided (the last shown by
+texdoc -f) for examples.  If you feel one of the aliases you defined locally
+should be added to the default configuration, please share it on the \tdml.
+
+Please note than aliasing is case-insensitive, and the aliases don't cascade:
+only aliases associated to the original keyword are used.
+Aliases are additive: if you define your own aliases for a keyword in your
+configuration file, and there are also aliases for the same keyword in the
+default configuration, they will add up. You can prevent the default aliases
+from begin applied for a particular keyword by saying stopalias keyword in
+your personal configuration file. It will keep the aliases defined before
+this directive (if any) and prevent all further aliasing on this keyword.
+
+If, for some reason, you want to prevent any alias from begin used for one
+particular session of texdoc, you can use the -A or --noalias command-line
+option (see~\ref{cl-a}).
 
-The concept of alias is very\footnote{See~\ref{ss-alias-rem} for why it is
-  actually \emph{too} simple.} simple: as you can see of the above example,
-when you type and geometry is aliased to geometry/manual.pdf, then
-everything happens as if you actually typed texdocgeometry/manual.pdf
-(without any further alias substitution), and \texdoc informs you that
-something happened so you can understand the results
-(see~\ref{cf-verbosity_level} to get rid of this message):
-
-\begin{cmdsubsec}{Command line options}{ss-alias-cl}
-  texdoc -a options name
-  texdoc --alias options name
-  texdoc -A options name
-  texdoc --noalias options name
-\end{cmdsubsec}
-
-By default, aliased are used in view, list and mixed modes, and disabled in
-search mode. But you may want to disable it, because the default alias doesn't
-do what you want\footnote{In this case, please report it to
-  \mailto{texdoc@tug.org}, so that the faulty alias can be updated.} or for
-another reason.  In this case, you just have to add -A or --noalias to the
-options, like:
+\subsection{Score directives}\label{ss-score}
 
 \begin{htcode}
-   texdoc -A -l geometry 
-  1 /usr/local/texlive/2008/texmf-doc/doc/polish/tex-virtual-academy-pl/
-  latex2e/macro/geometry.html
-  Please enter the number of the file to view, anything else to skip: 0
+  adjscore pattern = score adjustment
+  adjscore(keyword) pattern = score adjustment
 \end{htcode}
 
-On the contrary, you can force aliasing in search mode by using the -a or
---alias option, though it may not prove very useful.
-
-\subsection{Your own aliases}\label{ss-alias-own}
-
-You can define your own aliases, or override the default ones, in \texdoc's
-configuration files. You can get a list of those files by typing texdoc-f.
-For personal aliases, it is recommended that you use the second file, marked
-by a star (see~\ref{ss-prec} for details). You'll probably need to
-create in and one or two of the directories containing it.
+It is possible to adjust the score of results containing some pattern as a
+subword, either globally (for the result of all searches) or only 
+when searching with a particular keyword. This is done in the
+configuration file (\ref{ss-quick-file} or \ref{ss-prec}) using the 
+adjustscore directive. Here are a few examples from the default
+configuration file.
 
-Creating an alias is easy: you just insert a line like 
 \begin{htcode}
-  alias geometry = geometry/manual.pdf
+  adjscore /Makefile = -1000
+  adjscore /tex-virtual-academy-pl/ = -50
+  adjscore(tex) texdoc = -10
 \end{htcode}
-in your configuration file, and it's all.  You can have a look at the
-configuration file provided (the last one showed by texdoc-f) for examples.
-If you want to permanently unalias something, just insert a line
-name=name: it will overwrite the previous alias.
-
-\subsection{Remarks on aliases}\label{ss-alias-rem}
-
-Please be aware that this alias feature, or at least its intensive use to try
-to find the ``right'' documentation for a given package, should be temporary.
-Indeed, one problem is that currently aliases do \emph{hide} other files, while
-it is desirable that they just \emph{add} results in some case. However,
-defining a coherent behaviour (and how to maintain the needed database)
-requires work and time, and is therefore reported to future versions.
-
-In this vein, it would be desirable to have a notion of ``category'', like
-user documentation of a package, or man page of a program, or reference manual
-of a program, or documented source code of a package or program, or\dots If
-you have ideas about desirable categories and ways they should be handled,
-feel free to share them at the usual address.
-
-\section{Viewer selection}\label{s-viewer}
-
-A list of default viewers is defined in \texdoc, depending on your platform
-(Windows, MacOS X, other Unix). On Windows and MacOS, it uses your file
-associations like when you double-click files in the Explorer or the Finder.
-On Unix, it tries to find a viewer in the path from a list of ``known'
-viewers.
-
-If you want to use another viewer, you have two ways of telling this to
-\texdoc: in your configuration file or using environment variables.  If you
-hesitate, the configuration file is the recommended way.
-
-To find your configuration file, type texdoc-f and pick the file marked
-with a star (unless you are a system administrator or your home is shared
-between many machines whith different architectures, see~\ref{ss-prec}); you
-may need to create the file and a few directories. Then you can add lines
-like:
 
-\begin{htcode}
-  viewer_pdf = (xpdf %s) &
-  viewer_txt = less
-\end{htcode}
+All files named Makefile (and also files names Makefile-foo if there are
+any): are ``killed'' : by adjusting their score with such a large negative
+value, their final score will most probably be less than -100, so they will
+never be displayed. Files from the tex-virtual-academy-pl directory, on the
+other hand, are not killed but just get a malus, since they are a common
+source of ``fake'' matches which hide better results (even for the lucky ones
+who can read polish).
+
+The third directive gives a malus for results containing texdoc only if the
+search keyword is tex. Otherwise, such results would get a high score
+because the heuristic scoring would think texdoc is the name of \TeX's
+documentation. The value -10 is enough to ensure that those results will have
+a negative score, so wil not be displayed unless ``showall'' mode is active.
+
+\textbf{Warning}: Values of scores (like the default score for aliases, the
+range of heuristic scoring, etc.) may change in a future version of texdoc.
+Scoring is quite new and may need some adjustments. So, don't be surprised if
+you need to adapt your scoring directives after a future update of texdoc.
+This warning will disappear at some point.
+
+\subsection{File extensions}
+
+The allowed file extensions are defined by the configuration item ext_list
+(default: pdf, html, txt, ps, dvi, no extension). You can configure it with
+a line ext_list = your, list in a configuration file. Be aware
+that it will completely override the default list, not add to it. An empty
+string in the list means files without extension (no dot in the name), while a
+star means any extension.
+
+For scoring purposes, there is also a badext_list parameter: files whose
+extension is ``bad'' according to this list will get a lesser score (currently
+0). This only affect heuristic scoring (results found from the original
+keyword, not from aliases).
+
+\clearpage
 
-Here the %s stands for the name of the file to view. The first line sets
-xpdf as the pdf viewer, and use a bit of shell syntax to force it to run in
-the background (the () are here for compatibility with zip support,
-see~\ref{s-bugs}). The second line sets less as the text viewer: it doesn't
-use %s, which means the filename will be placed at the end of the command.
-
-The default extensions allowed are pdf, html, txt, dvi, ps, and no
-extension.  The txt viewer is used for files without extension.
-See~\ref{cf-ext_list} for how to allow for more extensions.
-
-The corresponding environment variables are PDFVIEWER, BROWSER, PAGER,
-DVIVIEWER, PSVIEWER. They follow the same convention as values from the
-configuration files, and override them if they are set. Since some of those
-variable are shared by other programs, you can override them just for \texdoc
-by adding _texdoc at the end, like in BROWSER_texdoc.
-
-\section{Full reference}\label{s-ref}
-
-The most useful command-line options, configuration values and all
-environment variables have been presented.  Here we complete our presentation
-and review all in a systematic way.
+\section{Full reference}
 
-\subsection{Precedence}\label{ss-prec}
+\subsection{Precedence of configuration sources}\label{ss-prec}
 
 Values for a particular setting can come from several sources. They are treated
 in the following order, where first value found is always used:
@@ -460,9 +453,10 @@
 
 \subsection{Command-line options}\label{ss-cl}
 
-Most of the command-line options correspond to an option that can be set from
-the config files. For them, we refer the reader to the description of the
-corresponding configuration option. 
+All command-line options (except the first three below) correspond to
+configuration item that can be set in the configuration files: we refer
+the reader to the corresponding section for the meaning of this configuration
+item.
 
 \begin{cmdsubsub}{-h, --help}{cl-h}
   -h, --help
@@ -471,7 +465,7 @@
 Shows a quick help message (namely a list of command-line options) and exits
 successfully.
 
-\begin{cmdsubsub}{-V, --version}{cl-v}
+\begin{cmdsubsub}{-V, --version}{cl-V}
   -V, --version
 \end{cmdsubsub}
 
@@ -482,56 +476,67 @@
 \end{cmdsubsub}
 
 Shows the list of the configuration files for the current installation and
-platform, with their status (active or not found) and a star marking the
-recommended file for user settings.
+platform, with their status (active, not found, or disabled
+(see~\ref{cf-lastfile_switch})) and exits successfully.
 
-\begin{cmdsubsub}{-w, -l, -m, -s, -r, --view, --list, --mixed, --search,
+\begin{cmdsubsub}{-w, -l, -m, -s, -r, --view, --list, --mixed, --showall,
     --regex}{cl-mode}
-  -w, --view, -l, --list, -m, --mixed, -s, --search, -r, --regex
+  -w, --view, -l, --list, -m, --mixed, -s, --showall, -r, --regex
 \end{cmdsubsub}
 
-See~\ref{cf-mode}.
+\hfill Set mode to the given value, see~\ref{cf-mode}.
 
 \begin{cmdsubsub}{-a, -A, --alias, --noalias}{cl-a}
   -a, --alias, -A, --noalias
 \end{cmdsubsub}
 
-See~\ref{s-alias}.
+Set alias_switch true (resp. false), see~\ref{cf-alias_switch}
 
 \begin{cmdsubsub}{-i, -I, --interact, --nointeract}{cl-i}
   -i, --interact, -I, --nointeract
 \end{cmdsubsub}
 
-See~\ref{cf-interact}.
+Set interact_switch to true (resp. false), see~\ref{cf-interact_switch}.
 
 \begin{cmdsubsub}{-e, --extensions}{cl-e}
   -e=l, --extensions=l
 \end{cmdsubsub}
 
-See~\ref{cf-ext_list}.  \emph{But} be aware that on the command line there
-should be no space at all, neither in the list (unless quoted according to you
-shell's convention) not between the -e or --extension option, the equal
-sign, and the list.  Also take care to quote the special value * if
-necessary.  The equal sign is optional.
-
-\begin{cmdsubsub}{-v, --verbosity, -d, --debug}{cl-n}
-  -v=n, --verbosity=n, -d, --debug
+Set ext_list, see~\ref{cf-ext_list}. \textbf{Warning}: this command-line
+option is deprecated and will likely be removed soon. It is recommended to set
+ext_list in a configuration file instead. Please protest on the \tdml if you
+want to keep this command-line option.
+
+\begin{cmdsubsub}{-v, --verbosity}{cl-v}
+  -v=n, --verbosity=n
+\end{cmdsubsub}
+
+Set verbosity_level to n, see~\ref{cf-verbosity_level}. Be aware that you
+must avoid spaces on the command line, and the = sign is optional.
+
+\begin{cmdsubsub}{-d, --debug}{cl-d}
+  -d, -d=list, --debug, --debug=list
 \end{cmdsubsub}
 
-See~\ref{cf-verbosity_level} and be aware that you must avoid spaces on the
-command line, and the = sign is optional. The --debug option sets
-verbosity at the maximum level.
+Set debug_list, see~\ref{cf-debug_list}. If not list is given, activates all
+available debug items.
+
+\begin{cmdsubsub}{-M, --machine}{cl-M}
+  -M, --machine
+\end{cmdsubsub}
+
+Set machine_switch to true, see~\ref{cf-machine_switch}.
 
 \subsection{Environment variables}\label{ss-envvar}
 
 They all correspond to some viewer_ext setting, and the reader is referred
-to~\ref{s-viewer} and~\ref{cf-viewer_*} for details. Also, environment
-variables used by older versions of \texdoc are accepted. You can append
-_texdoc to every name in the first column: this wins over every other name.
+to~\ref{cf-viewer_*} for details. Also, environment variables used by older
+versions of \texdoc are accepted. You can append _texdoc to every name in
+the first column: this wins over every other name.
 
 \begin{center}
-  \begin{tabular}{@{}l*3{@{ }l}@{}}
-    New name    & Old name 1        & Old name 2           & Config. param.\\
+  \begin{tabular}{*4l}
+    New name    & Old name 1        & Old name 2           & Config. item\\
     PAGER     & TEXDOCVIEW_txt  & TEXDOC_VIEWER_TXT  & viewer_txt  \\
     BROWSER   & TEXDOCVIEW_html & TEXDOC_VIEWER_HTML & viewer_html \\
     DVIVIEWER & TEXDOCVIEW_dvi  & TEXDOC_VIEWER_DVI  & viewer_dvi  \\
@@ -540,69 +545,69 @@
   \end{tabular}
 \end{center}
 
-\subsection{Configuration files}\label{ss-conf}
+\subsection{Configuration items}\label{ss-conf}
 
-\subsubsection{General structure}\label{sss-sonf-struct}
+\subsubsection{Structure of configuration files}\label{sss-sonf-struct}
 
 Configuration files are line-oriented text files. Comments begin with a #
 and run to the end of line. Lines containing only space are ignored. Space at
 the beginning or end of a line, as well as around an = sign, is ignored.
 Apart from comments and empty lines, each line must be of one of the following
-forms:
+forms.
 
 \begin{htcode}
-  config_param = value
-  alias name = target
+  configuration item = value
+  alias original keyword = name
+  alias(score) original keyword = name
+  stopalias original keyword
+  adjscore pattern = score adjustment
+  adjscore(keyword) pattern = score adjustment
 \end{htcode}
 
-where config_parameter consists of only letters, digits or - signs,
-name of letters, digits, - and _ signs. value and target are
-free strings (except that not every value is valid for every
-config_param, see below) and nothing in it need not be quoted (actually,
-quotes will be interpreted as part of the value, not as quotation marks).
-
-Lines which do not obey these rules raise a warning. However, unrecognised
-values of config_param raise no warning at the moment.
+We will concentrate on the configuration item part here, since other
+directives have already been presented (\ref{ss-alias} and \ref{ss-score}).
 
-The value is usually interpreted as a string, except when config_param
-ends with:
+In the above, value  never needs to be quoted: quotes would be interpreted
+as part of the value, not as quotation marks (this also holds for the other
+directives).
+
+Lines which do not obey these rules raise a warning, as well as unrecognised
+values of configuration item. The value can be an arbitrary string,
+except when the name of the configuration item ends with:
 \begin{enumerate}
   \item _list, then value is a coma-separated list of strings. Space
     around commas is ignored. Two consecutive comas or a coma at the beginning
     or end of the list means the empty string at the corresponding place.
   \item _switch, then value must be either true or false
-    (case-sensitive).
-  \item _level, then value is a non-negative integer.
+    (lowercase).
+  \item _level, then value is an integer.
 \end{enumerate}
+In these cases, an improper value will raise a warning too.
 
 \begin{cmdsubsub}{mode}{cf-mode}
-  mode = view, list, mixed, search, regex
+  mode = view, list, mixed, showall, regex
 \end{cmdsubsub}
-Set the  mode to the given value.  Default is view.  The first three values
-view, list, mixed use the same searching method: first search a file
-whose name is the name on the command line and whose extension is in
-ext_list (see~\ref{cf-ext_list}), and if nothing is found, then do a full
-search.  This means that a file matches if name is a substring of its
-path+name (and its extension is in the list). Here path does not mean the full
-path, but only the part below TEXMF/doc. The search mode forces a full
-search.
-
-The last mode, regex, looks for name in the path+filename as a Lua
-regex.  If you don't know Lua regexes you should be aware that the escape
-character is % and the - sign is a special character (which means the same
-as *? in Perl regexes).  For more details, see the Lua
-\href{http://www.lua.org/manual/}{reference manual} or the book
-\href{http://www.lua.org/pil/}{\emph{programming in Lua}}.  You might want to
-use\footnote{The quotes in the example are just to make the shell happy.}
--e='*' if your regex uses the $ anchor.%stopzone
+Set the  mode to the given value.  Default is view. All mode except regex
+have been presented in~\ref{ss-modes}.
 
-\begin{cmdsubsub}{interact}{cf-interact}
+In regex mode, the given name is interpreted as a Lua regex, and only files
+whose full name (including path) matches it are found. Alias and score
+mechanisms are disabled.  \textbf{Warning}: this mode is deprecated and will
+likely be removed soon.  Please protest on the \tdml if you want it to stay.
+
+\begin{cmdsubsub}{interact}{cf-interact_switch}
   interact_switch = true, false
 \end{cmdsubsub}
 
 Turn on or off interaction.  Default is on.  Turning interaction off prevents
 \texdoc to ask you to choose a file to view when there are multiple choices,
-and merely just print the list of files found.
+so it just prints the list of files found.
+
+\begin{cmdsubsub}{alias}{cf-alias_switch}
+  alias_switch = true, false
+\end{cmdsubsub}
+
+Turn on or off aliasing.  Default is on.
 
 \begin{cmdsubsub}{ext_list}{cf-ext_list}
   ext_list = list
@@ -612,8 +617,9 @@
 \begin{htcode}
   pdf, html, txt, dvi, ps,
 \end{htcode}
-This list is used to filter and  sort the results (with the default value: pdf
-first, etc).  Two special values are recognised:
+This list is used to filter and  sort the results that have the same
+score(with the default value: pdf first, etc).  Two special values are
+recognised:
 \begin{itemize}
   \item \emph{The empty element}. This means files without extensions, or more
     precisely without a dot in their name.  This is meant for files like
@@ -624,7 +630,7 @@
 
 There is a very special case: if the searched name has .sty extension,
 \texdoc enters a special search mode for .sty files (not located in the same
-place as real documentation files) for this name, independantly of the
+place as real documentation files) for this name, indepandantly of the
 current value of ext_list and mode (unless it is the regex mode). In an
 ideal world, this wouldn't be necessary since every sty file would have a
 proper documentation in pdf, html or plain text, but\dots
@@ -635,93 +641,81 @@
 \texdoc to be able to find man pages and display them with the man command,
 you can use
 \begin{htcode}
-  ext_list = 1, 5, pdf, html, txt, dvi, ps,
+  ext_list = pdf, html, 1, 5, txt, dvi, ps,
   viewer_1 = man
   viewer_5 = man
 \end{htcode}
-(This also makes man pages in man format take precedence over their pdf
-versions.)
+
+\begin{cmdsubsub}{badext_list}{cf-badext_list}
+  badext_list = list
+\end{cmdsubsub}
+
+Set the list of ``bad'' extensions to list.  Default is ``txt,''. Files
+with those extensions get a heuristic score of 0.
 
 \begin{cmdsubsub}{viewer_*}{cf-viewer_*}
   viewer_ext = cmd
 \end{cmdsubsub}
 
 Set the viewer command for files with extension ext to cmd. For files
-without extension, viewer_txt is used, and there's not viewer_ variable.
+without extension, viewer_txt is used, and there's no viewer_ variable.
 In cmd, %s can be used as a placeholder for the file name, which is
 otherwise inserted at the end of the command.  The command can be a arbitrary
 shell construct. 
 
-\begin{cmdsubsub}{alias}{cf-alias}
-  alias name = othername
+\begin{cmdsubsub}{verbosity_level}{cf-verbosity_level}
+  verbosity_level = n
 \end{cmdsubsub}
 
-Everything has already been said in section~\ref{s-alias}.
+Set the verbosity level to n. 3 means errors, warnings and informational
+message will be printed (on stdout); 2 means only errors and warnings, 1 only
+errors and 0 nothing (not recommended).
 
-\begin{cmdsubsub}{verbosity_level}{cf-verbosity_level}
-  verbosity_level = n
+\begin{cmdsubsub}{debug_list}{cf-debug_list}
+  debug_list = list
 \end{cmdsubsub}
 
-Set the verbosity level to n.  This determines whether \texdoc will print
-or not errors or debug information (to stderr). Default level is 3. The
-numeric codes are as follow:
-\begin{enumerate}[start=0]
-  \item Print nothing (not recommended).
-  \item Print only error messages.
-  \item Also print warnings.
-  \item Also print information messages.
-  \item[n] Also print debug(n-3) information messages.
-\end{enumerate}
+Set the list of activated debug items (default: none). For a list of available
+items, see the source code, file constants.tlu, variable known_debugs.
+Debug information is printed on standard error.
 
-Currently, debug goes from 1 to 3 : debug1 prints the command used to view a
-file just before executing it, debug2 prints information about setting
-configuration paramters, and debug3 about the search paths used.
+\begin{cmdsubsub}{machine_switch}{cf-machine_switch}
+  machine_switch = true, false
+\end{cmdsubsub}
+
+Turn on or off machine-readable output (default: off).  With this option
+active, the value of interact_switch is forced to false, and each line of
+output is
+\begin{htcode}
+  argument\tscore\tfilename
+\end{htcode}
+where argument is the name of the argument to which the results correspond
+(mainly useful if there were many arguments), \t is the tab (ascii 9)
+character, and the other entries are pretty self-explanatory. Nothing else is
+printed on stdout, except if a internal error occurs (in which case exit code
+will be 1). In the future, more tab-separated fields may be added at the end
+of the line, but the first 3 fields will remain unchanged.
 
 \begin{cmdsubsub}{lastfile_switch}{cf-lastfile_switch}
   lastfile_switch = true, false
 \end{cmdsubsub}
 
-Prevents \texdoc from reading any other configuration file after this one.
-Mainly useful for installing a newer version of \texdoc in your home (see the
+If set to true, prevents \texdoc from reading any other configuration file
+after this one (they will be reported as ``disabled'' by texdoc -f).  Mainly
+useful for installing a newer version of \texdoc in your home and preventing
+the default configuration file from older versions to be used(see the
 \href{http://tug.org/texdoc/}{web site} for instructions on how to do so).
 
 \subsection{Exit codes}\label{ss-exit}
 
-The current exit code are as follow:
+The current exit codes are:
 \begin{enumerate}[start=0]
   \item Success.
-  \item Syntax error.
-  \item Documentation not found for at least one argument.
+  \item Internal error.
+  \item Usage error.
 \end{enumerate}
 
-\section{Bugs, warnings}\label{s-bugs}
-
-There is currently no known bug (fingers crossed).  But a few things you should
-be warned about.
-
-First of all, \texdoc doesn't always succeed in finding documentation (or
-finds so many results that it is not useful).  Moreover, it cannot handle very
-correctly packages with many relevant documentation files at the moment
-(see~\ref{ss-alias-rem}).  Ideas about how to improve this are most welcome at
-the usual address.
-
-Second, support for zipped documentation, which have been ``available'' in
-previous versions of \texdoc, is now disabled by default. The reasons are that
-this support wasn't portable (didn't work on windows for example), and
-moreover we won't ship compressed documentation in \texlive.  However, the
-code has not been totally removed and should be easy to activate again. If you
-want to use this feature, please:
-\begin{enumerate}
-  \item Look in \texdoc's code for instructions (look for the support_zipped
-    variable and change it to true).
-  \item Check that the zip commands in texdoc's default match whatever command
-    is available on your system.
-\end{enumerate}
-
-Finally, \texdoc is also missing a GUI version (texdoctk has never been the
-GUI version of \texdoc, and is unmaintained and probably unmaintainable
-anyway).  This is on the list, but the time line is rather unclear at the
-moment.
+\clearpage
 
 \section{Licence}\label{s-licence}
 
@@ -752,10 +746,8 @@
 \end{itemize}
 
 \bigskip
-\begin{center}\Large\rmfamily
+\begin{center}\Large\rmfamily\bfseries
   Happy \TeX{}ing!
 \end{center}
 
 \end{document}
-
-
Index: texlive-base-2009/texmf/scripts/texdoc/alias.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/alias.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,95 @@
+-- configuration handling for texdoc
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'export_symbols',
+    'string', 'table', 'os', 'kpse', 'lfs', 'io',
+    'deb_print', 'tostring', 'tonumber',
+    'C',
+    'config',
+})
+
+-- structure of an alias entry
+-- 
+-- aliasentry = {
+--   name   = <string> pattern to be matched,
+--   score  = <number> associated score (may be nil),
+--   original = <boolean> is this the original keyword?,
+-- }
+
+-- alias is local to this file
+local alias = {}
+
+-- turn a name into a suitable alias entry
+-- if score is 'false', this is the original name
+function make_alias(pat, score)
+    local al = {}
+    al.name = pat
+    if score == false then
+        al.original = true
+    else
+        al.score = score -- may be nil
+    end
+    return al
+end
+
+-- add an alias value for a key
+function add_alias(key, value, score)
+    local k = string.lower(key)
+    alias[k] = alias[k] or { make_alias(key, false) }
+    if alias[k].stop then return end
+    table.insert(alias[k], make_alias(value, score))
+end
+
+-- prevent a key from begin further aliased
+function stop_alias(key)
+    local k = string.lower(key)
+    alias[k] = alias[k] or {}
+    alias[k].stop = true
+end
+
+-- get patterns for a name
+function get_patterns(name)
+    local n = string.lower(name)
+    if config.mode ~= 'regex' and config.alias_switch and alias[n] then
+        return alias[n]
+    else
+        return { make_alias(name, false) }
+    end
+end
+
+-- interpret a confline as an alias setting or return false
+function confline_to_alias(line, file, pos)
+    -- alias directive without score
+    local key, val = string.match(line, '^alias%s+([%w%p]+)%s*=%s*(.+)')
+    if key and val then
+        add_alias(key, val)
+        return true
+    end
+    -- alias directive with score
+    local score, key, val = string.match(line,
+        '^alias%(([%d+-.]+)%)%s+([%w%p]+)%s*=%s*(.+)')
+    if score then score = tonumber(score) end
+    if key and val and score then
+        add_alias(key, val, score)
+        return true
+    end
+    -- stopalias directive
+    local key = string.match(line, '^stopalias%s+(.+)')
+    if key then 
+        stop_alias(key)
+        return true
+    end
+    return false
+end
+
+-- finally export a few symbols
+export_symbols(L, {
+    'confline_to_alias',
+    'get_patterns',
+})
Index: texlive-base-2009/texmf/scripts/texdoc/config.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/config.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,533 @@
+-- configuration handling for texdoc
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'export_symbols',
+    'string', 'table', 'os', 'kpse', 'lfs', 'io',
+    'ipairs', 'pairs', 'tonumber', 'tostring', 'setmetatable', 'next', 'print',
+    'assert', 'error',
+    'err_print', 'win32_hook', 'deb_print',
+    'confline_to_alias', 'confline_to_score',
+    'C',
+    'config',
+})
+
+--------------------------   hide the config table   ---------------------------
+
+-- config is read-only
+function set_read_only(table, name)
+    assert(next(table) == nil,
+        'Internal error: '..name..' should be empty at this point.')
+    local ro = 'Internal error: attempt to update read-only table '
+    local real = {}
+    setmetatable(table, {
+        __index = real,
+        __newindex = function () error(ro..name..'.') end,
+    })
+    return function(k, v) real[k] = v end
+end
+
+real_set_config = set_read_only(config, 'config')
+
+
+-------------------------   general config functions   -------------------------
+
+-- set a config parameter, but don't overwrite it if already set
+-- three special types: *_list (list), *_switch (boolean), *_level (number)
+function set_config_element (key, value, context)
+    local is_known = false -- is key a valid option?
+    local option
+    for _, option in ipairs(C.known_options) do
+        if string.match(key, '^'..option..'$') then is_known = true break end
+    end
+    -- warn and exit if key is not a known option
+    if not is_known then config_warn(key, nil, context, true) return end
+    -- exit if key is already set (/!\ must test for nil, not false)
+    if not (config[key] == nil) then return nil end
+    -- detect the type of the key
+    if string.match(key, '_list$') then
+        -- coma-separated list
+        local values = string.explode(value, ',')
+        local inverse = {}
+        for i, j in ipairs(values) do -- sanitize values...
+            j = string.gsub(j, '%s*$', '')
+            j = string.gsub(j, '^%s*', '')
+            values[i] = j
+            inverse[j] = i -- ... and build inverse mapping on the way
+        end
+        real_set_config(key, values)
+        real_set_config(key..'_inv', inverse)
+        real_set_config(key..'_max', #values)
+    elseif string.find (key, '_switch$') then
+        -- boolean
+        if value == 'true' then
+            real_set_config(key, true)
+        elseif value == 'false' then
+            real_set_config(key, false)
+        else
+            config_warn (key, value, context)
+        end
+    elseif string.find (key, '_level$') then
+        -- integer
+        local val = tonumber (value)
+        if val then
+            real_set_config(key, val)
+        else
+            config_warn (key, value, context)
+        end
+    else -- string
+        real_set_config(key, value)
+    end
+    -- special case: if we just set debug_list, print version info now
+    if key == 'debug_list' then
+        deb_print('version', C.fullname..' version '..C.version)
+    end
+    -- now tell what we have just done, for debugging
+    deb_print('config',
+        "Setting '"..key.."="..value.."' "..context_to_string(context)..'.')
+end
+
+-- a helper function for warning messages in the above
+function config_warn (key, value, context, unknown)
+    local begin = unknown
+        and 'Unknown option "'..key..'"'
+        or 'Illegal value "'..tostring(value)..'" for option "'..key..'"'
+    local ending = '.  Skipping.'
+    err_print('warning', begin..' '..context_to_string(context)..ending)
+end
+
+-- interpreting 'context' for the previous functions
+function context_to_string(context)
+    if not context then return '(no context)' end
+    if      context.src == 'cl' then
+        return 'from command line option "'..context.name..'"'
+    elseif  context.src == 'env' then
+        return 'from environment variable "'..context.name..'"'
+    elseif  context.src == 'file' then
+        return 'in file "'..context.file..'" on line '..context.line
+    elseif  context.src == 'def' then
+        return 'from built-in defaults'
+    else
+        return 'from unkown source (should not happen, please report)'
+    end
+end
+
+-- set a whole list, also whithout overwriting
+function set_config_list (conf, context)
+    for key, value in pairs(conf) do
+        set_config_element (key, value, context)
+    end
+end
+
+------------------------   options from command line   -------------------------
+
+-- set config from the command line
+-- Please make sure to update C.usage_msg accordingly
+-- and set a default value in setup_config_from_defaults() if relevant.
+function setup_config_from_cl(arg)
+    local curr_arg
+    local function set_config_elt(key, val)
+        set_config_element(key, val, {src='cl', name=curr_arg})
+    end
+    while arg[1] and string.match(arg[1],'^%-') do
+        curr_arg = table.remove(arg,1)
+        -- special options
+        if (curr_arg == '-h') or (curr_arg == '--help') then
+            print (C.usage_msg)
+            os.exit(0)
+        elseif (curr_arg == '-V') or (curr_arg == '--version') then
+            print (C.progname .. ' ' .. C.version )
+            os.exit(0)
+        elseif (curr_arg == '-f') or (curr_arg == '--files') then
+            print (C.progname .. ' ' .. C.version )
+            setup_config_from_files ()
+            show_config_files (print, true)
+            os.exit(0)
+        -- options related to mode
+        elseif (curr_arg == '-w') or (curr_arg == '--view') then
+            set_config_elt('mode', 'view')
+        elseif (curr_arg == '-m') or (curr_arg == '--mixed') then
+            set_config_elt('mode', 'mixed')
+        elseif (curr_arg == '-l') or (curr_arg == '--list') then
+            set_config_elt('mode', 'list')
+        elseif (curr_arg == '-s') or (curr_arg == '--showall') then
+            set_config_elt ('mode', 'showall')
+        elseif (curr_arg == '--search') then
+            set_config_elt ('mode', 'showall')
+            err_print('warning', '--search has been renamed to --showall')
+            err_print('warning', 'Please use the new name.')
+        elseif (curr_arg == '-r') or (curr_arg == '--regex') then
+            set_config_elt ('mode', 'regex')
+        -- interaction
+        elseif (curr_arg == '-I') or (curr_arg == '--nointeract') then
+            set_config_elt('interact_switch', 'false')
+        elseif (curr_arg == '-i') or (curr_arg == '--interact') then
+            set_config_elt('interact_switch', 'true')
+        -- output format
+        elseif (curr_arg == '-M') or (curr_arg == '--machine') then
+            set_config_elt('machine_switch', 'true')
+        -- alias
+        elseif (curr_arg == '-A') or (curr_arg == '--noalias') then
+            set_config_elt('alias_switch', 'false')
+        elseif (curr_arg == '-a') or (curr_arg == '--alias') then
+            set_config_elt('alias_switch', 'true')
+        -- debug
+        elseif (curr_arg == '-d') or (curr_arg == '--debug') then
+            set_config_elt('debug_list', 'all')
+        elseif string.match(curr_arg, '^%-d=') then
+            local value = string.gsub(curr_arg, '^%-d=', '')
+            set_config_elt('debug_list', value)
+        elseif string.match(curr_arg, '^%-%-debug=') then
+            local value = string.gsub(curr_arg, '^%-%-debug=', '')
+            set_config_elt('debug_list', value)
+        -- verbosity
+        elseif string.match(curr_arg, '^%-v') then
+            local value = string.gsub(curr_arg, '^%-v=?', '')
+            set_config_elt('verbosity_level', value)
+        elseif string.match(curr_arg, '^%-%-verbosity') then
+            local value = string.gsub(curr_arg, '^%-%-verbosity=?', '')
+            set_config_elt('verbosity_level', value)
+        -- extensions list (deprecated)
+        elseif string.match(curr_arg, '^%-e') then
+            local value = string.gsub(curr_arg, '^%-e=?', '')
+            set_config_elt('ext_list', value)
+            err_print('warning',
+            '-e is deprecated and will likely be removed soon.')
+            err_print('warning',
+            'ext_list should be set in a configuration file instead.')
+            err_print('warning',
+            'Please protest on the texdoc mailing list if you need this.')
+        elseif string.match(curr_arg, '^%-%-extensions') then
+            local value = string.gsub(curr_arg, '^%-%-extensions=?', '')
+            set_config_elt('ext_list', value)
+            err_print('warning',
+            '--extensions is deprecated and will likely be removed soon.')
+            err_print('warning',
+            'ext_list should be set in a configuration file instead.')
+            err_print('warning',
+            'Please protest on the texdoc mailing list if you need this.')
+        -- problem
+        else
+            err_print('error', "unknown option: "..curr_arg)
+            print (C.error_msg)
+            os.exit(2)
+        end
+    end
+end
+
+-------------------------   config from environment   --------------------------
+
+-- set config from environment if available
+function setup_config_from_env ()
+    local function set_config_elt_from_vars(key, vars)
+        for _, var in ipairs(vars) do
+            local value = os.getenv(var)
+            if value then
+                set_config_element(key, value, {src='env', name=var})
+            end
+        end
+    end
+    set_config_elt_from_vars('viewer_pdf',
+    {"PDFVIEWER_texdoc", "TEXDOCVIEW_pdf", "TEXDOC_VIEWER_PDF", "PDFVIEWER"})
+    set_config_elt_from_vars('viewer_ps',
+    {"PSVIEWER_texdoc", "TEXDOCVIEW_ps", "TEXDOC_VIEWER_PS", "PSVIEWER"})
+    set_config_elt_from_vars('viewer_dvi',
+    {"DVIVIEWER_texdoc", "TEXDOCVIEW_dvi", "TEXDOC_VIEWER_DVI", "DVIVIEWER"})
+    set_config_elt_from_vars('viewer_html',
+    {"BROWSER_texdoc", "TEXDOCVIEW_html", "TEXDOC_VIEWER_HTML", "BROWSER"})
+    set_config_elt_from_vars('viewer_txt',
+    {"PAGER_texdoc", "TEXDOCVIEW_txt", "TEXDOC_VIEWER_TXT", "PAGER"})
+end
+
+----------------------   options and aliases from files   ----------------------
+
+-- set config+aliases from a particular config file assumed to exist
+function read_config_file(configfile)
+    local cnf = assert(io.open(configfile, 'r'))
+    local lineno = 0
+    while true do
+        local line=cnf:read('*line')
+        lineno = lineno + 1
+        if line == nil then break end  -- EOF
+        line = string.gsub(line, '%s*#.*$', '') -- comments begin with #
+        line = string.gsub(line, '%s*$', '')    -- remove trailing spaces
+        line = string.gsub(line, '^%s*', '')    -- remove leading spaces
+        -- try to interpret the line
+        local ok = string.match(line, '^%s*$') 
+        or confline_to_alias(line, configfile, lineno)
+        or confline_to_score(line, configfile, lineno)
+        or confline_to_config(line, configfile, lineno)
+        -- complain if it failed
+        if not ok then
+            err_print('warning',
+            'syntax error in '..configfile..' at line '..lineno..'.')
+        end
+    end
+    cnf:close()
+end
+
+-- interpret a confline as a config setting or return false
+function confline_to_config(line, file, pos)
+    local key, val = string.match(line, '^([%a%d_]+)%s*=%s*(.+)')
+    if key and val then
+        set_config_element(key, val, {src='file', file=file, line=pos})
+        return true
+    end
+    return false
+end
+
+
+-- return a table with config file and if they exist
+function get_config_files ()
+    local platform = string.match (kpse.var_value ('SELFAUTOLOC'), '.*/(.*)$')
+    local TEXMFHOME  = kpse.var_value ('TEXMFHOME')
+    local TEXMFLOCAL = kpse.var_value ('TEXMFLOCAL')
+    local TEXMFMAIN  = kpse.var_value ('TEXMFMAIN')
+    return {
+        TEXMFHOME  .. '/texdoc/texdoc-'..platform..'.cnf',
+        TEXMFHOME  .. '/texdoc/texdoc.cnf',
+        TEXMFHOME  .. '/texdoc/texdoc-dist.cnf',
+        TEXMFLOCAL .. '/texdoc/texdoc-'..platform..'.cnf',
+        TEXMFLOCAL .. '/texdoc/texdoc.cnf',
+        TEXMFMAIN  .. '/texdoc/texdoc.cnf'
+    }
+end
+
+-- the config_files table is shared by the next two functions
+do
+local config_files = {}
+
+-- set config/aliases from all config files
+function setup_config_from_files ()
+    for i, file in ipairs (get_config_files ()) do
+        local found = lfs.isfile(file)
+        config_files[i] = {
+            path = file,
+            status = found and (config.lastfile_switch
+            and 'disabled' or 'active') or 'absent',
+        }
+        if config_files[i].status == 'active' then
+            read_config_file (file)
+        end
+    end
+end
+
+-- now a special information function (see -f,--file option)
+function show_config_files (print_fun, prefix)
+    print_fun("Configuration files are:")
+    for i, file in ipairs (config_files) do
+        local home = prefix and
+        ((i==2) and "(*) " or "    ") -- home conffile is the 2nd
+        or ''
+        print_fun (home..file.status..'\t'..win32_hook(file.path))
+    end
+    if prefix then
+        print("(*) This is the recommended configuration file "
+        .. "for your personal preferences.")
+    end
+end
+
+end -- scope of config_files
+
+----------------------   options from built-in defaults   ----------------------
+
+-- for default viewer on general Unix, we have a list; the following two
+-- functions are used to check in the path which program is available
+
+-- check if "name" is the name of a file in the path
+-- Warning: to be used only on Unix! (separators, and PATH irrelevant on win32)
+-- the value of PATH is cached
+do local path_list = string.explode(os.getenv("PATH"), ':')
+function is_in_path(name)
+    for _, path in ipairs(path_list) do
+        if lfs.isfile(path..'/'..name) then return true end
+    end
+    return false
+end
+end
+
+-- guess a viewer from a list: 
+-- - try detecting desktop environments
+-- - or return the first element of "list" whose name is found in path
+-- - or nil
+-- caches results of desktop environment detection
+do local de_viewer
+function guess_viewer(cmds)
+    -- try desktop environment
+    if not de_viewer then de_viewer = desktop_environment_viewer() end
+    if de_viewer then return de_viewer end
+    -- or look along path
+    for _, cmd in ipairs(cmds) do
+        if is_in_path(cmd[1]) then return cmd[2] end
+    end
+end
+end
+
+-- returns a viewer specific to a desktop environement if relevant
+-- doesn't work on windows (uses io.popen)
+-- logic stolen from xdg-open (http://www.freedesktop.org/) and adapted
+function desktop_environment_viewer()
+    if os.getenv('KDE_SESSION_VERSION') and is_in_path('kde-open') then
+        return '(kde-open %s) &'                     -- kde 4 (or greater)
+    end
+    if os.getenv('KDE_FULL_SESSION') and is_in_path('kfmclient') then
+        return '(kfmclient exec %s) &'              -- kde < 4
+    end
+    if os.getenv('GNOME_DESKTOP_SESSION_ID') then   -- gnome
+        return '(gnome-open %s) &'
+    end
+    if not is_in_path('xprop') then return end
+    local xprop_fh = io.popen('xprop -root _DT_SAVE_MODE')
+    local xprop_out = xprop_fh:read('*line')
+    xprop_fh:close()
+    if string.find(xprop_out, '= "xfce4"$') then     -- xfce
+        return '(exo-open %s) &'
+    end
+end
+
+-- set some fall-back default values if no previous value is set
+function setup_config_from_defaults()
+    local function set_config_ls(ls) set_config_list(ls, {src='def'}) end
+    local function set_config_elt(key, val)
+        set_config_element(key, val, {src='def'})
+    end
+    if (os.type == "windows") then
+        set_config_ls {
+            -- Use 'start' to get file associations.
+            -- We need to quote the filenames, but the first quoted argument
+            -- is considered as the title by start, so we provide a dummy title.
+            -- Also, since the command line parser removes quotes if there
+            -- is no space inside, the dummy title must contain spaces.
+            viewer_dvi    = 'start "texdoc dvi viewer"',
+            viewer_html   = 'start "texdoc html viewer"',
+            viewer_pdf    = 'start "texdoc pdf viewer"',
+            viewer_ps     = 'start "texdoc ps viewer"',
+            -- 'more' is always available.
+            -- However, we can't assume texdoc is called from a cmd.exe window
+            -- (it can be run from the start->run menu), hence we make sure
+            -- to open a new window if needed.
+            viewer_txt    = 'start cmd /k more',
+        }
+    elseif (os.name == 'macosx') then
+        set_config_ls {
+            viewer_dvi    = 'open',
+            viewer_html   = 'open',
+            viewer_pdf    = 'open',
+            viewer_ps     = 'open',
+            viewer_txt    = 'less',
+        }
+    else -- generic Unix
+        set_config_ls {
+            viewer_dvi      = guess_viewer {
+                {'evince',      '(evince %s) &'},
+                {'okular',      '(okular %s) &'},
+                {'kdvi',        '(kdvi %s) &'},
+                {'xgdvi',       '(xgdvi %s) &'},
+                {'spawg',       '(spawg %s) &'},
+                {'spawx11',     '(spawx11 %s) &'},
+                {'tkdvi',       '(tkdvi %s) &'},
+                {'dvilx',       '(dvilx %s) &'},
+                {'advi',        '(advi %s) &'},
+                {'xdvik-ja',    '(xdvik-ja %s) &'},
+                {'xdvi',        '(xdvi %s) &'},
+                {'see',         '(see %s) &'}
+            },
+            viewer_html     = guess_viewer {
+                {'firefox',     '(firefox %s) &'},
+                {'seamonkey',   '(seamonkey %s) &'},
+                {'mozilla',     '(mozilla %s) &'},
+                {'konqueror',   '(konqueror %s) &'},
+                {'epiphany',    '(epiphany %s) &'},
+                {'opera',       '(opera %s) &'},
+                {'w3m',         'w3m'},
+                {'links',       'links'},
+                {'lynx',        'lynx'},
+                {'see',         'see'}
+            },
+            viewer_pdf      = guess_viewer {
+                {'evince',      '(evince %s) &'},
+                {'okular',      '(okular %s) &'},
+                {'kpdf',        '(kpdf %s) &'},
+                {'xpdf',        '(xpdf %s) &'},
+                {'acroread',    '(xpdf %s) &'},
+                {'see',         '(see %s) &'}
+            },
+            viewer_ps       = guess_viewer {
+                {'evince',      '(evince %s) &'},
+                {'okular',      '(okular %s) &'},
+                {'kghostview',  '(kghostview %s) &'},
+                {'gv',          '(gv %s) &'},
+                {'see',         '(see %s) &'}
+            },
+            viewer_txt      = guess_viewer {
+                {'most',        'most'},
+                {'less',        'less'},
+                {'more',        'more'}
+            }
+        }
+    end
+    -- then various, platform independant, stuff
+    set_config_ls {
+        mode                = 'view',
+        interact_switch     = 'true',
+        machine_switch      = 'false',
+        verbosity_level     = '2',
+        ext_list            = 'pdf, html, txt, ps, dvi, ',
+        badext_list         = 'txt, ',
+    }
+    -- must be set after mode!
+    set_config_elt ('alias_switch', alias_from_mode(config.mode))
+    -- zip-related options
+    if C.support_zipped then
+        set_config_ls {
+            zipext_list = 'gz, bz2',
+            unzip_gz    = 'gzip -d -c',
+            unzip_bz2   = 'bzip -d -c',
+            rm_file     = 'rm -f',
+            rm_dir      = 'rmdir'
+        }
+    end
+end
+
+-- the default value of config.alias_switch depends on the mode as follows
+function alias_from_mode (mode) -- /!\ returns a string!
+    if (mode == 'view') or (mode == 'mixed') or (mode == 'list') then
+        return 'true'
+    else
+        return 'false'
+    end
+end
+
+--------------------------   set all configuration   ---------------------------
+
+-- populate the config and alias arrays
+function setup_config_and_alias(arg)
+    -- setup config from all sources
+    setup_config_from_cl(arg)
+    setup_config_from_env()
+    setup_config_from_files()
+    setup_config_from_defaults()
+    -- regex mode is deprecated
+    if config.mode == 'regex' then 
+        err_print('warning', 
+        'Regex mode is deprecated and will likely be removed soon.')
+        err_print('warning', 
+        'Please protest on the texdoc mailing list if you need this.')
+    end
+    -- machine mode implies no interaction
+    if config.machine_switch == true then
+        real_set_config('interact_switch', false)
+    end
+    -- we were waiting for config.debug_list to be know to do this
+    show_config_files(function(s) deb_print('files', s) end)
+end
+
+-- finally export a few symbols
+export_symbols(L, {
+    'setup_config_and_alias',
+})
Index: texlive-base-2009/texmf/scripts/texdoc/constants.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/constants.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,115 @@
+-- Global "constants" for texdoc.
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'setmetatable', 'next', 'assert', 'error',
+    'arg',
+    'C',
+})
+
+-- progname and version
+fullname    = arg[0]
+progname    = 'texdoc'
+version = '0.61'
+
+-- make sure to update setup_config_from_cl() accordingly
+-- and set a default value in setup_config_from_defaults() if relevant
+usage_msg = [[
+texdoc tries to find appropriate TeX documentation for the specified NAME(s).
+With no NAME, it can print configuration information (-f, --files);
+the usual --help and --version options are also accepted.
+Usage: texdoc [OPTIONS]... [NAME]...
+  -f, --files           Print the name of the config files being used.
+  -w, --view            Use view mode: start a viewer.
+  -m, --mixed           Use mixed mode (view or list).
+  -l, --list            Use list mode: show a list of results.
+  -s, --showall         Use showall mode: show also "bad" results.
+  -r, --regex           Use regex mode. (Deprecated.)
+  -e, --extensions=L    Set ext_list=L. (Deprecated.)
+  -a, --alias           Use the alias table.
+  -A, --noalias         Don't use the alias table.
+  -i, --interact        Use interactive menus.
+  -I, --nointeract      Use plain lists, no interaction required.
+  -v, --verbosity=N     Set verbosity level to N.
+  -d, --debug[=list]    Activate debug for selected items (default all).
+  -M, --machine         Use a more machine-friendly output format.
+Environment: PAGER, BROWSER, PDFVIEWER, PSVIEWER, DVIVIEWER.
+Files: <texmf>/texdoc/texdoc.cnf files, see the -f option.
+Homepage: http://tug.org/texdoc/
+Manual: displayed by `texdoc texdoc'.]]
+
+error_msg = [[
+Try `texdoc --help' for a short help, `texdoc texdoc' for the user manual.]]
+notfound_msg = [[
+Sorry, no documentation found for PKGNAME.
+If you are unsure about the name, try searching CTAN's TeX catalogue at
+http://ctan.org/search.html#byDescription.]]
+notfound_msg_ph = 'PKGNAME'
+
+known_options = {
+    'viewer_.*',
+    'mode',
+    'interact_switch',
+    'machine_switch',
+    'alias_switch',
+    'ext_list',
+    'badext_list',
+    'verbosity_level',
+    'debug_list',
+    'lastfile_switch',
+    'rm_dir',
+    'rm_file',
+    'unzip_.*',
+    'zipext_list',
+}
+
+err_priority = {
+    error   = 1,
+    warning = 2,
+    info    = 3,
+}
+
+known_debugs = {
+    version = {},
+    files   = {},
+    config  = {'files'},
+    view    = {},
+    texdocs = {},
+    filesea = {},
+    lsrsea  = {},
+    kpse    = {'texdocs', 'filesea', 'lsrsea'},
+    score   = {},
+}
+
+place_holder = '%%s' -- used for viewer commands
+
+-- zip/gz support
+--
+-- optionally, texdoc can support compressed documentation, but this is
+-- system-dependant (commands for unzipping, temporary files, etc).
+-- Since TeX Live doesn't ship compressed documentation, and I'm too lazy to
+-- make zip support work reliably on all platforms, I don't turn into an
+-- official option. However, it should work on Unix platforms.
+--
+-- If you enable zip support here, please check the configuration in config.tlu
+-- (look for support_zipped). The zip command should write the unzipped file to
+-- STDOUT. Check carefully that everything works as expected, since it got far
+-- less testing than the rest of texdoc.
+--
+-- See also comments in texdoc.cnf about viewer settings.
+support_zipped = false
+
+-- make C a proxy to the local environment
+assert(next(C) == nil,
+    'Internal error: table of constants should be empty at this point')
+setmetatable(C, {
+    __index = L,
+    __newindew = function ()
+        error('Internal error: attempt to modify a constant.')
+    end
+})
Index: texlive-base-2009/texmf/scripts/texdoc/functions.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/functions.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,102 @@
+-- General use functions for texdoc
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'export_symbols',
+    'string', 'io', 'os',
+    'pairs', 'ipairs',
+    'C',
+    'config',
+})
+
+-- change '/' to '\' on windows
+if os.type == "windows" then
+    function win32_hook (path)
+        local res = string.gsub (path, '/', '\\')
+        return res -- get rid of gsub's 2nd return value
+    end
+else
+    function win32_hook (path)
+        return path
+    end
+end
+
+-- generic error display function (see the error_priority constant)
+function err_print (lvl, msg)
+    -- be careful: maybe config.verbosity_level is not set yet
+    local verbosity_level = config.verbosity_level or 2
+    if C.err_priority[lvl] <= verbosity_level then
+        io.stderr:write ("texdoc "..lvl..": "..msg.."\n")
+    end
+end
+
+do --scope of active_debugs
+local active_debugs
+
+-- generic debug function
+function deb_print(cat, msg)
+    -- make sure active_debugs is set
+    if not active_debugs then set_active_debugs() end
+    -- print message it belongs to an active category
+    if active_debugs and active_debugs[cat] or cat == 'XXX' then
+        io.stderr:write ("texdoc debug-"..cat..": "..msg.."\n")
+    end
+end
+
+-- set active_debugs
+function set_active_debugs()
+    if not config.debug_list then return end
+    active_debugs = {}
+    -- all debug options imply version info
+    if config.debug_list[1] then
+        active_debugs.version = true
+    else
+        return
+    end
+    -- if 'all' is the first keyword, just activate all categories
+    if config.debug_list[1] == 'all' then
+        for deb in pairs(C.known_debugs) do
+            active_debugs[deb] = true end
+        return
+    end
+    -- activate options from the list
+    for _, deb in ipairs(config.debug_list) do
+        local deps = C.known_debugs[deb]
+        if deps then
+            active_debugs[deb] = true
+            for _, d in ipairs(deps) do active_debugs[d] = true end
+        else
+            err_print('warning', "Unknown debug category '"..deb.."'.")
+        end
+    end
+end
+
+end -- scope of active_debugs
+
+-- if zip is support and file is base..'.'..zip with zip in zipext_list, 
+-- return base, zip -- otherwise, returns file, nil
+function parse_zip(file) 
+    if C.support_zipped then
+        local zip
+        for _, zip in ipairs(config.zipext_list) do
+            local l = #zip + 1
+            if string.sub(file, -l, -1) == '.'..zip then
+                return string.sub(file, 1, -l - 1), zip
+            end
+        end
+    end
+    return file, nil
+end
+
+-- finally export a few symbols
+export_symbols(L, {
+    'err_print',
+    'deb_print',
+    'win32_hook',
+    'parse_zip',
+})
Index: texlive-base-2009/texmf/scripts/texdoc/main.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/main.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,37 @@
+-- texdoc's main()
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'os',
+    'print', 'ipairs',
+    'arg',
+    'C',
+    'setup_config_and_alias',
+    'get_doclist',
+    'deliver_results',
+})
+
+-- setup config options and aliases from various places
+setup_config_and_alias(arg)
+
+-- make sure we actually have argument(s)
+if not arg[1] then
+    print(C.usage_msg)
+    os.exit(2)
+end
+
+-- main loop
+local docname
+for _, docname in ipairs(arg) do
+    -- do we have more then one argument?
+    local multiarg = not not arg[2]
+    -- get results
+    local doclist = get_doclist(docname)
+    -- deliver results to the user
+    deliver_results(docname, doclist, multiarg)
+end
Index: texlive-base-2009/texmf/scripts/texdoc/score.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/score.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,266 @@
+-- scoring functions for texdoc
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'export_symbols',
+    'string', 'table',
+    'pairs', 'ipairs', 'tostring', 'tonumber', 'assert',
+    'config', 'parse_zip', 'err_print', 'deb_print',
+})
+
+-- shared variables
+local global_adjscore, spec_adjscore = {}, {}
+
+-------------------------   configuration directives   -------------------------
+
+-- interpret a confline as a score directive or return false
+function confline_to_score(line, file, pos)
+    local keyw, pat, val
+    -- try global adjscore
+    pat, val = string.match(line, '^adjscore%s+([%w%p]+)%s*=%s*([%d+-.]+)')
+    if pat and val then 
+        return set_score_table(global_adjscore, pat, val)
+    end
+    -- try keyword specific adjscore
+    keyw, pat, val = string.match(line,
+    '^adjscore%(([%w%p]+)%)%s+([%w%p]+)%s*=%s*([%d+-.]+)')
+    if keyw and pat and val then 
+        keyw = string.lower(keyw)
+        spec_adjscore[keyw] = spec_adjscore[keyw] or {}
+        return set_score_table(spec_adjscore[keyw], pat, val)
+    end
+    return false
+end
+
+-- set key in score table to val, without overriding
+function set_score_table(tab, key, val)
+    local k = string.lower(key)
+    local v = tonumber(val)
+    if v then
+        if tab[k] == nil then tab[k] = v end
+        return true
+    end
+    return false
+end
+
+----------------------------   score computation   -----------------------------
+
+-- set the scores for a doclist
+function set_list_scores(list, original_kw)
+    for _, df in ipairs(list) do
+        set_score(df, original_kw)
+    end
+end
+
+-- set the score of a docfile
+function set_score(df, original_kw)
+    -- scoring is irrelevant in regex mode
+    if config.mode == 'regex' then df.score = 0 return end
+    deb_print('score', 'Start scoring '..df.realpath)
+    deb_print('score', 'Name used: '..df.name)
+    -- scoring is case-insenstitive (patterns are already lowercased)
+    local name = string.lower(df.name)
+    -- get score from patterns
+    local score = 0
+    for _, pat in ipairs(df.matches) do
+        local s = 0
+        local p = string.lower(pat.name)
+        if pat.original then
+            s = df.tree > -1 and heuristic_score(name, p) or 1
+        elseif is_exact(name, p) then
+            s = pat.score or 10 -- default alias score
+            deb_print('score', string.format(
+                "Matching alias '%s', score: %d", pat.name, s))
+        end
+        if s > score then score = s end
+    end
+    deb_print('score', 'Max pattern score: '..tostring(score))
+    -- adjust from keyword-specific tables
+    if df.tree > -1 and spec_adjscore[original_kw] then
+        for pat, val in pairs(spec_adjscore[original_kw]) do
+            if val and is_subword(name, pat) then
+                if score > 0 or val < 0 then score = score + val end
+                deb_print('score', string.format(
+                    "Adjust by '%d' from specific pattern '%s'", val, pat))
+            end
+        end
+    end
+    -- adjust from global tables
+    if df.tree > -1 then
+        for pat, val in pairs(global_adjscore) do
+            if val and is_subword(name, pat) then
+                if score > 0 or val < 0 then score = score + val end
+                deb_print('score', string.format(
+                    "Adjust by '%d' from global pattern '%s'", val, pat))
+            end
+        end
+    end
+    deb_print('score', 'Final score: '..tostring(score))
+    df.score = score
+end
+
+-- suffixes for heuristic match
+local suffixes = {
+    'doc', '-doc', '_doc', '.doc', '/doc',
+    'manual', '/manual', '-manual',
+    'userguide',
+    '-guide',
+    '-user',
+    '-man',
+}
+
+-- compute a heuristic score 0 <= s < 10 
+function heuristic_score(file, pat)
+    deb_print('score', 'Start heuristic scoring with pattern: '..pat)
+    -- if extension is bad, score is 0
+    local ext = config.ext_list[ext_pos(file)]
+    if ext and config.badext_list_inv[ext] then
+        deb_print('score', 'Bad extension, heuristic score 0')
+        return 0
+    end
+    -- score management
+    local score = 0
+    local function upscore(s, reason)
+        if s > score then
+            score = s
+            deb_print('score', 'New heuristic score: '..tostring(s)
+                ..'. Reason: '..reason)
+        end
+    end
+    local slash = not not string.find(pat, '/', 1, true)
+    -- look for exact or subword match
+    if is_exact(file, pat) then
+        upscore(4, 'exact match')
+    elseif is_subword(file, pat) then
+        upscore(1, 'subword match')
+    end
+    -- try derivatives unless pat contains a slash
+    if not slash then
+        for _, suffix in ipairs(suffixes) do
+            local deriv = pat..suffix
+            if is_exact(file, deriv) then
+                upscore(3, 'exact match for derived pattern: '..deriv)
+            elseif is_subword(file, deriv) then
+                upscore(2, 'subword match for derived pattern: '..deriv)
+            end
+        end
+    end
+    -- bonus for being in the right directory
+    if score > 0 and not slash
+        and string.find('/'..file, '/'..pat..'/', 1, true) then
+        upscore(score + 0.5, 'directory bonus')
+    end
+    -- done
+    deb_print('score', 'Final heuristic score: '..tostring(score))
+    return score
+end
+
+-- says if file is an exact match for pat
+function is_exact(file, pat)
+    file = parse_zip(file)
+    local slashes = string.gsub(pat, '[^/]+', '[^/]+')
+    basename = string.match(file, slashes..'$')
+    if not basename then return nil end
+    if basename == pat then return true end
+    for _, ext in ipairs(config.ext_list) do
+        if ext ~= '' and ext ~= '*' and basename == pat..'.'..ext then
+            return true
+        end
+    end
+    return false
+end
+
+-- say if pat is a "subword" of str
+function is_subword(str, pat)
+    local i, j = string.find(str, pat, 1, true)
+    return not not (i and j
+        and (i == 1 or is_delim(str, i) or is_delim(str, i-1))
+        and (j == #str or is_delim(str, j) or is_delim(str, j+1)))
+end
+
+-- say if character i of str is a delimiter (ponctuation)
+function is_delim(str, i)
+    return not not string.find(string.sub(str, i, i), '%p')
+end
+
+-- compare two docfile's: (see search.tlu for structure)
+-- 1. by score
+-- 2. then by extensions (ordered as in ext_list),
+-- 3. then by tree,
+-- 4. then lexicographically by filename.
+-- return true if a is better than b
+function docfile_order (a, b)
+    if a.score > b.score then
+        return true
+    elseif a.score < b.score then
+        return false
+    else
+        a.ext_pos = a.ext_pos or ext_pos(a.name)
+        b.ext_pos = b.ext_pos or ext_pos(b.name)
+        if a.ext_pos < b.ext_pos then
+            return true
+        elseif a.ext_pos > b.ext_pos then
+            return false
+        elseif a.tree > b.tree then
+            return true
+        elseif a.tree < b.tree then
+            return false
+        else
+            return (a.name < b.name)
+        end
+    end
+end
+
+-- returns the index of the most specific extension of file in ext_list,
+-- or config.ext_list_max + 1
+function ext_pos(file)
+    -- remove zipext if applicable
+    file = parse_zip(file)
+    -- now find the extension
+    local p, e, pos, ext
+    for p, e in ipairs(config.ext_list) do
+        if (e == '*') and (ext == nil) then
+            pos, ext = p, e
+        elseif (e == '') and not string.find(file, '.', 1, true) then
+            pos, ext = p, e
+        elseif string.sub(file, -string.len(e)-1) == '.'..e then
+            if (ext == nil) or (ext == '*')
+                or (string.len(e) > string.len(ext)) then
+                pos, ext = p, e
+            end
+        end
+    end
+    return pos or (config.ext_list_max + 1)
+end
+
+-----------------------------   public functions   -----------------------------
+
+-- return the "quality" of docfile
+function docfile_quality(df)
+    if df.score > 0 then
+        return 'good'
+    elseif df.score > -100 then
+        return 'bad'
+    else
+        return 'killed'
+    end
+end
+
+-- sort a doclist
+function sort_doclist(dl, original_kw)
+    dl:stop()
+    set_list_scores(dl, original_kw)
+    table.sort(dl, docfile_order)
+end
+
+-- export a few symbols
+export_symbols(L, {
+    'sort_doclist',
+    'docfile_quality',
+    'confline_to_score',
+})
Index: texlive-base-2009/texmf/scripts/texdoc/search.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/search.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,369 @@
+-- File searching functions for texdoc.
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'export_symbols',
+    'os', 'string', 'table', 'lfs', 'kpse', 'io', 
+    'ipairs', 'assert', 'error', 'tostring', 'setmetatable',
+    'deb_print', 'err_print', 'win32_hook', 'parse_zip',
+    'get_patterns', 'sort_doclist', 'docfile_quality',
+    'config', 'C',
+})
+
+-- shared by all functions in this file
+local s_doclist
+
+-----------------------   docfile and doclist objects   ------------------------
+
+-- doclist = {
+--     [1] = docfile1, [2] = docfiles2, ...,
+--     inv = { realpath1 = index1, ... }
+-- }
+--
+-- The inv subtable is such that for all i
+-- doclist.inv(doclist[i].realpath) == i
+
+local Doclist = {}
+Doclist.__index = Doclist
+
+-- create a new list of docfiles
+function Doclist:new()
+    local dl = { inv = {} }
+    setmetatable(dl, self)
+    return dl
+end
+
+-- add a docfile to a list
+function Doclist:add(df)
+    local index = self.inv[df.realpath]
+    if index then
+        self[index]:mergein(df)
+    else
+        local newindex = #self + 1
+        self[newindex] = df
+        self.inv[df.realpath] = newindex
+    end
+end
+
+-- stops a doclist
+function Doclist:stop()
+    self.inv = nil
+end
+
+-- docfile = {
+--     name     = filename (used for scoring only)
+--     tree     = code of the tree, see below
+--     matches  = {pattern1, pattern2, ...}
+-- }
+-- if tree > 1, this is the index of the tree in TEXDOCS
+-- if tree = 0, then name is relative to TLROOT (file found from tlpdb only)
+-- tree = - 1 if and only if file is a sty file. Here name is absolute.
+
+local Docfile = {}
+Docfile.__index = Docfile
+
+-- create a new docfile objet using initilisation info
+-- fields : name (relative to tree), tree, pattern
+function Docfile:new(info)
+    df = {}
+    setmetatable(df, self)
+    -- get realpath, tree and prepare name
+    df.tree = info.tree
+    if info.tree > 0 then
+        df.realpath = texdocs_tree_to_path(info.tree, info.name)
+    elseif info.tree == 0 then
+        error('Unimplemented')
+        df.realpath = get_tlroot()..'/'..info.name
+        info.name = string.gsub(info.name, '^texmf(-dist)?/doc/', '', 1)
+    elseif info.tree == -1 then
+        df.realpath = info.name
+    else
+        error('Internal error: bad tree number')
+    end
+    -- remove first component of name if at least two directory levels
+    if info.tree > -1 then
+        local name = string.match(info.name, '^..-/(.+/.+)$')
+        if name then
+            df.name = '/'..name
+        else
+            df.name = info.name
+        end
+    else
+        df.name = info.name
+    end
+    -- initialise the list of matches
+    if info.pattern then
+        df.matches = { info.pattern }
+    else
+        df.matches = {}
+    end
+    return df
+end
+
+-- merge a second docfile objet into self
+function Docfile:mergein(df)
+    if df.tree > self.tree then
+        self.name = df.name
+        self.tree = df.tree
+    end
+    for _, m in ipairs(df.matches) do
+        table.insert(self.matches, m)
+    end
+end
+
+-- from score.tlu
+Docfile.quality = docfile_quality
+
+------------------   get results from TEXDOCS (à la kpse)   -------------------
+
+do -- scope of doc_roots
+local doc_roots
+
+-- doc_roots is a Lua version of kpse's TEXDOCS
+-- structure of the doc_roots variable:
+-- doc_roots[i] = {
+--     path                 = <path>,
+--     index_mandatory      = <does path begin with !! in TEXDOCS?>
+--     recursion_allowed    = <does path ends with // in TEXDOCS?>,
+-- }
+
+-- set the doc_roots list from kpse's $TEXDOCS
+function get_texdocs ()
+    doc_roots = {}
+    local sep = (os.type == 'windows') and ';' or ':'
+    local kpse_texdocs = kpse.expand_var("$TEXDOCS")
+    -- expand the path and turn it into a lua list
+    local raw_doc_roots = string.explode(kpse.expand_braces(kpse_texdocs), sep)
+    local max = #raw_doc_roots + 1
+    for j, dir in ipairs(raw_doc_roots) do
+        local i = max - j
+        local dr = {}
+        local n
+        -- get path, !! and // values
+        dir, n = string.gsub (dir, '//$', '')
+        dr.recursion_allowed = (n == 1)
+        dr.path, n = string.gsub (dir, '^!!', '')
+        dr.index_mandatory = (n == 1)
+        deb_print('texdocs', string.format(
+            'texdocs[%d] = %s (index_mandatory=%s, recursion_allowed=%s)',
+            i, dr.path,
+            tostring(dr.index_mandatory),
+            tostring(dr.recursion_allowed)))
+        -- decide if we should use a ls-R index, the filesystem, or do nothing
+        local root, shift = lsr_root(dr.path)
+        if root and shift and dr.recursion_allowed then
+            dr.lsr = root
+            dr.lsr_shift = shift
+            deb_print('texdocs', string.format(
+                'texdocs[%d] using index: %s (shift=%s)', i, root, shift))
+        elseif not dr.index_mandatory and lfs.isdir(dr.path) then
+            dr.searchfs = true
+            deb_print('texdocs', string.format(
+                'texdocs[%d] using filesystem search', i))
+        end
+        -- register this in docroots
+        doc_roots[i] = dr
+    end
+end
+
+-- return the real path from a texdocs tree number + relative path
+function texdocs_tree_to_path(tree, rel)
+    if doc_roots == nil then get_texdocs() end
+    return win32_hook(doc_roots[tree].path..'/'..rel)
+end
+
+-- find docfiles in texdocs directories
+function get_doclist_texdocs(patlist)
+    if doc_roots == nil then get_texdocs() end
+    for code, dr in ipairs(doc_roots) do
+        if dr.lsr then
+            scan_lsr(patlist, code, dr.lsr, dr.lsr_shift)
+        elseif dr.searchfs then
+            scan_tree(patlist, code, dr.path, '', dr.recursion_allowed)
+        end
+    end
+end
+
+end -- scope of doc_roots
+
+-- find a ls-R file in a parent directory an return it or nil
+function lsr_root (path)
+    if not lfs.isdir (path) then return end
+    local root, shift = path, ''
+    if string.sub(root, -1) == '/' then root = string.sub(root, 1, -2) end
+    while string.find(root, '/', 1, true) do
+        if lfs.isfile(root..'/ls-R') then
+            return root, shift
+        end
+        local last_comp = string.match(root, '^.*/(.*)$')
+        -- /!\ cannot put last_comp in a regex: can contain special char
+        root = string.sub(root, 1, - (#last_comp + 2))
+        shift = last_comp..'/'..shift
+    end
+end
+
+-- scan a tree without ls-R file
+function scan_tree (patlist, code, base, cwd, recurse)
+    deb_print('filesea', "Entering directory: "..cwd)
+    for file in lfs.dir(base..'/'..cwd) do
+        if file ~= '.' and file ~= '..' then
+            local f = (cwd == '') and file or cwd..'/'..file
+            if lfs.isdir(base..'/'..f) then
+                if recurse then scan_tree(patlist, code, base, f, recurse) end
+            else
+                local df = process_file(patlist, file, f, code, true)
+                if df then s_doclist:add(df) end
+            end
+        end
+    end
+    deb_print('filesea', "Leaving directory: "..cwd)
+end
+
+-- scan a ls-R file
+function scan_lsr(patlist, code, cwd, shift)
+    local is_dir = {} -- is_dir[path] = true iff path is a dir
+    local results = Doclist:new()
+    local isdoc = false
+    local current_dir
+    local l = #shift
+    local lsr = assert(io.open(cwd..'/ls-R', 'r'))
+    local _ = lsr:read('*line') -- throw away first line (comment)
+    local maybe_dir = true -- next line may be a directory
+    while true do
+        local line = lsr:read('*line')
+        while line == '' do line, maybe_dir = lsr:read('*line'), true end
+        if line == nil then break end  -- EOF
+        local dir_line = maybe_dir and string.match (line, '^%./(.*):$')
+        if dir_line then
+            maybe_dir = false -- next line may not be a dir
+            if string.sub (dir_line, 1, l) == shift then
+                isdoc = true
+                current_dir = string.sub (dir_line, l+1)
+                is_dir[current_dir] = true
+                deb_print('lsrsea', 'Scanning directory: '..current_dir)
+            elseif isdoc then
+                deb_print('lsrsea', "Finished scanning: "..shift)
+                break -- we're exiting the ./doc (or shift) dir, so it's over
+            end
+        elseif isdoc then
+            local df = process_file(patlist, line, current_dir..'/'..line, code)
+            if df then results:add(df) end
+        end
+    end
+    lsr:close()
+    -- add non-directories to the list
+    for _, df in ipairs(results) do
+        if not is_dir[df.name] then
+            s_doclist:add(df)
+        end
+    end
+end
+
+-- says if file has a 'good' extenstion according to ext_list
+function check_ext(file)
+    file = string.lower(file)
+    -- remove zipext if applicable
+    file = parse_zip(file)
+    -- then do the normal thing
+    for _, e in ipairs(config.ext_list) do
+        if e == '*' then
+            return true
+        elseif (e == '') then
+            if not string.find(file, '.', 1, true) then
+                return true
+            end
+        else
+            local dot_e = '.'..e
+            if string.sub(file, -string.len(dot_e)) == dot_e then
+                return true
+            end
+        end
+    end
+    return false
+end
+
+-- return a docfile object if file "matches", nil ortherwise
+function process_file(patlist, file, pathfile, code)
+    deb_print('kpse', 'Processing file: '..pathfile)
+    local docfile
+    local pattern
+    for _, pattern in ipairs(patlist) do
+        if string.find(string.lower(pathfile), string.lower(pattern.name),
+                1, config.mode ~= 'regex') then
+            local good_ext = check_ext(file)
+            deb_print('kpse', string.format(
+                "File '%s' matches '%s'; good_ext=%s",
+                pathfile, pattern.name, tostring(good_ext)))
+            if good_ext then
+                local info = {
+                    name    = pathfile,
+                    tree    = code,
+                    pattern = pattern,
+                }
+                if docfile then
+                    docfile:mergein(Docfile:new(info))
+                else
+                    docfile = Docfile:new(info)
+                end
+            end
+        end
+    end
+    return docfile
+end
+
+----------------------------   look for sty files   ----------------------------
+
+-- add doclist entries for sty files in patlist
+function get_doclist_sty(patlist)
+    for _, pat in ipairs(patlist) do
+        local file = kpse.find_file(pat.name)
+        if file then
+            local df = Docfile:new({
+                name    = file,
+                tree    = -1,
+                pattern = pat,
+            })
+            s_doclist:add(df)
+        end
+    end
+end
+
+------------------------------   main function   -------------------------------
+
+-- find docfiles according to pattern
+function get_doclist(pattern)
+    -- get patterns (inc. aliases)
+    local normal, sty = normal_vs_sty(get_patterns(pattern))
+    -- initialise result list
+    s_doclist = Doclist:new()
+    -- get results
+    get_doclist_sty(sty)
+    get_doclist_texdocs(normal)
+    -- finally, sort results
+    sort_doclist(s_doclist, pattern)
+    return s_doclist
+end
+
+-- separate sty patterns from the rest
+function normal_vs_sty(list)
+    if config.mode == 'regex' then return list, {} end
+    local normal, sty = {}, {}
+    for _, p in ipairs(list) do
+        if string.match(string.lower(p.name), '%.([^/.]*)$') == 'sty' then
+            table.insert(sty, p)
+        else
+            table.insert(normal, p)
+        end
+    end
+    return normal, sty
+end
+
+-- finally export a few symbols
+export_symbols(L, {
+    'get_doclist',
+})
Index: texlive-base-2009/texmf/scripts/texdoc/texdoc.tlu
===================================================================
--- texlive-base-2009.orig/texmf/scripts/texdoc/texdoc.tlu	2009-10-19 05:39:29.000000000 +0900
+++ texlive-base-2009/texmf/scripts/texdoc/texdoc.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -1,7 +1,6 @@
 #!/usr/bin/env texlua
--- $Id: texdoc.tlu 15829 2009-10-18 20:39:29Z mpg $ -*-Lua-*-
 --[[
-Copyright 2008, 2009 Manuel Pgouri-Gonnard.
+Copyright 2008, 2009 Manuel Pégourié-Gonnard.
 
 This program is free software: you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -17,1061 +16,60 @@
 
 Previous work in the public domain:
 - Contributions from Reinhard Kotucha (2008).
-- First texlua versions by Frank Kster (2007).
+- First texlua versions by Frank Küster (2007).
 - Original shell script by Thomas Esser, David Aspinall, and Simon Wilkinson.
 --]]
 
---------------------------------------------------------------------------------
-------------------   global constants and general functions   ------------------
---------------------------------------------------------------------------------
-
------------------------------   global constants   -----------------------------
-
--- progname and version
-progname = 'texdoc'
-version = '0.47'
-if string.sub(version, -1) == '+' then
-    local svnrev = string.match('$Rev$', '%$Rev:%s*(%d*)%s*%$');
-    version = svnrev and version..' svn r'..svnrev or version..' git'
-end
-
--- make sure to update setup_config_from_cl() accordingly
--- and set a default value in setup_config_from_defaults() if relevant
-usage_msg = [[
-texdoc tries to find appropriate TeX documentation for the specified NAME(s).
-With no NAME, it can print configuration information (-f, --files);
-the usual --help and --version options are also accepted.
-Usage: texdoc [OPTIONS]... [NAME]...
-  -f, --files           Print the name of the config files being used.
-  -e, --extensions=L    Require file extensions to be in the list L.
-  -w, --view            Use view mode: start a viewer.
-  -m, --mixed           Use mixed mode (view or list).
-  -l, --list            Use list mode: don't start a viewer.
-  -s, --search          Search for name as a substring.
-  -r, --regex           Search for name as a lua regex.
-  -a, --alias           Use the alias table.
-  -A, --noalias         Don't use the alias table.
-  -i, --interact        Use interactive menus.
-  -I, --nointeract      Use plain lists, no interaction required.
-  -v, --verbosity=N     Set verbosity level to N.
-  -d, --debug           Set verbosity level to maximum.
-Environment: PAGER, BROWSER, PDFVIEWER, PSVIEWER, DVIVIEWER.
-Files: <texmf>/texdoc/texdoc.cnf files, see the -f option.
-Homepage: http://tug.org/texdoc/
-Manual: displayed by `texdoc texdoc'.]]
-
-error_msg = [[
-Try `texdoc --help' for a short help, `texdoc texdoc' for the user manual.]]
-notfound_msg = [[
-Sorry, no documentation found for PKGNAME.
-If you are unsure about the name, try searching CTAN's TeX catalogue at
-http://ctan.org/search.html#byDescription.]]
-
-known_options = {
-    'viewer_.*',
-    'mode',
-    'interact_switch', 'alias_switch',
-    'ext_list',
-    'verbosity_level',
-    'lastfile_switch',
-    'rm_dir',
-    'rm_file',
-    'unzip_bz2',
-    'unzip_gz',
-}
-
-err_priority = {
-    error   = 1,
-    warning = 2,
-    info    = 3,
-    debug1  = 4,
-    debug2  = 5,
-    debug3  = 6,
-}
-err_max = 6
-
-place_holder = '%%s' -- used for viewer commands
-
--- zip/gz support
---
--- optionally, texdoc can support compressed documentation, but this is
--- system-dependant (commands for unzipping, temporary files, etc).
--- Since TeX Live doesn't ship compressed doc, downstream distributors who
--- want to ship zipped doc should change support_zipped to true *and* make sure
--- everything  works for them (look for support_zipped in the code).
--- If you use this feature, please let us know: if nobody uses it,
--- we'll drop it at some point.
-support_zipped = false
-
---------------------------   general-use functions   ---------------------------
-
--- Remark: we always assume our tables have no hole (that is, no nil value
--- followed by a non-nil value). So we use the simple iterator below, and
--- the # operator sometimes (a bit faster than table.getn).
-function list (t)
-    local i = 0
-    return function ()
-        i = i + 1
-        return t[i]
-    end
-end
-
--- remove the 'abc/../' components in a path
-function simplify_path (path)
-    local res = string.gsub (path, '/[^/]+/%.%./', '/')
-    return res -- get rid of gsub's 2nd return value
-end
-
--- change '/' to '\' on windows, removine 'abc/../' components first
-if os.type == "windows" then
-    function win32_hook (path)
-        local res = string.gsub (simplify_path(path), '/', '\\')
-        return res -- get rid of gsub's 2nd return value
-    end
-else
-    function win32_hook (path)
-        return simplify_path(path)
-    end
-end
-
---------------------------------------------------------------------------------
---------------------------   functions for searching   -------------------------
---------------------------------------------------------------------------------
-
-------------------   exploring trees (kpse-style functions)   ------------------
-
--- global variables:
--- exact_docfiles: list of "exact matches"
--- rel_docfiles: list of "non-exact matches"
-
-do -- begin scope of doc_roots, a lua version of kpse's TEXDOCS
-local doc_roots
-
--- structure of the doc_roots variable:
--- doc_roots[i] = {
---     path                 = <path>,
---     index_mandatory      = <does path begin with !! in TEXDOCS?>
---     recursion_allowed    = <does path ends with // in TEXDOCS?>,
--- }
-
--- set the doc_roots list from kpse's $TEXDOCS
-function get_texdocs ()
-    doc_roots = {}
-    local sep = (os.type == 'windows') and ';' or ':'
-    local kpse_texdocs = kpse.expand_var("$TEXDOCS")
-    -- expand the path and turn it into a lua list
-    local raw_doc_roots = string.explode(kpse.expand_braces(kpse_texdocs), sep)
-    err_print('Search paths:', 'debug3')
-    for i, dir in ipairs(raw_doc_roots) do
-        doc_roots[i] = {}
-        local n
-        dir, n = string.gsub (dir, '//$', '')
-        doc_roots[i].recursion_allowed = (n == 1)
-        doc_roots[i].path, n = string.gsub (dir, '^!!', '')
-        doc_roots[i].index_mandatory = (n == 1)
-        err_print(string.format('%s (index_mandatory=%s, recursion_allowed=%s)',
-                doc_roots[i].path,
-                doc_roots[i].index_mandatory   and 'true' or 'false',
-                doc_roots[i].recursion_allowed and 'true' or 'false'),
-            'debug3')
-    end
-end
-
--- once get_texdocs() is done, roots are represented by their index in doc_roots
--- this is usefull to avoid fake matches and also for the sort routine
--- conversions are done by real_path() below and code_path() later
-
--- decode a path as given in *_docfiles into a real path
-function real_path(fake)
-    local code, file = string.match(fake, '^(.-):(.*)$')
-    code = tonumber(code)
-    return win32_hook(doc_roots[code].path..'/'..file)
-end
-
--- find docfiles "matching" pattern
-function populate_docfiles (pattern)
-    pattern = normalize_pattern(pattern)
-    rel_docfiles, exact_docfiles = {}, {} -- global
-    is_dir = {} -- global; is_dir[path] = true iff path is a dir, see scan_lsr
-    for code, doc_root in ipairs (doc_roots) do
-        root, shift = lsr_root (doc_root.path)
-        if root and shift and doc_root.recursion_allowed then
-            scan_lsr(root, code, shift, pattern)
-        elseif (not doc_root.index_mandatory)
-            and lfs.isdir(doc_root.path) then
-            scan_tree(code, doc_root.path, '',
-                pattern, doc_root.recursion_allowed)
-        end
-    end
-    exact_docfiles = rmdirs (exact_docfiles)
-    rel_docfiles = rmdirs (rel_docfiles)
-end
-
-end -- scope of doc_roots
-
--- encode the base path on two digits and concatenate with filename
-function code_path (code, file)
-    local padding = (code > 9) and '' or '0'
-    return padding..code..':'..file
-end
-
--- merge two components of a path, taking care of empty components
-function merge_path (a, b)
-    return ((a == '') or (b == '')) and a..b or a..'/'..b
-end
-
--- scan a tree without ls-R file
-function scan_tree (code, base, cwd, pattern, recurse)
-    for file in lfs.dir(base..'/'..cwd) do
-        if file ~= '.' and file ~= '..' then
-            local f = (cwd == '') and file or cwd..'/'..file
-            if lfs.isdir(base..'/'..f) then
-                if recurse then scan_tree(code, base, f, pattern, recurse) end
-            else
-                process_file(file, f, code, pattern, true)
-            end
-        end
-    end
-end
-
--- finds a ls-R file in a parent directory an return it or nil
-function lsr_root (path)
-    if not lfs.isdir (path) then return end
-    local root, shift = path, ''
-    if string.sub(root, -1) == '/' then root = string.sub(root, 1, -2) end
-    while string.find(root, '/', 1, true) do
-        if lfs.isfile(root..'/ls-R') then
-            return root, shift
-        end
-        local last_comp = string.match(root, '^.*/(.*)$')
-        -- /!\ cannot put last_comp in a regex: can contain special char
-        root = string.sub(root, 1, - (#last_comp + 2))
-        shift = last_comp..'/'..shift
-    end
-end
-
--- scan a ls-R file
-function scan_lsr (cwd, code, shift, pattern)
-    local isdoc = false
-    local current_dir
-    local l = #shift
-    local lsr = assert(io.open(cwd..'/ls-R', 'r'))
-    local _ = lsr:read('*line') -- throw away first line (comment)
-    local maybe_dir = true -- next line may be a directory
-    while true do
-        local line = lsr:read('*line')
-        while line == '' do line, maybe_dir = lsr:read('*line'), true end
-        if line == nil then break end  -- EOF
-        local dir_line = maybe_dir and string.match (line, '^%./(.*):$')
-        if dir_line then
-            maybe_dir = false -- next line may not be a dir
-            if string.sub (dir_line, 1, l) == shift then
-                isdoc = true
-                current_dir = string.sub (dir_line, l+1)
-                is_dir[code_path(code, current_dir)] = true
-            elseif isdoc then
-                break -- we're exiting the ./doc (or shift) dir, so it's over
-            end
-        elseif isdoc then
-            process_file (line, merge_path(current_dir, line), code, pattern)
-        end
-    end
-    lsr:close()
-end
-
--- remove directories from a list
-function rmdirs (files)
-    local res = {}
-    for f in list (files) do
-        if not is_dir[f] then table.insert(res, f) end
-    end
-    return res
-end
-
--- like populate_docfiles, but rel replaces exact if exact is empty
-function mixed_populate_docfiles (pattern)
-    populate_docfiles (pattern)
-    if not exact_docfiles[1] then
-        if not string.find (pattern, '/') then
-            err_print ("No exact match, trying full search mode.", "info")
-        end
-        exact_docfiles = rel_docfiles
-    end
-end
-
--- for sty files, we obviously don't want to look in TEXDOCS...
--- and we don't need a list since those are not duplicated (ahem...)
-function populate_docfiles_sty (styname)
-    exact_docfiles = { kpse.find_file (styname) }
-    rel_docfiles = {}
-end
-
-----------------------------   selecting results   -----------------------------
-
--- says if file has a 'good' extenstion according to ext_list
-function check_ext(file, pattern)
-    local good_ext, exact_match = false, false
-    local l, pat = string.len(pattern) + 1, pattern..'.'
-    for e in list(config.ext_list) do
-        if e == '*' then
-            good_ext = true
-            if string.sub(file, 1, l) == pat then exact_match = true end
-        elseif (e == '') then
-            if not string.find(file, '.', 1, true) then good_ext = true end
-            if file == pattern then exact_match = true end
-        else
-            if string.sub(file, -string.len(e)) == e then good_ext = true end
-            if file == pattern..'.'..e then exact_match = true end
-        end
-    end
-    return good_ext, exact_match
-end
-
--- include a file in the *_docfiles lists if it "matches"
-function process_file (file, pathfile, code, pattern)
-    file = string.lower(file)
-    local base, ext = string.match(file, '^(.*)%.(.*)$')
-    if string.find(string.lower(pathfile), pattern, 1, no_regex) then
-        local good_ext, exact_match = check_ext(file, pattern)
-        if good_ext then
-            if exact_match then
-                table.insert(exact_docfiles, code_path (code, pathfile))
-            else
-                table.insert(rel_docfiles, code_path (code, pathfile))
-            end
-        end
-    end
-end
-
--- for now, just make lowercase, but may do more later
-function normalize_pattern (pattern)
-    return string.lower(pattern)
-end
-
------------------------------   sorting results   ------------------------------
-
--- compare two filenames with the following rule:
--- 1. extensions are ordered as in ext_list first,
--- 2. then filenames lexicographically (this include tree ordering).
-function file_order (a, b)
-    local ext_a = extension(a)
-    local ext_b = extension(b)
-    ext_pos_a = config.ext_list_inv[ext_a] or (config.ext_list_max+1)
-    ext_pos_b = config.ext_list_inv[ext_b] or (config.ext_list_max+1)
-    if ext_pos_a < ext_pos_b then
-        return true
-    elseif ext_pos_a > ext_pos_b then
-        return false
-    else
-        return (a < b)
-    end
-end
-
--- returns the most specific extension of file in ext_list, or nil
-function extension(file)
-    local ext = nil
-    for e in list(config.ext_list) do
-        if (e == '*') and (ext == nil) then
-            ext = e
-        elseif (e == '') and not string.find(file, '.', 1, true) then
-            ext = e
-        elseif string.sub(file, -string.len(e)-1) == '.'..e then
-            if (ext == nil) or (ext == '*')
-                or (string.len(e) > string.len(ext)) then
-                ext = e
-            end
-        end
-    end
-    return ext
-end
-
---------------------------------------------------------------------------------
-----------------   functions to set config values and aliases   ----------------
---------------------------------------------------------------------------------
-
-----------------------------   general functions   -----------------------------
-
--- set a config parameter, but don't overwrite it if already set
--- three special types: *_list (list), *_switch (boolean), *_level (number)
-function set_config_element (key, value, context)
-    local is_known = false -- is key a valid option?
-    for option in list(known_options) do
-        if string.match(key, option) then is_known = true break end
-    end
-    -- warn and exit if key is not a known option
-    if not is_known then config_warn(key, nil, context) return end
-    -- exit if key is already set (/!\ must test for nil, not false)
-    if not (config[key] == nil) then return nil end
-    if string.match(key, '_list$') then -- coma-separated list
-        local values = string.explode(value, ',')
-        local inverse = {}
-        for i, j in ipairs(values) do -- sanitize values...
-            j = string.gsub(j, '%s*$', '')
-            j = string.gsub(j, '^%s*', '')
-            values[i] = j
-            inverse[j] = i -- ... and build inverse mapping on the way
-        end
-        config[key] = values
-        config[key..'_inv'] = inverse
-        config[key..'_max'] = #values
-    elseif string.find (key, '_switch$') then -- boolean
-        if value == 'true' then
-            config[key] = true
-        elseif value == 'false' then
-            config[key] = false
-        else
-            config_warn (key, value, context)
-        end
-    elseif string.find (key, '_level$') then -- integer
-        local val = tonumber (value)
-        if val then
-            config[key] = val
-        else
-            config_warn (key, value, context)
-        end
-    else -- string
-        config[key] = value
-    end
-    -- special case: if we just set verbosity_level, print version info now
-    if key == 'verbosity_level' then
-        err_print(arg[0]..' version '..version, 'debug1')
-    end
-    -- now tell what we have just done, for debugging
-    err_print('Setting "'..key..'='..value..'" '
-    ..context_to_string(context)..'.', 'debug2')
-end
-
--- a helper  function for warning messages in the above
-function config_warn (key, value, context)
-    local begin = value and 'Illegal value "'..value..'" for option "'..key..'"'
-    or 'Unknown option "'..key..'"'
-    local ending = '.  Skipping.'
-    err_print (begin..'\n    '..context_to_string(context)..ending, 'warning')
-end
-
--- interpreting 'context' for the previous functions
-function context_to_string(context)
-    if not context then return '(no context)' end
-    if      context.src == 'cl' then
-        return 'from command line option "'..context.name..'"'
-    elseif  context.src == 'env' then
-        return 'from environment variable "'..context.name..'"'
-    elseif  context.src == 'file' then
-        return 'in file "'..context.file..'" on line '..context.line
-    elseif  context.src == 'def' then
-        return 'from built-in defaults'
-    else
-        return 'from unkown source (should not happen, please report)'
-    end
-end
-
--- set a whole list, also whithout overwriting
-function set_config_list (conf, context)
-    for key, value in pairs(conf) do
-        set_config_element (key, value, context)
-    end
-end
-
--- set an alias (w/o overwriting)
-function set_alias (key, value)
-    if alias[key] == nil then
-        alias[key] = value
-    end
-end
-
-------------------------   options from command line   -------------------------
-
--- set config from the command line
--- Please make sure to update usage_msg accordingly
--- and set a default value in setup_config_from_defaults() if relevant.
--- TODO: should use some getopt_long()-like mechanism some day
-function setup_config_from_cl ()
-    local curr_arg
-    local function set_config_elt(key, val)
-        set_config_element(key, val, {src='cl', name=curr_arg})
-    end
-    while arg[1] and string.match(arg[1],'^%-') do
-        curr_arg = table.remove(arg,1)
-        if (curr_arg == '-h') or (curr_arg == '--help') then
-            print (usage_msg)
-            os.exit(0)
-        elseif (curr_arg == '-V') or (curr_arg == '--version') then
-            print (progname .. ' ' .. version )
-            os.exit(0)
-        elseif (curr_arg == '-f') or (curr_arg == '--files') then
-            print (progname .. ' ' .. version )
-            setup_config_from_files ()
-            show_config_files (print, true)
-            os.exit(0)
-        elseif (curr_arg == '-w') or (curr_arg == '--view') then
-            set_config_elt('mode', 'view')
-        elseif (curr_arg == '-m') or (curr_arg == '--mixed') then
-            set_config_elt('mode', 'mixed')
-        elseif (curr_arg == '-l') or (curr_arg == '--list') then
-            set_config_elt('mode', 'list')
-        elseif (curr_arg == '-s') or (curr_arg == '--search') then
-            set_config_element ('mode', 'search', {src='cl', name=curr_arg})
-        elseif (curr_arg == '-r') or (curr_arg == '--regex') then
-            set_config_element ('mode', 'regex', {src='cl', name=curr_arg})
-        elseif (curr_arg == '-I') or (curr_arg == '--nointeract') then
-            set_config_elt('interact_switch', 'false')
-        elseif (curr_arg == '-i') or (curr_arg == '--interact') then
-            set_config_elt('interact_switch', 'true')
-        elseif (curr_arg == '-A') or (curr_arg == '--noalias') then
-            set_config_elt('alias_switch', 'false')
-        elseif (curr_arg == '-a') or (curr_arg == '--alias') then
-            set_config_elt('alias_switch', 'true')
-        elseif (curr_arg == '-d') or (curr_arg == '--debug') then
-            set_config_elt('verbosity_level', err_max)
-        elseif string.match(curr_arg, '^%-v') then
-            local value = string.gsub(curr_arg, '^%-v=?', '')
-            set_config_elt('verbosity_level', value)
-        elseif string.match(curr_arg, '^%-%-verbosity') then
-            local value = string.gsub(curr_arg, '^%-%-verbosity=?', '')
-            set_config_elt('verbosity_level', value)
-        elseif string.match(curr_arg, '^%-e') then
-            local value = string.gsub(curr_arg, '^%-e=?', '')
-            set_config_elt('ext_list', value)
-        elseif string.match(curr_arg, '^%-%-extensions') then
-            local value = string.gsub(curr_arg, '^%-%-extensions=?', '')
-            set_config_elt('ext_list', value)
-        else
-            err_print ("unknown option: "..curr_arg, "error")
-            print (error_msg)
-            os.exit(1)
-        end
-    end
-end
-
--------------------------   config from environment   --------------------------
-
--- set config from environment if available
-function setup_config_from_env ()
-    local function set_config_elt_from_vars(key, vars)
-        for var in list(vars) do
-            local value = os.getenv(var)
-            if value then
-                set_config_element(key, value, {src='env', name=var})
-            end
-        end
-    end
-    set_config_elt_from_vars('viewer_pdf',
-    {"PDFVIEWER_texdoc", "TEXDOCVIEW_pdf", "TEXDOC_VIEWER_PDF", "PDFVIEWER"})
-    set_config_elt_from_vars('viewer_ps',
-    {"PSVIEWER_texdoc", "TEXDOCVIEW_ps", "TEXDOC_VIEWER_PS", "PSVIEWER"})
-    set_config_elt_from_vars('viewer_dvi',
-    {"DVIVIEWER_texdoc", "TEXDOCVIEW_dvi", "TEXDOC_VIEWER_DVI", "DVIVIEWER"})
-    set_config_elt_from_vars('viewer_html',
-    {"BROWSER_texdoc", "TEXDOCVIEW_html", "TEXDOC_VIEWER_HTML", "BROWSER"})
-    set_config_elt_from_vars('viewer_txt',
-    {"PAGER_texdoc", "TEXDOCVIEW_txt", "TEXDOC_VIEWER_TXT", "PAGER"})
-end
-
-----------------------   options and aliases from files   ----------------------
-
--- set config+aliases from a particular config file assumed to exist
-function read_config_file(configfile)
-    local cnf = assert(io.open(configfile, 'r'))
-    local lineno = 0
-    while true do
-        local key, val
-        local line=cnf:read('*line')
-        lineno = lineno + 1
-        if line == nil then break end  -- EOF
-        line = string.gsub(line, '%s*#.*$', '') -- comments begin with #
-        line = string.gsub(line, '%s*$', '')    -- remove trailing spaces
-        line = string.gsub(line, '^%s*', '')    -- remove leading spaces
-        key, val = string.match(line, '^([%a%d_]+)%s*=%s*(.+)')
-        if key and val then
-            set_config_element(key, val, {
-                src='file', file=configfile, line=lineno})
-        else
-            key, val = string.match(line, '^alias%s+([%a%d_-]+)%s*=%s*(.+)')
-            if key and val then
-                set_alias(key, val)
-            else
-                if (not string.match (line, '^%s*$')) then
-                    err_print ('syntax error in '..configfile..
-                    ' at line '..lineno..'.', 'warning')
-                end
-            end
-        end
-    end
-    cnf:close()
-end
-
--- return a table with config file and if they exist
-function get_config_files ()
-    local platform = string.match (kpse.var_value ('SELFAUTOLOC'), '.*/(.*)$')
-    local TEXMFHOME  = kpse.var_value ('TEXMFHOME')
-    local TEXMFLOCAL = kpse.var_value ('TEXMFLOCAL')
-    local TEXMFMAIN  = kpse.var_value ('TEXMFMAIN')
-    return {
-        TEXMFHOME  .. '/texdoc/texdoc-'..platform..'.cnf',
-        TEXMFHOME  .. '/texdoc/texdoc.cnf',
-        TEXMFHOME  .. '/texdoc/texdoc-dist.cnf',
-        TEXMFLOCAL .. '/texdoc/texdoc-'..platform..'.cnf',
-        TEXMFLOCAL .. '/texdoc/texdoc.cnf',
-        TEXMFMAIN  .. '/texdoc/texdoc.cnf'
-    }
-end
-
--- the config_files table is shared by the next two functions
-do
-local config_files = {}
-
--- set config/aliases from all config files
-function setup_config_from_files ()
-    for i, file in ipairs (get_config_files ()) do
-        local found = lfs.isfile(file)
-        config_files[i] = {
-            path = file,
-            status = found and (config.lastfile_switch
-            and 'disabled' or 'active') or 'absent',
-        }
-        if config_files[i].status == 'active' then
-            read_config_file (file)
-        end
-    end
-end
-
--- now a special information function (see -f,--file option)
-function show_config_files (print_fun, prefix)
-    print_fun("Configuration files are:")
-    for i, file in ipairs (config_files) do
-        local home = prefix and
-        ((i==2) and "(*) " or "    ") -- home conffile is the 2nd
-        or ''
-        print_fun (home..file.status..'\t'..win32_hook(file.path))
-    end
-    if prefix then
-        print("(*) This is the recommended configuration file "
-        .. "for your personal preferences.")
-    end
-end
-
-end -- scope of config_files
-
-----------------------   options from built-in defaults   ----------------------
-
--- for default viewer on general Unix, we have a list; the following two
--- functions are used to check in the path which program is available
-
--- check if "name" is the name of a file in the path
--- Warning: to be used only on Unix! (separators, and PATH irrelevant on win32)
-function is_in_path(name)
-    local path_list = string.explode(os.getenv("PATH"), ':')
-    for _, path in ipairs(path_list) do
-        if lfs.isfile(path..'/'..name) then return true end
-    end
-    return false
-end
-
--- return the first element of "list" whose name is found in path, or nil
-function first_in_path(cmds)
-    for _, cmd in ipairs(cmds) do
-        if is_in_path(cmd[1]) then return cmd[2] end
-    end
-    return nil
-end
-
--- set some fall-back default values if no previous value is set
-function setup_config_from_defaults()
-    local function set_config_ls(ls) set_config_list(ls, {src='def'}) end
-    local function set_config_elt(key, val)
-        set_config_element(key, val, {src='def'})
-    end
-    if (os.type == "windows") then
-        set_config_ls {
-            -- Use 'start' to get file associations.
-            -- We need to quote the filenames, but the first quoted argument
-            -- is considered as the title by start, so we provide a dummy title.
-            -- Also, since the command line parser removes quotes if there
-            -- is no space inside, the dummy title must contain spaces.
-            viewer_dvi    = 'start "texdoc dvi viewer"',
-            viewer_html   = 'start "texdoc html viewer"',
-            viewer_pdf    = 'start "texdoc pdf viewer"',
-            viewer_ps     = 'start "texdoc ps viewer"',
-            -- 'more' is always available.
-            -- However, we can't assume texdoc is called from a cmd.exe window
-            -- (it can be run from the start->run menu), hence we make sure
-            -- to open a new window if needed.
-            viewer_txt    = 'start cmd /k more',
-        }
-    elseif (os.name == 'macosx') then
-        set_config_ls {
-            viewer_dvi    = 'open',
-            viewer_html   = 'open',
-            viewer_pdf    = 'open',
-            viewer_ps     = 'open',
-            viewer_txt    = 'less',
-        }
-    else -- generic Unix
-        set_config_ls {
-            viewer_dvi      = first_in_path {
-                {'gnome-open',  '(gnome-open %s) &'},   -- gnome
-                {'kde-open',    '(kde-open %s) &'},     -- kde 4
-                {'kfmclient',   '(kfmclient exec %s) &'}, -- older kde
-                {'exo-open',    '(exo-open %s) &'},     -- xfce
-                {'xdg-open',    '(xdg-open %s) &'},     -- freedesktop.org
-                {'evince',      '(evince %s) &'},
-                {'okular',      '(okular %s) &'},
-                {'kdvi',        '(kdvi %s) &'},
-                {'xgdvi',       '(xgdvi %s) &'},
-                {'spawg',       '(spawg %s) &'},
-                {'spawx11',     '(spawx11 %s) &'},
-                {'tkdvi',       '(tkdvi %s) &'},
-                {'dvilx',       '(dvilx %s) &'},
-                {'advi',        '(advi %s) &'},
-                {'xdvik-ja',    '(xdvik-ja %s) &'},
-                {'xdvi',        '(xdvi %s) &'},
-                {'see',         '(see %s) &'}
-            },
-            viewer_html     = first_in_path {
-                {'gnome-open',  '(gnome-open %s) &'},   -- gnome
-                {'kde-open',    '(kde-open %s) &'},     -- kde 4
-                {'kfmclient',   '(kfmclient exec %s) &'}, -- older kde
-                {'exo-open',    '(exo-open %s) &'},     -- xfce
-                {'xdg-open',    '(xdg-open %s) &'},     -- freedesktop.org
-                {'firefox',     '(firefox %s) &'},
-                {'seamonkey',   '(seamonkey %s) &'},
-                {'mozilla',     '(mozilla %s) &'},
-                {'konqueror',   '(konqueror %s) &'},
-                {'epiphany',    '(epiphany %s) &'},
-                {'opera',       '(opera %s) &'},
-                {'w3m',         'w3m'},
-                {'links',       'links'},
-                {'lynx',        'lynx'},
-                {'see',         'see'}
-            },
-            viewer_pdf      = first_in_path {
-                {'gnome-open',  '(gnome-open %s) &'},   -- gnome
-                {'kde-open',    '(kde-open %s) &'},     -- kde 4
-                {'kfmclient',   '(kfmclient exec %s) &'}, -- older kde
-                {'exo-open',    '(exo-open %s) &'},     -- xfce
-                {'xdg-open',    '(xdg-open %s) &'},     -- freedesktop.org
-                {'evince',      '(evince %s) &'},
-                {'okular',      '(okular %s) &'},
-                {'kpdf',        '(kpdf %s) &'},
-                {'xpdf',        '(xpdf %s) &'},
-                {'acroread',    '(xpdf %s) &'},
-                {'see',         '(see %s) &'}
-            },
-            viewer_ps       = first_in_path {
-                {'gnome-open',  '(gnome-open %s) &'},   -- gnome
-                {'kde-open',    '(kde-open %s) &'},     -- kde 4
-                {'kfmclient',   '(kfmclient exec %s) &'}, -- older kde
-                {'exo-open',    '(exo-open %s) &'},     -- xfce
-                {'xdg-open',    '(xdg-open %s) &'},     -- freedesktop.org
-                {'evince',      '(evince %s) &'},
-                {'okular',      '(okular %s) &'},
-                {'kghostview',  '(kghostview %s) &'},
-                {'gv',          '(gv %s) &'},
-                {'see',         '(see %s) &'}
-            },
-            viewer_txt      = first_in_path {
-                {'most',        'most'},
-                {'less',        'less'},
-                {'more',        'more'}
-            }
-        }
+-- load a local environment, importing symbols from (this function's) _G
+-- usage: local L = {} load_env(L, {'a', 'b'})
+function load_env(l, symbols)
+    local _, symb
+    for _, symb in ipairs(symbols) do
+        assert(_G[symb] ~= nil,
+            'Internal error: trying to import undefined symbol '..symb..'.')
+        l[symb] = _G[symb]
+    end
+    setfenv(2, l)
+end
+
+-- export symbols from a local environment to (this fonction's) _G
+function export_symbols(l, symbols)
+    local _, symb
+    for _, symb in ipairs(symbols) do
+        assert(l[symb] ~= nil,
+            'Internal error: trying to export undefined symbol '..symb..'.')
+        assert(_G[symb] == nil,
+            'Internal error: trying to export existing symbol '..symb..'.')
+        _G[symb] = l[symb]
     end
-    -- then various, platform independant, stuff
-    set_config_ls {
-        mode                = 'view',
-        interact_switch     = 'true',
-        verbosity_level     = '3',
-    }
-    -- must be set after mode!
-    set_config_elt ('alias_switch', alias_from_mode(config.mode))
-    -- now a particular case for config.ext_list and zip-related stuff
-    if support_zipped then
-        set_config_elt('ext_list',
-        'pdf,pdf.gz,pdf.bz2, html,html.gz,html.bz2, txt,txt.gz,txt.bz2,'..
-        'man1.pdf, man5.pdf'..
-        'ps,ps.gz,ps.bz2, dvi,dvi.gz,dvi.bz2, ,gz,bz2')
-        set_config_ls {
-            unzip_gz    = 'gzip -d -c ',
-            unzip_bz2   = 'bzip -d -c ',
-            rm_file     = 'rm -f',
-            rm_dir      = 'rmdir'
-        }
-    else
-        set_config_elt('ext_list', 'pdf, html, txt, man1.pdf, man5.pdf, ps, dvi, ')
-    end
-end
-
--- the default value of config.alias_switch depends on the mode as follows
-function alias_from_mode (mode) -- /!\ returns a string!
-    if (mode == 'view') or (mode == 'mixed') or (mode == 'list') then
-        return 'true'
-    else
-        return 'false'
-    end
-
 end
 
---------------------------------------------------------------------------------
----------------   functions for viewing/displaying the results   ---------------
---------------------------------------------------------------------------------
-
----------------------------------   viewing   ----------------------------------
-
--- prepare for viewing: returns <viewer command> and <viewer replacement>
--- <viewer replacement> is either:
--- 1. the filename, quoted with "
--- 2. the filename, quoted with " followed by some rm commands
--- The second case happens when the doc was zipped. In the case, this function
--- unzips it in a tempdir so that the viewer command can use the unzipped file.
-function how_to_view (filename)
-    filename = real_path(filename) -- TODO: if not filename then ...
-    viewext, zipext = nil, nil
-    if support_zipped then
-        viewext, zipext = string.match(filename, '.*%.([^.]*)%.([^.]*)$')
-        if viewext and zipext then
-            unzip_command = config['unzip_'..zipext]
-            local basename_pattern = '.*/(.*%.' .. viewext .. ')'
-            basename = string.match(filename,basename_pattern)
-            tmpdir = os.tmpdir("/tmp/texdoc.XXXXXX")
-            unzip_commandline = unzip_command .. filename .. " > "
-            .. tmpdir .. "/" .. basename
-            if os.execute(unzip_commandline) then
-                filename = tmpdir .. "/" .. basename
-            else
-                print("Error executing \n" .. unzip_commandline)
-            end
-            viewer_replacement = '"' .. filename .. '"; '
-            .. config.rm_file .. ' ' .. filename .. '; '
-            .. config.rm_dir .. ' ' .. tmpdir
-        end
-    end
-    -- if viewext wasn't set zipped way, then try the normal way
-    if not viewext then
-        viewer_replacement = '"' .. filename .. '"'
-        -- files without extension are assumed to be text
-        viewext = string.match(filename,'.*%.(.*)$') or 'txt'
-        if not config['viewer_'..viewext] then
-            err_print ("cannot determine type of file\n\t"
-            ..filename.."Assuming text.  Set the `viewer_"..viewext..
-            "' variable in texdoc.cnf to avoid this.", "warning")
-            viewext = 'txt'
-            if not config['viewer_'..viewext] then
-                err_print ("text viewer not found.  This "..
-                "should not happen, sorry.  Skipping\n\t"..filename, "error")
-            end
-        end -- viewer for ext
-    end -- zipped or not
-    return config['viewer_'..viewext], viewer_replacement
-end
-
--- view a file, if possible
-function try_viewing (view_command, viewer_replacement)
-    if not view_command then
-        view_result = false
-    else
-        if string.match (view_command, place_holder) then
-            view_command = string.gsub(
-            view_command, place_holder, viewer_replacement)
-        else
-            view_command = view_command..' '..viewer_replacement
-        end
-        err_print(view_command, 'debug1')
-        view_result = os.execute(view_command)
-        if not view_result then
-            err_print ("the following command failed\n\t"
-            .. view_command, "error")
-        end
-    end
-    return view_result
+-- load a component of texdoc
+function texdoc_load(name)
+    local f = kpse.find_file('texdoc/'..name..'.tlu', 'texmfscripts')
+    assert(f, 'Internal error: unable to find texdoc module '..name..'.')
+    dofile(f)
 end
 
---------------------------------   displaying   --------------------------------
-
--- display a table, sorted, numbered with given offset (0 by default),
--- with real path
-function display_table (t, offset)
-    offset = offset or 0
-    table.sort(t, file_order)
-    for i, val in ipairs (t) do
-        print(string.format('%2d %s', i+offset, real_path(val)))
-    end
-end
-
--- print a list of files as a menu (with an optional complementary list)
-function print_menu (files, comp)
-    comp = comp or {}
-    max_lines = tonumber (config.max_lines) or 20
-    local f = #files
-    if config.interact_switch then
-        local n = f + #comp
-        if n > max_lines then
-            io.write (n, " results.  Display them all? (y/N) ")
-            local ans = io.read('*line')
-            if not ((ans == 'y') or (ans == 'Y')
-                -- io.read is quite strange wrt windows line endings :-(
-                or (ans == '\ry') or (ans == '\rY')) then return end
-        end
-    end
-    display_table (files)
-    display_table (comp, f)
-    if config.interact_switch then
-        io.write ("Please enter the number of the file to view, ",
-        "anything else to skip: ")
-        local num = tonumber(io.read('*line'))
-        if num and (num <= f) and files[num] then
-            try_viewing (how_to_view (files[num]))
-        elseif num and comp[num-f] then
-            try_viewing (how_to_view (comp[num-f]))
-        end
-    end
-end
-
---------------------------------------------------------------------------------
------------------------   functions for error handling   -----------------------
---------------------------------------------------------------------------------
-
--- exit codes (probably make sense only with a single argument)
--- 0    OK
--- 1    Usage
--- 2    No doc found for at least one arg
--- ?    Should do something for viewer problems etc
-
--- apologize/complain if something went wrong
-function apologize (reason, name)
-    if reason == 'notfound' then
-        exit_code = 2
-        msg = string.gsub (notfound_msg, 'PKGNAME', name)
-        print (msg) -- to get rid of gsub's 2nd value
-    else
-        exit_code = 255
-        err_print ('Oops, this should not happen'..
-        ' (unknown error code).  Sorry.', 'error')
-    end
-end
-
--- check that arg list is not empty
-function assert_arg_not_empty ()
-    if not arg[1] then
-        print (usage_msg)
-        os.exit(1)
-    end
-end
-
--- generic error display function (see the error_priority constant)
-function err_print (msg, lvl)
-    -- be careful: maybe config.verbosity_level is not set yet
-    local verbosity_level = config.verbosity_level or 2
-    if err_priority[lvl] <= verbosity_level then
-        io.stderr:write ("texdoc "..lvl..": "..msg.."\n")
-    end
-end
-
---------------------------------------------------------------------------------
----------------------------   main code execution   ----------------------------
---------------------------------------------------------------------------------
-
------------------------------   initialisations   ------------------------------
-
 -- initialize kpathsea
-kpse.set_program_name(arg[-1], "texdoc")
-
--- config options from command line, env, conf files or defaults
-config = {} -- everything is stored in this table ...
-alias = {}  -- ... except aliases
-assert_arg_not_empty ()
-setup_config_from_cl ()
-assert_arg_not_empty ()
-setup_config_from_env ()
-setup_config_from_files ()
-setup_config_from_defaults ()
-
--- now that config.verbosity_level is known...
-show_config_files(function(s) err_print(s, 'debug1') end)
-get_texdocs()
-
-------------------------   looping over the arguments   ------------------------
-
--- initialising and saving a few values
-exit_code = 0
-no_regex = true
-real_populate_docfiles = populate_docfiles
-real_mixed_populate_docfiles = mixed_populate_docfiles
-real_real_path = real_path
+kpse.set_program_name(arg[-1], 'texdoc')
 
--- the actual loop
-for docname in list (arg) do
-    -- inform the user which arg beeing treated if more than one was provided
-    if arg[2] then
-        print ("*** Results for: "..docname.." ***")
-    end
-    -- applying alias if relevant
-    if config.alias_switch and alias[docname] then
-        err_print (docname.." aliased to "..alias[docname], 'info')
-        docname = alias[docname]
-    end
-    -- exceptions for arguments with extension given
-    if config.mode ~= 'regex' then
-        docname_base, docname_ext = string.match (docname, '^(.*)%.(.*)$')
-        if docname_ext == 'sty' then
-            err_print ("using special search mode for sty files", 'info')
-            populate_docfiles = populate_docfiles_sty
-            mixed_populate_docfiles = populate_docfiles_sty
-            real_path = function (arg) return arg end
-        end
-    end
-    -- main "ifcase mode" construct
-    if (config.mode == 'regex') then
-        no_regex = false
-        populate_docfiles(docname)
-        if rel_docfiles[1] then
-            print_menu (rel_docfiles)
-        else
-            apologize ('notfound', docname)
-        end
-    elseif (config.mode == 'search') then
-        populate_docfiles(docname)
-        if exact_docfiles[1] or rel_docfiles[1] then
-            print_menu (exact_docfiles, rel_docfiles)
-        else
-            apologize ('notfound', docname)
-        end
-    elseif (config.mode == 'list') then
-        mixed_populate_docfiles (docname)
-        if exact_docfiles[1] then
-            print_menu (exact_docfiles)
-        else
-            apologize ('notfound', docname)
-        end
-    elseif (config.mode == 'view') then
-        mixed_populate_docfiles (docname)
-        if exact_docfiles[1] then
-            table.sort(exact_docfiles, file_order)
-            try_viewing (how_to_view(exact_docfiles[1]))
-        else
-            apologize ('notfound', docname)
-        end
-    elseif (config.mode == 'mixed') then
-        mixed_populate_docfiles (docname)
-        if (not exact_docfiles[1]) then         -- no results
-            apologize ('notfound', docname)
-        elseif (not exact_docfiles[2]) then     -- 1 result
-            local ok = try_viewing (how_to_view(exact_docfiles[1]))
-            if not ok then apologize ('oops') end
-        else                                    -- 2 or more results
-            print_menu (exact_docfiles)
-        end
-    end
-    -- restoring possibly diverted values
-    populate_docfiles = real_populate_docfiles
-    mixed_populate_docfiles = real_mixed_populate_docfiles
-    real_path = real_real_path
-end
+-- declare global variables;
+-- they will be made read-only as soon as they are set
+C = {}      -- constants
+config = {} -- configuration settings
+
+-- actually load the components now
+texdoc_load('constants')
+texdoc_load('functions')
+texdoc_load('alias')
+texdoc_load('score')
+texdoc_load('config')
+texdoc_load('search')
+texdoc_load('view')
 
-os.exit(exit_code)
+-- execute main()
+texdoc_load('main')
 
--- Local Variables:
--- lua-indent-level: 4
--- tab-width: 4
--- indent-tabs-mode: nil
--- End:
--- vim:sw=4 ts=4 expandtab:
+-- the end
+os.exit(0)
Index: texlive-base-2009/texmf/scripts/texdoc/view.tlu
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ texlive-base-2009/texmf/scripts/texdoc/view.tlu	2010-01-03 11:23:04.000000000 +0900
@@ -0,0 +1,176 @@
+-- view a document and/or display the list of results in texdoc
+--[[ 
+Copyright 2008, 2009 Manuel Pégourié-Gonnard
+Distributed under the terms of the GNU GPL version 3 or later.
+See texdoc.tlu for details.
+--]]
+
+local L = {}
+load_env(L, {
+    'export_symbols',
+    'string', 'os', 'table', 'io',
+    'tonumber', 'ipairs', 'print', 'assert',
+    'config', 
+    'C',
+    'deb_print', 'err_print', 'parse_zip',
+})
+
+-----------------------------   view a document   ------------------------------
+
+-- view a document
+-- see search.tlu for the structure of the argument
+function view_doc(docfile)
+    return view_file(docfile.realpath)
+end
+
+-- get viewer and viewer_replacement before calling try_viewing
+-- returns false of failure, true on success
+-- viewer_replacement is either:
+-- 1. the filename, quoted with "
+-- 2. the filename, quoted with " followed by some rm commands
+-- The second case happens when the doc was zipped. In the case, this function
+-- unzips it in a tempdir so that the viewer command can use the unzipped file.
+function view_file (filename)
+    local viewer, viewer_replacement
+    -- check if the file is zipped
+    local nozipname, zipext = parse_zip(filename)
+    -- determine viewer_replacement
+    if zipext then
+        local unzip_cmd = config['unzip_'..zipext]
+        if not unzip_cmd then
+            err_print('error',
+            "No unzip command for ."..zipext..' files, skipping '..filename)
+            return false
+        end
+        local tmpdir = os.tmpdir("/tmp/texdoc.XXXXXX")
+        if not tmpdir then
+            err_print('error', 'Failed to create tempdir to unzip.')
+            return false
+        end
+        local basename = string.match(nozipname, '.*/(.*)$') or nozipname
+        local tmpfile = '"'..tmpdir..'/'..basename..'"'
+        local unzip = unzip_cmd..' "'..filename..'">'..tmpfile
+        deb_print('view', "Unzip command: "..unzip)
+        if not os.execute(unzip) then
+            err_print('error', "Failed to unzip '"..filename.."'")
+            os.remove(tmpfile)
+            os.remove(tmpdir)
+            return false
+        end
+        viewer_replacement = ''..tmpfile..'; '
+            ..config.rm_file..' '..tmpfile..'; '
+            ..config.rm_dir..' '..tmpdir
+        filename = nozipname
+    else
+        viewer_replacement = '"'..filename..'"'
+    end
+    -- files without extension are assumed to be text
+    local viewext = string.match(filename,'.*%.([^/]*)$') or 'txt'
+    -- special case : sty files use txt viewer
+    if viewext == 'sty' then viewext = 'txt' end
+    if not config['viewer_'..viewext] then
+        err_print('warning',
+            "No viewer_"..viewext.." defined, using viewer_txt.")
+        viewext = 'txt'
+    end
+    assert(config['viewer_'..viewext], 'Internal error: no viewer found.')
+    return try_viewing(config['viewer_'..viewext], viewer_replacement)
+end
+
+-- view a file, if possible
+function try_viewing (view_command, viewer_replacement)
+    if string.match (view_command, C.place_holder) then
+        view_command = string.gsub(
+        view_command, C.place_holder, viewer_replacement)
+    else
+        view_command = view_command..' '..viewer_replacement
+    end
+    deb_print('view', 'View comand: '..view_command)
+    if not os.execute(view_command) then
+        err_print('error', "Failed to execute '"..view_command.."'")
+        return false
+    end
+    return true
+end
+
+-----------------------------   display results   ------------------------------
+
+-- print a list of files (structure: see search.tlu) as a menu
+-- if showall is false, stops as soon a bad result is encountered
+function print_menu(name, doclist, showall)
+    local max_lines = tonumber(config.max_lines) or 20
+    if config.interact_switch and doclist[max_lines+1] then
+        -- there may be too many lines, count them
+        local n
+        if showall then
+            n = #doclist
+        else
+            n = 0
+            while doclist[n+1] and doclist[n+1]:quality() == 'good' do
+                n = n + 1
+            end
+        end
+        if n > max_lines then
+            io.write (n, " results.  Display them all? (y/N) ")
+            local ans = io.read('*line')
+            if not ((ans == 'y') or (ans == 'Y')
+                -- io.read had a bug wrt windows eol on some versions of texlua
+                or (ans == '\ry') or (ans == '\rY')) then
+                return
+            end
+        end
+    end
+    local i, doc
+    for i, doc in ipairs (doclist) do
+        if doc:quality() == 'killed' then break end
+        if doc:quality() ~= 'good' and not showall then break end
+        if config.machine_switch == true then
+            print(name, doc.score, doc.realpath)
+        else
+            print(string.format('%2d %s', i, doc.realpath))
+        end
+    end
+    if config.interact_switch then
+        io.write ("Please enter the number of the file to view, ",
+        "anything else to skip: ")
+        local num = tonumber(io.read('*line'))
+        if num and doclist[num] then
+            view_doc(doclist[num])
+        end
+    end
+end
+
+-----------------------   deliver results base on mode   -----------------------
+
+function deliver_results(name, doclist, many)
+    -- ensure that results were found or apologize
+    if not doclist[1] or doclist[1]:quality() == 'killed' then
+        if not config.machine_switch then
+            local msg = string.gsub(C.notfound_msg, C.notfound_msg_ph, name)
+            print(msg) -- get rid of gsub's 2nd value
+        end
+        return
+    end
+    -- shall we show all of them or only the "good" ones?
+    local showall = (config.mode == 'regex') or (config.mode == 'showall')
+    if not showall and doclist[1]:quality() ~= 'good' then
+        showall = true
+        err_print('info', 'No good result found, showing all results.')
+    end
+    -- view result or show menu based on mode and number of results
+    if (config.mode == 'view')
+        or config.mode == 'mixed' and (not doclist[2]
+            or (doclist[2]:quality() ~= 'good' and not showall)) then
+        view_doc(doclist[1])
+    else
+        if many and not config.machine_switch then 
+            print ("*** Results for: "..name.." ***")
+        end
+        print_menu(name, doclist, showall)
+    end
+end
+
+-- finally export a few symbols
+export_symbols(L, {
+    'deliver_results',
+})
Index: texlive-base-2009/texmf/texdoc/texdoc.cnf
===================================================================
--- texlive-base-2009.orig/texmf/texdoc/texdoc.cnf	2009-10-19 05:39:29.000000000 +0900
+++ texlive-base-2009/texmf/texdoc/texdoc.cnf	2010-01-03 11:22:35.000000000 +0900
@@ -34,11 +34,11 @@
 # If you want to enable support for zipped documentation (see comments in
 # texdoc.tlu), you may want to adapt viewer_* so that it starts a subshell:
 #
-# viewer_pdf = (xpdf %s )&
+# viewer_pdf = (xpdf %s) &
 #
 # Otherwise, the & will have no effect since the viewing command is followed by
 # some cleanup-commands for temporary files. For the same reason, %s must be the
-# last thing on you command line: (xpdf %s -option) will not work.
+# last thing on your command line: (xpdf %s -option) will not work.
 
 ### Other settings ###
 
@@ -47,9 +47,49 @@
 #
 # mode = view
 # interact_switch = true
-# alias_switch = true				# but false if mode is 'regex'
-# ext_list = pdf, html, txt, man1.pdf, man5.pdf, ps, dvi,  # empty string at end
-# verbosity_level = 3
+# alias_switch = true
+# ext_list = pdf, html, txt, ps, dvi,	# Note: empty string at end
+# badext_list = txt, 			# Note: empty string at end
+# verbosity_level = 2 	# Print: 0 nothing, 1 errors, 2 warnings, 3: infos
+# debug_list = 	# the empty list
+# machine_switch = false
+
+### Score ###
+
+# Only results with positive scores are displayed (unless mode is 'showall').
+# Results with score <= 100 are never displayed.
+# 
+# You can adjust the score of results containing a pattern with adjscore,
+# either globally or only for specific keywords
+
+# Makefile's are never documentation, -1000 should be enough to kill them
+adjscore /Makefile = -1000
+
+# tex-virtual-academy provides a lot of fake matches
+adjscore /tex-virtual-academy-pl/ = -50
+
+# Uncomment this to make the man pages have a greater priority
+#adjscore .man1. = 5
+#adjscore .man5. = 5
+
+# 'texdoc' may look like "tex's documentation" but it isn't...
+adjscore(tex) texdoc = -10
+adjscore(tex) tex-gyre = -10
+adjscore(tex) tex-ps = -10
+
+# avoid too many results to be shown for 'latex'
+# package names
+adjscore(latex) guide-to-latex = -10 # only usefull with the book
+adjscore(latex) latex-web-companion = -10
+adjscore(latex) tufte-latex = -10
+adjscore(latex) cweb-latex = -10
+adjscore(latex) duerer-latex = -10
+adjscore(latex) cjw-latex = -10
+adjscore(latex) ocr-latex = -10
+# file names
+adjscore(latex) Content_LaTeX_Package_Demo = -10
+adjscore(latex) example_latex = -10
+adjscore(latex) test_latex = -10
 
 ### Aliases ###
 
@@ -114,6 +154,22 @@
 alias color = grfguide
 alias epsfig = grfguide
 
+# latex's required psnfss2e bundle
+alias mathpazo = psnfss2e
+alias mathptmx = psnfss2e
+alias helvet = psnfss2e
+alias avant = psnfss2e
+alias courier = psnfss2e
+alias chancery = psnfss2e
+alias bookman = psnfss2e
+alias newcent = psnfss2e
+alias charter = psnfss2e
+alias times = psnfss2e
+alias palatino = psnfss2e
+alias mathptm = psnfss2e
+alias mathpple = psnfss2e
+alias utopia = psnfss2e 
+
 # ams
 alias amsmath = amsldoc
 alias amslatex = amshelp
@@ -159,8 +215,8 @@
 alias caption-dev = caption.pdf
 
 # misc
-alias hyperref = hyperref/manual
-alias hyperref = hyperref.pdf
+alias hyperref = hyperref/manual.pdf
+alias hyperref-dev = hyperref.pdf
 alias fontinst = fontinstallationguide
 alias psfrag = pfgguide
 alias bibtex = btxdoc
@@ -191,111 +247,39 @@
 
 ## a few easy patterns
 
-# egrep 'manual\.pdf\>' docfiles.list
-alias cjhebrew = cjhebrew/manual
-alias elpres = elpres-manual
-alias interactiveworkbook = interactiveworkbookmanual
-alias msc = msc/manual
+# egrep 'manual\.pdf\>'
 alias pdfslide = pdfslide/demo
-alias pdftricks = pdftricks/manual
-alias pst-qtree = pst-qtree-manual
-alias sciposter = scipostermanual
-alias sectionbox = sectionboxmanual
 alias t-angles = t-manual
 alias texmate = texmate2manual
 alias tree-dvips = tree-manual
-alias lingmacros = lingmacros-manual
-alias velthuis = velthuis/manual
-alias wallpaper = wallpapermanual
 
-# egrep 'user\.pdf\>' docfiles.list
+# egrep 'user\.pdf\>'
 alias cweb-latex = cweb-user
-alias footnpag = footnpag-user
 alias seminar = sem-user
-alias rcs = rcs-user
 
-# egrep 'doc\.pdf\>' docfiles.list
-alias testflow = testflow_doc
-alias arev = arevdoc
+# egrep 'doc\.pdf\>'
 alias barcode = eandoc.pdf
 alias barr = diaxydoc.pdf
-alias clock = clockdoc
 alias doublestroke = dsdoc.pdf
 alias enctex = encdoc-e
 alias enctex-cz = encdoc
-alias ethiop = ethiodoc
-alias exam = examdoc
-alias fge = fge-doc
-alias figbib = figbib_doc
-alias greektex = greektexdoc
-alias gu = gudoc
-alias hitec = hitec_doc
 alias hyplain = hydoc.pdf
 alias jurabib = jbendoc
 alias jurabib-de = jbgerdoc
 alias juramisc = jmgerdoc
-alias mathdesign = mathdesign-doc
-alias linguex = linguex-doc
 alias marvosym = marvodoc
-alias mciteplus = mciteplus_doc
-alias musixtex = generic/musixtex/musixdoc.pdf
-alias mwcls = mwclsdoc
+alias musixtex = musixdoc
 alias ofs = ofsdoc-e
-alias ofs-cz = ofsdoc-e
-alias petiteannonce = petiteannonce.doc.pdf
+alias ofs-cz = ofsdoc
 alias petri-nets = pndoc
-alias pgf-soroban = pgf-soroban-doc
-alias pinlabel = pinlabdoc
-alias prosper = prosper-doc
-alias pst-3dplot = pst-3dplot-doc
-alias pst-asr = pst-asr-doc
-alias pst-bar = pst-bar-doc
-alias pst-barcode = pst-barcode-doc
-alias pst-circ = pst-circ-doc
-alias pst-coil = pst-coil-doc
-alias pst-coxcoor = pst-coxcoor_doc
-alias pst-coxeterp = pst-coxeterp_doc
-alias pst-eps = pst-eps-doc
-alias pst-fractal = pst-fractal-doc
-alias pst-fun = pst-fun-doc
-alias pst-func = pst-func-doc
 alias pst-geo = pst-map3d-doc
-alias pst-grad = pst-grad-doc
-alias pst-jtree = pst-jtree-doc
-alias pst-light3d = pst-light3d-doc
-alias pst-math = pst-math-doc
-alias pst-optexp = pst-optexp-doc
-alias pst-optic = pst-optic-doc
-alias pst-osci = pst-osci-doc
-alias pst-pad = pst-pad-doc
-alias pst-solides3d = pst-solides3d-doc
-alias pst-soroban = pst-soroban-doc
-alias pst-stru = pst-stru-doc
-alias pst-text = pst-text-doc
-alias pst-uml = pst-uml-doc
-alias pst-vue3d = pst-vue3d-doc
-alias pstricks-add = pstricks-add-doc
-alias pxfonts = pxfontsdocA4
-alias rotpages = rotpages-doc
 alias sanskrit = sktdoc
-alias sdrt = sdrt-doc
-alias synproof = synproof-doc
-alias talk = talkdoc
-alias teubner = teubner-doc
-alias tikz-inet = tikz-inet-doc
-alias toptesi = toptesi-doc
-alias txfonts = txfontsdocA4
-alias uebungsblatt = uebungsblatt-doc
-alias upmethodology = upmethodology-doc
-alias wasy = wasydoc
-alias xyling = xyli-doc
 
 ## aliases basically borrowed from texdoctk.dat with some adaptations
 
 alias texguide = usrguide
 alias lehman = fontinstallationguide
 alias uktugfaq = newfaq
-alias datenumber = datenumber/doc.
 alias datenumber-de = datenumber/docgerman
 alias index = ind
 alias genfont1 = fntguide
@@ -309,18 +293,15 @@
 alias euro = eurosamp
 alias fourier = fourier-doc-en
 alias lmfonts = lm-info
-alias skt = sktdoc
 alias t1enc1 = fontsmpl
 alias yfonts = yfonts/readme
 alias mfpic1 = mfpguide
 alias dutch = rapdoc
 alias montex = mlsquick
 alias MeX = base/mex.html
-# alias gentlpl = gentl-pl # temporarily rm'ed from TL (sources needed)
 alias akademia = tex-virtual-academy-pl/index.html
 alias cyrillic = cyrillic/00readme.txt
 alias otibet = otibet/unidoc
-alias memoir = memman
 alias layouts = layman
 alias texsis = texsis/base/README
 alias startex = startex/base/guide
@@ -352,7 +333,6 @@
 alias tangles = t-angles/t-manual
 alias mathenv = mdwtab
 alias nath = nathguide
-alias gauss = gauss-doc
 alias gnlogic = gn-logic14
 alias footnote1 = mdwtools/footnote
 alias footnote2 = yafoot/yafoot-man
@@ -378,12 +358,10 @@
 alias acmtrans = acmtr2e
 alias aastex = aastex/aasguide
 alias ieee = IEEEtran_HOWTO
-alias ieeepes = ieeepes_doc
 alias nrc = nrc/userguide
 alias kluwer = kluwer/usrman
 alias spie = spie/article
 alias psgo = psgo/README
-alias skak = skakdoc
 alias cv = curve/curve
 alias preprint = preprint/00readme.txt
 alias sffms = sffms_manual
@@ -481,7 +459,7 @@
 # the next line has no effect when this file is installed as
 # TEXMFMAIN/texdoc/texdoc.cnf but is useful when it is installed as
 # TEXMFHOME/texdoc/texdoc-dist.cnf for the purpose of installing a newer
-# version of texdoc in one's home (eg, running texdoc from SVN)
+# version of texdoc in one's home (eg, running the development version)
 lastfile_switch = true
 
 # vim: ts=8 noexpandtab:
Index: texlive-base-2009/tlpkg/texlive.tlpdb
===================================================================
--- texlive-base-2009.orig/tlpkg/texlive.tlpdb	2009-11-07 11:29:45.000000000 +0900
+++ texlive-base-2009/tlpkg/texlive.tlpdb	2010-01-03 11:21:01.000000000 +0900
@@ -96838,16 +96838,25 @@
  texmf/doc/man/man1/texdoc.man1.pdf
  texmf/doc/man/man1/texdoctk.1
  texmf/doc/man/man1/texdoctk.man1.pdf
+ texmf/doc/texdoc/News
  texmf/doc/texdoc/texdoc.pdf
  texmf/doc/texdoc/texdoc.tex
 runfiles size=41
  texmf/scripts/tetex/texdoctk.pl
+ texmf/scripts/texdoc/alias.tlu
+ texmf/scripts/texdoc/config.tlu
+ texmf/scripts/texdoc/constants.tlu
+ texmf/scripts/texdoc/functions.tlu
+ texmf/scripts/texdoc/main.tlu
+ texmf/scripts/texdoc/score.tlu
+ texmf/scripts/texdoc/search.tlu
+ texmf/scripts/texdoc/view.tlu
  texmf/scripts/texdoc/texdoc.tlu
  texmf/texdoc/texdoc.cnf
  texmf/texdoctk/texdocrc-win32.defaults
  texmf/texdoctk/texdocrc.defaults
  texmf/texdoctk/texdoctk.dat
-catalogue-date 2007-12-27 15:23:50 +0100
+catalogue-date 2009-11-10 00:58:07 +0100
 catalogue-license gpl
 
 name texdoc.alpha-linux
