% \iffalse meta-comment
%
% File: duckuments.dtx Copyright (C) 2018-2019 Jonathan P. Spratte
%
% It may be distributed and/or modified under the conditions of the LaTeX
% Project Public License (LPPL), either version 1.3c of this license or (at your
% option) any later version.  The latest version of this license is in the file
%
%   https://www.latex-project.org/lppl.txt
%
% ------------------------------------------------------------------------------
%
%<*driver>
\def\nameofplainTeX{plain}
\ifx\fmtname\nameofplainTeX\else
  \expandafter\begingroup
\fi
\input l3docstrip.tex
\askforoverwritefalse
\preamble

--------------------------------------------------------------
duckuments -- minimal working duckuments
E-mail: jspratte@yahoo.de
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
--------------------------------------------------------------

Copyright (C) 2018-2019 Jonathan P. Spratte

This  work may be  distributed and/or  modified under  the conditions  of the
LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
(at your option) any later version.  The latest version of this license is in
the file:

  http://www.latex-project.org/lppl.txt

This work is "maintained" (as per LPPL maintenance status) by
  Jonathan P. Spratte.

This work consists of the file  duckuments.dtx
and the derived files           duckuments.pdf,
                                duckuments.sty,
                                example-image-duck.tex and
                                example-image-duck-portrait.tex

\endpreamble
% stop docstrip adding \endinput
\postamble
\endpostamble
\generate{\file{duckuments.sty}{\from{duckuments.dtx}{pkg}}}
\generate{\file{example-image-duck.tex}{\from{duckuments.dtx}{eid}}}
\generate{\file{example-image-duck-portrait.tex}{\from{duckuments.dtx}{eidp}}}
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</driver>
%
%<*driver|pkg>
\RequirePackage{xparse}[2019-05-03]
\RequirePackage{letltxmacro,l3keys2e}
\def\duckuments@version{0.5}
\def\duckuments@date{2019-10-03}
%</driver|pkg>
%
%<*driver>
\ProvidesFile{duckuments.dtx}
  [\csname duckuments@date\endcsname\space minimal working duckuments]
\documentclass{l3doc}
\usepackage{duckuments}
\usepackage{enumitem}
\usepackage{l3color}
\newenvironment{options}
  {\begin{description}[style=nextline,font=\normalfont\ttfamily]}
  {\end{description}}
\begin{document}
  \DocInput{duckuments.dtx}
\end{document}
%</driver>
%
%<*eid>
\documentclass[tikz,multi]{standalone}

\usepackage{tikzducks}
\usepackage{duckuments}

\begin{document}
\duckumentsDrawRandomDucks
\end{document}
%</eid>
%
%<*eidp>
\documentclass[tikz,multi]{standalone}

\usepackage{tikzducks}
\usepackage{duckuments}

\begin{document}
\duckumentsDrawRandomDucks*
\end{document}
%</eidp>
%
%<*pkg>
\ProvidesExplPackage
  {duckuments}          {\duckuments@date}
  {\duckuments@version} {minimal working duckuments}
%</pkg>
% \fi
%
% \title{The \pkg{duckuments} package}
% \author{Jonathan P. Spratte\thanks{E-mail: jspratte@yahoo.de}}
% \makeatletter
% \date{version \duckuments@version, released \duckuments@date}
% \makeatother
% \maketitle
% \tableofcontents
%
% \begin{documentation}^^A>>=
%
% \section{Introducktion}^^A>>=
%
% This package was inspired by the question
% \href{https://tex.stackexchange.com/questions/419751}
% {getting ducks in example images}.
% It began on the idea to patch \cs{includegraphics} to automatically change its
% behaviour if |example-image-duck| is used, but then it turned out to be a
% simple alternative to the \pkg{blindtext} package.
%
% It is written as a docstrip file: executing |latex duckuments.dtx| generates
% the \file{duckuments.sty}, \file{example-image-duck.tex}, and
% \file{example-image-duck-portrait.tex} file and typesets this duckumentation;
% execute |tex duckuments.dtx| to only generate the files \file{duckuments.sty},
% \file{example-image-duck.tex}, and \file{example-image-duck-portrait.tex}.
%
% For its functionality \file{example-image-duck.tex} and
% \file{example-image-duck-portrait.tex} must be compiled at least once. The
% sources are hosted on
% \href{https://github.com/Skillmon/ltx_duckuments}{github}.
%
% \textbf{The package should support any engine.} However for engines other than
% \pdfTeX, \LuaTeX, and \XeTeX\ it requires |extractbb| to be legal in a
% shell-escape (which should normally be the case).
%^^A=<<
%
% \section{Duckumentation}^^A>>=
%
% \subsection{Ducky content}^^A>>=
%
% \begin{function}{\duckument}^^A>>=
%   \begin{syntax}
%     \cs{duckument}\oarg{key=value}
%   \end{syntax}
%   Produces a duckument with one sectioning entry of each level starting at
%   \cs{chapter} (if available) and two variants of the list environment
%   \env{itemize}, \env{enumerate}, and \env{description}, one only at top
%   level and one with 4~environments nested. The \meta{key=value}s accept every
%   key as explained in \autoref{sec:keys}, but not every key has an effect.
% \end{function}^^A=<<
%
% \begin{function}{\blindduck}^^A>>=
%   \begin{syntax}
%     \cs{blindduck}\oarg{key=value}
%   \end{syntax}
%   Produces one paragraph of dummy content. The \meta{key=value}s accept every
%   key as explained in \autoref{sec:keys}, but not every key has an effect.
% \end{function}^^A=<<
%
% \begin{function}{\ducklist}^^A>>=
%   \begin{syntax}
%     \cs{ducklist}\meta{*}\marg{environment}
%   \end{syntax}
%   Sets a list of the specified \meta{environment}, if \meta{*} is given
%   \cs{item}\oarg{dummy} is used instead of only \cs{item}. For |description|
%   the starred version is used automatically.
% \end{function}^^A=<<
%
% \begin{function}{\ducklistlist}^^A>>=
%   \begin{syntax}
%     \cs{ducklistlist}\meta{*}\marg{list}
%   \end{syntax}
%   Sets 4~levels of a nested list of the specified \meta{environment}, if
%   \meta{*} is given \cs{item}\oarg{dummy} is used instead of only \cs{item}.
%   For |description| the starred version is used automatically.
% \end{function}^^A=<<
%
% \begin{function}{\duckitemize}^^A>>=
%   Abbreviation for \cs{ducklist}|{itemize}|.
% \end{function}^^A=<<
%
% \begin{function}{\duckenumerate}^^A>>=
%   Abbreviation for \cs{ducklist}|{enumerate}|.
% \end{function}^^A=<<
%
% \begin{function}{\duckdescription}^^A>>=
%   Abbreviation for \cs{ducklist}|{description}|.
% \end{function}^^A=<<
%^^A=<<
%
% \subsection{Other Macros}^^A>>=
%
% \begin{function}{\duckumentsCreateExampleFiles}^^A>>=
%   Creates the files \file{example-image-duck.tex} and
%   \file{example-image-duck-portrait.tex} in the current working directory.
% \end{function}^^A=<<
%
% \begin{function}{\duckumentsDrawRandomDucks}^^A>>=
%   \begin{syntax}
%     \cs{duckumentsDrawRandomDucks}\meta{*}\oarg{count}
%   \end{syntax}
%   Draws \meta{count} random \pkg{tikzducks} using
%   \pkg{Ti\textit{k}Z}. \meta{count} defaults to \cs{duckuments@randoms}.
%   Note that \pkg{duckuments} doesn't load \pkg{Ti\textit{k}Z}, this macro is
%   for the use in \file{example-image-duck.tex} and
%   \file{example-image-duck-portrait.tex}. If the optional star is given, the
%   images will be drawn in portrait orientation else in landscape.
% \end{function}^^A=<<
%^^A=<<
%
% \subsection{Patches}^^A>>=
%
% The package patches \cs{includegraphics} if \pkg{graphicx} is loaded at the
% time the patch is applied (see \autoref{sec:keys}, |immediate|). The patch
% changes the behaviour if the used image file is \file{example-image-duck} or
% \file{example-image-duck-portrait}. If that is the case, a random page of that
% document is used. There shouldn't be any change in behaviour if other files
% are used.
%
% The patch is done so that one can use \pkg{tikzducks} ducks without the need
% of loading \pkg{tikz} in a minimal working duckument as example images.
%^^A=<<
%
% \subsection{Options}\label{sec:keys}^^A>>=
%
% The package and commands which take a \oarg{key=value} accept the following
% options. Some of which only make sense as package options. The
% \textbf{\texttt{bold}} printed value is the one used if you don't specify a
% value. The \textit{\texttt{italic}} printed value is the initial one.
% \begin{options}
%   \item[toc=\textbf{true}$\vert$\textit{false}]
%     If |true| the \cs{duckument} contains a ToC. During package load time the
%     key doesn't throw errors but only warnings for values other than |true|
%     and |false|. This is done for compatibility reasons with classes which
%     take a non-boolean |toc| option (like those of KOMA-script).
%   \item[maths=\textbf{both}$\vert$inline$\vert$display$\vert$\textit{none}]
%     If |both| the \cs{blindduck} (which is also used by \cs{duckument})
%     contains both inline and displayed math. With |inline| and |display| the
%     respective maths is activated. |none| disables both.
%   \item[full]
%     This typesets the full range of \cs{blindduck}. Don't use this as a
%     package option.
%   \item[all]
%     synonym for |full|.
%   \item[immediate=\textbf{true}$\vert$\textit{false}]
%     If |true| \cs{includegraphics} is patched during package load time, else
%     the patching is done \cs{AtBeginDocument}.
% \end{options}
% Additionally \cs{blindduck} and \cs{duckument} accept another key which must
% match one of the following patterns and doesn't get any value. Patterns:
% \bgroup
% \def\num#1{\texttt{\meta{num#1}}}%
% \begin{description}[style=nextline,font=\normalfont\ttfamily]
%   \item[\meta{num1}] The paragraph \num{1} is printed.
%   \item[\meta{num1-}] Like the above
%   \item[\meta{-num2}] The paragraphs up to \num{2} are printed.
%   \item[\meta{num1-num2}] The paragraphs from \num{1} up to \num{2}
%     are printed.
%   \item[\meta{-}] The next paragraph is printed.
% \end{description}
% If the used pattern includes a ``|-|'' a \cs{par} is used after each
% paragraph. If any pattern is used the next pattern that doesn't include a
% \num{1} starts with the paragraph after the last used paragraph, cycling back
% to the first after the last available paragraph.
% \egroup
%^^A=<<
%^^A=<<
%
% \end{documentation}^^A=<<
%
% \begin{implementation}^^A>>=
%
% \section{Implementation}
%
%    \begin{macrocode}
%<*pkg>
%    \end{macrocode}
% 
%    \begin{macrocode}
%<@@=duckuments>
%    \end{macrocode}
%
% \subsection{Check for possible problems}^^A>>=
%
% Check whether \file{example-image-duck.pdf} exists.
%    \begin{macrocode}^^A>>=
\file_if_exist:nF { example-image-duck.pdf }
  {%>>=
%    \end{macrocode}
% If the current \cs{jobname} doesn't match \file{example-image-duck} throw an
% error.
%    \begin{macrocode}
    \str_if_eq:VnF \c_sys_jobname_str { example-image-duck }
      {
        \msg_new:nnnn { duckuments } { missing~file }
          {
            The~file~`#1`~can't~be~found.~Make~sure~to~create~it
            \tl_if_empty:nF{#2}{~#2}.
          }
          { Sorry~for~the~inconvenience.~#3 }
        \msg_error:nnnnn { duckuments } { missing~file }
          { example-image-duck.pdf }
          {
            by~compiling~example-image-duck.tex~at~least~once
          }
          {
            If~you~don't~find~the~file~on~your~machine~you~can~use~
            `\duckumentsCreateExampleFiles`~in~your~document~to~produce~a~copy~
            in~the~current~working~directory.
          }
      }
  }%=<<
%    \end{macrocode}^^A=<<
% And do the same for \file{example-image-duck-portrait.pdf}.
%    \begin{macrocode}^^A>>=
\file_if_exist:nF { example-image-duck-portrait.pdf }
  {%>>=
    \str_if_eq:VnF \c_sys_jobname_str { example-image-duck-portrait }
      {
        \msg_if_exist:nnF { duckuments } { missing~file }
          {
            \msg_new:nnnn { duckuments } { missing~file }
              {
                The~file~`#1`~can't~be~found.~Make~sure~to~create~it
                \tl_if_empty:nF{#2}{~#2}.
              }
              { Sorry~for~the~inconvenience.~#3 }
          }
        \msg_error:nnnnn { duckuments } { missing~file }
          { example-image-duck-portrait.pdf }
          {
            by~compiling~example-image-duck-portrait.tex~at~least~once
          }
          {
            If~you~don't~find~the~file~on~your~machine~you~can~use~
            `\duckumentsCreateExampleFiles`~in~your~document~to~produce~a~copy~
            in~the~current~working~directory.
          }
      }
  }%=<<
%    \end{macrocode}^^A=<<
%^^A=<<
%
% \subsection{Variables}^^A>>=
%
% \begin{variable}{\duckuments@randoms}^^A>>=
%   Stores the number of random ducks in \file{example-image-duck.pdf}.
%    \begin{macrocode}
\newcommand*\duckuments@randoms{128}
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\l_duckuments_immediate_bool}^^A>>=
%   Stores whether the patch is to be done during package load time.
%    \begin{macrocode}
\bool_new:N \l_duckuments_immediate_bool
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\l_duckuments_toc_bool}^^A>>=
%   Stores whether to display a ToC in \cs{duckument}.
%    \begin{macrocode}
\bool_new:N \l_duckuments_toc_bool
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\l_duckuments_math_inline_bool}^^A>>=
%   Stores whether to display inline math in \cs{blindduck}.
%    \begin{macrocode}
\bool_new:N \l_duckuments_math_inline_bool
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\l_duckuments_math_display_bool}^^A>>=
%   Stores whether to display displayed math in \cs{blindduck}.
%    \begin{macrocode}
\bool_new:N \l_duckuments_math_display_bool
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\l_duckuments_blindduck_pars_bool}^^A>>=
%   Stores whether each paragraph of \cs{blindduck} should end with a \cs{par}.
%    \begin{macrocode}
\bool_new:N \l_duckuments_blindduck_pars_bool
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\l_duckuments_range_seq}^^A>>=
%   Stores the paragraphs range for \cs{blindduck}.
%    \begin{macrocode}
\seq_new:N \l_duckuments_range_seq
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\g_duckuments_blindduck_start_int}^^A>>=
%   Stores the paragraph with which \cs{blindduck} should start.
%    \begin{macrocode}
\int_new:N \g_duckuments_blindduck_start_int
\int_gset:Nn \g_duckuments_blindduck_start_int { \c_one_int }
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\g_duckuments_blindduck_end_int}^^A>>=
%   Stores the paragraph with which \cs{blindduck} should end.
%    \begin{macrocode}
\int_new:N \g_duckuments_blindduck_end_int
%    \end{macrocode}
% \end{variable}^^A=<<
%^^A=<<
%
% \subsection{Constants}^^A>>=
%
% \begin{variable}{\c_duckuments_example_regex}^^A>>=
%   Regex against which the patch of \cs{includegraphics} is testing.
%    \begin{macrocode}
\regex_const:Nn \c_duckuments_example_regex
  {
     example-image-duck
    |example-image-duck.pdf
    |example-image-duck-portrait
    |example-image-duck-portrait.pdf
  }
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\c_duckuments_range_regex}^^A>>=
%   Regex against which the optional range in \cs{blindduck} is checked.
%    \begin{macrocode}
\regex_const:Nn \c_duckuments_range_regex { (\d+|\d+-|-\d+|\d+-\d+|-) }
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\c_duckuments_blindduck_pars_int}^^A>>=
%    \begin{macrocode}
\int_const:Nn \c_duckuments_blindduck_pars_int { 5 }
%    \end{macrocode}
% \end{variable}^^A=<<
%
% \begin{variable}{\c_duckuments_example_pages_int}^^A>>=
% Define a macro that gets the page count of a PDF (this is engine dependent):
%    \begin{macrocode}
\sys_if_engine_pdftex:T
  {
    \cs_new_protected:Npn \duckuments_set_to_pdf_page_count:Nn #1 #2
      {
        \group_begin:
        \pdfximage { #2 }
        \exp_args:NNNo
        \group_end:
        \int_set:Nn #1 { \the \pdflastximagepages }
      }
  }
\sys_if_engine_luatex:T
  {
    \cs_new_protected:Npn \duckuments_set_to_pdf_page_count:Nn #1 #2
      {
        \group_begin:
        \saveimageresource { #2 }
        \exp_args:NNNo
        \group_end:
        \int_set:Nn #1 { \lastsavedimageresourcepages }
      }
  }
\sys_if_engine_xetex:T
  {
    \cs_new_protected:Npn \duckuments_set_to_pdf_page_count:Nn #1 #2
      {
        \int_set:Nn #1 { \XeTeXpdfpagecount " #2 " }
      }
  }
\bool_lazy_any:nTF
  {
    { \sys_if_engine_luatex_p: }
    { \sys_if_engine_pdftex_p: }
    { \sys_if_engine_xetex_p: }
  }
  { \if_false: }
  { \if_true: }
  \group_begin:
  \char_set_catcode_other:N \%
  \cs_new_protected:Npn \duckuments_set_to_pdf_page_count:Nn #1 #2
    {
      \group_begin:
      \char_set_catcode_other:N \%
      \char_set_catcode_letter:N \:
      \char_set_catcode_ignore:n { 32 }
      \ior_shell_open:Nn \g_tmpa_ior { extractbb ~ -O ~ #2 }
      \ior_map_inline:Nn \g_tmpa_ior
        {
          \__duckuments_set_to_pdf_page_count_aux_a:w ##1 %%Pages: \q_stop
        }
      \ior_close:N \g_tmpa_ior
      \exp_args:NNNo
      \group_end:
      \int_set:Nn #1 { \int_use:N \l_tmpa_int }
    }
  \cs_new_protected:Npn \__duckuments_set_to_pdf_page_count_aux_a:w
    #1 %%Pages: #2 \q_stop
    {
      \tl_if_empty:nT { #1 }
        { \__duckuments_set_to_pdf_page_count_aux_b:w #2 \q_stop }
    }
  \cs_new_protected:Npn \__duckuments_set_to_pdf_page_count_aux_b:w
    #1 %%Pages: \q_stop
    {
      \int_set:Nn \l_tmpa_int { #1 }
      \ior_map_break: 
    }
  \group_end:
\fi:
%    \end{macrocode}
% Setting the constant:
%    \begin{macrocode}
\bool_if:nTF
  {
    \str_if_eq_p:Vn \c_sys_jobname_str { example-image-duck }
    || \str_if_eq_p:Vn \c_sys_jobname_str { example-image-duck-portrait }
  }
  { \int_const:Nn \c_duckuments_example_pages_int { \c_one_int } }
  {
    \group_begin:
      \duckuments_set_to_pdf_page_count:Nn \l_tmpa_int
        { example-image-duck.pdf }
      \duckuments_set_to_pdf_page_count:Nn \l_tmpb_int
        { example-image-duck-portrait.pdf }
      \int_const:Nn \c_duckuments_example_pages_int
        { \int_min:nn { \l_tmpa_int } { \l_tmpb_int } }
    \group_end:
  }
%    \end{macrocode}
% \end{variable}^^A=<<
%^^A=<<
%
% \subsection{Messages}^^A>>=
%
%    \begin{macrocode}^^A duckuments option~unknown >>=
\msg_new:nnnn { duckuments } { option~unknown }
  {
    Unknown~option~'#1'~for~package~duckuments.
  }
  { 
    \ ~__________________________________\\
    \ (Quack!~Nothing~here,~sorry.~Quack!)\\
    \ ~""""""""""""""""""""""""""""""""""\\
    \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\string\ \\
    \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~>()_\\
    \ \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~(__)__
  }
%    \end{macrocode}^^A=<<
%    \begin{macrocode}^^A duckuments non-boolean~toc >>=
\msg_new:nnnn { duckuments } { non-boolean~toc }
  {
    A~non-boolean~value~`#1`~was~received~for~the~`toc`~option~during~package~
    load~time.~It~is~assumed~this~was~given~to~\string\documentclass\ and~
    therefore~ignored.
  }
  { 
    \ ~__________________________________\\
    \ (Quack!~Nothing~here,~sorry.~Quack!)\\
    \ ~""""""""""""""""""""""""""""""""""\\
    \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\string\ \\
    \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~>()_\\
    \ \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~(__)__
  }
%    \end{macrocode}^^A=<<
%    \begin{macrocode}^^A duckuments out~of~range >>=
\msg_new:nnnn { duckuments } { out~of~range }
  {
    You~requested~element~#3~out~of~the~range~#1~to~#2~of~array~'#4'.\\
    I'll~just~use~element~#1~for~you.
  }
  { 
    \ ~__________________________________\\
    \ (Quack!~Nothing~here,~sorry.~Quack!)\\
    \ ~""""""""""""""""""""""""""""""""""\\
    \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\string\ \\
    \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~>()_\\
    \ \ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~\ ~(__)__
  }
%    \end{macrocode}^^A=<<
%
% \begin{macro}{\duckuments_patch_see_duckumentation:}^^A>>=
%    \begin{macrocode}
\cs_new:Npn \duckuments_patch_see_duckumentation:
  {%>>=
    \cs_set:Nn \msg_see_documentation_text:n
      {
        \\\\
        See~the~\str_if_eq:nnTF { ##1 } { duckuments } { duckumentation }
          {
            \str_if_eq:nnTF { ##1 } { LaTeX } { LaTeX3~ } { ##1~ }
            documentation
          }~for~further~information.
      }
  }%=<<
\duckuments_patch_see_duckumentation:
%    \end{macrocode}
% \end{macro}^^A=<<
%^^A=<<
%
% \subsection{Options and Configurations}^^A>>=
%    \begin{macrocode}
\keys_define:nn { duckuments }
  {%>>=
    ,immediate .bool_set:N = \l_duckuments_immediate_bool
    ,immediate .default:n = true
    ,full  .code:n =
      \duckuments_blindduck_range_test:n { 1-\c_duckuments_blindduck_pars_int }
    ,all   .meta:n = { full }
    ,maths .choice:
    ,maths / both    .code:n =
      {
        \bool_set_true:N \l_duckuments_math_inline_bool
        \bool_set_true:N \l_duckuments_math_display_bool
      }
    ,maths / display .code:n = \bool_set_true:N \l_duckuments_math_display_bool
    ,maths / inline  .code:n = \bool_set_true:N \l_duckuments_math_inline_bool
    ,maths / none    .code:n =
      {
        \bool_set_false:N \l_duckuments_math_inline_bool
        \bool_set_false:N \l_duckuments_math_display_bool
      }
    ,maths .default:n = both
    ,toc   .code:n =
      {
        \str_case:nnF { #1 }
          {
            { true  } { \bool_set_true:N  \l_duckuments_toc_bool }
            { false } { \bool_set_false:N \l_duckuments_toc_bool }
          }
          {
            \msg_warning:nnn { duckuments } { non-boolean~toc } { #1 }
          }
      }
    ,toc     .default:n = true
    ,unknown .code:n =
      { \msg_error:nnx { duckuments } { option~unknown } { \l_keys_key_tl } }
  }%=<<
\ProcessKeysOptions { duckuments }
\keys_define:nn { duckuments }
  {%>>=
    ,toc     .undefine:
    ,toc     .bool_set:N = \l_duckuments_toc_bool
    ,toc     .default:n = true
    ,unknown .code:n = \duckuments_blindduck_range_test:V \l_keys_key_tl
  }%=<<
\bool_if:NTF \l_duckuments_immediate_bool
  { \AtEndOfPackage { \duckuments_patch_includegraphics: } }
  { \AtBeginDocument { \duckuments_patch_includegraphics: } }
%    \end{macrocode}
%^^A=<<
%
% \subsection{Functions}^^A>>=
%
% \subsubsection{Duckument Level}^^A>>=
%
% \begin{macro}{\duckument}^^A>>=
%    \begin{macrocode}
\NewDocumentCommand \duckument { O{} }
  {%>>=
    \group_begin:
    \keys_set:nn { duckuments } { #1 }
    \bool_if:NT \l_duckuments_toc_bool { \tableofcontents }
    \cs_if_exist_use:NT \chapter
      { {\duckuments@headings@text{0}} \blindduck }
    \duckuments@headings{1} \blindduck
    \duckuments@headings{2} \blindduck
    \duckuments@headings{3} \blindduck
    \duckuments@headings{4} \blindduck
    \section {Lists}
    \duckuments_list_example:n { itemize }
    \duckuments_list_example:n { enumerate }
    \duckuments_list_example:n { description }
    \group_end:
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\blindduck}^^A>>=
%    \begin{macrocode}
\NewDocumentCommand \blindduck { O{} }
  {%>>=
    \group_begin:
    \keys_set:nn { duckuments } { #1 }
    \duckuments@blindduck@text
    \bool_if:NT \l_duckuments_blindduck_pars_bool { \par }
    \group_end:
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\ducklist}^^A>>=
%    \begin{macrocode}
\NewDocumentCommand \ducklist {s m}
  {%>>=
    \begin{#2}
      \IfBooleanTF { #1 }
        {\ducklists@content@starred}
        {
          \str_if_eq:nnTF { #2 } { description }
            \ducklists@content@starred
            \ducklists@content
        }
    \end{#2}
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
% \begin{macro}{\ducklistlist}^^A>>=
%    \begin{macrocode}
\NewDocumentCommand \ducklistlist { s m }
  {%>>=
    \IfBooleanTF { #1 }
      { \duckuments@listlist@starred { #2 } }
      {
        \str_if_eq:nnTF { #2 } { description }
          { \duckuments@listlist@starred { description } }
          { \duckuments@listlist{#2} }
      }
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckenumerate}^^A>>=
%    \begin{macrocode}
\newcommand*\duckenumerate{\ducklist{enumerate}}
%    \end{macrocode}
% \end{macro}^^A=<<
% \begin{macro}{\duckitemize}^^A>>=
%    \begin{macrocode}
\newcommand*\duckitemize{\ducklist{itemize}}
%    \end{macrocode}
% \end{macro}^^A=<<
% \begin{macro}{\duckdescription}^^A>>=
%    \begin{macrocode}
\newcommand*\duckdescription{\ducklist{description}}
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckumentsCreateExampleFiles}^^A>>=
% Create example-image-duck.tex
%    \begin{macrocode}
\newcommand*\duckumentsCreateExampleFiles
  {%>>=
    \iow_new:N \duckuments_example_file_iow
    \iow_open:Nn \duckuments_example_file_iow { example-image-duck.tex }
    \iow_now:Nn \duckuments_example_file_iow
      { \documentclass[tikz,multi]{standalone} }
    \iow_now:Nn \duckuments_example_file_iow
      { \usepackage{tikzducks} }
    \iow_now:Nn \duckuments_example_file_iow
      { \usepackage{duckuments} }
    \iow_now:Nn \duckuments_example_file_iow
      { \begin{document} }
    \iow_now:Nn \duckuments_example_file_iow
      { \duckumentsDrawRandomDucks }
    \iow_now:Nn \duckuments_example_file_iow
      { \end{document} }
    \iow_close:N \duckuments_example_file_iow
%    \end{macrocode}
% Create example-image-duck-portrait.tex
%    \begin{macrocode}
    \iow_open:Nn \duckuments_example_file_iow
      { example-image-duck-portrait.tex }
    \iow_now:Nn \duckuments_example_file_iow
      { \documentclass[tikz,multi]{standalone} }
    \iow_now:Nn \duckuments_example_file_iow
      { \usepackage{tikzducks} }
    \iow_now:Nn \duckuments_example_file_iow
      { \usepackage{duckuments} }
    \iow_now:Nn \duckuments_example_file_iow
      { \begin{document} }
    \iow_now:Nn \duckuments_example_file_iow
      { \duckumentsDrawRandomDucks* }
    \iow_now:Nn \duckuments_example_file_iow
      { \end{document} }
    \iow_close:N \duckuments_example_file_iow
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
% \begin{macro}{\duckumentsDrawRandomDucks}^^A>>=
%    \begin{macrocode}
\newcommand*\duckumentsDrawRandomDucks
  {%>>=
    \@ifstar
      {\duckumentsDrawRandomDucks@portrait}
      {\duckumentsDrawRandomDucks@landscape}%
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%^^A=<<
%
% \subsubsection{Intern}^^A>>=
%
% \begin{macro}{\duckuments@headings}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@headings[1]
  {%>>=
    \ifcase#1\relax
      \expandafter\chapter
    \or \expandafter\section
    \or \expandafter\subsection
    \or \expandafter\subsubsection
    \or \expandafter\paragraph
    \else \expandafter\@gobble
    \fi
    {\duckuments@headings@text{#1}}
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@headings@level}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@headings@level[1]
  {%>>=
    (
    \ifcase#1
      chapter
    \or section
    \or subsection
    \or subsubsection
    \or paragraph
    \fi
    )
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@ifinline}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@ifinline[2][]
  { \bool_if:NTF \l_duckuments_math_inline_bool { #2 } { #1 } }
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@ifdisplay}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@ifdisplay[2][]
  { \bool_if:NTF \l_duckuments_math_display_bool { #2 } { #1 } }
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_list_example:n}^^A>>=
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \duckuments_list_example:n #1
  {%>>=
    \subsection{Example\ for\ ducks\ (#1)}
    \ducklist { #1 }
    \subsubsection{Nested\ ducks}
    \ducklistlist { #1 }
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@enquote}^^A>>=
%    \begin{macrocode}
\NewDocumentCommand \duckuments@enquote { s +m }
  {%>>=
    \IfBooleanTF { #1 }
      {
        \cs_if_exist_use:NTF
          \enquote { * { #2 } }
          { `#2' }
      }
      {
        \cs_if_exist_use:NTF
          \enquote { { #2 } }
          {``#2''}
      }
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckumentsDrawRandomDucks@landscape}^^A>>=
%    \begin{macrocode}
\newcommand*\duckumentsDrawRandomDucks@landscape[1][\duckuments@randoms]
  {%>>=
    \foreach\x in {1,2,...,#1}
      {\duckumentsDrawRandomDucks@draw{6.47214}{4}{3.23607}{2}}
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckumentsDrawRandomDucks@portrait}^^A>>=
%    \begin{macrocode}
\newcommand*\duckumentsDrawRandomDucks@portrait[1][\duckuments@randoms]
  {%>>=
    \foreach\x in {1,2,...,#1}
      {\duckumentsDrawRandomDucks@draw{1.8541}{3}{.92705}{1.5}}
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckumentsDrawRandomDucks@draw}^^A>>=
%    \begin{macrocode}
\newcommand*\duckumentsDrawRandomDucks@draw[4]
  {%>>=
    \begin{tikzpicture}
      \draw[fill=gray!50,use~as~bounding~box] (0,0) rectangle (#1,#2);
      \draw[gray,thin] (0,0) -- (#1,#2);
      \draw[gray,thin] (0,#2) -- (#1,0);
      \draw[gray,thin] (#3,0) -- (#3,#2);
      \draw[gray,thin] (0,#4) -- (#1,#4);
      \node at (#3,#4) {\tikz\randuck;};
      \draw[black] (0,0) rectangle (#1,#2);
    \end{tikzpicture}
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_patch_includegraphics:}^^A>>=
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \duckuments_patch_includegraphics:
  {%>>=
    \@ifpackageloaded { graphicx }
      {
        \LetLtxMacro\duckuments@includegraphicsBAK\includegraphics
        \RenewDocumentCommand \includegraphics
          { >{\duckuments_starred:n}s O{} o m }
          {
            \IfValueTF { ##3 }
              { \duckuments@includegraphicsBAK##1[{##2}][{##3}]{##4} }
              {
                \regex_match:NnTF \c_duckuments_example_regex { ##4 }
                  {
                    \duckuments@includegraphicsBAK##1
                      [{page=\duckuments_random_page:,##2}]
                      { ##4 }
                  }
                  {
                    \duckuments@includegraphicsBAK##1[{##2}]{##4}
                  }
              }
          }
      }
      {}
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_blindduck_range_test:n}^^A>>=
%    \begin{macrocode}
\cs_new_protected:Npn \duckuments_blindduck_range_test:n #1
  {%>>=
    \regex_match:NnTF \c_duckuments_range_regex { #1 }
      {
        \seq_set_split:Nnn \l_duckuments_range_seq { - } { #1 }
        \int_compare:nNnTF
          { \c_one_int } = { \seq_count:N \l_duckuments_range_seq }
          {
            \cs_set:Npn \duckuments@blindduck@text
              {
                \duckuments_blindduck_single_par:n { #1 } 
                \duckuments_blindduck_set_next_start:n { #1 }
              }
          }
          {
            \bool_set_true:N \l_duckuments_blindduck_pars_bool
            \exp_args:Nx
            \tl_if_empty:nF
              { \seq_item:Nn \l_duckuments_range_seq { \c_one_int } }
              {
                \int_gset:Nn \g_duckuments_blindduck_start_int
                  { \seq_item:Nn \l_duckuments_range_seq { \c_one_int } }
              }
            \exp_args:Nx
            \tl_if_empty:nTF { \seq_item:Nn \l_duckuments_range_seq { 2 } }
              {
                \int_gset_eq:NN
                  \g_duckuments_blindduck_end_int
                  \g_duckuments_blindduck_start_int
              }
              {
                \int_set:Nn \g_duckuments_blindduck_end_int
                  { \seq_item:Nn \l_duckuments_range_seq { 2 } }
              }
            \duckuments_blindduck_set_text:xx
              { \int_use:N \g_duckuments_blindduck_start_int }
              { \int_use:N \g_duckuments_blindduck_end_int }
          }
      }
      {
        \exp_args:NnnV
          \msg_error:nnn { duckuments } { option~unknown } \l_keys_key_tl
      }
  }%=<<
\cs_generate_variant:Nn \duckuments_blindduck_range_test:n { V }
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_blindduck_set_text:nn}^^A>>=
%    \begin{macrocode}
\cs_new:Npn \duckuments_blindduck_set_text:nn #1 #2
  {%>>=
    \def \duckuments@blindduck@text
      {
        \int_step_function:nnnN { #1 } { \c_one_int } { #2 }
          \duckuments_blindduck_par_loop:n
        \duckuments_blindduck_set_next_start:n { #2 }
      }
  }%=<<
\cs_generate_variant:Nn \duckuments_blindduck_set_text:nn { xx }
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_blindduck_set_next_start:n}^^A>>=
%    \begin{macrocode}
\cs_new:Npn \duckuments_blindduck_set_next_start:n #1
  {%>>=
    \int_gset:Nn \g_duckuments_blindduck_start_int
      { \int_mod:nn { #1 } { \c_duckuments_blindduck_pars_int } + \c_one_int }
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_blindduck_single_par:n}^^A>>=
%    \begin{macrocode}
\cs_new:Npn \duckuments_blindduck_single_par:n #1
  {%>>=
    \bool_if:nTF
      {
        \int_compare_p:nNn { #1 } > { \c_duckuments_blindduck_pars_int }
        || \int_compare_p:nNn { #1 } < { \c_one_int }
      }
      {
        \msg_error:nnxxxx { duckuments } { out~of~range }
          { 1 } { \int_use:N \c_duckuments_blindduck_pars_int } { #1 }
          { blindduck~paragraphs }
        \duckuments@blindduck@text@i
      }
      {
        \use:c { duckuments@blindduck@text@ \int_to_roman:n { #1 } }
      }
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_blindduck_par_loop:n}^^A>>=
%    \begin{macrocode}
\cs_new:Npn \duckuments_blindduck_par_loop:n #1
  {%>>=
    \duckuments_blindduck_single_par:n { #1 }
    \par
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_starred:n}^^A>>=
%    \begin{macrocode}
\cs_new_protected:Npn \duckuments_starred:n #1
  {%>>=
    \IfBooleanTF { #1 }
      { \def\ProcessedArgument{*} }
      { \def\ProcessedArgument{} } 
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments_random_page:}^^A>>=
%    \begin{macrocode}
\cs_new:Npn \duckuments_random_page:
  { \int_rand:n { \c_duckuments_example_pages_int } }
%    \end{macrocode}
% \end{macro}^^A=<<
%
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%
% \begin{macro}{\duckuments@blindduck@text}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@blindduck@text{\duckuments@blindduck@text@i}
\newcommand*\duckuments@blindduck@text@i
  {%>>=
    There once was a very smart but sadly blind duck. When it was still a small
    duckling it was renowned for its good vision. But sadly as the duck grew
    older it caught a sickness which caused its eyesight to worsen. It became so
    bad, that the duck couldn't read the notes it once took containing much of
    inline math\duckuments@ifinline{ just like its favoured equation: $d = u_c
    \cdot k$}. Only displayed equations remained legible%
    \duckuments@ifdisplay[.]{ so it could still read \begin{equation}d = r a^k
    e\hbox{.}\end{equation}} That annoyed the smart duck, as it wasn't able to
    do its research any longer. It called for its underduckling and said:
    \duckuments@enquote{Go, find me the best eye ducktor there is. He shall
    heal me from my disease!}%
  }%=<<
\newcommand*\duckuments@blindduck@text@ii
  {%>>=
    \duckuments@enquote{But my duck, how are you supposed to manage your daily
    routines without my visual guidance}, replied the underduckling. The smart
    duck's face turned grim in anger. \duckuments@enquote{You dare to talk
    back?} The underduckling blushed ashamed. How could he have objections
    after his duck gave strict orders? The underduckling was so embarrassed
    about his own behaviour he had to solve an equation.%
  }%=<<
\newcommand*\duckuments@blindduck@text@iii
  {%>>=
    After the equation was solved and the underduckling prepared his leave for
    the next day it fell asleep in a shaky mood. It did not know what the
    journey had prepared for him and if he was prepared enough for it. His sleep
    was restless. The dreams he had that night were not calm and bright as they
    used to be for an innocent underduckling.%
  }%=<<
\newcommand*\duckuments@blindduck@text@iv
  {%>>=
    Before dawn the underduckling woke. He didn't have the feeling of being well
    rested. But nonetheless he knew that this was the day he should leave.
    Except saying goodbye to his beloved ones there was nothing holding him
    back. His duck had sent him on the most important mission a five weeks old
    inexperienced underduckling was ever sent on. He bid farewell to his mother,
    all his brothers and sisters, and finally from his duck. The bag was
    shouldered, the boots were tied, the underduckling left.%
  }%=<<
\newcommand*\duckuments@blindduck@text@v
  {%>>=
    As the underduckling went along he saw a tree. It was so tall he couldn't
    even approximate its height. Oh, how small he felt. What should he, a small
    duckling whose plumage was still fluffy, achieve in this vast, gigantic
    world? He stuck his trembling wings under the straps of his backpack to calm
    his shaking limbs. Where should he start his search? How should he survive
    in the hostile nature surrounding the sheltered pond of his community?
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@headings@text}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@headings@text[1]
  {A friendly duck at level #1 \duckuments@headings@level{#1}}
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\ducklists@content}^^A>>=
%    \begin{macrocode}
\newcommand*\ducklists@content
  {%>>=
    \item First swims father drake
    \item Then floats mother duck
    \item After her paddles baby duckling
    \item And over there bathes uncle canard
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\ducklists@content@starred}^^A>>=
%    \begin{macrocode}
\newcommand*\ducklists@content@starred
  {%>>=
    \item[drake] is the swimming father
    \item[duck] is the floating mother
    \item[duckling] is the paddling baby
    \item[canard] is the bathing uncle
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@listlist}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@listlist[1]
  {%>>=
    \begin{#1}
      \item swimming father drake
        \begin{#1}
          \item swimming father drake
            \begin{#1}
              \item swimming father drake
                \begin{#1}
                  \item swimming father drake
                  \item floating mother duck
                \end{#1}
              \item floating mother duck
            \end{#1}
          \item floating mother duck
        \end{#1}
      \item floating mother duck
    \end{#1}%
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%
% \begin{macro}{\duckuments@listlist@starred}^^A>>=
%    \begin{macrocode}
\newcommand*\duckuments@listlist@starred[1]
  {%>>=
    \begin{#1}
      \item[drake] is the swimming father
        \begin{#1}
          \item[drake] is the swimming father
            \begin{#1}
              \item[drake] is the swimming father
                \begin{#1}
                  \item[drake] is the swimming father
                  \item[duck] is the floating mother
                \end{#1}
              \item[duck] is the floating mother
            \end{#1}
          \item[duck] is the floating mother
        \end{#1}
      \item[duck] is the floating mother
    \end{#1}%
  }%=<<
%    \end{macrocode}
% \end{macro}^^A=<<
%^^A=<<
%^^A=<<
%
%    \begin{macrocode}
\endinput
%    \end{macrocode}
%
% \end{implementation}^^A=<<
%
%    \begin{macrocode}
%</pkg>
%    \end{macrocode}
%
% \clearpage
% \section{The story of the duck}^^A>>=
%
% \bgroup
% \ExplSyntaxOn
% \newcount\duckuments_count_for_duckumentation_only
% \cs_set:Nn \duckuments_blindduck_par_loop:n
%   {^^A>>=
%     \advance\duckuments_count_for_duckumentation_only1
%     \llap
%       {
%         \group_begin:
%         \color_select:nn { gray } { 0.5 }
%         \rlap
%           {
%             \smash
%               {
%                 \parbox[t]{2cm}
%                   {
%                     \scriptsize\raggedright
%                     paragraph~\the\duckuments_count_for_duckumentation_only
%                   }
%               }
%           }
%         \hspace{\dimexpr\marginparsep+2cm\relax}
%         \group_end:
%       }
%     \vspace{-\baselineskip}
%     \duckuments_blindduck_single_par:n { #1 }
%     \par
%   }^^A=<<
% \ExplSyntaxOff
% \blindduck[full]
% \egroup^^A=<<
%
%
^^A vim: fdm=marker foldmarker=>>=,=<<
