texlive[50627] trunk: texdoc (28mar19)

commits+karl at tug.org commits+karl at tug.org
Thu Mar 28 21:58:51 CET 2019


Revision: 50627
          http://tug.org/svn/texlive?view=revision&revision=50627
Author:   karl
Date:     2019-03-28 21:58:51 +0100 (Thu, 28 Mar 2019)
Log Message:
-----------
texdoc (28mar19)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/texdoc/texdoc.tlu
    trunk/Master/texmf-dist/doc/man/man1/texdoc.1
    trunk/Master/texmf-dist/doc/man/man1/texdoc.man1.pdf
    trunk/Master/texmf-dist/doc/support/texdoc/NEWS
    trunk/Master/texmf-dist/doc/support/texdoc/README.md
    trunk/Master/texmf-dist/doc/support/texdoc/texdoc.pdf
    trunk/Master/texmf-dist/doc/support/texdoc/texdoc.tex
    trunk/Master/texmf-dist/scripts/texdoc/texdoc.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib.tlu
    trunk/Master/texmf-dist/texdoc/texdoc.cnf

Added Paths:
-----------
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-alias.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-cli.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-config.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-const.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-score.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-search.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-util.tlu
    trunk/Master/texmf-dist/scripts/texdoc/texdoclib-view.tlu

Removed Paths:
-------------
    trunk/Master/texmf-dist/scripts/texdoc/alias.tlu
    trunk/Master/texmf-dist/scripts/texdoc/config.tlu
    trunk/Master/texmf-dist/scripts/texdoc/constants.tlu
    trunk/Master/texmf-dist/scripts/texdoc/functions.tlu
    trunk/Master/texmf-dist/scripts/texdoc/main.tlu
    trunk/Master/texmf-dist/scripts/texdoc/score.tlu
    trunk/Master/texmf-dist/scripts/texdoc/search.tlu
    trunk/Master/texmf-dist/scripts/texdoc/view.tlu

Modified: trunk/Build/source/texk/texlive/linked_scripts/texdoc/texdoc.tlu
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/texdoc/texdoc.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Build/source/texk/texlive/linked_scripts/texdoc/texdoc.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,11 +1,17 @@
 #!/usr/bin/env texlua
 
--- texdoc.tlu: small wrapper around main.tlu
--- (makes it easier to install a new version of texdoc in TEXMFHOME)
+-- texdoc.tlu: the main program of texdoc
 --
--- The TeX Live team, GPLv3, see texdoclib.tlu for details
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
 
+-- Note: we keep this file small as much as possible so that make it easier
+--       to install a new version of texdoc in TEXMFHOME.
+
+-- setup the kpse library and load texdoclib
 kpse.set_program_name(arg[-1], 'texdoc')
-require('texdoc.main')
+local texdoc = require('texdoclib')
 
+-- execute
+texdoc.cli.exec()
+
 -- vim: ft=lua:

Modified: trunk/Master/texmf-dist/doc/man/man1/texdoc.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/texdoc.1	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/doc/man/man1/texdoc.1	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,7 +1,7 @@
 .\" generated with Ronn/v0.7.3
 .\" http://github.com/rtomayko/ronn/tree/0.7.3
 .
-.TH "TEXDOC" "1" "June 2018" "Texdoc 3.0" "Texdoc manual"
+.TH "TEXDOC" "1" "March 2019" "Texdoc 3.1" "Texdoc manual"
 .
 .SH "NAME"
 \fBtexdoc\fR \- find & view documentation in TeX Live
@@ -10,29 +10,11 @@
 \fBtexdoc\fR [OPTION\.\.\.] NAME\.\.\.
 .
 .br
-\fBtexdoc\fR ACTION
+\fBtexdoc\fR [OPTION\.\.\.] ACTION
 .
 .SH "DESCRIPTION"
 Try to find appropriate TeX documentation for the specified NAME(s)\. Alternatively, perform the given ACTION and exit\.
 .
-.SH "ACTIONS"
-.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-Print this help message\.
-.
-.TP
-\fB\-V\fR, \fB\-\-version\fR
-Print the version number\.
-.
-.TP
-\fB\-f\fR, \fB\-\-files\fR
-Print the list of configuration files used\.
-.
-.TP
-\fB\-\-just\-view FILE\fR
-Display file, given with full path (no searching)\.
-.
 .SH "OPTIONS"
 .
 .TP
@@ -69,7 +51,7 @@
 .
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
-Print additional information (eg, viewer command)\.
+Print additional information (e\.g\., viewer command)\.
 .
 .TP
 \fB\-D\fR, \fB\-\-debug\fR
@@ -76,15 +58,90 @@
 Activate all debug output (equal to "\-\-debug=all")\.
 .
 .TP
-\fB\-d\fRLIST, \fB\-\-debug\fR=LIST
-Activate debug output restricted to LIST\.
+\fB\-d\fR LIST, \fB\-\-debug\fR=LIST
+Activate debug output restricted to the items specified in LIST\.
 .
+.br
+Available items: \fBconfig\fR, \fBfiles\fR, \fBsearch\fR, \fBscore\fR, \fBtexdocs\fR, \fBtlpdb\fR, \fBversion\fR, \fBview\fR, and \fBall\fR to activate all of these\.
+.
+.TP
+\fB\-c\fR NAME=VALUE
+Set configuration item NAME to VALUE\.
+.
+.SH "ACTIONS"
+.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print this help message\.
+.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number\.
+.
+.TP
+\fB\-f\fR, \fB\-\-files\fR
+Print the list of configuration files used\.
+.
+.TP
+\fB\-\-just\-view\fR FILE
+Display FILE, given with full path (no searching)\.
+.
 .SH "ENVIRONMENT"
-PAGER, BROWSER, PDFVIEWER, PSVIEWER, DVIVIEWER, and *_texdoc of each\.
 .
+.TP
+\fBBROWSER\fR, \fBBROWSER_texdoc\fR
+Set the command to be used for HTML documents\.
+.
+.TP
+\fBDVIVIEWER\fR, \fBDVIVIEWER_texdoc\fR
+Set the command to be used for DVI documents\.
+.
+.TP
+\fBMDVIEWER\fR, \fBMDVIEWER_texdoc\fR
+Set the command to be used for Markdown documents\.
+.
+.TP
+\fBPAGER\fR, \fBPAGER_texdoc\fR
+Set the command to be used for text documents\.
+.
+.TP
+\fBPDFVIEWER\fR, \fBPDFVIEWER_texdoc\fR
+Set the command to be used for PDF documents\.
+.
+.TP
+\fBPSVIEWER\fR, \fBPSVIEWER_texdoc\fR
+Set the command to be used for PS documents\.
+.
+.TP
+\fBLANG\fR, \fBLC_ALL\fR and so on
+Set the locale (which will influence on the search results)\.
+.
+.TP
+\fBTEXDOCS\fR
+In addition to the documents included in the TeX Live database, Texdoc also searches documentation under TEXMF trees specified by the kpathsea variable \fBTEXDOCS\fR\.
+.
 .SH "FILES"
 \fB<texmf>/texdoc/texdoc\.cnf\fR, see output of the \fB\-\-files\fR option\.
 .
+.SH "EXIT STATUS"
+The \fBtexdoc\fR command exists with one of the following values:
+.
+.TP
+0
+Success\.
+.
+.TP
+1
+Internal error\.
+.
+.TP
+2
+Usage error\.
+.
+.TP
+3
+No documentation found\.
+.
 .SH "REPORTING BUGS"
 Report bugs to \fItexdoc at tug\.org\fR\.
 .

Modified: trunk/Master/texmf-dist/doc/man/man1/texdoc.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/texdoc/NEWS
===================================================================
--- trunk/Master/texmf-dist/doc/support/texdoc/NEWS	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/doc/support/texdoc/NEWS	2019-03-28 20:58:51 UTC (rev 50627)
@@ -2,6 +2,14 @@
 ===============
 (This file public domain.)
 
+Version 3.1 (TeX Live 2019)
+===========================
+- New option -c: changing configure temporally
+- New config item `texlive_tlpdb` to specify a path for texlive.tlpdb
+- Fixed an issue that texdoc fails to open gzipped file in GNOME/XFCE
+- Added prefixes to script files not to contaminate kpse search space
+- Many other small improvements and bug fixes
+
 Version 3.0 (TeX Live 2018)
 ===========================
 This version has two big features:

Modified: trunk/Master/texmf-dist/doc/support/texdoc/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/support/texdoc/README.md	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/doc/support/texdoc/README.md	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,6 +1,7 @@
-# Texdoc (v3.0)
+# Texdoc v3.1 (2019-03-28)
 
 [![Build Status](https://travis-ci.org/TeX-Live/texdoc.svg?branch=master)](https://travis-ci.org/TeX-Live/texdoc)
+[![Build status](https://ci.appveyor.com/api/projects/status/uq28ms7eba7ns6d3/branch/master?svg=true)](https://ci.appveyor.com/project/wtsnjp/texdoc/branch/master)
 
 Texdoc is a command line program to find and view documentation in TeX Live.
 
@@ -55,7 +56,7 @@
 
 ### Generating all documentation
 
-This will generate both the PDF and the manpage in `doc/` directory.
+Following will generate both the PDF and the manpage in `doc/` directory.
 
 ```
 $ rake doc
@@ -63,37 +64,49 @@
 
 ### Generating a pre-hashed cache file
 
-This will generate a pre-hashed cache file `script/Data.tlpdb.lua`. This task have to be done under a TeX Live setup with tlpdb.
+Following will generate a pre-hashed cache file `script/Data.tlpdb.lua`. This task have to be done under a TeX Live setup with tlpdb.
 
 ```
 $ rake gen_datafile
 ```
 
-### Running all tests
+### Running tests
 
-This will run all tests in `spec/` directory.
+Following will run all tests in `spec/` directory.
 
 ```
 $ rake test
 ```
 
+Alternatively, you can give spec names with the `--list` (`-l`) option for this task. E.g., following will run only `spec/action/help_spec.rb` and `spec/mode/list_spec.rb`:
+
+```
+$ rake test -- -l action/help,mode/list
+```
+
 ### Showing all available tasks
 
-This will show all available tasks with a short discription.
+Following will show all available tasks with a short description.
 
 ```
 $ rake -T
 ```
 
+In addition to that, for options available tasks (e.g., `rake test` and `rake run_texdoc`) you can get options information with `-h` option for each task:
+
+```
+$ rake test -- -h
+```
+
 ## Further Information
 
-More specific information (e.g. TODO) can be found in the Wiki of our GitHub repository. Please visit:
+More specific information (e.g., TODO) can be found in the Wiki of our GitHub repository. Please visit:
 
 * <https://github.com/TeX-Live/texdoc/wiki>
 
 ## Copyright and License
 
-Copyright 2008-2018 Manuel Pégourié-Gonnard, Takuto Asakura, Karl Berry, and Norbert Preining. All rights reserved.
+Copyright 2008 Manuel Pégourié-Gonnard, Takuto Asakura, and the TeX Live Team.
 
 This package is distributed under the terms of the GNU General Public License as published by the Free Software Foundation, either [version 3](./COPYING) of the License, or (at your option) any later version.
 

Modified: trunk/Master/texmf-dist/doc/support/texdoc/texdoc.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/texdoc/texdoc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/support/texdoc/texdoc.tex	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/doc/support/texdoc/texdoc.tex	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,13 +1,11 @@
+%#!xelatex
 % Texdoc user manual
-% Copyright 2018 Manuel Pégourié-Gonnard and Takuto Asakura
+% Copyright 2008 Manuel Pégourié-Gonnard and Takuto Asakura
 % distributed under the terms of GPL v3 or later
 
-%!TEX encoding=utf-8
-%!TEX program=xelatex
-
 \setlength\overfullrule{5pt}
 
-\documentclass[a4paper, oneside]{scrartcl}
+\documentclass[a4paper,oneside]{scrartcl}
 \usepackage{fontspec}
 \usepackage{xunicode}
 
@@ -19,13 +17,13 @@
 \newcommand\mylangle{$\langle$}
 \newcommand\myrangle{$\rangle$}
 
-\usepackage{xargs, xspace, fancyvrb, xcolor, pifont, calc, ifmtarg, mathstyle}
+\usepackage{xargs,xspace,fancyvrb,xcolor,pifont,calc,ifmtarg,mathstyle}
 
-\usepackage[sf, bf]{titlesec}
+\usepackage[sf,bf]{titlesec}
 \titlelabel{\makebox[0pt][r]{\thetitle\kern1pc}}
-\titleformat{\subsubsection}[runin]{\itshape}{%
-  \makebox[0pt][r]{\thetitle\kern1pc}}{%
-  0pt}{}[\maybedot\space --- \kern0pt]
+\titleformat{\subsubsection}[runin]{\itshape}
+  {\makebox[0pt][r]{\thetitle\kern1pc}}
+  {0pt}{}[\maybedot\space --- \kern0pt]
 \titlespacing{\subsubsection}{0pt}{0.5\baselineskip}{0pt}
 
 \usepackage{enumitem}
@@ -40,7 +38,8 @@
   pdftitle={Texdoc: find and view documentation in TeX Live},
   pdfauthor={Manuel Pégourié-Gonnard, Takuto Asakura},
   pdfsubject={Texdoc's user manual},
-  pdfkeywords={Texdoc, TeX Live, manual, documentation}}
+  pdfkeywords={Texdoc, TeX Live, manual, documentation},
+}
 
 \usepackage[yyyymmdd]{datetime}
 \renewcommand{\dateseparator}{-}
@@ -68,15 +67,13 @@
   formatcom=\cofont,
   defineactive=\makeallfancy,
   codes=\fancyactives,
-  }
-\newcommand\fancyactives{%
-  \catcode`\«\active}
-\newcommand\makeallfancy{%
-  \makefancyog}
-{\catcode`\«\active
-\global\def\makefancyog{%
-  \def«##1»{\meta{##1}}}
 }
+\newcommand\fancyactives{\catcode`\«\active}
+\newcommand\makeallfancy{\makefancyog}
+\bgroup
+  \catcode`\«\active
+  \global\def\makefancyog{\def«##1»{\meta{##1}}}
+\egroup
 
 \newif\ifframed
 \newlength\dec
@@ -88,7 +85,7 @@
   \def\bmtext{#2}%
   \def\thelabel{#3}%
   \SaveVerbatim[samepage, gobble=2]{verbmat}%
-  }{%
+}{%
   \endSaveVerbatim
   \xdef\sectioncmd{\noexpand\nodotthistime
     \thecmd[\bmtext]{%
@@ -100,32 +97,31 @@
           \BUseVerbatim{verbmat}}%
       \fi
       \noexpand\label{\thelabel}}}%
-  \aftergroup\sectioncmd}
+  \aftergroup\sectioncmd
+}
 \makeatother
 
 \newcommand\maybedot{.}
-\newcommand\nodotthistime{%
-  \renewcommand\maybedot{%
-    \global\def\maybedot{.}}}
+\newcommand\nodotthistime{\renewcommand\maybedot{\global\def\maybedot{.}}}
 
-\newenvironment{cmdsubsec}[2]{%
-  \framedtrue \commandes\subsection{#1}{#2}%
-  }{%
-  \endcommandes}
+\newenvironment{cmdsubsec}[2]
+  {\framedtrue \commandes\subsection{#1}{#2}}
+  {\endcommandes}
 
-\newenvironment{cmdsubsub}[2]{%
-  \framedfalse \commandes\subsubsection{#1}{#2}%
-  }{%
-  \endcommandes}
+\newenvironment{cmdsubsub}[2]
+  {\framedfalse \commandes\subsubsection{#1}{#2}}
+  {\endcommandes}
 
 \makeatletter
-\newenvironment{htcode}{% % code en hors-texte
-  \SaveVerbatim[samepage, gobble=2]{verbmat}%
-  }{%
-  \endSaveVerbatim
-  \par\medskip\noindent\hspace*{\parindent}%
-  \BUseVerbatim{verbmat}%
-  \par\medskip\@endpetrue}
+% code in hors-text
+\newenvironment{htcode}
+  {\SaveVerbatim[samepage, gobble=2]{verbmat}}
+  {
+    \endSaveVerbatim
+    \par\medskip\noindent\hspace*{\parindent}%
+    \BUseVerbatim{verbmat}%
+    \par\medskip\@endpetrue
+  }
 \makeatother
 \DefineShortVerb{\|}
 
@@ -139,7 +135,7 @@
 \subtitle{Find \& view documentation in \texlive\\
   \href{https://tug.org/texdoc/}{https://tug.org/texdoc/}}
 \author{Manuel Pégourié-Gonnard\and Takuto Asakura}
-\date{v3.0 \today}
+\date{v3.1\quad \today}
 
 \begin{document}
 \VerbatimFootnotes
@@ -150,7 +146,7 @@
 
 \subsection{Basics}
 
-Texdoc is a command line tool which search and view documentations in \texlive.
+Texdoc is a command line tool which find and view documentation in \texlive.
 If you type
 %
 \begin{quote}
@@ -158,21 +154,21 @@
 \end{quote}
 %
 in your command line, the documentation of the |«name»| package will pop up. Of
-course, replace |«name»| with the actual name of the package.  To look up the
-documentation of more than one package at once, just use multiple |«name»|s as
-arguments.
+course, you have to replace |«name»| with the actual name of the package. To
+look up the documentation of more than one package at once, just use multiple
+|«name»|s as arguments.
 
 \subsection{Modes}\label{ss-modes}
 
 Texdoc has different modes that determine how results will be handled. In the
-default, ``view'' mode, it opens 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.
+default, ``view'' mode, it opens the first (supposedly the best) result with a
+suitable 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.
+ask you which one you want to view. It is useful when there another 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
@@ -194,14 +190,14 @@
 \subsection{Configuration files}\label{ss-quick-file}
 
 Use |texdoc --files| to know where to put your personal configuration file;
-you'll need to create this file (an possibly some directories) the first time.
+you'll need to create this file (a possibly some directories) the first time.
 (If you want to know the full list of possible configuration files,
 see~\ref{ss-prec}.)
 
-In order to select you favorite mode, just insert a line |mode = «yourmode»|
-in this file, where |«yourmode»| is one of |view|, |mixed|, |list| or
-|showall|. To set your favorite language, use |lang = «2-letter code»|, though
-it is usually detected automatically.
+In order to select you favorite mode, just insert a line |mode = «mode»| in
+this file, where |«mode»| is one of |view|, |mixed|, |list| or |showall|. To
+set your favorite language, use |lang = «2-letter code»|, though it is usually
+detected automatically.
 
 The configuration file 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
@@ -210,7 +206,7 @@
 \subsection{Viewers}\label{ss-viewer}
 
 Texdoc's mechanism for choosing a viewer varies according to your platform.
-On Windows, macOS, or Unix with KDE, Gnome or XFCE, it uses your file
+On Windows, macOS, or Unix with KDE, GNOME, or XFCE, it uses your file
 associations like when you double-click files in the Explorer, the Finder or
 your default file manager (except for the text viewer, which is always a
 pager). Otherwise, it tries to find a viewer in the path from a list of
@@ -225,13 +221,13 @@
 
 \subsection{You can stop reading now}
 
-The next part explains Texdoc mechanisms for finding the best results and how
-to cutomize them. The default configuration file tries hard to set appropriate
-values so that you normally don't need to fiddle with that, but you may be
-curious or have special needs.
+Following parts explain Texdoc's mechanisms for finding the best results and
+how to customize them. We have been trying hard to optimize the default
+configuration values so that you normally don't need to fiddle with that, but
+you may be curious or have special needs.
 
 The final part is a full reference including a few points omitted in the
-present and next part.
+present and next parts.
 
 \clearpage
 
@@ -247,7 +243,7 @@
     selects all files containing |«keyword»| in their name (including the
     directory name);
   \item In the \texlive Database, it looks for packages named
-    |«keyword»| or containing a file |«keyword».«ext»| where |«ext»| may me
+    |«keyword»| or containing a file |«keyword».«ext»| where |«ext»| may be
     |sty| or |cls|, and selects all the documentation files from this package.
 \end{enumerate}
 Files are filtered by extension: only files with known extensions may be
@@ -255,7 +251,7 @@
 find the closest package name to the |«keyword»| and reselect the files (see
 \ref{ss-fuzzy}).
 
-The selected files are then score according to some simple heuristics.  For
+The selected files are then score according to some simple heuristics. For
 example, a file named |«keyword».pdf|, is good, |«keyword»-«lang».pdf| will
 score higher if your favorite language |«lang»| is detected or configured,
 |«keyword»-doc| will be preferred over |«keyword»whatever|, files in a
@@ -282,7 +278,7 @@
 For example, assume you are looking for the documentation of the shortvrb
 {\LaTeX} package. Texdoc will find |shortvrb.sty| in the |latex| \texlive
 package, but since this package contains a lot of documentation files, none of
-which contains the string |shortverb|, it will sort them basically at random.
+which contains the string |shortvrb|, it will sort them basically at random.
 
 Here comes the notion of \emph{alias}: in the default configuration file,
 |shortvrb| is aliased to |base/doc|, so that when you type |texdoc shortvrb|,
@@ -337,13 +333,13 @@
 |+1| score upgrade.
 
 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
+|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.
 
 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. To prevent the default aliases
-from begin applied for a particular keyword, include |stopalias «keyword»| in
+from being applied for a particular keyword, include |stopalias «keyword»| in
 your personal configuration file. It will preserve the aliases defined before
 this directive (if any) but prevent all further aliasing on this keyword.
 
@@ -364,8 +360,8 @@
 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 a configuration file
-(\ref{ss-quick-file} or \ref{ss-prec}) using the |adjustscore| directive. Here
-are a few examples from the default configuration file.
+(\ref{ss-quick-file} or \ref{ss-prec}) using the |adjscore| directive. Here are
+a few examples from the default configuration file.
 
 \begin{htcode}
   adjscore /Makefile = -1000
@@ -385,17 +381,17 @@
 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.
+a negative score, so will 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.
 So, don't be surprised if you need to adapt your scoring directives after a
-future update of Texdoc.  This warning will hopefully disappear at some point.
+future update of Texdoc. This warning will hopefully disappear at some point.
 
 \subsection{File extensions and names}\label{ss-ext}
 
 The allowed file extensions are defined by the configuration item |ext_list|
-(default: pdf, html, htm, txt, ps, dvi, no extension). You can configure it
+(default: pdf, html, htm, txt, md, 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
@@ -418,24 +414,28 @@
 \subsection{Variants}\label{ss-variants}
 
 The documentation for a given package is often found in a file named like
-|«package»-doc|. To handle this properlr, Texdoc gives a special score files
+|«package»-doc|. To handle this properly, Texdoc gives a special score files
 named |«package»«suffix»| where |«suffix»| is one element of the list given by
 the configuration setting |suffix_list|.
 
 To customise this list, add a line with |suffix_list = «your, list»| in a
-configuration files. Be warned, it will replace the default list, no expand
+configuration file. Be warned, it will replace the default list, no expand
 it. You'll find the default list in the shipped configuration file; feel free
 to suggest additions on the \tdml (with a real-life example).
 
 \subsection{Fuzzy search}\label{ss-fuzzy}
 
-When the normal search can't find any document in \texlive, Texdoc will execute
-fuzzy search without user-interactions. The results of fuzzy search are shown
-by as an informational message. (you can see that with option |-v|)
+When the normal search can't find any document in {\texlive}, Texdoc will
+execute fuzzy search without user-interactions. The fuzzy search finds the
+closest name of package in {\texlive}\footnote{Note that the feature searches
+only package names at this point. Other objects such as aliases cannot be found
+by the fuzzy search.} to the input |«keyword»|. The results of fuzzy search are
+shown by as an informational message (you can see that with option |-v|).
 
-The default allowance of Levenshtein distance is 5. You can change this
-default value by specifying |fuzzy_level| in your |texdoc.cnf| (see
-\ref{cf-fuzzy_level}).
+The default allowance of Levenshtein distance is 5. You can change this default
+value by specifying |fuzzy_level| in your |texdoc.cnf| (see
+\ref{cf-fuzzy_level}). Results of fuzzy search could be irreproducible if
+multiple strings have the same Levenshtein distance.
 
 \clearpage
 
@@ -482,7 +482,7 @@
   -h, --help
 \end{cmdsubsub}
 
-Show a quick help message (namely a list of command-line options) and exit
+Shows a quick help message (namely a list of command-line options) and exit
 successfully.
 
 \begin{cmdsubsub}{-V, --version}{cl-V}
@@ -489,15 +489,16 @@
   -V, --version
 \end{cmdsubsub}
 
-Show the current version of the program and exit successfully.
+Shows the current version of the program and exit successfully.
 
 \begin{cmdsubsub}{-f, --files}{cl-f}
   -f, --files
 \end{cmdsubsub}
 
-Show the list of configuration files for the current installation and
-platform, with their status (active, not found, or disabled
-(see~\ref{cf-lastfile_switch})) and exit successfully.
+Shows the list of configuration files for the current installation and
+platform, with their status and exit successfully. Normally, only ``active''
+and ``disabled'' files are shown (see~\ref{cf-lastfile_switch}). To show ``not
+found'' files as well, you can use |--verbose|.
 
 \begin{cmdsubsub}{--just-view}{cl-just-view}
   --just-view «file»
@@ -518,7 +519,7 @@
   -i, --interact, -I, --nointeract
 \end{cmdsubsub}
 
-Set |interact_switch| to true (resp. false), see~\ref{cf-interact_switch}.
+Set |interact_switch| to true (or false), see~\ref{cf-interact_switch}.
 
 \begin{cmdsubsub}{-M, --machine}{cl-M}
   -M, --machine
@@ -543,14 +544,21 @@
 \end{cmdsubsub}
 
 Set |debug_list|, see~\ref{cf-debug_list}. If you specify |-D| or |--debug|
-without the list, activates all available debug items.
+without specifying a list, activates all available debug items.
 
+\begin{cmdsubsub}{-c}{cl-c}
+  -c «name»=«value»
+\end{cmdsubsub}
+
+Set configuration item |«name»| to |«value»|. This is a general way to access
+any configuration items listed in \ref{ss-conf} from command line.
+
 \subsection{Environment variables}\label{ss-envvar}
 
 They all correspond to some |viewer_«ext»| setting, and the reader is referred
 to~\ref{cf-viewer_*} for details.\footnote{Old names of environment variables,
-namely |TEXDOCVIEW_{txt,html,dvi,ps,pdf}| and
-|TEXDOC_VIEWER_{TXT,HTML,DVI,PS,PDF}|, are deprecated but still work.} You can
+namely |TEXDOCVIEW_{html,dvi,md,txt,pdf,ps}| and
+|TEXDOC_VIEWER_{HTML,DVI,MD,TXT,PDF,PS}|, are deprecated but still work.} You can
 append |_texdoc| to every name in the first column: this wins over every other
 name.
 
@@ -557,11 +565,12 @@
 \begin{center}
 \begin{tabular}{ll}
 Environment variables & Configuration items \\
-|PAGER|               & |viewer_txt|        \\
 |BROWSER|             & |viewer_html|       \\
 |DVIVIEWER|           & |viewer_dvi|        \\
+|MDVIEWER|            & |viewer_md|         \\
+|PAGER|               & |viewer_txt|        \\
+|PDFVIEWER|           & |viewer_pdf|        \\
 |PSVIEWER|            & |viewer_ps|         \\
-|PDFVIEWER|           & |viewer_pdf|        \\
 \end{tabular}
 \end{center}
 
@@ -610,7 +619,7 @@
 \begin{cmdsubsub}{mode}{cf-mode}
   mode = «view, list, mixed, showall»
 \end{cmdsubsub}
-Set the  mode to the given value.  Default is |view|. The various modes
+Set the  mode to the given value. Default is |view|. The various modes
 have been presented in~\ref{ss-modes}.
 
 \begin{cmdsubsub}{interact}{cf-interact_switch}
@@ -617,7 +626,7 @@
   interact_switch = «true, false»
 \end{cmdsubsub}
 
-Turn on or off interaction.  Default is on.  Turning interaction off prevents
+Turn on or off interaction. Default is on. Turning interaction off prevents
 Texdoc from asking you to choose a file to view when there are multiple
 choices, so it just prints the list of files found.
 
@@ -632,18 +641,20 @@
   ext_list = «list»
 \end{cmdsubsub}
 
-Set the list of recognised extensions to |«list»|.  Default is
+Set the list of recognised extensions to |«list»|. The default value is:
+%
 \begin{htcode}
-  pdf, html, htm, txt, dvi, ps,
+  pdf, html, htm, txt, md, dvi, ps,
 \end{htcode}
+%
 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
+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
-    |README|, etc.  The file is assumed to be plain text for viewing purpose.
-  \item |*| means any extension.  Of course if it is present in the list, it
+    precisely without a dot in their name. This is meant for files like
+    |README|, etc. The file is assumed to be plain text for viewing purpose.
+  \item |*| means any extension. Of course if it is present in the list, it
     can be the only element!
 \end{itemize}
 
@@ -655,11 +666,11 @@
 or plain text, but\dots
 
 For each |«ext»| in |ext_list| there should be a corresponding |viewer_«ext»|
-value set.  Defaults are defined corresponding to the default |ext_list|, but
-you can add values if you want.  For example, if you want Texdoc to be able
+value set. Defaults are defined corresponding to the default |ext_list|, but
+you can add values if you want. For example, if you want Texdoc to be able
 to find man pages and display them with the |man| command, you can use
 \begin{htcode}
-  ext_list = pdf, html, htm, 1, 5, txt, dvi, ps,
+  ext_list = pdf, html, htm, 1, 5, txt, md, dvi, ps,
   viewer_1 = man
   viewer_5 = man
 \end{htcode}
@@ -672,8 +683,8 @@
   badext_list = «list»
 \end{cmdsubsub}
 
-Set the list of ``bad'' extensions to |«list»|.  Default is ``|txt,|''. Files
-with those extensions get a malus of |1| on their heurisitc score if it was
+Set the list of ``bad'' extensions to |«list»|. Default is ``|txt,|''. Files
+with those extensions get a malus of |1| on their heuristic score if it was
 previously positive.
 
 \begin{cmdsubsub}{basename_list}{cf-basename_list}
@@ -680,7 +691,7 @@
   basename_list = «list»
 \end{cmdsubsub}
 
-Set the list of ``known'' base names to |«list»|.  Default is ``|readme|''.
+Set the list of ``known'' base names to |«list»|. Default is ``|readme|''.
 Files with those base names are selected regardless of their extension. If the
 extension is unknown, the text viewer will be used to view the file.
 
@@ -688,8 +699,8 @@
   badbasename_list = «list»
 \end{cmdsubsub}
 
-Set the list of ``bad'' base names to |«list»|.  Default is ``|readme|''. Files
-with those names get a malus of |1| on their heurisitc score if it was
+Set the list of ``bad'' base names to |«list»|. Default is ``|readme|''. Files
+with those names get a malus of |1| on their heuristic score if it was
 previously positive.
 
 \begin{cmdsubsub}{viewer_*}{cf-viewer_*}
@@ -699,7 +710,7 @@
 Set the viewer command for files with extension |«ext»| to |«cmd»|. For files
 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
+otherwise inserted at the end of the command. The command can be an arbitrary
 shell construct.
 
 \begin{cmdsubsub}{lang}{cf-lang}
@@ -721,9 +732,10 @@
   debug_list = «list»
 \end{cmdsubsub}
 
-Set the list of activated debug items (default: none; if the command-line
-option is used without arguments, the list defaults to all known debug items).
-Implies |--verbose|. Debug information is printed on standard error.
+Set the list of activated debug items (default: none). Available debug items
+are |config|, |files|, |search|, |score|, |texdocs|, |tlpdb|, |version|,
+|view|, and |all| to activate all of these. Implies |--verbose|. Debug
+information are printed on standard error.
 
 \begin{cmdsubsub}{max_line}{cf-max_lines}
   max_lines = «number»
@@ -737,7 +749,7 @@
   machine_switch = «true, false»
 \end{cmdsubsub}
 
-Turn on or off machine-readable output (default: off).  With this option
+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}
@@ -744,15 +756,15 @@
   «argument»\t«score»\t«filename»
 \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)
+(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
+printed on stdout, except if an 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.
 
 Currently, there are two additional fields: a two-letter language code, and an
 unstructured description, both taken from the CTAN catalogue (via the \texlive
-database). These fields may be empty and they are not guaranteed to keep the
+database). These fields may be empty, and they are not guaranteed to keep the
 same meaning in future versions of Texdoc.
 
 \begin{cmdsubsub}{zipext_list}{cf-zipext_list}
@@ -759,16 +771,16 @@
   zipext_list = «list»
 \end{cmdsubsub}
 
-List of supported extensions for zipped files (default: empty).  Allows
+List of supported extensions for zipped files (default: empty). Allows
 compressed files with names like |foobar.«zip»|, with |«zip»| in the given
 |«list»|, to be found and unzipped before the viewer is started (the
 temporary file will be destroyed right after).
 
 \textbf{Warning.} Support for zipped documentation is not meant to work on
-windows, a Unix shell is assumed! If you add anything to this list, please
-make sure that you also set a corresponding |unzip=«ext»| value for each
-|«ext»| in the list. Also make sure you are using blocking (i.e. not returning
-immediately) viewers.
+windows, a Unix shell is assumed! If you add anything to this list, please make
+sure that you also set a corresponding |unzip=«ext»| value for each |«ext»| in
+the list. At the same time, make sure you are using blocking (i.e., not
+returning immediately) viewers.
 
 \textit{Remark.} \texlive doesn't ship compressed documentation files, so
 this option is mainly useful with re-packaged version of \texlive that do,
@@ -794,11 +806,12 @@
   lastfile_switch = «true, false»
 \end{cmdsubsub}
 
-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{https://tug.org/texdoc/}{web site} for instructions on how to do so).
+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{https://github.com/TeX-Live/texdoc}{README} for instructions on how to do
+so).
 
 \begin{cmdsubsub}{fuzzy_level}{cf-fuzzy_level}
   fuzzy_level = «n»
@@ -814,12 +827,13 @@
   \item Success.
   \item Internal error.
   \item Usage error.
+  \item No documentation found.
 \end{enumerate}
 
 \section{Licence}\label{s-licence}
 
-The current Texdoc program and its documentation are copyright 2008--2018
-Manuel Pégourié-Gonnard, Takuto Asakura, Karl Berry, and Norbert Preining.
+The current version of Texdoc program and its documentation are copyright 2008
+Manuel Pégourié-Gonnard, Takuto Asakura, and the {\texlive} Team.
 
 They are 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
@@ -828,11 +842,11 @@
 
 This program is distributed in the hope that it will be useful, but
 \emph{without any warranty}; without even the implied warranty of
-\emph{merchantability} or \emph{fitness for a particular purpose}.  See the
+\emph{merchantability} or \emph{fitness for a particular purpose}. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License along with
-this program.  If not, see \url{http://www.gnu.org/licenses/}.
+this program. If not, see \url{http://www.gnu.org/licenses/}.
 
 \bigskip
 
@@ -845,7 +859,7 @@
 \end{itemize}
 
 \bigskip
-\begin{center}\Large\rmfamily\bfseries
+\begin{center}\Large\bfseries
   Happy {\TeX}ing!
 \end{center}
 

Deleted: trunk/Master/texmf-dist/scripts/texdoc/alias.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/alias.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/alias.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,119 +0,0 @@
--- alias.tlu: configuration handling for texdoc
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
---[[ structure of the alias table
-
-alias = {
-  name1 = { <true or nill> stop, <aliasentry> aliasentry1, ... },
-  ...
-}
-stop == true means further alias directives should be ignored
-
-aliasentry = {
-  name      = <string> pattern to be matched,
-  score     = <number or nil> associated score,
-  original  = <true or nil> is this the original keyword?,
-  locale    = <true or nil> is this entry found via config.lang?
-}
-score == nil means to use the default score (defined in score.tlu)
-
---]]
-
--- 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 being 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, no_alias)
-    local n = string.lower(name)
-    -- get normal aliases
-    local res
-    if alias[n] and not no_alias then
-        res = alias[n]
-    else
-        res = { make_alias(name, false) }
-    end
-    -- check for language-specific aliases
-    local lang = config.lang and alias[n .. '-' .. config.lang]
-    if lang then
-        for _, entry in ipairs(lang) do
-            if not entry.original then
-                table.insert(res, {
-                    name    = entry.name,
-                    score   = entry.score,
-                    locale  = true,
-                })
-            end
-        end
-    end
-    return res
-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
-
--- iterator over the list of keys in the alias table
-function aliased_names()
-    return function(_, cur)
-        return (next(alias, cur))
-    end
-end
-
-return {
-    confline_to_alias = confline_to_alias,
-    get_patterns      = get_patterns,
-    aliased_names     = aliased_names,
-}
-
--- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/config.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/config.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/config.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,583 +0,0 @@
--- config.tlu: configuration handling for texdoc
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
---------------------------   hide the config table   --------------------------
-
--- config is read-only (but not "deep" 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
-        if context.src ~= 'def' then
-            deb_print('config', "Ignoring '"..key.."="..value.."' "
-                ..context_to_string(context)..'.')
-        end
-        return nil
-    end
-    -- record the source of the setting
-    real_set_config(key..'_src', context.src)
-    -- detect the type of the key
-    if string.match(key, '_list$') then
-        -- coma-separated list
-        local values
-        if value == '' then
-            values = {}
-        else
-            values = string.explode(value, ',')
-        end
-        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 == 'loc' then
-        return 'from operating system locale'
-    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 action = true
-    local function set_config_elt(key, val)
-        set_config_element(key, val, {src='cl', name=curr_arg})
-    end
-
-    -- modified Alternative Get Opt
-    -- cf. http://lua-users.org/wiki/AlternativeGetOpt
-    local function getopt(arg, options)
-        local tmp
-        local tab = {}
-        local saved_arg = { table.unpack(arg) }
-        for k, v in ipairs(saved_arg) do
-            if string.sub(v, 1, 2) == "--" then
-                table.remove(arg, 1)
-                local x = string.find(v, "=", 1, true)
-                if x then tab[string.sub(v, 3, x-1)] = string.sub(v, x+1)
-                else      tab[string.sub(v, 3)] = true
-                end
-            elseif string.sub(v, 1, 1) == "-" then
-                table.remove(arg, 1)
-                local y = 2
-                local l = string.len(v)
-                local jopt
-                while (y <= l) do
-                    jopt = string.sub(v, y, y)
-                    if string.find(options, jopt, 1, true) then
-                        if y < l then
-                            tmp = string.sub(v, y+1)
-                            y = l
-                        else
-                            table.remove(arg, 1)
-                            tmp = saved_arg[k + 1]
-                        end
-                        if string.match(tmp, '^%-') then
-                            tab[jopt] = false
-                        else
-                            tab[jopt] = tmp
-                        end
-                    else
-                        tab[jopt] = true
-                    end
-                    y = y + 1
-                end
-            end
-        end
-        return tab
-    end
-
-    opts = getopt(arg, 'd')
-    for k, v in pairs(opts) do
-        if #k == 1 then
-            curr_arg = '-' .. k
-        else
-            curr_arg = '--' .. k
-        end
-
-        -- action
-        if (curr_arg == '-h') or (curr_arg == '--help') then
-            action = 'help'
-        elseif (curr_arg == '-V') or (curr_arg == '--version') then
-            action = 'version'
-        elseif (curr_arg == '-f') or (curr_arg == '--files') then
-            action = 'files'
-        elseif curr_arg == '--just-view' then
-            action = 'view'
-        -- 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')
-        -- 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')
-        -- debug
-        elseif (curr_arg == '-d') or (curr_arg == '--debug') then
-            if v == true then v = 'all' end
-            set_config_elt('debug_list', v)
-        elseif curr_arg == '-D' then
-            set_config_elt('debug_list', 'all')
-        -- verbosity
-        elseif (curr_arg == '-q') or (curr_arg == '--quiet') then
-            set_config_elt('verbosity_level', C.min_verbosity)
-        elseif (curr_arg == '-v') or (curr_arg == '--verbose') then
-            set_config_elt('verbosity_level', C.max_verbosity)
-        -- problem
-        else
-            err_print('error', "unknown option: "..curr_arg)
-            err_print('error', C.error_msg)
-            return false
-        end
-    end
-    return action
-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", "PDFVIEWER", "TEXDOCVIEW_pdf", "TEXDOC_VIEWER_PDF"})
-    set_config_elt_from_vars('viewer_ps',
-      {"PSVIEWER_texdoc", "PSVIEWER", "TEXDOCVIEW_ps", "TEXDOC_VIEWER_PS"})
-    set_config_elt_from_vars('viewer_dvi',
-      {"DVIVIEWER_texdoc", "DVIVIEWER", "TEXDOCVIEW_dvi", "TEXDOC_VIEWER_DVI"})
-    set_config_elt_from_vars('viewer_html',
-      {"BROWSER_texdoc", "BROWSER", "TEXDOCVIEW_html", "TEXDOC_VIEWER_HTML"})
-    set_config_elt_from_vars('viewer_md',
-      {"MDVIEWER_texdoc", "PAGER", "TEXDOCVIEW_md", "TEXDOC_VIEWER_MD"})
-    set_config_elt_from_vars('viewer_txt',
-      {"PAGER_texdoc", "PAGER", "TEXDOCVIEW_txt", "TEXDOC_VIEWER_TXT"})
-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 the list of configuration files
-function get_config_files()
-    -- get names
-    local platform = string.match (kpse.var_value ('SELFAUTOLOC'), '.*/(.*)$')
-    local names = {
-        'texdoc-'..platform..'.cnf',
-        'texdoc.cnf',
-        'texdoc-dist.cnf',
-    }
-    -- get dirs
-    local sep = (os.type == 'windows') and ';' or ':'
-    local texmf_texdoc = kpse.expand_path('$TEXMF/texdoc')
-    local dirs = texmf_texdoc:explode(sep)
-    -- merge them
-    local ret = {}
-    for _, dir in ipairs(dirs) do
-        for _, name in ipairs(names) do
-            local pathname = dir .. '/' .. name
-            if lfs.isfile(pathname) then
-                table.insert(ret, pathname)
-            end
-        end
-    end
-    return ret
-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 ()
-    local file_list = get_config_files()
-    for i, file in ipairs (file_list) do
-        local status = config.lastfile_switch and 'disabled' or 'active'
-        config_files[i] = {
-            path = file,
-            status = status,
-        }
-        if 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, verbose)
-    local pref = verbose and '    ' or ''
-    print_fun("Configuration files are:")
-    for i, file in ipairs (config_files) do
-        print_fun(pref..file.status..'\t'..w32_path(file.path))
-    end
-    if verbose then
-        print_fun('Recommended file(s) for personal settings:')
-        local sep = (os.type == 'windows') and ';' or ':'
-        local texmfhomes = string.explode(kpse.var_value('TEXMFHOME'), sep)
-        for _, home in ipairs(texmfhomes) do
-            print_fun(pref..home..'/texdoc/texdoc.cnf')
-        end
-    end
-end
-
-end -- scope of config_files
-
-----------------------   config from locale settings   -------------------------
-
-function setup_config_from_locale()
-    local current = os.setlocale(nil, "all")
-    os.setlocale("", "all")
-    local native = os.setlocale(nil, "time")
-    os.setlocale(current, "all")
-    local lang = string.match(native, "^[a-z][a-z]")
-    if lang then
-        set_config_element("lang", lang, {src="loc"})
-    end
-end
-
-----------------------   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:
--- - xdg-open from freedesktop if available
--- - 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 the freedesktop method
-    if is_in_path('xdg-open') then
-        return '(xdg-open %s) &'
-    end
-    -- 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
-        if is_in_path('gvfs-open') then return '(gvfs-open %s) &' end
-        if is_in_path('gnome-open') then return '(gnome-open %s) &' end
-    end
-    if not is_in_path('xprop') then return end
-    local xprop_fh = io.popen('xprop -root _DT_SAVE_MODE 2>/dev/null')
-    local xprop_out = xprop_fh:read('*line')
-    xprop_fh:close()
-    if xprop_out and string.find(xprop_out, '= "xfce4"$') then     -- xfce
-        return '(exo-open %s) &'
-    end
-end
-
--- set viewers from defaults (done only if necessary)
-function get_default_viewers()
-    local function set_config_ls(ls) set_config_list(ls, {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',
-            viewer_md     = viewer_txt,
-        }
-    elseif (os.name == 'macosx') then
-        set_config_ls {
-            viewer_dvi    = 'open',
-            viewer_html   = 'open',
-            viewer_pdf    = 'open',
-            viewer_ps     = 'open',
-            viewer_txt    = 'less',
-            viewer_md     = viewer_txt,
-        }
-    else -- generic Unix
-        set_config_ls {
-            viewer_dvi      = guess_viewer {
-                {'xdvi',        '(xdvi %s) &'},
-                {'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) &'},
-                {'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 {
-                {'xpdf',        '(xpdf %s) &'},
-                {'evince',      '(evince %s) &'},
-                {'okular',      '(okular %s) &'},
-                {'kpdf',        '(kpdf %s) &'},
-                {'acroread',    '(xpdf %s) &'},
-                {'see',         '(see %s) &'}
-            },
-            viewer_ps       = guess_viewer {
-                {'gv',          '(gv %s) &'},
-                {'evince',      '(evince %s) &'},
-                {'okular',      '(okular %s) &'},
-                {'kghostview',  '(kghostview %s) &'},
-                {'see',         '(see %s) &'}
-            },
-            viewer_txt      = guess_viewer {
-                {'most',        'most'},
-                {'less',        'less'},
-                {'more',        'more'}
-            },
-            viewer_md = viewer_txt,
-        }
-    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
-    -- various, platform independent, stuff
-    set_config_ls {
-        mode                = 'view',
-        interact_switch     = 'true',
-        machine_switch      = 'false',
-        ext_list            = 'pdf, htm, html, txt, ps, dvi, ',
-        basename_list       = 'readme, 00readme',
-        badext_list         = 'txt, ',
-        badbasename_list    = 'readme, 00readme',
-        suffix_list         = '',
-        verbosity_level     = C.def_verbosity,
-        debug_list          = '',
-        max_lines           = '20',
-        fuzzy_level         = '5',
-    }
-    -- zip-related options
-    set_config_ls {
-        zipext_list         = '',
-        rm_file             = 'rm -f',
-        rm_dir              = 'rmdir',
-    }
-end
-
---------------------------   set all configuration   ---------------------------
-
--- populate the config and alias arrays
-function setup_config_and_alias(arg)
-    -- setup config from all sources
-    local ret = setup_config_from_cl(arg)
-    setup_config_from_env()
-    setup_config_from_files()
-    setup_config_from_locale()
-    setup_config_from_defaults()
-    -- machine mode implies no interaction
-    if config.machine_switch == true then
-        real_set_config('interact_switch', false)
-    end
-    -- debug implies verbose
-    if #config.debug_list > 0 then
-        real_set_config('verbosity_level', tonumber(C.max_verbosity))
-    end
-    -- we were waiting for config.debug_list to be known to do this
-    show_config_files(function(s) deb_print('files', s) end)
-    -- propagated return value of _from_cl()
-    return ret
-end
-
-return {
-    setup_config_and_alias = setup_config_and_alias,
-    get_default_viewers    = get_default_viewers,
-    show_config_files      = show_config_files,
-    read_config_file       = read_config_file,
-}
-
--- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/constants.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/constants.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/constants.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,145 +0,0 @@
--- constants.tlu: global "constants" for texdoc.
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
--- use an empty environment that will become texdoc_env.C (see EOF)
-local constants = {}
-local kpse = kpse
-local setfenv = setfenv
-local texdoc_env
-if setfenv then
-    texdoc_env = getfenv()
-    setfenv(1, constants)
-else
-    texdoc_env = _ENV
-    _ENV = constants
-end
-
--- BEGIN constants
-
--- progname and version
-fullname     = kpse.find_file('texdoc/texdoclib', 'lua')
-progname     = 'Texdoc'
-version      = '3.0'
-
--- make sure to update setup_config_from_cl() accordingly
--- and set a default value in setup_config_from_defaults() if relevant
-usage_msg = [[
-Usage: texdoc [OPTION...] NAME...
-  or:  texdoc ACTION
-
-Try to find appropriate TeX documentation for the specified NAME(s).
-Alternatively, perform the given ACTION and exit.
-
-Actions:
-Options:
-  -w, --view            Use view mode: start a viewer. (default)
-  -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.
-
-  -i, --interact        Use interactive menus. (default)
-  -I, --nointeract      Use plain lists, no interaction required.
-  -M, --machine         Machine-readable output for lists (implies -I).
-
-  -q, --quiet           Suppress warnings and most error messages.
-  -v, --verbose         Print additional information (eg, viewer command).
-  -D, --debug           Activate all debug output (equal to "--debug=all").
-  -dLIST, --debug=LIST  Activate debug output restricted to LIST.
-
-Environment variables: PAGER, BROWSER, PDFVIEWER, PSVIEWER, DVIVIEWER,
-and *_texdoc of each.
-
-Files: <TEXMF>/texdoc/texdoc.cnf; see output of the --files option.
-Full manual available via `texdoc texdoc'.
-
-Website: <https://tug.org/texdoc/>
-Repository: <https://github.com/TeX-Live/texdoc>
-Please email bugs to <texdoc at tug.org>.]]
-
-copyright_msg = [[
-Copyright 2018 Manuel Pégourié-Gonnard, Takuto Asakura, Karl Berry, and Norbert Preining.
-License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
-This is free software: you are free to change and redistribute it.]]
-
-actions_ph = 'Actions:\n'
-
-known_options = {
-    'viewer_.*',
-    'mode',
-    'interact_switch',
-    'machine_switch',
-    'ext_list',
-    'basename_list',
-    'badext_list',
-    'badbasename_list',
-    'suffix_list',
-    'verbosity_level',
-    'debug_list',
-    'lastfile_switch',
-    'rm_dir',
-    'rm_file',
-    'unzip_.*',
-    'zipext_list',
-    'max_lines',
-    'lang',
-    'fuzzy_level',
-}
-
-error_msg = [[
-Try `texdoc --help' for short help, `texdoc texdoc' for full 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'
-
-err_priority = {
-    error   = 1,
-    warning = 2,
-    info    = 3,
-}
-min_verbosity='0'  -- (nothing at all)
-max_verbosity='3'
-def_verbosity='2'
-
-known_debugs = {
-    version = {},
-    files   = {},
-    config  = {'files'},
-    view    = {},
-    texdocs = {},
-    score   = {},
-    tlpdb   = {}
-}
-
--- various cache or non-cache files
-cache_name = 'texdoc/cache-tlpdb.lua' -- relative to TEXMFVAR
-data_tlpdb_name = 'texdoc/Data.tlpdb.lua'
-
-place_holder = '%%s' -- used for viewer commands
-
--- END constants
-
--- get our previous environment back
-if setfenv then
-    setfenv(1, texdoc_env)
-else
-    _ENV = texdoc_env
-end
-
--- Make global C a read-only proxy to the local <constants>.
--- Note this is not deep read-only: C.known_debugs is read-only, but
--- C.known_debugs.version isn't, for instance.
-assert(next(C) == nil,
-    'Internal error: table of constants should be empty at this point')
-setmetatable(C, {
-    __index = constants,
-    __newindew = function ()
-        error('Internal error: attempt to modify a constant.')
-    end
-})
-
--- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/functions.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/functions.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/functions.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,118 +0,0 @@
--- functions.tlu: general-use functions for texdoc
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
--- change '/' to '\' on windows
--- Use: internal representation of files always use forward slashes.
--- This function should be called only before displaying a file name.
-if os.type == "windows" then
-    function w32_path (path)
-        return (string.gsub (path, '/', '\\'))
-    end
-else
-    function w32_path (path)
-        return path
-    end
-end
-
--- remove the last direcory component of a path
-if os.type == 'windows' then
-    function path_parent(path)
-        return string.match(path, '^(.*)[\\/]')
-    end
-else
-    function path_parent(path)
-        return string.match(path, '^(.*)/')
-    end
-end
-
--- generic error display function (see the err_priority constant)
-function err_print (lvl, msg)
-    -- be careful: maybe config.verbosity_level is not set yet
-    local verbosity_level = config.verbosity_level or tonumber(C.def_verbosity)
-    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 file is base..'.'..zip with zip in zipext_list, return: base, zip
--- otherwise, return: file, nil
-function parse_zip(file) 
-    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
-    return file, nil
-end
-
--- print a usage message, with the proper 'active values' line
-function print_usage(actions)
-    local usage_msg = C.usage_msg
-    -- include actions if any
-    if actions then
-        usage_msg = usage_msg:gsub(C.actions_ph,
-            C.actions_ph .. actions .. '\n\n')
-    else
-        usage_msg = usage_msg:gsub(C.actions_ph, '')
-    end
-    -- finally print it
-    print(usage_msg)
-end
-
-return {
-    err_print   = err_print,
-    deb_print   = deb_print,
-    w32_path    = w32_path,
-    parse_zip   = parse_zip,
-    print_usage = print_usage,
-    path_parent = path_parent,
-}
-
--- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/main.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/main.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/main.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,73 +0,0 @@
--- main.tlu: default command-line interface of texdoc
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
--- load texdoclib (kpse initialized by the wrapper)
-local texdoc = require('texdoc.texdoclib')
-
--- exit codes
-local exit_ok = 0
-local exit_error = 1 -- apparently hard-coded in Lua
-local exit_usage = 2
-
--- action command-line options
-local action_help = [[
-  -h, --help            Print this help message.
-  -V, --version         Print the version number.
-  -f, --files           Print the list of configuration files used.
-  --just-view FILE      Display FILE, given with full path (no searching).]]
-
--- get configuration and parse command line
-local action = texdoc.setup_config_and_alias(arg)
-if not action then
-    os.exit(exit_usage)
-end
-
--- handle action options
-if action == 'help' then
-    texdoc.print_usage(action_help)
-    os.exit(exit_ok)
-elseif action == 'version' then
-    print(texdoc.const.progname .. ' ' .. texdoc.const.version)
-    print('\n' .. texdoc.const.copyright_msg)
-    os.exit(exit_ok)
-elseif action == 'files' then
-    print(texdoc.const.fullname .. ' ' .. texdoc.const.version)
-    texdoc.show_config_files(print, true)
-    os.exit(exit_ok)
-elseif action == 'view' then
-    if not arg[1] then
-        texdoc.err_print('error', "missing file operand to --just-view")
-        texdoc.err_print('error', texdoc.const.error_msg)
-        os.exit(exit_usage)
-    end
-    local ok = texdoc.view_file(arg[1])
-    os.exit(ok and exit_ok or exit_error)
-end
-
--- make sure we actually have argument(s)
-if not arg[1] then
-    texdoc.err_print('error', "no action specified")
-    texdoc.err_print('error', texdoc.const.error_msg)
-    os.exit(exit_usage)
-end
-
--- initialise databases
-texdoc.init_databases()
-
--- 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 = texdoc.get_doclist(docname)
-    -- deliver results to the user
-    texdoc.deliver_results(docname, doclist, multiarg)
-end
-
--- the end
-os.exit(exit_ok)
-
--- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/score.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/score.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/score.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,291 +0,0 @@
--- score.tlu: scoring functions for texdoc
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
--- 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 case-insenstitive (patterns are already lowercased)
-    local name = string.lower(df.shortname)
-    deb_print('score', '----------')
-    deb_print('score', 'Start scoring '..df.realpath)
-    deb_print('score', 'Name used: '..name)
-    -- get score from patterns
-    local score = -10
-    for _, pat in ipairs(df.matches) do
-        local s = -10
-        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
-            local bonus, msg = 0, ''
-            if pat.locale then
-                bonus, msg = 5, ', (language-based)'
-            end
-            s = (pat.score or 10) + bonus -- default alias score is 10
-            deb_print('score', string.format(
-                "Matching alias '%s', score: %g%s", pat.name, s, msg))
-        end
-        if s > score then score = s end
-    end
-    deb_print('score', 'Max pattern score: '..tostring(score))
-    -- get score from tlp associations
-    if score == -10 and df.tlptodoc then
-        score = -1
-        deb_print('score', 'New score: '..tostring(score)
-            ..' from package name association')
-    end
-    if score == -10 and df.runtodoc then
-        score = -5
-        deb_print('score', 'New score: '..tostring(score)
-            ..' from sty/cls association')
-    end
-    -- bonus for metadata
-    if df.details then
-        if string.find(string.lower(df.details), 'readme') then
-            score = score + 0.1
-            deb_print('score', 'Catalogue "readme" bonus: +0.1')
-        else
-            score = score + 1.5
-            deb_print('score', 'Catalogue details bonus: +1.5')
-        end
-    end
-    -- 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
-                score = score + val
-                deb_print('score', string.format(
-                    "Adjust by %g 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 > -10 or val < 0 then score = score + val end
-                deb_print('score', string.format(
-                    "Adjust by %g from global pattern '%s'", val, pat))
-            end
-        end
-    end
-    deb_print('score', 'Final score: '..tostring(score))
-    df.score = score
-end
-
--- compute a heuristic score -10 <= s < 10
-function heuristic_score(file, pat)
-    deb_print('score', 'Start heuristic scoring with pattern: '..pat)
-    -- score management
-    local score = -10
-    local function upscore(s, reason, force)
-        if s > score or force 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_locale(file, pat) then
-        upscore(5, 'exact match with correct locale')
-    elseif 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(config.suffix_list) 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
-    -- if extension is bad, score becomes an epsilon
-    local ext = config.ext_list[ext_pos(file)]
-    if ext and config.badext_list_inv[ext] and score > 0 then
-        upscore(0.1, 'bad extension', true)
-    end
-    -- if basename is bad, score becomes an epsilon
-    if has_bad_basename(file) and score > 0 then
-        upscore(0.1, 'bad basename', true)
-    end
-    -- bonus for being in the right directory
-    if string.find('/'..file, '/'..pat..'/', 1, true) and not slash then
-        upscore(score + 1.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
-
--- says if file is an exact match for pat and the current locale
-function is_exact_locale(file, pat)
-    if string.match(pat, '%-%l%l%l?$') then
-        -- don't match if the pattern appears to include a language code
-        return false
-    end
-    local lang = config.lang
-    if lang then
-        return is_exact(file, pat .. '-' .. lang)
-            or is_exact(file, lang .. '-' .. pat)
-    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
-
--- say if a filename has a bad basename
-function has_bad_basename(file)
-    file = file:gsub('.*/', '')
-    for _, b in ipairs(config.badbasename_list) do
-        if file:find('^'..b..'$') or file:find('^'..b..'%.') then
-            return true
-        end
-    end
-    return false
-end
-
--- compare two docfile's: (see search.tlu for structure)
--- 1. by score
--- 2. then by extensions (ordered as in ext_list),
--- 3. then lexicographically by filename.
--- 4. then by tree.
--- 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
-    elseif a.ext_pos < b.ext_pos    then return true
-    elseif a.ext_pos > b.ext_pos    then return false
-    elseif a.basename < b.basename  then return true
-    elseif a.basename > b.basename  then return false
-    else return (a.tree > b.tree)
-    end
-end
-
------------------------------   public functions   -----------------------------
-
--- 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
-
--- 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
-
-return {
-    sort_doclist      = sort_doclist,
-    docfile_quality   = docfile_quality,
-    ext_pos           = ext_pos,
-    is_exact          = is_exact,
-    confline_to_score = confline_to_score,
-}
-
--- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/search.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/search.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/search.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,696 +0,0 @@
--- search.tlu: file searching functions for texdoc.
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
--- Warning: every single function here assumes init_databases() has been called.
-
--- shared by all functions in this file
-local s_doclist -- the Doclist objet to be populated by various functions
-local s_meta -- {[normname] = meta, ...} (populated by init_tlp_database)
-local vanilla -- is this a vanilla TL or a re-package one without tlpdb?
-
------------------------   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:lower()) == i
-Paths are lowercased in order to avoid duplicates on windows.
---]]
-
-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)
-    if not df.realpath then return end -- useful if vanilla == false
-    local index = self.inv[df.realpath:lower()]
-    if index then
-        self[index]:mergein(df)
-    else
-        local newindex = #self + 1
-        self[newindex] = df
-        self.inv[df.realpath:lower()] = newindex
-    end
-end
-
--- stops a doclist
-function Doclist:stop()
-    self.inv = nil
-end
-
---[[
-docfile = {
-    -- name and tree are mendatory
-    name      = filename (used for scoring only)
-    tree      = code of the tree, see below
-    -- at least one of the following fields should exist
-    matches   = {pattern1, pattern2, ...} or {}
-    runtodoc  = true if there is a runfile -> docfile association
-    tlptodoc  = true if there is a tlp name -> docfile association
-    -- those are virtual members, see below
-    realpath  = full path
-    normname  = nomrmalised (path removed up to the 'doc' component)
-    shortname = short name used for scoring
-    basename  = basename
-    lang      = language tag from the catalogue metadata
-    details   = details tag from the catalogue metadata
-    quality   = 'good', 'bad', or 'killed' depending on score
-    ext_pos   = position of the extension in ext_list
-    -- set for elements of a list as a side effect of sort_doclist()
-    score     = score
-}
-if tree > 1, this is the index of the tree in TEXDOCS
-if tree = 0, then name is relative to TLROOT
-tree = - 1 if and only if file is a sty file. Here name is absolute.
---]]
-
--- Docfile objects inherit members from Docfile
--- and have virtual members implemented by get_<member>() methods
--- for best cache performance, getters should not return nil
-local Docfile = {}
-function Docfile:__index(key)
-    if Docfile[key] then return Docfile[key] end
-    local getter = Docfile['get_'..key]
-    if getter then
-        rawset(self, key, getter(self))
-        return rawget(self, key)
-    end
-end
-
--- create a new docfile objet using initilisation info
--- required fields: name, tree
-function Docfile:new(info)
-    local df = {}
-    setmetatable(df, self)
-    for k, v in pairs(info) do
-        if k == 'pattern' then
-            df.matches = { info.pattern }
-        else
-            df[k] = v
-        end
-    end
-    return df
-end
-
--- merge a second docfile objet in, assuming it represents the same file
-function Docfile:mergein(df)
-    for k, v in pairs(df) do
-        if k == 'matches' then
-            for _, m in ipairs(df.matches or {}) do
-                table.insert(self.matches, m)
-            end
-        else
-            self[k] = v
-        end
-    end
-end
-
--- return the full path to the file
-function Docfile:get_realpath()
-    if self.tree > 0 then 
-        return texdocs_tree_to_path(self.tree, self.name)
-    elseif self.tree == 0 then
-        if vanilla then
-            return get_tlroot()..'/'..self.name
-        else
-            return kpse.find_file(self.normname, 'TeX system documentation')
-        end
-    else
-        return self.name
-    end
-end
-
--- normalise a name from the tlpdb (use for s_meta indexes)
-function reloc_tlpdb_path(name)
-    return string.gsub(name, '^texmf[^/]*/doc/', '', 1)
-end
-
--- return normalised name
-function Docfile:get_normname()
-    return (self.tree == 0) and reloc_tlpdb_path(self.name) or self.name
-end
-
--- retrieve the lang from meta
-function Docfile:get_lang()
-    local meta = s_meta[self.normname]
-    return meta and (meta.lang or false) or false
-end
-
--- retrieve the details from meta
-function Docfile:get_details()
-    local meta = s_meta[self.normname]
-    return meta and (meta.details or false) or false
-end
-
--- return the short name used for scoring
-function Docfile:get_shortname()
-    if self.tree == -1 then return self.name end
-    -- remove first component of name if at least two directory levels
-    return string.match(self.normname, '^..-/(.+/.+)$') or self.normname
-end
-
--- return the base name
-function Docfile:get_basename()
-    return string.gsub(self.name, '.*/', '', 1)
-end
-
--- for interface consistency, matches should always be a table, never nil
-function Docfile:get_matches()
-    return {}
-end
-
--- from score.tlu
-Docfile.get_quality = docfile_quality
-
--- from score.tlu
-function Docfile:get_ext_pos()
-    return ext_pos(self.basename)
-end
-
----------------------   manage TEXDOCS trees à la kpse   ----------------------
-
-do -- scope of doc_roots
-local doc_roots
-
---[[
-doc_roots[i] = {
-    path    = initial path,
-    db      = { [file1] = basename1, [file2] = basename2, ... },
-}
---]]
-
--- populate the doc_roots filename databases
-function init_texdocs_database()
-    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 n
-        local path, db
-        -- get path, !! and // values
-        dir, n = string.gsub (dir, '//$', '')
-        local recursion_allowed = (n == 1)
-        local path, n = string.gsub (dir, '^!!', '')
-        local index_mandatory = (n == 1)
-        deb_print('texdocs', string.format(
-            'texdocs[%d] = %s (index_mandatory=%s, recursion_allowed=%s)',
-            i, path, tostring(index_mandatory), tostring(recursion_allowed)))
-        -- decide if we should use a ls-R index, the filesystem, or do nothing
-        local root, shift = lsr_root(path)
-        if root and shift and recursion_allowed then
-            deb_print('texdocs', string.format(
-                'texdocs[%d] using index: %s (shift=%s)', i, root, shift))
-            db = init_lsr_db(root, shift)
-        elseif not index_mandatory and lfs.isdir(path) then
-            deb_print('texdocs', string.format(
-                'texdocs[%d] using filesystem search', i))
-            db = init_tree_db(path, recursion_allowed)
-        end
-        -- register this in docroots
-        doc_roots[i] = { path = path, db = db }
-    end
-end
-
--- return the real path from a texdocs tree number + relative path
-function texdocs_tree_to_path(tree, rel)
-    return doc_roots[tree].path..'/'..rel
-end
-
--- find docfiles in texdocs directories
-function get_doclist_texdocs(patlist)
-    for code, dr in ipairs(doc_roots) do
-        if dr.db then scan_db(patlist, code, dr.db) end
-    end
-end
-
-end -- scope of doc_roots
-
--- find a ls-R file in a parent directory and 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
-
--- build a db from a ls-R file
-function init_lsr_db(root, shift)
-    -- open the file
-    local lsr = assert(io.open(root..'/ls-R', 'r'))
-    local _ = lsr:read('*line') -- throw away first line (comment)
-    -- scan it
-    local db = {}
-    local maybe_dir, isdoc = true, false
-    local current_dir
-    local l = #shift
-    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)
-                db[current_dir] = nil
-            elseif isdoc then
-                break -- we're exiting the ./doc (or shift) dir, so it's over
-            end
-        elseif isdoc then
-            local file = (current_dir == '') and line or current_dir..'/'..line
-            if check_ext(line) then db[file] = line end
-        end
-    end
-    lsr:close()
-    return db
-end
-
--- build a db for a tree without ls-R index
-function init_tree_db(base, recurse)
-    local db = {}
-    local function init_tree_db_rec(dir)
-        for file in lfs.dir(base..'/'..dir) do
-            if file ~= '.' and file ~= '..' then
-                local f = (dir == '') and file or dir..'/'..file
-                if lfs.isdir(base..'/'..f) then
-                    if recurse then init_tree_db_rec(f) end
-                else
-                    if check_ext(file) then db[f] = file end
-                end
-            end
-        end
-    end
-    init_tree_db_rec('')
-    return db
-end
-
---------------------   select results from TEXDOCS trees   ---------------------
-
--- scan a database
-function scan_db(patlist, code, lsr_db)
-    for file, basename in pairs(lsr_db) do
-        local df = process_file(patlist, basename, file, code)
-        if df then s_doclist:add(df) end
-    end
-end
-
--- says if file has a known extenstion according to ext_list
--- (or known basename according to basename_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
-    -- is the basename good?
-    for _, b in ipairs(config.basename_list) do
-        if file:find('^'..b..'$') or file:find('^'..b..'%.') then
-            return true
-        end
-    end
-    return false
-end
-
--- say if a file (with its path) matches a pattern
-function matches(pattern, file)
-    if pattern.original then
-        return string.find(file:lower(), pattern.name:lower(), 1, true)
-    else
-        return is_exact(file, pattern.name)
-    end
-end
-
--- return a docfile object if file "matches", nil ortherwise
-function process_file(patlist, file, pathfile, code)
-    local docfile
-    local pattern
-    for _, pattern in ipairs(patlist) do
-        if matches(pattern, pathfile) 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
-    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
-
---------------------------------   use tlpdb   ---------------------------------
-
--- tlpdb mean TeX Live Package DataBase and tlp means TeX Live Package
-
--- find the TeX Live root
-function get_tlroot()
-    local tlroot = kpse.var_value('SELFAUTOPARENT')
-    get_tlroot = function() return tlroot end
-    return tlroot
-end
-
--- return true if cache exists and is newer than original, false otherwise
-function good_cache(cache, ori)
-    local cache_date = lfs.attributes(cache, 'modification')
-    if not cache_date then return false end
-    local ori_date = assert(lfs.attributes(ori, 'modification'))
-    return cache_date > ori_date
-end
-
--- make sure a given directory exists, or return nil plus an error string
-function mkdir_p(dir)
-    if lfs.isdir(dir) then return true end
-    local parent = path_parent(dir)
-    if parent then
-        local ok, msg = mkdir_p(parent)
-        if not ok then return nil, msg end
-    end
-    return lfs.mkdir(dir)
-end
-
--- get tlpinfo tables initialised by whatever mean
-function init_tlp_database()
-    local TEXMFVAR = kpse.var_value('TEXMFVAR')
-    local cache_file = TEXMFVAR..'/'..C.cache_name
-    local texlive_tlpdb = get_tlroot()..'/tlpkg/texlive.tlpdb'
-    vanilla = lfs.isfile(texlive_tlpdb)
-    if vanilla then
-        if good_cache(cache_file, texlive_tlpdb) then
-            deb_print('tlpdb', 'Using cached data from '..cache_file)
-            get_tlpinfo_from_cache(cache_file)
-        else
-            deb_print('tlpdb', 'Getting data from tlpdb file '..texlive_tlpdb)
-            get_tlpinfo_from_tlpdb(texlive_tlpdb)
-            deb_print('tlpdb', 'Writing data in cache file '..cache_file)
-            local ok, msg = mkdir_p(path_parent(cache_file))
-            if not ok then
-                err_print('warning',
-                'Failed to create cache file in '..cache_file..':')
-                err_print('warning', msg)
-            else
-                print_out_tlpinfo(cache_file)
-            end
-        end
-    else
-        deb_print('tlpdb', 'Using shipped tlpdb data.')
-        get_tlpinfo_from_dist()
-    end
-end
-
-do -- begin scope of tlpinfo tables
-local tlp_from_runfile -- { [runfile_basename] = {tlp1 = true, ...}, ... }
-local tlp_doclist -- { [tlp_name] = { relname1, relname2, ...}, ... }
-
--- populate tlpinfo tables using the given texlive.tlpdb
-function get_tlpinfo_from_tlpdb(filename)
-    s_meta, tlp_from_runfile, tlp_doclist = {}, {}, {}
-    local curr_tlp
-    local state = 'none'
-    for line in io.lines(filename) do
-        if state == 'none' and string.find(line, '^name ') then
-            -- begin a new package
-            curr_tlp = string.lower(string.sub(line, 6, -1))
-            tlp_doclist[curr_tlp] = {}
-        elseif state == 'docfiles' then
-            if not string.find(line, '^ ') then
-                state = 'none'
-            else
-                local file = string.match(line, '^ ([^ ]*)')
-                local meta = string.match(line, '^ [^ ]* (.+)')
-                local basename = string.match(file, '([^/]*)$')
-                if check_ext(basename) then
-                    -- we've got a docfile here, add it
-                    table.insert(tlp_doclist[curr_tlp], file)
-                    if meta then
-                        local details = string.match(meta, 'details="([^"]+)"')
-                        local lang = string.match(meta, 'language="([^"]+)"')
-                        s_meta[reloc_tlpdb_path(file)] = {
-                            details = details,
-                            lang = lang,
-                        }
-                    end
-                end
-            end
-        elseif state == 'runfiles' then
-            if not string.find(line, '^ ') then
-                state = 'none'
-            else
-                -- check for interesting runfiles
-                local e = string.sub(line, -4, -1)
-                if e == '.tex' or e == '.sty' or e == '.cls' then
-                    local f = string.match(line, '.*/(.*)%.')
-                    tlp_from_runfile[f] = tlp_from_runfile[f] or {}
-                    tlp_from_runfile[f][curr_tlp] = true
-                end
-            end
-        end
-        -- update state
-        if string.find(line, '^docfiles ') then
-            state = 'docfiles'
-        elseif string.find(line, '^runfiles ') then
-            state = 'runfiles'
-        end
-    end
-    remove_useless_tlp()
-end
-
--- remove entries for tlp without any docfile
-function remove_useless_tlp()
-    for tlp, doclist in pairs(tlp_doclist) do
-        if #doclist == 0 then tlp_doclist[tlp] = nil end
-    end
-    for runfile, tlp_set in pairs(tlp_from_runfile) do
-        for tlp in pairs(tlp_set) do
-            if not tlp_doclist[tlp] then
-                tlp_from_runfile[runfile][tlp] = nil
-            end
-        end
-    end
-end
-
--- print out data from tlpdb in dofile()-able form
-function print_out_tlpinfo(filename)
-    local fh = assert(io.open(filename, 'w'))
-    local function printf(s, ...) fh:write(string.format(s, ...)) end
-    -- s_meta
-    printf('local s_meta = {\n')
-    for k, v in pairs(s_meta) do
-        printf('  [%q] = {', k)
-        for i, j in pairs(v) do printf('[%q] = %q, ', i, j) end
-        printf('},\n')
-    end
-    printf('}\n')
-    -- tlp_from_runfile
-    printf('local tlp_from_runfile = {\n')
-    for k, v in pairs(tlp_from_runfile) do
-        printf('  [%q] = {', k)
-        for f in pairs(v) do printf('[%q]=true,', f) end
-        printf('},\n')
-    end
-    printf('}\n')
-    -- tlp_doclist
-    printf('local tlp_doclist = {\n')
-    for k, v in pairs(tlp_doclist) do
-        printf('  [%q] = {\n', k)
-        for _, f in ipairs(v) do printf('    %q,\n', f) end
-        printf('  },\n')
-    end
-    printf('}\n')
-    printf('return s_meta, tlp_from_runfile, tlp_doclist\n')
-    fh:close()
-end
-
--- get pre-hashed tlpdb info from a cache file
-function get_tlpinfo_from_cache(filename)
-    s_meta, tlp_from_runfile, tlp_doclist = dofile(filename)
-end
-
--- get pre-hashed tlpdb info from a pseudo-cache file
-function get_tlpinfo_from_dist()
-    local f = assert(kpse.find_file(C.data_tlpdb_name, 'texmfscripts'))
-    s_meta, tlp_from_runfile, tlp_doclist = dofile(f)
-end
-
--- get docfiles for pattern using specific tlpdb information
-function get_doclist_tlpdb(pattern)
-    -- runfile to tlp to docfile
-    if tlp_from_runfile[pattern] then
-        for tlp in pairs(tlp_from_runfile[pattern]) do
-            for _, file in ipairs(tlp_doclist[tlp]) do
-                s_doclist:add(Docfile:new{
-                    name        = file,
-                    tree        = 0,
-                    runtodoc    = true,
-                })
-            end
-        end
-    end
-    -- tlp name to docfile
-    if tlp_doclist[pattern] then
-        for _, file in ipairs(tlp_doclist[pattern]) do
-            s_doclist:add(Docfile:new{
-                name            = file,
-                tree            = 0,
-                tlptodoc        = true,
-            })
-        end
-    end
-end
-
--- fuzzy search by using levenshtein distance
-function fuzzy_search(pattern)
-    local tmp_d
-    local min = 100
-    local result
-
-    for p in pairs(tlp_doclist) do
-        tmp_d = levenshtein(pattern, p)
-        if tmp_d < min then
-            min, result = tmp_d, p
-        end
-    end
-
-    if min <= config.fuzzy_level then
-        return result
-    else
-        return ''
-    end
-end
-
--- calculate levenshtein distance by dynamic programming
--- cf. http://lua-users.org/lists/lua-l/2008-01/msg00095.html
-function levenshtein(s, t)
-    local s, t = tostring(s), tostring(t)
-    if type(s) == 'string' and type(t) == 'string' then
-        local m, n, d = #s, #t, {}
-        for i = 0, m do d[i] = { [0] = i } end
-        for j = 1, n do d[0][j] = j end
-        for i = 1, m do
-            for j = 1, n do
-                local cost = s:sub(i,i) == t:sub(j,j) and 0 or 1
-                d[i][j] = math.min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cost)
-            end
-        end
-        return d[m][n]
-    end
-end
-
-end --scope of tlpinfo table
-
-------------------------------   main function   -------------------------------
-
--- initialise the various databases (must be called first)
-function init_databases()
-    init_texdocs_database()
-    init_tlp_database()
-end
-
--- find docfiles according to pattern
-function get_doclist(pattern, no_alias)
-    -- initialise result list
-    s_doclist = Doclist:new()
-    -- 1. normal search with the input pattern
-    doc_search(pattern, no_alias)
-    -- 2. if no result, execute fuzzy search
-    if not s_doclist[1] then
-        local f_res = fuzzy_search(pattern)
-        if f_res ~= '' then
-            err_print('info', 'Fuzzy search result: ' .. f_res)
-            pattern = f_res
-            doc_search(pattern, no_alias)
-        end
-    end
-    -- finally, sort results
-    sort_doclist(s_doclist, pattern)
-    return s_doclist
-end
-
-function doc_search(pattern, no_alias)
-    -- get patterns (inc. aliases)
-    local normal, sty = normal_vs_sty(get_patterns(pattern, no_alias))
-    -- get results; _texdocs search comes after _tlpdb search so that
-    -- files found by both will have the priority of the _texdocs tree.
-    -- (https://puszcza.gnu.org.ua/bugs/?369)
-    get_doclist_sty(sty)
-    get_doclist_tlpdb(pattern)
-    get_doclist_texdocs(normal)
-end
-
--- separate sty patterns from the rest
-function normal_vs_sty(list)
-    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
-
-return {
-    init_databases = init_databases,
-    get_doclist    = get_doclist,
-}
-
--- vim: ft=lua:

Modified: trunk/Master/texmf-dist/scripts/texdoc/texdoc.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoc.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoc.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,11 +1,17 @@
 #!/usr/bin/env texlua
 
--- texdoc.tlu: small wrapper around main.tlu
--- (makes it easier to install a new version of texdoc in TEXMFHOME)
+-- texdoc.tlu: the main program of texdoc
 --
--- The TeX Live team, GPLv3, see texdoclib.tlu for details
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
 
+-- Note: we keep this file small as much as possible so that make it easier
+--       to install a new version of texdoc in TEXMFHOME.
+
+-- setup the kpse library and load texdoclib
 kpse.set_program_name(arg[-1], 'texdoc')
-require('texdoc.main')
+local texdoc = require('texdoclib')
 
+-- execute
+texdoc.cli.exec()
+
 -- vim: ft=lua:

Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-alias.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-alias.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-alias.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,127 @@
+-- texdoclib-alias.tlu: alias handling for texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+--[[ structure of the alias table
+
+alias = {
+  name1 = {<true or nill> stop, <aliasentry> aliasentry1, ...},
+  ...
+}
+stop == true means further alias directives should be ignored
+
+aliasentry = {
+  name      = <string> pattern to be matched,
+  score     = <number or nil> associated score,
+  original  = <true or nil> is this the original keyword?,
+  locale    = <true or nil> is this entry found via config.lang?
+}
+score == nil means to use the default score (defined in texdoclib-score.tlu)
+
+--]]
+
+-- dependencies
+local texdoc = {
+    config = require('texdoclib-config'),
+}
+
+-- shortcuts
+local M = {}
+
+-- 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
+local 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
+local 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 being further aliased
+local 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 M.get_patterns(name, no_alias)
+    local n = string.lower(name)
+
+    -- get normal aliases
+    local res
+    if alias[n] and not no_alias then
+        res = alias[n]
+    else
+        res = {make_alias(name, false)}
+    end
+
+    -- check for language-specific aliases
+    local config_lang = texdoc.config.get_value('lang')
+    local lang = config_lang and alias[n .. '-' .. config_lang]
+    if lang then
+        for _, entry in ipairs(lang) do
+            if not entry.original then
+                table.insert(res, {
+                    name = entry.name,
+                    score = entry.score,
+                    locale = true,
+                })
+            end
+        end
+    end
+
+    return res
+end
+
+-- interpret a confline as an alias setting or return false
+function M.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
+
+-- iterator over the list of keys in the alias table
+-- Note: currently this function is not used (for debug)
+function M.aliased_names()
+    return function(_, cur)
+        return (next(alias, cur))
+    end
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-alias.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-cli.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-cli.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-cli.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,219 @@
+-- texdoclib-cli.tlu: command line interfaces for texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+-- dependencies
+local texdoc = {
+    const = require('texdoclib-const'),
+    util = require('texdoclib-util'),
+    config = require('texdoclib-config'),
+    search = require('texdoclib-search'),
+    view = require('texdoclib-view'),
+}
+
+-- shortcuts
+local M = {}
+local C = texdoc.const
+local err_print = texdoc.util.err_print
+
+--------------------------   parsing options   --------------------------
+
+-- modified Alternative GetOpt
+-- cf. http://lua-users.org/wiki/AlternativeGetOpt
+local function getopt(arg, options)
+    local tmp
+    local tab = {}
+    local saved_arg = {table.unpack(arg)}
+
+    for k, v in ipairs(saved_arg) do
+        if string.sub(v, 1, 2) == '--' then
+            table.remove(arg, 1)
+            local x = string.find(v, '=', 1, true)
+            if x then
+                table.insert(tab, {string.sub(v, 3, x-1), string.sub(v, x+1)})
+            else
+                table.insert(tab, {string.sub(v, 3), true})
+            end
+        elseif string.sub(v, 1, 1) == '-' then
+            table.remove(arg, 1)
+            local y = 2
+            local l = string.len(v)
+            local jopt
+            while (y <= l) do
+                jopt = string.sub(v, y, y)
+                if string.find(options, jopt, 1, true) then
+                    if y < l then
+                        tmp = string.sub(v, y+1)
+                        y = l
+                    else
+                        table.remove(arg, 1)
+                        tmp = saved_arg[k + 1]
+                    end
+                    if string.match(tmp, '^%-') then
+                        table.insert(tab, {jopt, false})
+                    else
+                        table.insert(tab, {jopt, tmp})
+                    end
+                else
+                    table.insert(tab, {jopt, true})
+                end
+                y = y + 1
+            end
+        end
+    end
+
+    return tab
+end
+
+local function parse_options()
+    local curr_arg
+    local action = true
+    local cl_config = {}
+
+    local function insert_cl_config(key, val, opt_name)
+        table.insert(cl_config, {key, val, opt_name})
+    end
+
+    -- actual parsing
+    opts = getopt(arg, 'cd')
+
+    for _, tp in ipairs(opts) do
+        local k, v = tp[1], tp[2]
+        if #k == 1 then
+            curr_arg = '-' .. k
+        else
+            curr_arg = '--' .. k
+        end
+
+        -- action
+        if (curr_arg == '-h') or (curr_arg == '--help') then
+            action = 'help'
+        elseif (curr_arg == '-V') or (curr_arg == '--version') then
+            action = 'version'
+        elseif (curr_arg == '-f') or (curr_arg == '--files') then
+            action = 'files'
+        elseif curr_arg == '--just-view' then
+            action = 'view'
+
+        -- mode
+        elseif (curr_arg == '-w') or (curr_arg == '--view') then
+            insert_cl_config('mode', 'view', curr_arg)
+        elseif (curr_arg == '-m') or (curr_arg == '--mixed') then
+            insert_cl_config('mode', 'mixed', curr_arg)
+        elseif (curr_arg == '-l') or (curr_arg == '--list') then
+            insert_cl_config('mode', 'list', curr_arg)
+        elseif (curr_arg == '-s') or (curr_arg == '--showall') then
+            insert_cl_config('mode', 'showall', curr_arg)
+
+        -- interaction
+        elseif (curr_arg == '-I') or (curr_arg == '--nointeract') then
+            insert_cl_config('interact_switch', 'false', curr_arg)
+        elseif (curr_arg == '-i') or (curr_arg == '--interact') then
+            insert_cl_config('interact_switch', 'true', curr_arg)
+
+        -- output format
+        elseif (curr_arg == '-M') or (curr_arg == '--machine') then
+            insert_cl_config('machine_switch', 'true', curr_arg)
+
+        -- config
+        elseif curr_arg == '-c' then
+            local item, value = string.match(v, '^([%a%d_]+)%s*=%s*(.+)')
+            insert_cl_config(item, value, curr_arg)
+
+        -- debug
+        elseif (curr_arg == '-d') or (curr_arg == '--debug') then
+            if v == true then v = 'all' end
+            insert_cl_config('debug_list', v, curr_arg)
+        elseif curr_arg == '-D' then
+            insert_cl_config('debug_list', 'all', curr_arg)
+
+        -- verbosity
+        elseif (curr_arg == '-q') or (curr_arg == '--quiet') then
+            insert_cl_config('verbosity_level', C.min_verbosity, curr_arg)
+        elseif (curr_arg == '-v') or (curr_arg == '--verbose') then
+            insert_cl_config('verbosity_level', C.max_verbosity, curr_arg)
+
+        -- having trouble
+        else
+            err_print('error', 'unknown option: ' .. curr_arg)
+            err_print('error', C.error_msg)
+            return false
+        end
+    end
+
+    return action, cl_config
+end
+
+--------------------------   process execution   --------------------------
+
+-- handling actions
+local function do_action(action)
+    if action == 'help' then
+        texdoc.util.print_usage()
+        os.exit(C.exit_ok)
+    elseif action == 'version' then
+        print(string.format(
+            '%s %s (%s)', C.progname, C.version, C.release_date) ..
+            '\n\n' .. C.copyright_msg)
+        os.exit(C.exit_ok)
+    elseif action == 'files' then
+        print(C.fullname .. ' ' .. C.version)
+        texdoc.config.show_config_files(true)
+        os.exit(C.exit_ok)
+    elseif action == 'view' then
+        if not arg[1] then
+            err_print('error', 'Missing file operand to --just-view.')
+            err_print('error', C.error_msg)
+            os.exit(C.exit_usage)
+        end
+        texdoc.view.view_file(arg[1])
+        os.exit(C.exit_ok)
+    end
+end
+
+-- the main loop
+local function do_texdoc()
+    texdoc.search.init_databases()
+
+    for _, docname in ipairs(arg) do
+        -- do we have more then one argument?
+        local multiarg = not not arg[2]
+        -- get results
+        local doclist = texdoc.search.get_doclist(docname)
+        -- deliver results to the user
+        texdoc.view.deliver_results(docname, doclist, multiarg)
+    end
+end
+
+--------------------------   the main function   --------------------------
+
+function M.exec()
+    -- parsing command line options
+    local action, cl_config = parse_options()
+
+    if not action then
+        os.exit(C.exit_usage)
+    end
+
+    -- setup config and alias
+    texdoc.config.setup_config_and_alias(cl_config)
+
+    -- special action
+    do_action(action)
+
+    -- do we actually have arguments?
+    if not arg[1] then
+        err_print('error', 'No action specified.')
+        err_print('error', C.error_msg)
+        os.exit(C.exit_usage)
+    end
+
+    -- the main feature
+    do_texdoc()
+
+    os.exit(C.exit_ok)
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-cli.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-config.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-config.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-config.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,559 @@
+-- texdoclib-config.tlu: handling config of texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+-- shortcuts
+local M = {}
+local C = require('texdoclib-const')
+
+-- config is local to this file
+local config = {}
+
+--------------------------   handling dependencies   --------------------------
+
+-- in this file, dependencies should be required ondemand to prevent infinite
+-- recursion.
+
+local texdoc = {}
+
+-- import specified function from the submodule
+local function import_function(mod, func)
+    texdoc[mod] = texdoc[mod] or require('texdoclib-' .. mod)
+    return texdoc[mod][func]
+end
+
+--------------------------   hide the config table   --------------------------
+
+-- config is read-only (but not "deep" read-only)
+local 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
+local real_set_config = set_read_only(config, 'config')
+
+-- the accessor
+function M.get_value(key) return config[key] end
+
+-------------------------   general config functions   ------------------------
+
+-- interpreting 'context' in this section
+local 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 == 'loc' then
+        return 'from operating system locale'
+    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
+
+-- a helper function for warning messages in this section
+local function config_warn(key, value, context, unknown)
+    local err_print = import_function('util', 'err_print')
+    local begin = unknown
+        and string.format('Unknown option "%s"', key)
+        or string.format('Illegal value "%s" for option "%s"',
+            key, tostring(value))
+    texdoc.util.err_print('warning',
+        '%s %s. Skipping.', begin, context_to_string(context))
+end
+
+-- set a config parameter, but don't overwrite it if already set
+-- three special types: *_list (list), *_switch (boolean), *_level (number)
+function M.set_config_element(key, value, context)
+    local dbg_print = import_function('util', 'dbg_print')
+    local parse_error = false
+
+    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
+        if context.src ~= 'def' then
+            dbg_print('config', 'Ignoring "%s=%s" %s.',
+                key, tostring(value), context_to_string(context))
+        end
+        return nil
+    end
+
+    -- record the source of the setting
+    real_set_config(key .. '_src', context.src)
+
+    -- detect the type of the key
+    if string.match(key, '_list$') then
+        -- coma-separated list
+        local values
+        if value == '' then
+            values = {}
+        else
+            values = string.explode(value, ',')
+        end
+
+        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)
+            parse_error = true
+        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)
+            parse_error = true
+        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
+        dbg_print('version', '%s v%s', C.fullname, C.version)
+    end
+
+    -- now tell what we have just done, for debugging
+    if not parse_error then
+        dbg_print('config', 'Setting "%s=%s" %s.',
+            key, tostring(value), context_to_string(context))
+    end
+end
+local set_config_element = M.set_config_element
+
+-- set a whole list, also without overwriting
+local function set_config_list(conf, context)
+    for key, value in pairs(conf) do
+        set_config_element(key, value, context)
+    end
+end
+
+------------------------   config from command line   ------------------------
+
+-- set config from the command line
+-- Note: Make sure to set a default value in setup_config_from_defaults()
+--       if relevant.
+local function setup_config_from_cl(cl_config)
+    for _, e in ipairs(cl_config) do
+        set_config_element(e[1], e[2], {src='cl', name=e[3]})
+    end
+end
+
+-------------------------   config from environment   --------------------------
+
+-- set config from environment if available
+local 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', 'PDFVIEWER', 'TEXDOCVIEW_pdf', 'TEXDOC_VIEWER_PDF'})
+    set_config_elt_from_vars('viewer_ps',
+      {'PSVIEWER_texdoc', 'PSVIEWER', 'TEXDOCVIEW_ps', 'TEXDOC_VIEWER_PS'})
+    set_config_elt_from_vars('viewer_dvi',
+      {'DVIVIEWER_texdoc', 'DVIVIEWER', 'TEXDOCVIEW_dvi', 'TEXDOC_VIEWER_DVI'})
+    set_config_elt_from_vars('viewer_html',
+      {'BROWSER_texdoc', 'BROWSER', 'TEXDOCVIEW_html', 'TEXDOC_VIEWER_HTML'})
+    set_config_elt_from_vars('viewer_md',
+      {'MDVIEWER_texdoc', 'MDVIEWER', 'TEXDOCVIEW_md', 'TEXDOC_VIEWER_MD'})
+    set_config_elt_from_vars('viewer_txt',
+      {'PAGER_texdoc', 'PAGER', 'TEXDOCVIEW_txt', 'TEXDOC_VIEWER_TXT'})
+end
+
+----------------------   options and aliases from files   ----------------------
+
+-- interpret a confline as a config setting or return false
+local 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
+
+-- set config and aliases from a particular config file assumed to exist
+local function read_config_file(configfile)
+    local err_print = import_function('util', 'err_print')
+    local confline_to_alias = import_function('alias', 'confline_to_alias')
+    local confline_to_score = import_function('score', 'confline_to_score')
+
+    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 %s at line %d.', configfile, lineno)
+        end
+    end
+    cnf:close()
+end
+
+-- return the list of configuration files
+local function get_config_files()
+    -- get names
+    local platform = string.match(kpse.var_value('SELFAUTOLOC'), '.*/(.*)$')
+    local names = {
+        'texdoc-' .. platform .. '.cnf',
+        'texdoc.cnf',
+        'texdoc-dist.cnf',
+    }
+
+    -- get dirs
+    local sep = (os.type == 'windows') and ';' or ':'
+    local texmf_texdoc = kpse.expand_path('$TEXMF/texdoc')
+    local dirs = texmf_texdoc:explode(sep)
+
+    -- merge them
+    local ret = {}
+    for _, dir in ipairs(dirs) do
+        for _, name in ipairs(names) do
+            local pathname = dir .. '/' .. name
+            table.insert(ret, pathname)
+        end
+    end
+    return ret
+end
+
+-- the config_files table is shared by the following two functions
+local setup_config_from_files
+
+do -- begin scope of config_files
+local config_files = {}
+
+-- set config/aliases from all config files
+setup_config_from_files = function()
+    local file_list = get_config_files()
+
+    for i, file in ipairs(file_list) do
+        -- determine the status of the config file
+        local status
+        if lfs.isfile(file) then
+            status = config.lastfile_switch and 'disabled' or 'active'
+        else
+            status = 'not found'
+        end
+
+        -- register it
+        config_files[i] = {
+            path = file,
+            status = status,
+        }
+
+        -- read only if active
+        if status == 'active' then
+            read_config_file(file)
+        end
+    end
+end
+
+-- now a special information function (see -f,--file option)
+function M.show_config_files(is_action)
+    local w32_path = import_function('util', 'w32_path')
+    local dbg_print = import_function('util', 'dbg_print')
+
+    -- controled print_func
+    local indent = is_action and '    ' or ''
+    local print_func = is_action and print
+        or function(s) dbg_print('files', s) end
+
+    -- show the list of configuration files
+    print_func('Configuration files are:')
+    for i, file in ipairs(config_files) do
+        -- if not verbose, do not show "not found" files for -f
+        if file.status ~= "not found"
+                or (not is_action or config.verbosity_level == 3) then
+            print_func(indent .. file.status .. '\t' .. w32_path(file.path))
+        end
+    end
+
+    -- show the recommendation (only for the "files" action)
+    if is_action then
+        print_func('Recommended file(s) for personal settings:')
+        local sep = (os.type == 'windows') and ';' or ':'
+        local texmfhomes = string.explode(kpse.var_value('TEXMFHOME'), sep)
+        for _, home in ipairs(texmfhomes) do
+            print_func(indent .. w32_path(home .. '/texdoc/texdoc.cnf'))
+        end
+    end
+end
+
+end -- end scope of config_files
+
+----------------------   config from locale settings   -------------------------
+
+local function setup_config_from_locale()
+    local current = os.setlocale(nil, 'all')
+    os.setlocale('', 'all')
+    local native = os.setlocale(nil, 'time')
+    os.setlocale(current, 'all')
+    local lang = string.match(native, '^[a-z][a-z]')
+    if lang then
+        set_config_element('lang', lang, {src='loc'})
+    end
+end
+
+----------------------   options from built-in defaults   ----------------------
+
+-- for default viewer on general Unix, we have a list; the following function is
+-- 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
+local is_in_path
+do local path_list = string.explode(os.getenv('PATH'), ':')
+is_in_path = function(name)
+    for _, path in ipairs(path_list) do
+        if lfs.isfile(path .. '/' .. name) then return true end
+    end
+    return false
+end
+end
+
+-- returns a viewer specific to a desktop environment if relevant
+-- doesn't work on windows (uses io.popen)
+-- logic stolen from xdg-open (http://www.freedesktop.org/) and adapted
+local function desktop_environment_viewer()
+    local xdg_current_desktop = os.getenv('XDG_CURRENT_DESKTOP') or ''
+    if (os.getenv('KDE_SESSION_VERSION') or os.getenv('KDE_FULL_SESSION'))
+        or string.match(xdg_current_desktop, '.*KDE.*') then
+        if is_in_path('kde-open') then return '(kde-open %s) &' end
+        if is_in_path('kfmclient') then return '(kfmclient exec %s) &' end
+    end
+    if os.getenv('GNOME_DESKTOP_SESSION_ID')
+        or string.match(xdg_current_desktop, '.*GNOME.*') then  -- gnome
+        if is_in_path('gvfs-open') then return '(gvfs-open %s) &' end
+        if is_in_path('gnome-open') then return '(gnome-open %s) &' end
+    end
+    if not is_in_path('xprop') then return end
+    local xprop_fh = io.popen('xprop -root _DT_SAVE_MODE 2>/dev/null')
+    local xprop_out = xprop_fh:read('*line')
+    xprop_fh:close()
+    if xprop_out and string.find(xprop_out, '= "xfce4"$') then  -- xfce
+        return '(exo-open %s) &'
+    end
+end
+
+-- guess a viewer from a list:
+-- - xdg-open from freedesktop if available
+-- - 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
+local guess_viewer
+do local de_viewer
+guess_viewer = function(cmds)
+    -- try the freedesktop method
+    if is_in_path('xdg-open') then
+        return '(xdg-open %s) &'
+    end
+    -- 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
+
+-- set viewers from defaults (done only if necessary)
+function M.get_default_viewers()
+    local function set_config_ls(ls) set_config_list(ls, {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',
+            viewer_md = viewer_txt,
+        }
+    elseif (os.name == 'macosx') then
+        set_config_ls {
+            viewer_dvi = 'open',
+            viewer_html = 'open',
+            viewer_pdf = 'open',
+            viewer_ps = 'open',
+            viewer_txt = 'less',
+            viewer_md = viewer_txt,
+        }
+    else -- generic Unix
+        set_config_ls {
+            viewer_dvi = guess_viewer {
+                {'xdvi', '(xdvi %s) &'},
+                {'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) &'},
+                {'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 {
+                {'xpdf', '(xpdf %s) &'},
+                {'evince', '(evince %s) &'},
+                {'okular', '(okular %s) &'},
+                {'kpdf', '(kpdf %s) &'},
+                {'acroread', '(xpdf %s) &'},
+                {'see', '(see %s) &'}
+            },
+            viewer_ps = guess_viewer {
+                {'gv', '(gv %s) &'},
+                {'evince', '(evince %s) &'},
+                {'okular', '(okular %s) &'},
+                {'kghostview', '(kghostview %s) &'},
+                {'see', '(see %s) &'}
+            },
+            viewer_txt = guess_viewer {
+                {'most', 'most'},
+                {'less', 'less'},
+                {'more', 'more'}
+            },
+            viewer_md = viewer_txt,
+        }
+    end
+end
+
+-- set some fall-back default values if no previous value is set
+local 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
+    -- various, platform independent, stuff
+    set_config_ls {
+        mode = 'view',
+        interact_switch = 'true',
+        machine_switch = 'false',
+        ext_list = 'pdf, htm, html, txt, md, ps, dvi, ',
+        basename_list = 'readme, 00readme',
+        badext_list = 'txt, ',
+        badbasename_list = 'readme, 00readme',
+        suffix_list = '',
+        verbosity_level = C.def_verbosity,
+        debug_list = '',
+        max_lines = '20',
+        fuzzy_level = '5',
+    }
+    -- zip-related options
+    set_config_ls {
+        zipext_list = '',
+        rm_file = 'rm -f',
+        rm_dir = 'rmdir',
+    }
+end
+
+--------------------------   set all configuration   ---------------------------
+
+-- populate the config and alias arrays
+function M.setup_config_and_alias(cl_config)
+
+    -- setup config from all sources
+    setup_config_from_cl(cl_config)
+    setup_config_from_env()
+    setup_config_from_files()
+    setup_config_from_locale()
+    setup_config_from_defaults()
+
+    -- machine mode implies no interaction
+    if config.machine_switch == true then
+        real_set_config('interact_switch', false)
+    end
+
+    -- debug implies verbose
+    if #config.debug_list > 0 then
+        real_set_config('verbosity_level', tonumber(C.max_verbosity))
+    end
+
+    -- we were waiting for config.debug_list to be known to do this
+    M.show_config_files()
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-config.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-const.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-const.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-const.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,158 @@
+-- texdoclib-const.tlu: global constants for texdoc
+--
+-- The TeX Live team, GPLv3, see texdoclib.tlu for details
+
+-- use an empty environment that will become texdoc_env.C (see EOF)
+local constants = {}
+local kpse = kpse
+local setfenv = setfenv
+local texdoc_env
+
+if setfenv then -- Lua <5.2
+    texdoc_env = getfenv()
+    setfenv(1, constants)
+else
+    texdoc_env = _ENV
+    _ENV = constants
+end
+
+-- BEGIN constants
+
+-- progname and version
+fullname = kpse.find_file('texdoc/texdoclib', 'lua')
+progname = 'Texdoc'
+version = '3.1'
+release_date = '2019-03-28'
+
+-- make sure to update setup_config_from_cl() accordingly
+-- and set a default value in setup_config_from_defaults() if relevant
+usage_msg = [[
+Usage: texdoc [OPTION...] NAME...
+  or:  texdoc [OPTION...] ACTION
+
+Try to find appropriate TeX documentation for the specified NAME(s).
+Alternatively, perform the given ACTION and exit.
+
+Options:
+  -w, --view        Use view mode: start a viewer. (default)
+  -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.
+
+  -i, --interact    Use interactive menus. (default)
+  -I, --nointeract  Use plain lists, no interaction required.
+  -M, --machine     Machine-readable output for lists (implies -I).
+
+  -q, --quiet       Suppress warnings and most error messages.
+  -v, --verbose     Print additional information (e.g., viewer command).
+  -D, --debug       Activate all debug output (equal to "--debug=all").
+  -d LIST, --debug=LIST
+                    Activate debug output restricted to LIST.
+  -c NAME=VALUE     Set configuration item NAME to VALUE.
+
+Actions:
+  -h, --help        Print this help message.
+  -V, --version     Print the version number.
+  -f, --files       Print the list of configuration files used.
+  --just-view FILE  Display FILE, given with full path (no searching).
+
+Full manual available via `texdoc texdoc'.
+
+Website: <https://tug.org/texdoc/>
+Repository: <https://github.com/TeX-Live/texdoc>
+Please email bugs to <texdoc at tug.org>.]]
+
+copyright_msg = [[
+Copyright 2008 Manuel Pégourié-Gonnard, Takuto Asakura, and the TeX Live Team.
+License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
+This is free software: you are free to change and redistribute it.]]
+
+actions_ph = 'Actions:\n'
+
+known_options = {
+    'viewer_.*',
+    'mode',
+    'interact_switch',
+    'machine_switch',
+    'ext_list',
+    'basename_list',
+    'badext_list',
+    'badbasename_list',
+    'suffix_list',
+    'verbosity_level',
+    'debug_list',
+    'lastfile_switch',
+    'rm_dir',
+    'rm_file',
+    'unzip_.*',
+    'zipext_list',
+    'max_lines',
+    'lang',
+    'fuzzy_level',
+    'texlive_tlpdb',
+}
+
+error_msg = [[
+Try `texdoc --help' for short help, `texdoc texdoc' for full manual.]]
+
+notfound_msg = [[
+Sorry, no documentation found for "PKGNAME".
+If you are unsure about the name, try full-text searching on CTAN.
+Search form: <https://www.ctan.org/search/>]]
+notfound_msg_ph = 'PKGNAME'
+
+-- exit codes
+exit_ok = 0
+exit_error = 1 -- apparently hard-coded in Lua
+exit_usage = 2
+exit_notfound = 3
+
+err_priority = {
+    error = 1,
+    warning = 2,
+    info = 3,
+}
+min_verbosity = '0'  -- (nothing at all)
+max_verbosity = '3'
+def_verbosity = '2'
+
+known_debugs = {
+    config = {'files'},
+    files = {},
+    search = {},
+    score = {},
+    texdocs = {},
+    tlpdb = {},
+    version = {},
+    view = {},
+}
+
+-- various cache or non-cache files
+cache_name = 'texdoc/cache-tlpdb.lua' -- relative to TEXMFVAR
+data_tlpdb_name = 'texdoc/Data.tlpdb.lua'
+
+place_holder = '%%s' -- used for viewer commands
+
+-- END constants
+
+-- get our previous environment back
+if setfenv then
+    setfenv(1, texdoc_env)
+else
+    _ENV = texdoc_env
+end
+
+-- Make table C a read-only proxy to the local <constants>.
+-- Note this is not deep read-only: C.known_debugs is read-only, but
+-- C.known_debugs.version isn't, for instance.
+local C = {}
+setmetatable(C, {
+    __index = constants,
+    __newindew = function()
+        error('Internal error: attempt to modify a constant.')
+    end
+})
+
+return C
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-const.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-score.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-score.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-score.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,293 @@
+-- texdoclib-score.tlu: scoring functions for texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+-- dependencies
+local texdoc = {
+    util = require('texdoclib-util'),
+    config = require('texdoclib-config'),
+}
+
+-- shortcuts
+local M = {}
+local dbg_print = texdoc.util.dbg_print
+
+-- shared variables
+local global_adjscore, spec_adjscore = {}, {}
+
+-------------------------   configuration directives   -------------------------
+
+-- set key in score table to val, without overriding
+local 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
+
+-- interpret a confline as a score directive or return false
+function M.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
+
+----------------------------   score computation   -----------------------------
+
+-- says if pat is a "subword" of str
+local function is_subword(str, pat)
+    local function is_delim(str, i)
+        return not not string.find(string.sub(str, i, i), '%p')
+    end
+
+    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
+
+-- says if a filename has a bad basename
+local function has_bad_basename(file)
+    file = file:gsub('.*/', '')
+    for _, b in ipairs(texdoc.config.get_value('badbasename_list')) do
+        if file:find('^' .. b .. '$') or file:find('^' .. b .. '%.') then
+            return true
+        end
+    end
+    return false
+end
+
+-- compute a heuristic score -10 <= s < 10
+local function heuristic_score(file, pat)
+    dbg_print('score', 'Start heuristic scoring with pattern: ' .. pat)
+    -- score management
+    local score = -10
+    local function upscore(s, reason, force)
+        if s > score or force then
+            score = s
+            dbg_print('score',
+                'New heuristic score: %.1f. Reason: %s', s, reason)
+        end
+    end
+    local slash = not not string.find(pat, '/', 1, true)
+    -- look for exact or subword match
+    if M.is_exact_locale(file, pat) then
+        upscore(5, 'exact match with correct locale')
+    elseif M.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(texdoc.config.get_value('suffix_list')) do
+            local deriv = pat..suffix
+            if M.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
+    -- if extension is bad, score becomes an epsilon
+    local ext = texdoc.config.get_value('ext_list')[M.ext_pos(file)]
+    if ext and texdoc.config.get_value('badext_list_inv')[ext] and score > 0 then
+        upscore(0.1, 'bad extension', true)
+    end
+    -- if basename is bad, score becomes an epsilon
+    if has_bad_basename(file) and score > 0 then
+        upscore(0.1, 'bad basename', true)
+    end
+    -- bonus for being in the right directory
+    if string.find('/' .. file, '/' .. pat .. '/', 1, true) and not slash then
+        upscore(score + 1.5, 'directory bonus')
+    end
+    -- done
+    dbg_print('score', 'Final heuristic score: %.1f', score)
+    return score
+end
+
+-- set the score of a docfile
+local function set_score(df, original_kw)
+    -- scoring is case-insensitive (patterns are already lowercased)
+    local name = string.lower(df.shortname)
+    dbg_print('score', '----------')
+    dbg_print('score', 'Start scoring ' .. df.realpath)
+    dbg_print('score', 'Name used: ' .. name)
+    -- get score from patterns
+    local score = -10
+    for _, pat in ipairs(df.matches) do
+        local s = -10
+        local p = string.lower(pat.name)
+        if pat.original then
+            s = df.tree > -1 and heuristic_score(name, p) or 1
+        elseif M.is_exact(name, p) then
+            local bonus, note = 0, ''
+            if pat.locale then
+                bonus, note = 5, ', (language-based)'
+            end
+            s = (pat.score or 10) + bonus -- default alias score is 10
+            dbg_print('score',
+                'Matching alias "%s", score: %.1f%s', pat.name, s, note)
+        end
+        if s > score then score = s end
+    end
+    dbg_print('score', 'Max pattern score: %.1f', score)
+    -- get score from tlp associations
+    if score == -10 and df.tlptodoc then
+        score = -1
+        dbg_print('score',
+            'New score: %.1f from package name association', score)
+    end
+    if score == -10 and df.runtodoc then
+        score = -5
+        dbg_print('score',
+            'New score: %.1f from sty/cls association', score)
+    end
+    -- bonus for metadata
+    if df.details then
+        if string.find(string.lower(df.details), 'readme') then
+            score = score + 0.1
+            dbg_print('score', 'Catalogue "readme" bonus: +0.1')
+        else
+            score = score + 1.5
+            dbg_print('score', 'Catalogue details bonus: +1.5')
+        end
+    end
+    -- 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
+                score = score + val
+                dbg_print('score',
+                    'Adjust by %.1f 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 > -10 or val < 0 then score = score + val end
+                dbg_print('score',
+                    'Adjust by %.1f from global pattern "%s"', val, pat)
+            end
+        end
+    end
+    dbg_print('score', 'Final score: %.1f', score)
+    df.score = score
+end
+
+-- set the scores for a doclist
+local function set_list_scores(list, original_kw)
+    for _, df in ipairs(list) do
+        set_score(df, original_kw)
+    end
+end
+
+-- says if file is an exact match for pat
+function M.is_exact(file, pat)
+    file = texdoc.util.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(texdoc.config.get_value('ext_list')) do
+        if ext ~= '' and ext ~= '*' and basename == pat .. '.' .. ext then
+            return true
+        end
+    end
+    return false
+end
+
+-- says if file is an exact match for pat and the current locale
+function M.is_exact_locale(file, pat)
+    if string.match(pat, '%-%l%l%l?$') then
+        -- don't match if the pattern appears to include a language code
+        return false
+    end
+    local lang = texdoc.config.get_value('lang')
+    if lang then
+        return M.is_exact(file, pat .. '-' .. lang)
+            or M.is_exact(file, lang .. '-' .. pat)
+    end
+    return false
+end
+
+-- compare two docfile's: (see texdoclib-search.tlu for structure)
+-- 1. by score
+-- 2. then by extensions (ordered as in ext_list),
+-- 3. then lexicographically by fullpath.
+-- 4. then by tree.
+-- return true if a is better than b
+local function docfile_order(a, b)
+    if     a.score > b.score       then return true
+    elseif a.score < b.score       then return false
+    elseif a.ext_pos < b.ext_pos   then return true
+    elseif a.ext_pos > b.ext_pos   then return false
+    elseif a.realpath < b.realpath then return true
+    elseif a.realpath > b.realpath then return false
+    else return (a.tree > b.tree)
+    end
+end
+
+-----------------------------   public functions   -----------------------------
+
+-- returns the index of the most specific extension of file in ext_list,
+-- or config.ext_list_max + 1
+function M.ext_pos(file)
+    -- remove zipext if applicable
+    file = texdoc.util.parse_zip(file)
+    -- now find the extension
+    local p, e, pos, ext
+    for p, e in ipairs(texdoc.config.get_value('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 (texdoc.config.get_value('ext_list_max') + 1)
+end
+
+-- return the "quality" of docfile
+function M.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 M.sort_doclist(dl, original_kw)
+    dl:stop()
+    set_list_scores(dl, original_kw)
+    table.sort(dl, docfile_order)
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-score.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-search.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-search.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-search.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,771 @@
+-- texdoclib-search.tlu: file searching functions for texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+-- Warning: Some functions here assume that M.init_databases() has been called.
+
+-- dependencies
+local texdoc = {
+    const = require('texdoclib-const'),
+    util = require('texdoclib-util'),
+    alias = require('texdoclib-alias'),
+    score = require('texdoclib-score'),
+    config = require('texdoclib-config'),
+}
+
+-- shortcuts
+local M = {}
+local C = texdoc.const
+local err_print = texdoc.util.err_print
+local dbg_print = texdoc.util.dbg_print
+
+-- shared by all functions in this file
+local s_doclist -- the Doclist object to be populated by various functions
+local s_meta -- {[normname] = meta, ...} (populated by init_tlp_database)
+local vanilla -- is this a vanilla TL or a re-package one without tlpdb?
+
+----------------------------   utility functions   -----------------------------
+
+-- find the TeX Live root
+local function get_tlroot()
+    local tlroot = kpse.var_value('TEXMFROOT')
+    get_tlroot = function() return tlroot end
+    return tlroot
+end
+
+-- says if file has a known extension according to ext_list
+-- (or known basename according to basename_list)
+local function check_ext(file)
+    file = string.lower(file)
+    -- remove zipext if applicable
+    file = texdoc.util.parse_zip(file)
+    -- then do the normal thing
+    for _, e in ipairs(texdoc.config.get_value('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
+    -- is the basename good?
+    for _, b in ipairs(texdoc.config.get_value('basename_list')) do
+        if file:find('^' .. b .. '$') or file:find('^' .. b .. '%.') then
+            return true
+        end
+    end
+    return false
+end
+
+-----------------------   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:lower()) == i
+Paths are lowercased in order to avoid duplicates on windows.
+--]]
+
+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)
+    -- if no realpath information, unable to add
+    -- (useful if vanilla == false)
+    if not df.realpath then return end
+
+    -- check the existence of the file
+    if not lfs.isfile(df.realpath) then
+        dbg_print('search', 'File %s not found.  Skipping.', df.realpath)
+        return
+    end
+
+    -- add the docfile to the list
+    local index = self.inv[df.realpath:lower()]
+    if index then
+        self[index]:mergein(df)
+    else
+        dbg_print('search', 'File %s found.', df.realpath)
+
+        local newindex = #self + 1
+        self[newindex] = df
+        self.inv[df.realpath:lower()] = newindex
+    end
+end
+
+-- stops a doclist
+function Doclist:stop()
+    self.inv = nil
+end
+
+--[[
+docfile = {
+    -- name and tree are mandatory
+    name      = filename (used for scoring only)
+    tree      = code of the tree, see below
+    -- at least one of the following fields should exist
+    matches   = {pattern1, pattern2, ...} or {}
+    runtodoc  = true if there is a runfile -> docfile association
+    tlptodoc  = true if there is a tlp name -> docfile association
+    -- those are virtual members, see below
+    realpath  = full path
+    normname  = nomrmalised (path removed up to the 'doc' component)
+    shortname = short name used for scoring
+    basename  = basename
+    lang      = language tag from the catalogue metadata
+    details   = details tag from the catalogue metadata
+    quality   = 'good', 'bad', or 'killed' depending on score
+    ext_pos   = position of the extension in ext_list
+    -- set for elements of a list as a side effect of sort_doclist()
+    score     = score
+}
+if tree > 1, this is the index of the tree in TEXDOCS
+if tree = 0, then name is relative to TLROOT
+tree = - 1 if and only if file is a sty file. Here name is absolute.
+--]]
+
+-- Docfile objects inherit members from Docfile
+-- and have virtual members implemented by get_<member>() methods
+-- for best cache performance, getters should not return nil
+local Docfile = {}
+function Docfile:__index(key)
+    if Docfile[key] then return Docfile[key] end
+    local getter = Docfile['get_' .. key]
+    if getter then
+        rawset(self, key, getter(self))
+        return rawget(self, key)
+    end
+end
+
+-- create a new docfile object using initialisation info
+-- required fields: name, tree
+function Docfile:new(info)
+    local df = {}
+    setmetatable(df, self)
+    for k, v in pairs(info) do
+        if k == 'pattern' then
+            df.matches = {info.pattern}
+        else
+            df[k] = v
+        end
+    end
+    return df
+end
+
+-- merge a second docfile object in, assuming it represents the same file
+function Docfile:mergein(df)
+    for k, v in pairs(df) do
+        if k == 'matches' then
+            for _, m in ipairs(df.matches or {}) do
+                table.insert(self.matches, m)
+            end
+        else
+            self[k] = v
+        end
+    end
+end
+
+-- return the full path to the file
+local texdocs_tree_to_path  -- definition later
+function Docfile:get_realpath()
+    if self.tree > 0 then
+        return texdocs_tree_to_path(self.tree, self.name)
+    elseif self.tree == 0 then
+        if vanilla then
+            return get_tlroot() .. '/' .. self.name
+        else
+            return kpse.find_file(self.normname, 'TeX system documentation')
+        end
+    else
+        return self.name
+    end
+end
+
+-- normalise a name from the tlpdb (use for s_meta indexes)
+local function reloc_tlpdb_path(name)
+    return string.gsub(name, '^texmf[^/]*/doc/', '', 1)
+end
+
+-- return normalised name
+function Docfile:get_normname()
+    return (self.tree == 0) and reloc_tlpdb_path(self.name) or self.name
+end
+
+-- retrieve the lang from meta
+function Docfile:get_lang()
+    local meta = s_meta[self.normname]
+    return meta and (meta.lang or false) or false
+end
+
+-- retrieve the details from meta
+function Docfile:get_details()
+    local meta = s_meta[self.normname]
+    return meta and (meta.details or false) or false
+end
+
+-- return the short name used for scoring
+function Docfile:get_shortname()
+    if self.tree == -1 then return self.name end
+    -- remove first component of name if at least two directory levels
+    return string.match(self.normname, '^..-/(.+/.+)$') or self.normname
+end
+
+-- return the base name
+function Docfile:get_basename()
+    return string.gsub(self.name, '.*/', '', 1)
+end
+
+-- for interface consistency, matches should always be a table, never nil
+function Docfile:get_matches()
+    return {}
+end
+
+-- from texdoclib-score.tlu
+Docfile.get_quality = texdoc.score.docfile_quality
+
+-- from texdoclib-score.tlu
+function Docfile:get_ext_pos()
+    return texdoc.score.ext_pos(self.basename)
+end
+
+--------------------   select results from TEXDOCS trees   ---------------------
+
+-- says if a file (with its path) matches a pattern
+local function matches(pattern, file)
+    if pattern.original then
+        return string.find(file:lower(), pattern.name:lower(), 1, true)
+    else
+        return texdoc.score.is_exact(file, pattern.name)
+    end
+end
+
+-- return a docfile object if file "matches", nil otherwise
+local function process_file(patlist, file, pathfile, code)
+    local docfile
+    local pattern
+    for _, pattern in ipairs(patlist) do
+        if matches(pattern, pathfile) 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
+    return docfile
+end
+
+-- scan a database
+local function scan_db(patlist, code, lsr_db)
+    for file, basename in pairs(lsr_db) do
+        local df = process_file(patlist, basename, file, code)
+        if df then s_doclist:add(df) end
+    end
+end
+
+---------------------   manage TEXDOCS trees à la kpse   ----------------------
+
+-- build a db from a ls-R file
+local function init_lsr_db(root, shift)
+    -- open the file
+    local lsr = assert(io.open(root .. '/ls-R', 'r'))
+    local _ = lsr:read('*line') -- throw away first line (comment)
+
+    -- scan it
+    local db = {}
+    local maybe_dir, isdoc = true, false
+    local current_dir
+    local l = #shift
+    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)
+                db[current_dir] = nil
+            elseif isdoc then
+                break -- we're exiting the ./doc (or shift) dir, so it's over
+            end
+        elseif isdoc then
+            local file = (current_dir == '') and line or current_dir .. '/' .. line
+            if check_ext(line) then db[file] = line end
+        end
+    end
+
+    lsr:close()
+
+    return db
+end
+
+-- build a db for a tree without ls-R index
+local function init_tree_db(base, recurse)
+    local db = {}
+    local function init_tree_db_rec(dir)
+        for file in lfs.dir(base .. '/' .. dir) do
+            if file ~= '.' and file ~= '..' then
+                local f = (dir == '') and file or dir .. '/' .. file
+                if lfs.isdir(base..'/'..f) then
+                    if recurse then init_tree_db_rec(f) end
+                else
+                    if check_ext(file) then db[f] = file end
+                end
+            end
+        end
+    end
+    init_tree_db_rec('')
+    return db
+end
+
+local init_texdocs_database, get_doclist_texdocs
+
+do -- begin scope of doc_roots
+local doc_roots
+
+--[[
+doc_roots[i] = {
+    path    = initial path,
+    db      = {[file1] = basename1, [file2] = basename2, ...},
+}
+--]]
+
+-- populate the doc_roots filename databases
+init_texdocs_database = function()
+    -- find a ls-R file in a parent directory and return it or nil
+    local 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
+
+    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 n
+        local path, db
+
+        -- get path, !! and // values
+        dir, n = string.gsub (dir, '//$', '')
+        local recursion_allowed = (n == 1)
+        local path, n = string.gsub (dir, '^!!', '')
+        local index_mandatory = (n == 1)
+        dbg_print('texdocs',
+            'texdocs[%d] = %s (index_mandatory=%s, recursion_allowed=%s)',
+            i, path, tostring(index_mandatory), tostring(recursion_allowed))
+
+        -- decide if we should use a ls-R index, the filesystem, or do nothing
+        local root, shift = lsr_root(path)
+        if root and shift and recursion_allowed then
+            dbg_print('texdocs',
+                'texdocs[%d] using index: %s (shift=%s)', i, root, shift)
+            db = init_lsr_db(root, shift)
+        elseif not index_mandatory and lfs.isdir(path) then
+            dbg_print('texdocs',
+                'texdocs[%d] using filesystem search', i)
+            db = init_tree_db(path, recursion_allowed)
+        end
+
+        -- register this in docroots
+        doc_roots[i] = {path=path, db=db}
+    end
+end
+
+-- find docfiles in texdocs directories
+get_doclist_texdocs = function(patlist)
+    for code, dr in ipairs(doc_roots) do
+        if dr.db then scan_db(patlist, code, dr.db) end
+    end
+end
+
+-- return the real path from a texdocs tree number + relative path
+texdocs_tree_to_path = function (tree, rel)
+    return doc_roots[tree].path .. '/' .. rel
+end
+
+end -- end scope of doc_roots
+
+----------------------------   look for sty files   ----------------------------
+
+-- add doclist entries for sty files in patlist
+local 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
+
+--------------------------------   use tlpdb   ---------------------------------
+
+-- tlpdb mean TeX Live Package DataBase and tlp means TeX Live Package
+
+-- return true if cache exists and is newer than original, false otherwise
+local function good_cache(cache, ori)
+    local cache_date = lfs.attributes(cache, 'modification')
+    if not cache_date then return false end
+    local ori_date = assert(lfs.attributes(ori, 'modification'))
+    return cache_date > ori_date
+end
+
+-- make sure a given directory exists, or return nil plus an error string
+local function mkdir_p(dir)
+    if lfs.isdir(dir) then return true end
+    local parent = texdoc.util.path_parent(dir)
+    if parent then
+        local ok, msg = mkdir_p(parent)
+        if not ok then return nil, msg end
+    end
+    return lfs.mkdir(dir)
+end
+
+local print_out_tlpinfo, get_doclist_tlpdb
+local get_tlpinfo_from_tlpdb, get_tlpinfo_from_cache, get_tlpinfo_from_dist
+
+do -- begin scope of tlpinfo tables
+local tlp_from_runfile -- {[runfile_basename] = {tlp1 = true, ...}, ...}
+local tlp_doclist -- {[tlp_name] = {relname1, relname2, ...}, ...}
+
+-- remove entries for tlp without any docfile
+local function remove_useless_tlp()
+    for tlp, doclist in pairs(tlp_doclist) do
+        if #doclist == 0 then tlp_doclist[tlp] = nil end
+    end
+    for runfile, tlp_set in pairs(tlp_from_runfile) do
+        for tlp in pairs(tlp_set) do
+            if not tlp_doclist[tlp] then
+                tlp_from_runfile[runfile][tlp] = nil
+            end
+        end
+    end
+end
+
+-- populate tlpinfo tables using the given texlive.tlpdb
+get_tlpinfo_from_tlpdb = function(filename)
+    s_meta, tlp_from_runfile, tlp_doclist = {}, {}, {}
+    local curr_tlp
+    local state = 'none'
+    for line in io.lines(filename) do
+        if state == 'none' and string.find(line, '^name ') then
+            -- begin a new package
+            curr_tlp = string.lower(string.sub(line, 6, -1))
+            tlp_doclist[curr_tlp] = {}
+        elseif state == 'docfiles' then
+            if not string.find(line, '^ ') then
+                state = 'none'
+            else
+                local file = string.match(line, '^ ([^ ]*)')
+                local meta = string.match(line, '^ [^ ]* (.+)')
+                local basename = string.match(file, '([^/]*)$')
+                if check_ext(basename) then
+                    -- we've got a docfile here, add it
+                    table.insert(tlp_doclist[curr_tlp], file)
+                    if meta then
+                        local details = string.match(meta, 'details="([^"]+)"')
+                        local lang = string.match(meta, 'language="([^"]+)"')
+                        s_meta[reloc_tlpdb_path(file)] = {
+                            details = details,
+                            lang = lang,
+                        }
+                    end
+                end
+            end
+        elseif state == 'runfiles' then
+            if not string.find(line, '^ ') then
+                state = 'none'
+            else
+                -- check for interesting runfiles
+                local e = string.sub(line, -4, -1)
+                if e == '.tex' or e == '.sty' or e == '.cls' then
+                    local f = string.match(line, '.*/(.*)%.')
+                    tlp_from_runfile[f] = tlp_from_runfile[f] or {}
+                    tlp_from_runfile[f][curr_tlp] = true
+                end
+            end
+        end
+        -- update state
+        if string.find(line, '^docfiles ') then
+            state = 'docfiles'
+        elseif string.find(line, '^runfiles ') then
+            state = 'runfiles'
+        end
+    end
+    remove_useless_tlp()
+end
+
+-- print out data from tlpdb in dofile()-able form
+print_out_tlpinfo = function(filename)
+    local fh = assert(io.open(filename, 'w'))
+    local function printf(s, ...) fh:write(string.format(s, ...)) end
+
+    -- s_meta
+    printf('local s_meta = {\n')
+    for k, v in pairs(s_meta) do
+        printf('  [%q] = {', k)
+        for i, j in pairs(v) do printf('[%q] = %q, ', i, j) end
+        printf('},\n')
+    end
+    printf('}\n')
+
+    -- tlp_from_runfile
+    printf('local tlp_from_runfile = {\n')
+    for k, v in pairs(tlp_from_runfile) do
+        printf('  [%q] = {', k)
+        for f in pairs(v) do printf('[%q]=true,', f) end
+        printf('},\n')
+    end
+    printf('}\n')
+
+    -- tlp_doclist
+    printf('local tlp_doclist = {\n')
+    for k, v in pairs(tlp_doclist) do
+        printf('  [%q] = {\n', k)
+        for _, f in ipairs(v) do printf('    %q,\n', f) end
+        printf('  },\n')
+    end
+    printf('}\n')
+    printf('return s_meta, tlp_from_runfile, tlp_doclist\n')
+
+    fh:close()
+end
+
+-- get pre-hashed tlpdb info from a cache file
+get_tlpinfo_from_cache = function(filename)
+    s_meta, tlp_from_runfile, tlp_doclist = dofile(filename)
+end
+
+-- get pre-hashed tlpdb info from a pseudo-cache file
+get_tlpinfo_from_dist = function()
+    local f = kpse.find_file(C.data_tlpdb_name, 'texmfscripts')
+    if not f then
+        err_print('error', 'No texlive.tlpdb nor shipped tlpdb data found.')
+        os.exit(C.exit_usage)
+    end
+    dbg_print('tlpdb', 'Getting data from shipped tlpdb data file ' .. f)
+    s_meta, tlp_from_runfile, tlp_doclist = dofile(f)
+end
+
+-- get docfiles for pattern using specific tlpdb information
+get_doclist_tlpdb = function(pattern)
+    -- runfile to tlp to docfile
+    if tlp_from_runfile[pattern] then
+        for tlp in pairs(tlp_from_runfile[pattern]) do
+            for _, file in ipairs(tlp_doclist[tlp]) do
+                s_doclist:add(Docfile:new{
+                    name = file,
+                    tree = 0,
+                    runtodoc = true,
+                })
+            end
+        end
+    end
+    -- tlp name to docfile
+    if tlp_doclist[pattern] then
+        for _, file in ipairs(tlp_doclist[pattern]) do
+            s_doclist:add(Docfile:new{
+                name = file,
+                tree = 0,
+                tlptodoc = true,
+            })
+        end
+    end
+end
+
+-- calculating Levenshtein distance by dynamic programming
+-- cf. http://lua-users.org/lists/lua-l/2008-01/msg00095.html
+function M.levenshtein(s, t)
+    local s, t = tostring(s), tostring(t)
+    if type(s) == 'string' and type(t) == 'string' then
+        local m, n, d = #s, #t, {}
+        for i = 0, m do d[i] = {[0] = i} end
+        for j = 1, n do d[0][j] = j end
+        for i = 1, m do
+            for j = 1, n do
+                local cost = s:sub(i,i) == t:sub(j,j) and 0 or 1
+                d[i][j] = math.min(
+                    d[i-1][j] + 1, d[i][j-1] + 1, d[i-1][j-1] + cost
+                )
+            end
+        end
+        return d[m][n]
+    end
+end
+
+-- fuzzy search by using Levenshtein distance
+function M.fuzzy_search(pattern)
+    local tmp_d
+    local min = math.huge
+    local result = ''
+
+    for p in pairs(tlp_doclist) do
+        tmp_d = M.levenshtein(pattern, p)
+        if tmp_d < min then
+            min, result = tmp_d, p
+        end
+    end
+
+    return result, min
+end
+
+end -- end scope of tlpinfo table
+
+-- get tlpinfo tables initialised by whatever mean
+local function init_tlp_database()
+    local TEXMFVAR = kpse.var_value('TEXMFVAR')
+    local cache_file = TEXMFVAR .. '/' .. C.cache_name
+
+    -- set vanilla and detect texlive.tlpdb to use
+    local texlive_tlpdb = get_tlroot() .. '/tlpkg/texlive.tlpdb'
+    vanilla = lfs.isfile(texlive_tlpdb)
+    local tlpdb_found = vanilla
+
+    local custom_texlive_tlpdb = texdoc.config.get_value('texlive_tlpdb')
+    if custom_texlive_tlpdb then
+        if lfs.isfile(custom_texlive_tlpdb) then
+            texlive_tlpdb = custom_texlive_tlpdb
+            tlpdb_found = true
+        else
+            err_print('warning',
+                'Specified texlive.tlpdb does not exist: ' ..
+                texdoc.util.w32_path(custom_texlive_tlpdb))
+            err_print('warning',
+                'Fallback to use the texlive.tlpdb in the distribution.')
+        end
+    end
+
+    -- get tlpinfo
+    if tlpdb_found then
+        if good_cache(cache_file, texlive_tlpdb) then
+            dbg_print('tlpdb', 'Using cached data from ' .. cache_file)
+            get_tlpinfo_from_cache(cache_file)
+        else
+            dbg_print('tlpdb', 'Getting data from tlpdb file ' .. texlive_tlpdb)
+            get_tlpinfo_from_tlpdb(texlive_tlpdb)
+            dbg_print('tlpdb', 'Writing data in cache file ' .. cache_file)
+            local ok, msg = mkdir_p(texdoc.util.path_parent(cache_file))
+            if not ok then
+                err_print('warning',
+                    'Failed to create cache file in %s:', cache_file)
+                err_print('warning', msg)
+            else
+                print_out_tlpinfo(cache_file)
+            end
+        end
+    else
+        dbg_print('tlpdb', 'Using shipped tlpdb data.')
+        get_tlpinfo_from_dist()
+    end
+end
+
+------------------------------   main function   -------------------------------
+
+-- initialise the various databases (must be called first)
+function M.init_databases()
+    init_texdocs_database()
+    init_tlp_database()
+end
+
+-- find docfiles according to pattern
+function M.get_doclist(pattern, no_alias)
+    -- separate sty patterns from the rest
+    local function normal_vs_sty(list)
+        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
+
+    local function doc_search(pattern, no_alias)
+        -- get patterns (inc. aliases)
+        local patterns = texdoc.alias.get_patterns(pattern, no_alias)
+        local normal, sty = normal_vs_sty(patterns)
+
+        -- get results; _texdocs search comes after _tlpdb search so that
+        -- files found by both will have the priority of the _texdocs tree.
+        -- (https://puszcza.gnu.org.ua/bugs/?369)
+        get_doclist_sty(sty)
+        get_doclist_tlpdb(pattern)
+        get_doclist_texdocs(normal)
+    end
+
+    -- initialise result list
+    s_doclist = Doclist:new()
+
+    -- 1. normal search with the input pattern
+    doc_search(pattern, no_alias)
+
+    -- 2. if no result, execute fuzzy search
+    local fuzzy_level = texdoc.config.get_value('fuzzy_level')
+    if not s_doclist[1] and fuzzy_level > 0 then
+        local f_res, f_lev = M.fuzzy_search(pattern)
+        if f_lev <= fuzzy_level then
+            err_print('info', 'Fuzzy search result: ' .. f_res)
+            dbg_print('search', 'Levenshtein distance: ' .. f_lev)
+            pattern = f_res
+            doc_search(pattern, no_alias)
+        else
+            dbg_print('search', 'Fuzzy search result: ' .. f_res)
+            dbg_print('search', 'Levenshtein distance: ' .. f_lev)
+        end
+    end
+
+    -- finally, sort results
+    texdoc.score.sort_doclist(s_doclist, pattern)
+    return s_doclist
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-search.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-util.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-util.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-util.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,127 @@
+-- texdoclib-util.tlu: utility functions for texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+-- dependencies
+local texdoc = {
+    const = require('texdoclib-const'),
+    config = require('texdoclib-config'),
+}
+
+-- shortcuts
+local M = {}
+local C = texdoc.const
+
+-- change '/' to '\' on windows
+-- Note: Internal representation of files always use forward slashes.
+--       This function should be called only before displaying a path.
+if os.type == 'windows' then
+    function M.w32_path(path)
+        return (string.gsub(path, '/', '\\'))
+    end
+else
+    function M.w32_path(path)
+        return path
+    end
+end
+
+-- remove the last directory component of a path
+if os.type == 'windows' then
+    function M.path_parent(path)
+        return string.match(path, '^(.*)[\\/]')
+    end
+else
+    function M.path_parent(path)
+        return string.match(path, '^(.*)/')
+    end
+end
+
+-- generic log display function
+local function log(label, msg, ...)
+    io.stderr:write('texdoc ' .. label .. ': ' .. msg:format(...) .. '\n')
+end
+
+-- generic error display function (see the err_priority constant)
+function M.err_print(lvl, msg, ...)
+    -- be careful: maybe config item "verbosity_level" has not set yet
+    local verbosity_level = texdoc.config.get_value('verbosity_level')
+        or tonumber(C.def_verbosity)
+
+    -- print if the priority is higher than current verbosity level
+    if C.err_priority[lvl] <= verbosity_level then
+        log(lvl, msg, ...)
+    end
+end
+local err_print = M.err_print
+
+do -- begin scope of active_debugs
+local active_debugs
+
+-- set active_debugs
+local function set_active_debugs()
+    local debug_list = texdoc.config.get_value('debug_list')
+
+    if not debug_list then return end
+    active_debugs = {}
+
+    -- all debug options imply version info
+    if debug_list[1] then
+        active_debugs.version = true
+    else
+        return
+    end
+
+    -- if 'all' is the first keyword, just activate all categories
+    if debug_list[1] == 'all' then
+        for dbg in pairs(C.known_debugs) do
+            active_debugs[dbg] = true end
+        return
+    end
+
+    -- activate options from the list
+    for _, dbg in ipairs(debug_list) do
+        local deps = C.known_debugs[dbg]
+        if deps then
+            active_debugs[dbg] = true
+            for _, d in ipairs(deps) do active_debugs[d] = true end
+        else
+            err_print('warning', 'Unknown debug category "' .. dbg .. '".')
+        end
+    end
+end
+
+-- generic debug function
+function M.dbg_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
+        log('debug-' .. cat, msg, ...)
+    end
+end
+
+end -- end scope of active_debugs
+
+-- if file is base .. '.' .. zip with zip in zipext_list, return: base, zip
+-- otherwise, return: file, nil
+function M.parse_zip(file)
+    local zip
+    for _, zip in ipairs(texdoc.config.get_value('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
+
+    return file, nil
+end
+
+-- print a usage message
+function M.print_usage()
+    print(C.usage_msg)
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-util.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-view.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib-view.tlu	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib-view.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -0,0 +1,246 @@
+-- texdoclib-view.tlu: view a document and/or display the list of results in texdoc
+--
+-- The TeX Live Team, GPLv3, see texdoclib.tlu for details
+
+-- dependencies
+local texdoc = {
+    const = require('texdoclib-const'),
+    util = require('texdoclib-util'),
+    config = require('texdoclib-config'),
+}
+
+-- shortcuts
+local M = {}
+local C = texdoc.const
+local err_print = texdoc.util.err_print
+local dbg_print = texdoc.util.dbg_print
+
+-----------------------------   view a document   -----------------------------
+
+-- view a document
+-- see texdoclib-search.tlu for the structure of the argument
+local function view_doc(docfile)
+    M.view_file(docfile.realpath)
+end
+
+-- view a file, if possible
+local 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
+
+    -- try to catch problems with missing DISPLAY on Unix
+    if os.type == 'unix' and not (os.name == 'macosx')
+            and os.getenv('DISPLAY') == nil then
+        err_print('warning',
+            'DISPLAY is not set; your viewer will likely have problems.')
+        err_print('warning',
+            'Try --list to list results instead of displaying them.')
+    end
+    err_print('info', 'View command: ' .. view_command)
+
+    -- See long comment below this function for the LC_CTYPE story.
+    -- We only want to reset the environment if we have the value
+    -- to reset it to. In older versions of luatex, status.lc_* will be nil.
+    local env_lc_ctype = status.lc_ctype
+    local luatex_lc_ctype = os.setlocale(nil, 'ctype')
+    if (env_lc_ctype) then
+        err_print('info', 'Setting environment LC_CTYPE to: ' .. env_lc_ctype)
+        os.setenv('LC_CTYPE', env_lc_ctype)
+    end
+
+    -- the big casino: run the external command.
+    if os.execute(view_command) > 0 then
+        err_print('error', 'Failed to execute: ' .. view_command)
+        os.exit(C.exit_error)
+    end
+
+    -- reset back to "C" (should always be C and always happen, but in case...)
+    if (luatex_lc_ctype) then
+        os.setenv('LC_CTYPE', luatex_lc_ctype)
+    end
+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 "" and followed by some rm commands
+--
+-- The second case happens when the doc is zipped. In the case, this function
+-- unzips it in a tmpdir so that the viewer command can use the unzipped file.
+function M.view_file(filename)
+    local viewer, viewer_replacement
+
+    -- check if the file is zipped
+    local nozipname, zipext = texdoc.util.parse_zip(filename)
+
+    -- determine viewer_replacement
+    if zipext then
+        local unzip_cmd = texdoc.config.get_value('unzip_' .. zipext)
+
+        if not unzip_cmd then
+            err_print('error', 'No unzip command for ".%s" files.', zipext)
+            os.exit(C.exit_error)
+        end
+
+        local tmpdir = os.tmpdir('/tmp/texdoc.XXXXXX')
+        if not tmpdir then
+            err_print('error', 'Failed to create tempdir to unzip.')
+            os.exit(C.exit_error)
+        end
+
+        local basename = string.match(nozipname, '.*/(.*)$') or nozipname
+        local tmpfile = '"' .. tmpdir .. '/' .. basename .. '"'
+        local unzip = unzip_cmd .. ' "' .. filename .. '">' .. tmpfile
+        dbg_print('view', 'Unzip command: ' .. unzip)
+
+        if not os.execute(unzip) then
+            err_print('error', 'Failed to unzip ' .. filename)
+            os.remove(tmpfile)
+            os.remove(tmpdir)
+            os.exit(C.exit_error)
+        end
+
+        -- it is necessary to sleep a few secounds. Otherwise, the temporary
+        -- file could be removed before opening it.
+        viewer_replacement = tmpfile .. '; sleep 2; ' ..
+            texdoc.config.get_value('rm_file') .. ' ' ..tmpfile .. '; ' ..
+            texdoc.config.get_value('rm_dir') .. ' ' .. tmpdir
+        filename = nozipname
+    else
+        viewer_replacement = '"' .. texdoc.util.w32_path(filename) .. '"'
+    end
+
+    -- files without extension are assumed to be text
+    local viewext = (filename:match('.*%.([^/]*)$') or 'txt'):lower()
+
+    -- special case : sty files use txt viewer
+    -- FIXME: hardcoding such cases this way is not very clean
+    if viewext == 'sty' then viewext = 'txt' end
+    if viewext == 'texlive' then viewext = 'txt' end
+    if viewext == 'htm' then viewext = 'html' end
+
+    -- get a viewer from built-in defaults if not already set
+    if not texdoc.config.get_value('viewer_' .. viewext) then
+        texdoc.config.get_default_viewers()
+    end
+
+    -- still no viewers? use txt as a fallback
+    if not texdoc.config.get_value('viewer_' .. viewext) then
+        err_print('warning',
+            'No viewer defined for ".%s" files, using "viewer_txt" instead.',
+            viewext)
+        viewext = 'txt'
+    end
+
+    -- finally, check validity of the viewer
+    viewer = texdoc.config.get_value('viewer_' .. viewext)
+    assert(viewer, 'Internal error: no viewer found.')
+    dbg_print('view', 'Using "viewer_%s" to open the file.', viewext )
+
+    return try_viewing(viewer, viewer_replacement)
+end
+
+-- Explanation of locale madness:
+-- LuaTeX resets LC_CTYPE, LC_COLLATE, LC_NUMERIC to "C". That is good for
+-- inside luatex, but when we run an external program, if the user's
+-- environment is something else, we want to switch back to it. As of
+-- TL 2017 LuaTeX, we can inspect the user's locale with status.lc_ctype, etc.
+--
+-- For texdoc purposes, what matters is LC_CTYPE (so we don't bother with
+-- the others). For example, with the less pager, when LC_CTYPE=C,
+-- non-ASCII bytes are displayed as "<xx>", where xx is the two hex
+-- digits for the byte.
+
+-----------------------------   display results   -----------------------------
+
+-- print a list of docfile objects (see texdoclib-search.tlu) as a menu
+-- if showall is false, stop as soon as a bad result is encountered
+local function print_menu(name, doclist, showall)
+    local max_lines = tonumber(texdoc.config.get_value('max_lines'))
+    if texdoc.config.get_value('interact_switch') and doclist[max_lines + 1] then
+        -- there may be too many lines, count them
+        local n = 0
+        for _, doc in pairs(doclist) do
+            if doc.quality == 'good' or
+                    (showall and doc.quality ~= 'killed') then
+                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, last_i
+    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 texdoc.config.get_value('machine_switch') == true then
+            print(name, doc.score, texdoc.util.w32_path(doc.realpath),
+            doc.lang or '', doc.details or '')
+        else
+            last_i = i -- save for test below
+            print(string.format('%2d %s', i, texdoc.util.w32_path(doc.realpath)))
+            if doc.details or doc.lang then
+                local line = '   = '
+                if doc.lang then line = line .. '[' .. doc.lang .. '] ' end
+                if doc.details then line = line .. doc.details end
+                print(line)
+            end
+        end
+    end
+    if texdoc.config.get_value('interact_switch') then
+        io.write('Enter number of file to view, RET to view 1, anything else to skip: ')
+        local num_str = io.read('*line')
+        -- That returns the empty string on an empty line, nil on EOF.
+        -- We only want to default to viewing 1 on an empty line.
+        -- Use Lua's faked ternary operator for fun and brevity:
+        num = (num_str == '' and 1 or tonumber(num_str))
+        if num and doclist[num] and num <= last_i then
+            view_doc(doclist[num])
+        end
+    end
+end
+
+-----------------------   deliver results based on mode   ---------------------
+
+function M.deliver_results(name, doclist, many)
+    -- ensure that results were found or apologize
+    if not doclist[1] or doclist[1].quality == 'killed' then
+        local msg = string.gsub(C.notfound_msg, C.notfound_msg_ph, name)
+        io.stderr:write(msg .. '\n') -- get rid of gsub's 2nd value
+        os.exit(C.exit_notfound)
+    end
+    -- shall we show all of them or only the "good" ones?
+    local showall = (texdoc.config.get_value('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 (texdoc.config.get_value('mode') == 'view')
+            or texdoc.config.get_value('mode') == 'mixed' and (not doclist[2]
+            or (doclist[2].quality ~= 'good' and not showall)) then
+        view_doc(doclist[1])
+    else
+        if many and not texdoc.config.get_value('machine_switch') then
+            print('*** Results for: ' .. name .. ' ***')
+        end
+        print_menu(name, doclist, showall)
+    end
+end
+
+return M
+
+-- vim: ft=lua:


Property changes on: trunk/Master/texmf-dist/scripts/texdoc/texdoclib-view.tlu
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: trunk/Master/texmf-dist/scripts/texdoc/texdoclib.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/texdoclib.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/texdoclib.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,8 +1,7 @@
 -- texdoclib.tlu: the texdoc library
 
 --[[
-Copyright 2008-2018 Manuel Pégourié-Gonnard, Takuto Asakura, Karl Berry, and
-Norbert Preining.
+Copyright 2008 Manuel Pégourié-Gonnard, Takuto Asakura, and the TeX Live Team.
 
 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
@@ -11,10 +10,10 @@
 
 This program is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>.
+this program. If not, see <https://www.gnu.org/licenses/>.
 
 Previous work in the public domain:
 - Contributions from Reinhard Kotucha (2008).
@@ -22,87 +21,17 @@
 - Original shell script by Thomas Esser, David Aspinall, and Simon Wilkinson.
 --]]
 
-------------------------   functions for submodules   ------------------------
+local texdoc = {
+    const = require('texdoclib-const'),
+    util = require('texdoclib-util'),
+    alias = require('texdoclib-alias'),
+    score = require('texdoclib-score'),
+    config = require('texdoclib-config'),
+    search = require('texdoclib-search'),
+    view = require('texdoclib-view'),
+    cli = require('texdoclib-cli'),
+}
 
--- texdoc is divided in submodules (files). Each module is loaded in a private
--- copy of a shared environment, and can export symbols to this environments
--- by returning a table to be merge with this environment.
+return texdoc
 
--- return a simple (not deep) copy of a table
-local function simple_copy(t)
-    local c = {}
-    for sym, val in pairs(t) do
-        c[sym] = val
-    end
-    return c
-end
-
--- initialise the shared environment with a copy of the global environment
-local prv_env = simple_copy(_G)
-if setfenv then
-    setfenv(1, prv_env)
-else
-    _ENV = prv_env
-end
-
--- import symbols from a table to the share environment
-local function import_symbols(symbols, name)
-    for sym, val in pairs(symbols) do
-        assert(val ~= nil,
-            'Internal error: '..name..' exporting undefined symbol '..sym..'.')
-        assert(prv_env[sym] == nil,
-            'Internal error: '..name..' exporting existing symbol '..sym..'.')
-        prv_env[sym] = val
-    end
-end
-
--- load a submodule of texdoc
-local function texdoc_do(name)
-    local pathname = kpse.find_file('texdoc/'..name, 'lua')
-    assert(pathname, 'Internal error: missing submodule: '..name)
-    local submod
-    if setfenv then
-        submod = assert(loadfile (pathname))
-        setfenv(submod, simple_copy(prv_env))
-    else
-        local f = assert(io.open(pathname))
-        local s = f:read('*a')
-        f:close()
-        submod = assert(load(s, pathname, 'bt', simple_copy(prv_env)))
-        -- submod = assert(loadfile(pathname, 'bt', simple_copy(prv_env)))
-    end
-    local symbols = submod()
-    if symbols then import_symbols(symbols, name) end
-end
-
-------------------------   initilisation & main code   -------------------------
-
--- pre-declare variables in the shared environment
-C = {}      -- constants
-config = {} -- configuration settings
-
--- actually load the submodules now
-texdoc_do('constants')
-texdoc_do('functions')
-texdoc_do('alias')
-texdoc_do('score')
-texdoc_do('config')
-texdoc_do('search')
-texdoc_do('view')
-
-return {
-    setup_config_and_alias = setup_config_and_alias,
-    read_config_file       = read_config_file,
-    init_databases         = init_databases,
-    print_usage            = print_usage,
-    get_doclist            = get_doclist,
-    deliver_results        = deliver_results,
-    aliased_names          = aliased_names,
-    show_config_files      = show_config_files,
-    config                 = config,
-    view_file              = view_file,
-    err_print              = err_print,
-    const                  = C,
-}
-
 -- vim: ft=lua:

Deleted: trunk/Master/texmf-dist/scripts/texdoc/view.tlu
===================================================================
--- trunk/Master/texmf-dist/scripts/texdoc/view.tlu	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/scripts/texdoc/view.tlu	2019-03-28 20:58:51 UTC (rev 50627)
@@ -1,226 +0,0 @@
--- view.tlu view a document and/or display the list of results in texdoc
---
--- Manuel Pégourié-Gonnard and the TeX Live team, GPLv3,
--- see texdoclib.tlu for details
-
------------------------------   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 = '"'..w32_path(filename)..'"'
-    end
-    -- files without extension are assumed to be text
-    local viewext = (filename:match('.*%.([^/]*)$') or 'txt'):lower()
-    -- special case : sty files use txt viewer
-    if viewext == 'sty' then viewext = 'txt' end
-    -- FIXME: hardcoding such cases this way is not very clean
-    if viewext == 'texlive' then viewext = 'txt' end
-    if viewext == 'htm' then viewext = 'html' end
-    -- get a viewer from built-in defaults if not already set
-    if not config['viewer_'..viewext] then
-        get_default_viewers()
-    end
-    -- still no viewers? use txt as a fallback
-    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
-
-    -- try to catch problems with missing DISPLAY on Unix
-    if os.type == 'unix' and not (os.name == 'macosx')
-            and os.getenv('DISPLAY') == nil then
-        err_print('warning',
-        "DISPLAY is not set; your viewer will likely have problems.")
-        err_print('warning',
-        "Try --list to list results instead of displaying them.")
-    end
-    err_print('info', 'View command: '..view_command)
-     
-    -- See long comment below this function for the LC_CTYPE story.
-    -- We only want to reset the environment if we have the value
-    -- to reset it to. In older versions of luatex, status.lc_* will be nil.
-    local env_lc_ctype = status.lc_ctype
-    local luatex_lc_ctype = os.setlocale(nil, 'ctype')
-    if (env_lc_ctype) then
-      err_print('info', "Setting environment LC_CTYPE to: "..env_lc_ctype)
-      os.setenv("LC_CTYPE", env_lc_ctype)
-    end
-
-    -- the big casino: run the external command.
-    if not os.execute(view_command) then
-        err_print('error', "Failed to execute: "..view_command)
-        return false
-    end
-    
-    -- reset back to "C" (should always be C and always happen, but in case...)
-    if (luatex_lc_ctype) then
-      os.setenv("LC_CTYPE", luatex_lc_ctype)
-    end
-
-    return true
-end
-
--- Explanation of locale madness:
--- LuaTeX resets LC_CTYPE, LC_COLLATE, LC_NUMERIC to "C". That is good for
--- inside luatex, but when we run an external program, if the user's
--- environment is something else, we want to switch back to it. As of
--- TL 2017 LuaTeX, we can inspect the user's locale with status.lc_ctype, etc.
--- 
--- For texdoc purposes, what matters is LC_CTYPE (so we don't bother with
--- the others). For example, with the less pager, when LC_CTYPE=C,
--- non-ASCII bytes are displayed as "<xx>", where xx is the two hex
--- digits for the byte.
--- 
--- See <texdoc-dev-source>/tools/Makefile for a standalone test case.
-
------------------------------   display results   -----------------------------
-
--- print a list of docfile objects (see search.tlu) as a menu
--- if showall is false, stop as soon as a bad result is encountered
-function print_menu(name, doclist, showall)
-    local max_lines = tonumber(config.max_lines)
-    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, last_i
-    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, w32_path(doc.realpath),
-            doc.lang or '', doc.details or '')
-        else
-            last_i = i -- save for test below
-            print(string.format('%2d %s', i, w32_path(doc.realpath)))
-            if doc.details or doc.lang then
-                local line = '   = '
-                if doc.lang then line = line..'['..doc.lang..'] ' end
-                if doc.details then line = line..doc.details end
-                print(line)
-            end
-        end
-    end
-    if config.interact_switch then
-        io.write ("Enter number of file to view, ",
-        "RET to view 1, anything else to skip: ")
-        local num_str = io.read('*line')
-        -- That returns the empty string on an empty line, nil on EOF.
-        -- We only want to default to viewing 1 on an empty line.
-        -- Use Lua's faked ternary operator for fun and brevity:
-        num = (num_str == "" and 1 or tonumber(num_str))
-        if num and doclist[num] and num <= last_i then
-            view_doc(doclist[num])
-        end
-    end
-end
-
------------------------   deliver results based 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 == '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
-
-return {
-    view_file       = view_file,
-    deliver_results = deliver_results,
-}
-
--- vim: ft=lua:

Modified: trunk/Master/texmf-dist/texdoc/texdoc.cnf
===================================================================
--- trunk/Master/texmf-dist/texdoc/texdoc.cnf	2019-03-28 20:58:25 UTC (rev 50626)
+++ trunk/Master/texmf-dist/texdoc/texdoc.cnf	2019-03-28 20:58:51 UTC (rev 50627)
@@ -2,10 +2,10 @@
 # Public domain.
 #
 # DO NOT edit this file!
-# For your personal settings, run 'texdoc -f' and use the file indicated by a
-# star; you may need to create it.  DO NOT copy the present file, please
-# create a new one (you may want to copy/paste/edit portions of the present
-# file however, or just read it for inspiration).
+# For your personal settings, run 'texdoc -f' and use the recommended file; you
+# may need to create it. DO NOT copy the present file, please create a new one
+# (you may want to copy/paste/edit portions of the present file however, or
+# just read it for inspiration).
 #
 # For system-wide configuration or other uses, you may want to use the other
 # files listed, see the manual (texdoc texdoc) for details. The files are read
@@ -18,9 +18,8 @@
 # Everything after a # on a line is ignored.
 # Spaces at the beginning/end of a line, as well as empty lines, are ignored.
 #
-# For more details, see the texdoc manual (try `texdoc texdoc').
+# For more details, see the texdoc manual (try 'texdoc texdoc').
 
-

 # General settings
 # ================
 
@@ -49,40 +48,40 @@
 ## Zipped documentation support
 
 # WARNING: support for zipped documents works only on Unix. Make sure that the
-# values of the associated options are adapted to your system.  Read the above
+# values of the associated options are adapted to your system. Read the above
 # warning concerning viewers.
 
 # Built-in defaults (for reference):
 #
-# zipext_list   =       # (empty list)
-# rm_file       = rm -f
-# rm_dir        = rmdir
+# zipext_list =        # the empty list
+# rm_file = rm -f
+# rm_dir = rmdir
 #
 # For each "ext" in zipext_list, you must define a "unzip_ext" unzipper.
 # The unzipped data must be printed on stdout. Example:
 #
 # zipext_list = gz
-# unzip_gz    = gzip -d -c
+# unzip_gz = gzip -d -c
 
 ## User interaction
 
 # Built-in defaults (for reference):
 #
-# mode             = view
+# mode = view
 #
-# interact_switch  = true
-# machine_switch   = false
+# interact_switch = true
+# machine_switch = false
 #
-# verbosity_level  = 2  # Print: 0: nothing, 1: errors, 2: warnings, 3: infos
-# debug_list       =    # the empty list
+# verbosity_level = 2  # Print: 0: nothing, 1: errors, 2: warnings, 3: infos
+# debug_list =         # the empty list
 
 ## Documentation searching
 
 # Built-in defaults (for reference):
 #
-# ext_list    = pdf, htm, html, txt, ps, dvi,  # Note: empty string at end
-# badext_list = txt,                           # Note: empty string at end
-# basename_list    = readme, 00readme
+# ext_list = pdf, html, htm, txt, md, ps, dvi,  # Note: empty string at end
+# badext_list = txt,                            # Note: empty string at end
+# basename_list = readme, 00readme
 # badbasename_list = readme, 00readme
 
 ## Fuzzy search
@@ -89,12 +88,11 @@
 
 # Built-in defaults (for reference):
 #
-# fuzzy_level  = 5
+# fuzzy_level = 5
 
 # Known suffixes for documentation
 suffix_list = doc, -doc, _doc, .doc, /doc, manual, /manual, -manual, userguide, /user_guide, -guide, -user, -man, notes, -info, ref
 
-

 # Score adjustments
 # =================
 
@@ -103,7 +101,7 @@
 # Results with score <= -100 are never displayed.
 #
 # The score of results containing a given pattern can be adjusted using the
-# 'adjscore' directive, either globally or only for specific queries.  It is
+# 'adjscore' directive, either globally or only for specific queries. It is
 # also possible to set the score directly in alias directives, see the next
 # section.
 #
@@ -119,71 +117,66 @@
 # Makefile are never documentation, just as documents in src or source subdir
 # -1000 should be enough to kill them
 adjscore /Makefile = -1000
-adjscore /src/     = -1000
-adjscore /source/  = -1000
+adjscore /src/ = -1000
+adjscore /source/ = -1000
 
 # licence files aren't very likely to contain relevant documentation, but it
 # feels wrong to totally kill them
 adjscore copying = -10
 adjscore license = -10
-adjscore gpl     = -10
+adjscore gpl = -10
 
 # tex-virtual-academy provides a lot of spurious matches
 adjscore /tex-virtual-academy-pl/ = -50
 
 # test and example files are not likely the best documentation
-adjscore example   = -1
-adjscore examples  = -1
-adjscore sample    = -1
-adjscore samples   = -1
-adjscore test      = -3
-adjscore tests     = -3
-adjscore /demo/    = -1
-adjscore /demos/   = -1
+adjscore example = -1
+adjscore examples = -1
+adjscore sample = -1
+adjscore samples = -1
+adjscore test = -3
+adjscore tests = -3
+adjscore /demo/ = -1
+adjscore /demos/ = -1
 adjscore /figures/ = -3
-adjscore /images/  = -3
+adjscore /images/ = -3
 
-# readme's usually get a negative score because they have a bad extension,
+# readme files usually get negative scores because they have bad extensions,
 # but they're still slightly better than other results with negative scores
-adjscore readme = 0.1
+adjscore readme = +0.1
 
-# uncomment this to make the man pages have a greater priority
-#adjscore .man1. = 5
-#adjscore .man5. = 5
-
 ## Specific adjustments
 
-# 'texdoc' may look like "tex's documentation" but it isn't
-# similar problem with 'tex-*'
-adjscore(tex) texdoc   = -10
+# 'texdoc' may look like "tex's documentation" but it isn't; 'tex-*' as well
+adjscore(tex) texdoc = -10
 adjscore(tex) tex-gyre = -10
-adjscore(tex) tex-ps   = -10
+adjscore(tex) tex-ps = -10
 
 # avoid too many results to be shown for 'latex'
 # package names
-adjscore(latex) cjw-latex                  = -10
-adjscore(latex) cweb-latex                 = -10
-adjscore(latex) duerer-latex               = -10
-adjscore(latex) guide-to-latex             = -10 # only useful with the book
-adjscore(latex) latex-web-companion        = -10
-adjscore(latex) ocr-latex                  = -10
-adjscore(latex) tufte-latex                = -10
+adjscore(latex) cjw-latex = -10
+adjscore(latex) cweb-latex = -10
+adjscore(latex) duerer-latex = -10
+adjscore(latex) guide-to-latex = -10          # only useful with the book
+adjscore(latex) latex-web-companion = -10
+adjscore(latex) ocr-latex = -10
+adjscore(latex) tufte-latex = -10
 # file names
 adjscore(latex) Content_LaTeX_Package_Demo = -10
-adjscore(latex) example_latex              = -10
-adjscore(latex) test_latex                 = -10
+adjscore(latex) example_latex = -10
+adjscore(latex) test_latex = -10
 
 # beamer
 adjscore(beamer) beamer-tut-pt/tutorialbeamer = +10
-adjscore(beamer) beamer-FUBerlin              = -3
-adjscore(beamer) beamer-tut-pt                = -10
-adjscore(beamer) presentations                = -10
+adjscore(beamer) beamer-FUBerlin = -3
+adjscore(beamer) beamer-tut-pt = -10
+adjscore(beamer) presentations = -10
 
 # misc
-adjscore(context) circuitikz   = -10
-adjscore(context) /gnuplot/    = -3
+adjscore(context) circuitikz = -10
+adjscore(context) /gnuplot/ = -3
 adjscore(context) context.man1 = +2
-adjscore(symbols) /staves/     = -5
+adjscore(symbols) /staves/ = -5
 
 # catalogue info missing in the tlcontrib version of the package :-(
 adjscore(pgf) pgfmanual.pdf = +5
@@ -192,7 +185,7 @@
 adjscore(hyph-utf8) hyphenation.pdf = +5
 
 # let's not have context version found first
-adjscore(fixme) /third/  = -6
+adjscore(fixme) /third/ = -6
 
 # prioritize newer document
 adjscore(babel-german) ngermanb.pdf = +5
@@ -200,7 +193,9 @@
 # prioritize man page
 adjscore(findhyph) findhyph.man1 = +5
 
-

+# prioritize official latex-tools
+adjscore(layout) /tools/ = +1
+
 # Aliases
 # =======
 
@@ -213,8 +208,8 @@
 
 ## Essential documentation
 
-alias live     = texlive-en
-alias texlive  = texlive-en
+alias live = texlive-en
+alias texlive = texlive-en
 alias tex-live = texlive-en
 
 ## various stuff
@@ -221,35 +216,36 @@
 
 # a few useful general documents
 alias faq-en = newfaq
-alias faq    = newfaq
-alias latex  = latex-doc-ptr
+alias faq = newfaq
+alias latex = latex-doc-ptr
 
 # various lshort translations
 adjscore(lshort) /lshort-english/ = +0.5                   # original
-alias lshort-de                   = l2kurz                 # german
-alias lshort-pl                   = lshort-polish/lshort2e # polish
-alias lshort-pt                   = pt-lshort              # portuguese
-alias lshort-sk                   = slshorte               # slovak
-alias lshort-es                   = lshort-spanish/lshort-a4 # spanish
+alias lshort-de = l2kurz                                   # german
+alias lshort-ja = jlshort                                  # japanese
+alias lshort-pl = lshort-polish/lshort2e                   # polish
+alias lshort-pt = pt-lshort                                # portuguese
+alias lshort-sk = slshorte                                 # slovak
+alias lshort-es = lshort-spanish/lshort-a4                 # spanish
 
 # *TeX engines reference manuals, man pages and related
-alias e-tex-ref  = etex_man
-alias etex-ref   = etex_man
+alias e-tex-ref = etex_man
+alias etex-ref = etex_man
 alias pdftex-ref = pdftex-a
-#alias xetex-ref  = xetex-reference # OK
-alias xelatex    = xetex-reference
+#alias xetex-ref = xetex-reference # OK
+alias xelatex = xetex-reference
 alias luatex-ref = luatexref-t
 
 # by default, <engine> = <engine>-ref (duplicated: no alias cascading)
-alias e-tex      = etex_man
-alias etex       = etex_man
-alias pdftex     = pdftex-a
-#alias xetex      = xetex-reference # OK
-alias xelatex    = xetex-reference
-alias luatex     = luatexref-t
+alias e-tex = etex_man
+alias etex = etex_man
+alias pdftex = pdftex-a
+#alias xetex = xetex-reference # OK
+alias xelatex = xetex-reference
+alias luatex = luatexref-t
 
-alias e-tex-man  = etex.man1
-alias etex-man   = etex.man1
+alias e-tex-man = etex.man1
+alias etex-man = etex.man1
 alias pdftex-man = pdftex.man1
 #alias xetex-man = xetex.man1 # missing
 alias luatex-man = luatex.man1
@@ -257,169 +253,172 @@
 alias luatex-pkg = oberdiek/luatex.pdf
 
 # latex/basic classes
-alias article   = classes
-alias book      = classes
-alias report    = classes
-#alias ltxguide  = ? # missing
-#alias minimal   = ? # missing
+alias article = classes
+alias book = classes
+alias report = classes
+#alias ltxguide = ? # missing
+#alias minimal = ? # missing
 adjscore(minimal) europecv = -1000 # false positive
 
 # latex/basic packages, sorted by dtx
-alias doc          = base/doc
-alias shortvrb     = base/doc
-alias letter       = base/letter
-alias slides       = base/slides
-alias(20) fontenc  = encguide
+alias doc = base/doc
+alias shortvrb = base/doc
+alias letter = base/letter
+alias slides = base/slides
+alias(20) fontenc = encguide
 alias(20) textcomp = encguide
-alias fix-cm       = fixltx2e
-alias bezier       = latex209
-alias fleqn        = latex209
-alias leqno        = latex209
-alias openbib      = latex209
-alias t1enc        = latex209
-alias makeidx      = makeindx
-alias showidx      = makeindx
-alias flafter      = source2e
-alias fontenc      = source2e
-alias textcomp     = source2e
-alias tracefnt     = source2e
+alias fix-cm = fixltx2e
+alias bezier = latex209
+alias fleqn = latex209
+alias leqno = latex209
+alias openbib = latex209
+alias t1enc = latex209
+alias makeidx = makeindx
+alias showidx = makeindx
+alias flafter = source2e
+alias fontenc = source2e
+alias textcomp = source2e
+alias tracefnt = source2e
 # TODO: try to avoid the huge amount of false positives for `doc' itself.
 
 # latex's required graphics bundle
-alias color-dev    = color
-alias epsfig-dev   = epsfig
+alias color-dev = color
+alias epsfig-dev = epsfig
 alias graphics-dev = graphics
 alias graphicx-dev = graphicx
-alias color        = grfguide
-alias epsfig       = grfguide
-alias graphics     = grfguide
-alias graphicx     = grfguide
+alias color = grfguide
+alias epsfig = grfguide
+alias graphics = grfguide
+alias graphicx = grfguide
 
 # latex's required psnfss2e bundle
-alias avant     = psnfss2e
-alias bookman   = psnfss2e
-alias chancery  = psnfss2e
-alias charter   = psnfss2e
-alias courier   = psnfss2e
-alias helvet    = psnfss2e
-alias mathpazo  = psnfss2e
-alias mathpple  = psnfss2e
-alias mathptm   = psnfss2e
-alias mathptmx  = psnfss2e
-alias newcent   = psnfss2e
-alias palatino  = psnfss2e
-alias times     = psnfss2e
-alias utopia    = psnfss2e
+alias avant = psnfss2e
+alias bookman = psnfss2e
+alias chancery = psnfss2e
+alias charter = psnfss2e
+alias courier = psnfss2e
+alias helvet = psnfss2e
+alias mathpazo = psnfss2e
+alias mathpple = psnfss2e
+alias mathptm = psnfss2e
+alias mathptmx = psnfss2e
+alias newcent = psnfss2e
+alias palatino = psnfss2e
+alias times = psnfss2e
+alias utopia = psnfss2e
 
 # ams
-alias amsfonts    = amsfndoc
-alias amslatex2   = technote
-alias amsmath     = amsldoc
-alias amsrefs     = amsrdoc
-alias amsthm      = amsthdoc
-alias amsart      = instr-l
-alias amsbook     = instr-l
-alias amscls      = instr-l
-alias amsproc     = instr-l
-alias amsart-dev  = amsclass
+alias amsfonts = amsfndoc
+alias amslatex2 = technote
+alias amsmath = amsldoc
+alias amsrefs = amsrdoc
+alias amsthm = amsthdoc
+alias amsart = instr-l
+alias amsbook = instr-l
+alias amscls = instr-l
+alias amsproc = instr-l
+alias amsart-dev = amsclass
 alias amsbook-dev = amsclass
-alias amscls-dev  = amsclass
+alias amscls-dev = amsclass
 alias amsproc-dev = amsclass
 alias amsmath-dev = amsmath
 
 # koma-script
-alias koma           = scrguien
-alias koma-script    = scrguien
-alias scrartcl       = scrguien
-alias scrbook        = scrguien
-alias scrreprt       = scrguien
-alias typearea       = scrguien
-alias koma-de        = scrguide
+alias koma = scrguien
+alias koma-script = scrguien
+alias scrartcl = scrguien
+alias scrbook = scrguien
+alias scrreprt = scrguien
+alias typearea = scrguien
+alias koma-de = scrguide
 alias koma-script-de = scrguide
-alias scrartcl-de    = scrguide
-alias scrbook-de     = scrguide
-alias scrreprt-de    = scrguide
-alias typearea-de    = scrguide
+alias scrartcl-de = scrguide
+alias scrbook-de = scrguide
+alias scrreprt-de = scrguide
+alias typearea-de = scrguide
 
 # tugboat package and classes
 alias tugboat = ltubguid
 
 # caption
-alias caption     = caption-eng
+alias caption = caption-eng
 alias caption-dev = caption.pdf
 
 # metapost by various names
-alias    metapost = mpman
+alias metapost = mpman
 alias(5) metapost = mpgraph
 alias(5) metapost = mpintro
-alias    mpost    = mpman
-alias(5) mpost    = mpgraph
-alias(5) mpost    = mpintro
-alias    mp       = mpman
-alias(5) mp       = mpgraph
-alias(5) mp       = mpintro
+alias mpost = mpman
+alias(5) mpost = mpgraph
+alias(5) mpost = mpintro
+alias mp = mpman
+alias(5) mp = mpgraph
+alias(5) mp = mpintro
 
 # latex3 and friends
-alias latex3        = ltx3info
-alias l3bootstrap   = interface3
-alias l3names       = interface3
-alias l3basics      = interface3
-alias l3expan       = interface3
-alias l3prg         = interface3
-alias l3quark       = interface3
-alias l3token       = interface3
-alias l3int         = interface3
-alias l3skip        = interface3
-alias l3tl          = interface3
-alias l3seq         = interface3
-alias l3clist       = interface3
-alias l3prop        = interface3
-alias l3box         = interface3
-alias l3coffins     = interface3
-alias l3color       = interface3
-alias l3msg         = interface3
-alias l3keys        = interface3
-alias l3file        = interface3
-alias l3fp          = interface3
-alias l3luatex      = interface3
+alias latex3 = ltx3info
+alias(3) expl3 = interface3
+alias(3) expl3 = source3
+alias l3bootstrap = interface3
+alias l3names = interface3
+alias l3basics = interface3
+alias l3expan = interface3
+alias l3prg = interface3
+alias l3quark = interface3
+alias l3token = interface3
+alias l3int = interface3
+alias l3skip = interface3
+alias l3tl = interface3
+alias l3seq = interface3
+alias l3clist = interface3
+alias l3prop = interface3
+alias l3box = interface3
+alias l3coffins = interface3
+alias l3color = interface3
+alias l3msg = interface3
+alias l3keys = interface3
+alias l3file = interface3
+alias l3fp = interface3
+alias l3luatex = interface3
 
 # misc
-alias autofe          = ucs
-alias afoot           = arabtex-doc
-alias arabicfont      = bezos
-alias bibtex          = btxdoc
-alias changes         = changes.english.pdf
-alias(5) cmsuper      = cm-super/FAQ
-alias cm-super        = cm-super/README
-alias cmsuper         = cm-super/README
-alias cyrillic        = cyrillic/00readme.txt
-alias elsarticle      = elsdoc
-alias(0.1) fontinst   = fontinstallationguide
-alias hyperref        = hyperref/manual.pdf
-alias hyperref-dev    = hyperref.pdf
-alias iso             = isoman
-alias lettrine        = lettrine # to hide context/third/lettrine-doc.pdf
-alias nonfloat-de     = nonfloat
-alias nonfloat        = nonfloat-en
-alias xstring-fr      = xstring_doc_fr
-alias arabic          = arabi/user_guide
-alias 3parttable      = threeparttable
-alias croatian        = babel
-alias mls             = montex
-alias vrbexin         = verbasef
-alias dtk             = dtk/doc/beispiel.pdf
-alias musixtex        = musixdoc
-alias mychemistry     = mychemistry_en
-alias mychemistry-de  = mychemistry_de
-alias cjk             = CJK.txt # FIXME: should be case insensitive
-alias ieee            = IEEEtran_HOWTO
-alias layouts         = layman
-alias plnfss          = plnfss.txt # XXX
-alias teubner         = teubner-doc
-alias xypic           = xyguide
-alias kvoptions-patch = kvoptions # XXX?
-alias cweb            = cwebman # XXX: is in 'cweb' dir, should win
-alias einfuehrung     = einfuehrung/README # tl should get "readme" tag
+alias autofe = ucs
+alias afoot = arabtex-doc
+alias arabicfont = bezos
+alias bibtex = btxdoc
+alias changes = changes.english.pdf
+alias cm = cm/README
+alias(5) cmsuper = cm-super/FAQ
+alias cm-super = cm-super/README
+alias cmsuper = cm-super/README
+alias cyrillic = cyrillic/00readme.txt
+alias elsarticle = elsdoc
+alias(0.1) fontinst = fontinstallationguide
+alias hyperref = hyperref/manual.pdf
+alias hyperref-dev = hyperref.pdf
+alias iso = isoman
+alias lettrine = lettrine          # to hide context/third/lettrine-doc.pdf
+alias nonfloat-de = nonfloat
+alias nonfloat = nonfloat-en
+alias xstring-fr = xstring_doc_fr
+alias arabic = arabi/user_guide
+alias 3parttable = threeparttable
+alias croatian = babel
+alias mls = montex
+alias vrbexin = verbasef
+alias dtk = dtk/doc/beispiel.pdf
+alias musixtex = musixdoc
+alias mychemistry = mychemistry_en
+alias mychemistry-de = mychemistry_de
+alias cjk = CJK.txt                # FIXME: should be case insensitive
+alias ieee = IEEEtran_HOWTO
+alias layouts = layman
+alias plnfss = plnfss.txt # XXX
+alias teubner = teubner-doc
+alias xypic = xyguide
+alias kvoptions-patch = kvoptions  # XXX?
+alias cweb = cwebman               # XXX: is in 'cweb' dir, should win
+alias einfuehrung = einfuehrung/README # tl should get "readme" tag
 
 ## a few easy patterns
 
@@ -430,47 +429,46 @@
 alias cweb-latex = cweb-user
 
 # egrep 'doc\.pdf\>'
-alias barcode     = eandoc.pdf
-alias enctex-cz   = encdoc
-alias ngerman     = gerdoc
-alias jurabib-de  = jbgerdoc
-alias ofs-cz      = ofsdoc
-alias ofs         = ofsdoc-e
-alias pst-geo     = pst-map3d-doc
+alias barcode = eandoc.pdf
+alias enctex-cz = encdoc
+alias ngerman = gerdoc
+alias jurabib-de = jbgerdoc
+alias ofs-cz = ofsdoc
+alias ofs = ofsdoc-e
+alias pst-geo = pst-map3d-doc
 
 ## aliases basically borrowed from texdoctk.dat with some adaptations
-
-alias akletter      = akletter/lettereng
-alias arydshln      = arydshln-man
-alias cv            = curve/curve
+alias akletter = akletter/lettereng
+alias arydshln = arydshln-man
+alias cv = curve/curve
 alias datenumber-de = datenumber/docgerman
-alias labels(1)     = envlab/elguide
-alias expressg      = expeg
-alias flcards       = flashcards
-alias lehman        = fontinstallationguide
-alias gnlogic       = gn-logic14
-alias kluwer        = kluwer/usrman
-alias lmfonts       = lm-info
-alias mathenv       = mdwtab
-alias montex        = mlsquick
-alias mltex         = mltex/mltex.txt
-alias natbib2       = natnotes
-alias uktugfaq      = newfaq
-alias onrannual     = onrannual/README
-alias otibet        = otibet/unidoc
-alias pbdiagram     = pb-manual
-alias tikz          = pgfmanual
-alias apmgraph      = pmgraph
-alias preprint      = preprint/00readme.txt
-alias dutch         = rapdoc
-alias startex       = startex/base/guide
-alias tangles       = t-angles/t-manual
-alias tex4ht        = tex4ht/mn.html
-alias(60) akademia  = tex-virtual-academy-pl/index.html
-alias treetex       = tree_doc
-alias lineno        = ulineno
-alias texguide      = usrguide
-alias(5) xypic      = xyrefer
+alias labels(1) = envlab/elguide
+alias expressg = expeg
+alias flcards = flashcards
+alias lehman = fontinstallationguide
+alias gnlogic = gn-logic14
+alias kluwer = kluwer/usrman
+alias lmfonts = lm-info
+alias mathenv = mdwtab
+alias montex = mlsquick
+alias mltex = mltex/mltex.txt
+alias natbib2 = natnotes
+alias uktugfaq = newfaq
+alias onrannual = onrannual/README
+alias otibet = otibet/unidoc
+alias pbdiagram = pb-manual
+alias tikz = pgfmanual
+alias apmgraph = pmgraph
+alias preprint = preprint/00readme.txt
+alias dutch = rapdoc
+alias startex = startex/base/guide
+alias tangles = t-angles/t-manual
+alias tex4ht = tex4ht/mn.html
+alias(60) akademia = tex-virtual-academy-pl/index.html
+alias treetex = tree_doc
+alias lineno = ulineno
+alias texguide = usrguide
+alias(5) xypic = xyrefer
 
 ## packages from ctan/macros/latex/contrib/misc or with doc in .sty only
 
@@ -482,28 +480,28 @@
 # produce suitable documentation for all these packages (thanks to Philipp
 # Stephani and Robin Fairbairns mostly).
 
-alias(4.1) 3parttable    = 3parttable.sty
-alias(4.1) bibcheck      = bibcheck.sty
-alias(4.1) concrete      = concrete.sty
-alias(4.1) linsys        = linsys.sty
-alias(4.1) mitpress      = mitpress.sty
-alias(4.1) nextpage      = nextpage.sty
-alias(4.1) setspace      = setspace.sty
-alias(4.1) statex        = statex.sty
-alias(4.1) statex2       = statex2.sty
+alias(4.1) 3parttable = 3parttable.sty
+alias(4.1) bibcheck = bibcheck.sty
+alias(4.1) concrete = concrete.sty
+alias(4.1) linsys = linsys.sty
+alias(4.1) mitpress = mitpress.sty
+alias(4.1) nextpage = nextpage.sty
+alias(4.1) setspace = setspace.sty
+alias(4.1) statex = statex.sty
+alias(4.1) statex2 = statex2.sty
 alias(4.1) texilikecover = texilikecover.sty
-alias(4.1) thrmappendix  = thrmappendix.sty
-alias(4.1) topcapt       = topcapt.sty
-alias(4.1) vrbexin       = vrbexin.sty
+alias(4.1) thrmappendix = thrmappendix.sty
+alias(4.1) topcapt = topcapt.sty
+alias(4.1) vrbexin = vrbexin.sty
 
-

 # Final hack
+# ================
 #
 # The next line has no effect when this file is installed as the last
 # configuration file (default) but is useful when you install it as the "tricky"
 # configuration file (usually TEXMFHOME/texdoc/texdoc-dist.cnf) whose mere
-# existence is a hack to make it easier to run the the development version, see
-# <http://tug.org/texdoc/dev/>.
+# existence is a hack to make it easier to run the development version, see
+# <https://github.com/TeX-Live/texdoc>.
 #
 # It is strongly recommended NOT to use it in any other circumstance.
 lastfile_switch = true



More information about the tex-live-commits mailing list