diff options
author | Karl Berry <karl@freefriends.org> | 2019-01-13 23:31:16 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-01-13 23:31:16 +0000 |
commit | 231f2bfbc6deb5f053659c5062e9b5be2ed8e5c8 (patch) | |
tree | 4aefb4a44dffac03ea25bdc1ead9ccbbf787da31 | |
parent | 45703352bcad374f3e88099a40425df3ba5c3395 (diff) |
ducksay (13jan19)
git-svn-id: svn://tug.org/texlive/trunk@49691 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/ducksay/ducksay.pdf | bin | 483844 -> 513927 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/ducksay/ducksay.dtx | 710 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ducksay/ducksay.animals.tex | 63 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ducksay/ducksay.code.v1.tex | 27 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ducksay/ducksay.code.v2.tex | 218 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ducksay/ducksay.sty | 150 |
6 files changed, 707 insertions, 461 deletions
diff --git a/Master/texmf-dist/doc/latex/ducksay/ducksay.pdf b/Master/texmf-dist/doc/latex/ducksay/ducksay.pdf Binary files differindex 940be196f80..96e483a2dc8 100644 --- a/Master/texmf-dist/doc/latex/ducksay/ducksay.pdf +++ b/Master/texmf-dist/doc/latex/ducksay/ducksay.pdf diff --git a/Master/texmf-dist/source/latex/ducksay/ducksay.dtx b/Master/texmf-dist/source/latex/ducksay/ducksay.dtx index ec0e0cf52d2..48643bd6b35 100644 --- a/Master/texmf-dist/source/latex/ducksay/ducksay.dtx +++ b/Master/texmf-dist/source/latex/ducksay/ducksay.dtx @@ -63,7 +63,12 @@ and the derived files ducksay.pdf \ProvidesFile{ducksay.dtx} [\csname ducksay@date\endcsname\ cowsay for LaTeX] \documentclass{l3doc} +% silence the false positives about internal control sequences in the animals +\csname msg_redirect_name:nnn\endcsname{l3doc}{foreign-internal}{none} \usepackage[version=2]{ducksay} +\usepackage{marginnote} +\newcommand\sinceversion[1] + {\marginnote{\footnotesize\textsf{v#1}\kern-\marginparsep}} \let\metaORIG\meta \protected\def\meta #1{\texttt{\metaORIG{#1}}} \DucksayOptions{arg=tab,msg-align=l,vpad=1} @@ -102,6 +107,16 @@ and the derived files ducksay.pdf } {\end{description}} \makeatletter +\renewcommand*\paragraph + {% + \@startsection + {paragraph} + {4} + {\z@} + {-3.25ex \@plus -1ex \@minus -.2ex} + {1ex \@plus .2ex} + {\normalfont\normalsize\bfseries}% + } \newcommand*\availableAnimal[1] {% \@for\cs:=#1\do @@ -152,7 +167,7 @@ and the derived files ducksay.pdf \hfil \makebox[.\marginparwidth][l] {% - \ducksay[head-in,MSG=\footnotesize,msg-align=c,align=t] + \ducksay[head-in,MSG=\footnotesize,msg-align=c] {It's always\\good to\\keep the\\overview!}% }% }% @@ -173,7 +188,7 @@ and the derived files ducksay.pdf \smash {% \footnotesize - \ducksay[small-yoda,wd=39,ht=3,msg-align=c,rel-align=r] + \ducksay[small-yoda,wd=39,ht=3,msg-align=c,body-align=r] {Hosted at\\\url{https://github.com/Skillmon/ltx_ducksay}\\it is.}% } \egroup @@ -187,8 +202,8 @@ and the derived files ducksay.pdf \NeedsTeXFormat{LaTeX2e} \RequirePackage{xparse,l3keys2e} -\def\ducksay@version{2.2.1} -\def\ducksay@date{2019-01-08} +\def\ducksay@version{2.3} +\def\ducksay@date{2019-01-13} \ProvidesExplPackage {ducksay} {\ducksay@date} @@ -231,31 +246,43 @@ and the derived files ducksay.pdf % % \section{Documentation}\def\DocImp{Documentation}% % -% \subsection{Downward Compatibility Issues} +% \subsection{Downward Compatibility Issues}\label{sec:down}^^A>>> % \marginpar^^A>>> % { % \tiny -% \ducksay[snail,MSG=\footnotesize,align=t]{Yep, I screwed up!} +% \ducksay[snail,MSG=\footnotesize]{Yep, I screwed up!} % }^^A<<< % % \begin{itemize} -% \item Versions prior to v2.0 did use a regular expression for the option +% \item +% \sinceversion{2.0} +% Versions prior to v2.0 did use a regular expression for the option % |ligatures|, see \autoref{sec:options} for more on this issue. With v2.0 % I do refer to the package's version, not the code variant which can be % selected with the |version| option. % \item In a document created with package versions prior to v2.0 you'll have % to specify the option |version=1| in newer versions to make those old % documents behave like they used to. -% \end{itemize} +% \item +% \sinceversion{2.3} +% Since v2.3 \cs{AddAnimal} and \cs{AddColoredAnimal} behave +% differently. You no longer have to make sure that in the first three lines +% every backslash which is only preceded by spaces is the bubble's tail. +% Instead you can specify which symbol should be the tail and how many of +% such symbols there are. See \autoref{sec:macros} for more about the +% current behaviour. +% \item The |add-think| key is deprecated and will throw an error starting +% with v2.3. In future versions it will be removed. +% \end{itemize}^^A<<< % -% \subsection{Shared between versions} +% \subsection{Shared between versions}^^A>>> % -% \subsubsection{Macros}^^A>>> +% \subsubsection{Macros}\label{sec:macros}^^A>>> % \marginpar^^A>>> % { % \tiny % \hfill -% \ducksay[bunny,MSG=\footnotesize,align=t,body-mirrored] +% \ducksay[bunny,MSG=\footnotesize,body-mirrored] % {Macros for everyone!} % }^^A<<< % @@ -284,34 +311,33 @@ and the derived files ducksay.pdf % % \begin{function}{\AddAnimal}^^A>>> % \begin{syntax} -% \cs{AddAnimal}\meta{*}\marg{animal}\meta{ascii-art} +% \cs{AddAnimal}\meta{*}\oarg{options}\marg{animal}\meta{ascii-art} % \end{syntax} % adds \anml\ to the known animals. \meta{ascii-art} is multi-line verbatim % and therefore should be delimited either by matching braces or by anything % that works for \cs{verb}. If the star is given \anml\ is the new default. % One space is added to the begin of \anml\ (compensating the opening symbol). -% For example, |snowman| is added with:\\[1ex] +% The symbols signalizing the speech bubble's tail (in the |hedgehog| example +% below the two |s|) can be set using the |tail-symbol| option and only the +% first |tail-count| occurrences will be substituted (see +% \autoref{sec:addoptions} for more about these options). For example, +% |hedgehog| is added with:\\[1ex] % \begin{minipage}{\linewidth} %\begin{verbatim} -% \AddAnimal{snowman} -% { \ -% \ _[_]_ -% (") -% >-( : )-< -% (__:__)} +% \AddAnimal[tail-symbol=s]{hedgehog} +% { s .\|//||\||. +% s |/\/||/|//|/| +% /. `|/\\|/||/|| +% o__,_|//|/||\||'} %\end{verbatim} -% \end{minipage} +% \end{minipage}\\[1ex] % It is not checked whether the animal already exists, you could therefore -% redefine existing animals with this macro.\\ -% The symbols signalizing the speech (in the |snowman| example above the two -% backslashes) should at most be used in the first three lines, as they get -% replaced by |O| and |o| for \cs{duckthink}. They also shouldn't be preceded -% by anything other than a space in that line. +% redefine existing animals with this macro. % \end{function}^^A<<< % % \begin{function}{\AddColoredAnimal}^^A>>> % \begin{syntax} -% \cs{AddColoredAnimal}\meta{*}\marg{animal}\meta{ascii-art} +% \cs{AddColoredAnimal}\meta{*}\oarg{options}\marg{animal}\meta{ascii-art} % \end{syntax} % It does the same as \cs{AddAnimal} but allows three different colouring % syntaxes. You can use \cs{textcolor} in the \meta{ascii-art} with the syntax @@ -324,7 +350,7 @@ and the derived files ducksay.pdf % |\bgroup\color{red}RedText\egroupOtherText| is valid syntax). You can't nest % delimited \cs{color}s.\\ % Also you can use an undelimited \cs{color}. It affects anything until the -% end of the current line (or, if used inside of the \meta{text} of an +% end of the current line (or, if used inside of the \meta{text} of a % delimited \cs{color}, anything until the end of that delimited \cs{color}'s % \meta{text}). The syntax would be \cs{color}\marg{color}.\\ % The package doesn't load anything providing those colouring commands for you @@ -333,13 +359,26 @@ and the derived files ducksay.pdf % normal \cs{AddAnimal}. % \end{function}^^A<<< % +% \begin{function}{\AnimalOptions}^^A>>> +% \begin{syntax} +% \cs{AnimalOptions}\meta{*}\marg{animal}\marg{options} +% \end{syntax} +% With this macro you can set \anml\ specific \meta{options}. If the star is +% given any currently set options for this \anml\ are dropped and only the +% ones specified in \meta{options} will be applied, else \meta{options} will +% be added to the set options for this \anml. The set \meta{options} can +% set the |tail-1| and |tail-2| options and therefore overwrite the effects of +% \cs{duckthink}, as \cs{duckthink} really is just \cs{ducksay} with the +% |think| option. +% \end{function}^^A<<< +% %^^A<<< % % \subsubsection{Options}\label{sec:options}^^A>>> % \marginpar % {% % \vspace*{-2em}\tiny -% \ducksay[pig,MSG=\footnotesize,align=t]{Options.\\For every occasion}% +% \ducksay[pig,MSG=\footnotesize]{Options.\\For every occasion}% % } % The following options are available independent on the used code variant (the % value of the |version| key). They might be used as package options -- unless @@ -369,33 +408,58 @@ and the derived files ducksay.pdf % |}| so that they can't form ligatures. Giving no argument (or an empty % one) might enhance compilation speed by disabling this replacement. The % formation of ligatures was only observed in combination with -% \verb|\usepackage[T1]{fontenc}| by the author of this package. Therefore -% giving the option |ligatures| without an argument might enhance the -% compilation speed for you without any drawbacks. Initially this is set to +% |\usepackage[T1]{fontenc}| by the author of this package. Therefore giving +% the option |ligatures| without an argument might enhance the compilation +% speed for you without any drawbacks. Initially this is set to % \texttt{\csuse{\detokenize{l_ducksay_ligatures_tl}}}.\\ % \textbf{Note:} In earlier releases this option's expected argument was a % regular expression. This means that this option is not fully % downward compatible with older versions. The speed gain however seems % worth it (and I hope the affected documents are few). -% \item[add-think=\meta{bool}] -% by default the animals for \cs{duckthink} are not created during package -% load time, but only when they are really used -- but then they are created -% globally so it just has to be done once. This is done because they rely on -% a rather slow regular expression. If you set this key to |true| each -% \cs{AddAnimal} will also create the corresponding \cs{duckthink} variant -% immediately. +% \item[no-tail] +% Sets |tail-1| and |tail-2| to be a space. +% \item[say] +% Sets |tail-1| and |tail-2| as backslashes. +% \item[tail-1=\meta{token list}] +% Sets the first tail symbol in the output to be \meta{token list}. If set +% outside of \cs{ducksay} and \cs{duckthink} it will be overwritten inside +% of \cs{duckthink} to be |O|. +% \item[tail-2=\meta{token list}] +% Sets every other tail symbol except the first one in the output to be +% \meta{token list}. If set outside of \cs{ducksay} and \cs{duckthink} it +% will be overwritten inside of \cs{duckthink} to be |o|. +% \item[think] +% Sets |tail-1=O| and |tail-2=o|. +% \end{options} +% +% \paragraph{Options for \cs{AddAnimal}}\label{sec:addoptions} +% The options described here are only available in \cs{AddAnimal} and +% \cs{AddColoredAnimal}. +% \begin{options} +% \item[tail-count=\meta{int}] +% sets the number of tail symbols to be replaced in \cs{AddAnimal} and +% \cs{AddColoredAnimal}. Initial value is 2. If the value is negative every +% occurrence of |tail-symbol| will be replaced. +% \item[tail-symbol=\meta{str}] +% the symbol used in \cs{AddAnimal} and \cs{AddColoredAnimal} to mark the +% bubble's tail. The argument gets \cs{detokenize}d. Initially a single +% backslash. % \end{options} %^^A<<< % +%^^A<<< +% % \SetVersion{1}% -% \subsection{Version 1}\label{sec:v1} +% \subsection{Version 1}\label{sec:v1}^^A>>> % -% \subsubsection{Introduction} +% \subsubsection{Introduction}^^A>>> % % This version is included for legacy support (old documents should behave the % same without any change to them -- except the usage of |version=1| as an -% option). For the bleeding edge version of \pkg{ducksay} skip this subsection -% and read \autoref{sec:v2}. +% option, for a more or less complete list of downward compatibility related +% problems see \autoref{sec:down}). For the bleeding edge version of +% \pkg{ducksay} skip this subsection and read \autoref{sec:v2}. +%^^A<<< % % \subsubsection{Macros}\label{sec:macros1}^^A>>> % \marginpar @@ -403,7 +467,7 @@ and the derived files ducksay.pdf % \rlap % {% % \tiny -% \ducksay[yoda,MSG=\footnotesize,align=t]{Use those, you might}% +% \ducksay[yoda,MSG=\footnotesize]{Use those, you might}% % }% % } % The following is the description of macros which differ in behaviour from @@ -426,11 +490,9 @@ and the derived files ducksay.pdf % \end{syntax} % options might include any of the options described in \autoref{sec:options} % and \autoref{sec:options1} if not otherwise specified. Prints an \anml\ -% thinking \msg. \msg\ is not read in verbatim. It is implemented using -% regular expressions replacing a |\| which is only preceded by |\s*| in the -% first three lines with |O| and |o|. It is therefore slower than -% \cs{ducksay}. Multi-line \msg s are possible using |\\|. |\\| should not be -% contained in a macro definition but at toplevel. Else use the option |ht|. +% thinking \msg. \msg\ is not read in verbatim. Multi-line \msg s are possible +% using |\\|. |\\| should not be contained in a macro definition but at +% toplevel. Else use the option |ht|. % \end{function}^^A<<< %^^A<<< % @@ -439,7 +501,7 @@ and the derived files ducksay.pdf % {% % \vspace*{-2em}\tiny % \hfill -% \ducksay[hedgehog,MSG=\footnotesize,align=t]{Everyone likes\\options}% +% \ducksay[hedgehog,MSG=\footnotesize]{Everyone likes\\options}% % } % The following options are available to \cs{ducksay}, \cs{duckthink}, and % \cs{DucksayOptions} and if not otherwise specified also as package options: @@ -452,7 +514,7 @@ and the derived files ducksay.pdf % use \meta{code} in a group right before the body (meaning the \anml). % Might be used as a package option but not all control sequences work out % of the box there. E.g.\@ to right-align the \anml\ to the bubble, use -% \verb|body=\hfill|. +% |body=\hfill|. % \item[align=\meta{valign}] % use \meta{valign} as the vertical alignment specifier given to the % \env{tabular} which is around the contents of \cs{ducksay} and @@ -480,31 +542,35 @@ and the derived files ducksay.pdf % \begingroup % \reversemarginpar % \marginpar -% {\tiny\hfill\ducksay[frog,MSG=\footnotesize,align=t]{Ohh, no!}} +% {\tiny\hfill\ducksay[frog,MSG=\footnotesize,t]{Ohh, no!}} % \endgroup % \begin{itemize} % \item no automatic line wrapping % \end{itemize}^^A<<< % +%^^A<<< +% % \SetVersion{2}% -% \subsection{Version 2}\label{sec:v2} +% \subsection{Version 2}\label{sec:v2}^^A>>> % \marginpar^^A>>> % { % \fontsize{3.5pt}{3.5pt}\selectfont -% \ducksay[unicorn,MSG=\footnotesize,align=t]{Here's all the good stuff!} +% \makebox[\marginparwidth] +% {\ducksay[unicorn,MSG=\footnotesize]{Here's all the good stuff!}}% % }^^A<<< % % \subsubsection{Introduction}^^A>>> % -% Version 2 is the current version of \pkg{ducksay}. It features automatic line +% Version~2 is the current version of \pkg{ducksay}. It features automatic line % wrapping (if you specify a fixed width) and in general more options (with some % nasty argument parsing). % -% If you're already used to version 1 you should note one important thing: You -% should only specify the |version|, the |ligatures| and |add-think| during -% package load time as arguments to \cs{usepackage}. The other keys might not -% work or do unintended things and only don't throw errors or warnings because -% of the legacy support of version 1. +% If you're already used to version~1 you should note one important thing: You +% should only specify the |version| and the |ligatures| during package load time +% as arguments to \cs{usepackage}. The other keys might not work or do +% unintended things and only don't throw errors or warnings because of the +% legacy support of version~1. After the package is loaded, keys only used for +% version~1 will throw an error. % %^^A<<< % @@ -512,7 +578,7 @@ and the derived files ducksay.pdf % \marginpar^^A>>> % { % \tiny -% \ducksay[duck-family,MSG=\footnotesize,align=t,body-mirrored] +% \ducksay[duck-family,MSG=\footnotesize,t,body-mirrored] % {Look at those, kids!} % }^^A<<< % @@ -543,11 +609,6 @@ and the derived files ducksay.pdf % \end{syntax} % The only difference to \cs{ducksay} is that in \cs{duckthink} the \anml s % think the \msg\ and don't say it.\\ -% It is implemented using regular expressions replacing a |\| which is only -% preceded by |\s*| (any number of space tokens) in the first three lines with -% |O| and |o|. It's first use per \anml\ might therefore be slower than -% \cs{ducksay} depending on the |add-think| key (see its description in -% \autoref{sec:options}). % \end{function}^^A<<< % %^^A<<< @@ -556,7 +617,7 @@ and the derived files ducksay.pdf % \marginpar^^A>>> % { % \tiny -% \hfill\ducksay[small-rabbit,MSG=\footnotesize,align=t] +% \hfill\ducksay[small-rabbit,MSG=\footnotesize] % {Fast, use options!} % }^^A<<< % In version 2 the following options are available. Keep in mind that you @@ -728,9 +789,12 @@ and the derived files ducksay.pdf % \pkg{array} is used afterwards. The package default is |\raggedleft|. It % might be useful if you want to use \pkg{ragged2e}'s \cs{RaggedLeft} for % example. -% \item[msg-to-bubble=\meta{pole}] +% \item[msg-to-body=\meta{pole}] % defines the horizontal coffin \meta{pole} to be used as the reference % point for the placement of the \anml\ beneath the \msg. See \PolesInfo. +% \item[no-bubble=\meta{bool}] +% If |true| the \msg\ will not be surrounded by a bubble. Package default is +% of course |false|. % \item[none=\meta{bool}] % One could say this is a special animal. If |true| no animal body will be % used (resulting in just the speech bubble). Package default is of course @@ -778,6 +842,8 @@ and the derived files ducksay.pdf % %^^A<<< % +%^^A<<< +% % \SetVersion{}% % \subsection{Dependencies}^^A>>> % \marginpar @@ -787,7 +853,7 @@ and the derived files ducksay.pdf % {% % \ducksay % [ -% kangaroo,MSG=\footnotesize,align=t +% kangaroo,MSG=\footnotesize % ,body-mirrored,body-to-msg=r,msg-to-body=hc % ] % {We rely on you}% @@ -805,10 +871,12 @@ and the derived files ducksay.pdf % \hfill % \makebox[8em][r] % {% -% \ducksay[whale,MSG=\footnotesize,align=t] -% {I'm the\\new one.}% +% \ducksay[knight,MSG=\footnotesize,t] +% {I'm the\\new one.}\\ +% \ducksay[crusader,MSG=\footnotesize,body=\normalsize,t] +% {Deus\\vult!\rlap{\footnotemark}}% % }% -% } +% }\footnotetext{Latin; ``I'm new, too.''} % The following animals are provided by this package. I did not create them (but % altered some), they belong to their original creators. % \bgroup @@ -837,7 +905,9 @@ and the derived files ducksay.pdf % ,rabbit^^A % ,snail^^A % ,whale^^A +% ,crusader^^A % ,unicorn^^A +% ,knight^^A % }\end{multicols}\begin{multicols}{2} % \availableAnimal{^^A % ,r2d2^^A @@ -856,7 +926,7 @@ and the derived files ducksay.pdf % \rlap % {% % \tiny -% \ducksay[squirrel,MSG=\footnotesize,align=t] +% \ducksay[squirrel,MSG=\footnotesize,t] % {WTFPL would be a\\better license.}% % }% % } @@ -884,7 +954,7 @@ and the derived files ducksay.pdf % {% % \tiny % \ducksay -% [vader,MSG=\footnotesize,align=t,arg=tab,msg-align=c] +% [vader,MSG=\footnotesize,arg=tab,msg-align=c,body-align=c] % {% % Only rebel scum reads\\documentation!\\ % Join the dark side,\\read the implementation.% @@ -904,6 +974,7 @@ and the derived files ducksay.pdf % \begin{macrocode} \int_new:N \l_ducksay_msg_width_int \int_new:N \l_ducksay_msg_height_int +\int_new:N \l_ducksay_tail_symbol_count_int % \end{macrocode} % \paragraph{Sequences} % \begin{macrocode} @@ -911,17 +982,18 @@ and the derived files ducksay.pdf % \end{macrocode} % \paragraph{Token lists} % \begin{macrocode} -\tl_new:N \l_ducksay_say_or_think_tl \tl_new:N \l_ducksay_align_tl \tl_new:N \l_ducksay_msg_align_tl \tl_new:N \l_ducksay_animal_tl \tl_new:N \l_ducksay_body_tl \tl_new:N \l_ducksay_bubble_tl \tl_new:N \l_ducksay_tmpa_tl +\tl_new:N \l_ducksay_tail_symbol_out_one_tl +\tl_new:N \l_ducksay_tail_symbol_out_two_tl +\tl_new:N \l_ducksay_tail_symbol_in_tl % \end{macrocode} % \paragraph{Boolean} % \begin{macrocode} -\bool_new:N \l_ducksay_also_add_think_bool \bool_new:N \l_ducksay_version_one_bool \bool_new:N \l_ducksay_version_two_bool % \end{macrocode} @@ -933,14 +1005,7 @@ and the derived files ducksay.pdf %^^A<<< % % \subsubsection{Regular Expressions}^^A>>> -% Regular expressions for \cs{duckthink} -% \begin{macrocode} -\regex_const:Nn \c_ducksay_first_regex { \A(.\s*)\\ } -\regex_const:Nn \c_ducksay_second_regex { \A(.[^\c{null}]*\c{null}\s*)\\ } -\regex_const:Nn \c_ducksay_third_regex { - \A(.[^\c{null}]*\c{null}[^\c{null}]*\c{null}\s*)\\ } -% \end{macrocode} -% And for \cs{AddColoredAnimal} +% Regular expressions for \cs{AddColoredAnimal} % \begin{macrocode} \regex_const:Nn \c_ducksay_textcolor_regex { \cO(?:\\textcolor\{(.*?)\}\{(.*?)\}) } @@ -955,6 +1020,8 @@ and the derived files ducksay.pdf % \begin{macrocode} \msg_new:nnn { ducksay } { load-time-only } { The~`#1`~key~is~to~be~used~only~during~package~load~time. } +\msg_new:nnn { ducksay } { deprecated-key } + { The~`\l_keys_key_tl`~key~is~deprecated.~Sorry~for~the~inconvenience. } % \end{macrocode} %^^A<<< % @@ -983,7 +1050,17 @@ and the derived files ducksay.pdf ,rel-align .value_required:n = true ,ligatures .tl_set:N = \l_ducksay_ligatures_tl ,ligatures .initial:n = { `<>,'- } - ,add-think .bool_set:N = \l_ducksay_also_add_think_bool + ,tail-1 .tl_set:N = \l_ducksay_tail_symbol_out_one_tl + ,tail-1 .initial:x = \c_backslash_str + ,tail-2 .tl_set:N = \l_ducksay_tail_symbol_out_two_tl + ,tail-2 .initial:x = \c_backslash_str + ,no-tail .meta:n = { tail-1 = { ~ }, tail-2 = { ~ } } + ,think .meta:n = { tail-1 = { O }, tail-2 = { o } } + ,say .code:n = + { + \exp_args:Nx \DucksayOptions + { tail-1 = { \c_backslash_str }, tail-2 = { \c_backslash_str } } + } ,version .choice: ,version / 1 .code:n = { @@ -996,6 +1073,7 @@ and the derived files ducksay.pdf \bool_set_true:N \l_ducksay_version_two_bool } ,version .initial:n = 2 + ,add-think .code:n = \msg_error:nn { ducksay } { deprecated-key } } % \end{macrocode} % @@ -1011,6 +1089,22 @@ and the derived files ducksay.pdf } % \end{macrocode} % +% \paragraph{Keys for \cs{AddAnimal}}^^A>>> +% Define keys meant for \cs{AddAnimal} and \cs{AddColoredAnimal} only in their +% own regime: +% \begin{macrocode} +\keys_define:nn { ducksay / add-animal } + { + ,tail-symbol .code:n = + \tl_set:Nx \l_ducksay_tail_symbol_in_tl { \tl_to_str:n { #1 } } + ,tail-symbol .initial:o = \c_backslash_str + ,tail-count .int_set:N = \l_ducksay_tail_symbol_count_int + ,tail-count .initial:n = 2 + } +% \end{macrocode} +% +%^^A<<< +% %^^A<<< % % \subsubsection{Functions}^^A>>> @@ -1018,27 +1112,13 @@ and the derived files ducksay.pdf % \paragraph{Generating Variants of External Functions}^^A>>> % % \begin{macrocode} -\cs_generate_variant:Nn \tl_if_eq:nnT { VnT } +\cs_generate_variant:Nn \tl_replace_once:Nnn { NVn } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NVn } % \end{macrocode} %^^A<<< % % \paragraph{Internal}^^A>>> % -% \begin{macro}{\ducksay_create_think_animal:n}^^A>>> -% \begin{macrocode} -\cs_new_protected:Npn \ducksay_create_think_animal:n #1 - { - \group_begin: - \tl_set_eq:Nc \l_ducksay_tmpa_tl { g_ducksay_animal_say_#1_tl } - \regex_replace_once:NnN \c_ducksay_first_regex { \1O } \l_ducksay_tmpa_tl - \regex_replace_once:NnN \c_ducksay_second_regex { \1o } \l_ducksay_tmpa_tl - \regex_replace_once:NnN \c_ducksay_third_regex { \1o } \l_ducksay_tmpa_tl - \tl_gset_eq:cN { g_ducksay_animal_think_#1_tl } \l_ducksay_tmpa_tl - \group_end: - } -% \end{macrocode} -% \end{macro}^^A<<< -% % \begin{macro}{\ducksay_replace_verb_newline:Nn}^^A>>> % \begin{macrocode} \cs_new_protected:Npx \ducksay_replace_verb_newline:Nn #1 #2 @@ -1069,27 +1149,65 @@ and the derived files ducksay.pdf % \end{macrocode} % \end{macro}^^A<<< % -% \begin{macro}{\ducksay_add_animal_inner:nn}^^A>>> +% \begin{macro}{\ducksay_add_animal_inner:nnnn}^^A>>> % \begin{macrocode} -\cs_new_protected:Npn \ducksay_add_animal_inner:nn #1 #2 +\cs_new_protected:Npn \ducksay_add_animal_inner:nnnn #1 #2 #3 #4 { - \tl_set:Nn \l_ducksay_tmpa_tl { \ #2 } - \tl_map_inline:Nn \l_ducksay_ligatures_tl - { \tl_replace_all:Nnn \l_ducksay_tmpa_tl { ##1 } { { ##1 } } } - \ducksay_replace_verb_newline:Nn \l_ducksay_tmpa_tl { \tabularnewline\null } - \tl_gset_eq:cN { g_ducksay_animal_say_#1_tl } \l_ducksay_tmpa_tl - \keys_define:nn { ducksay } + \group_begin: + \keys_set:nn { ducksay / add-animal } { #1 } + \tl_set:Nn \l_ducksay_tmpa_tl { \ #3 } + \int_compare:nNnTF { \l_ducksay_tail_symbol_count_int } < { \c_zero_int } + { + \tl_replace_once:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_one_tl + \tl_replace_all:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_two_tl + } + { + \int_compare:nNnT { \l_ducksay_tail_symbol_count_int } > + { \c_zero_int } + { + \tl_replace_once:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_one_tl + \int_step_inline:nnn { 2 } { \l_ducksay_tail_symbol_count_int } + { + \tl_replace_once:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_two_tl + } + } + } + \tl_map_inline:Nn \l_ducksay_ligatures_tl + { \tl_replace_all:Nnn \l_ducksay_tmpa_tl { ##1 } { { ##1 } } } + \ducksay_replace_verb_newline:Nn \l_ducksay_tmpa_tl + { \tabularnewline\null } + \exp_args:NNnV + \group_end: + \tl_set:cn { l_ducksay_animal_#2_tl } \l_ducksay_tmpa_tl + \exp_args:Nnx \keys_define:nn { ducksay } { - #1 .code:n = + #2 .code:n = { - \tl_if_exist:cF - { g_ducksay_animal_ \l_ducksay_say_or_think_tl _#1_tl } - { \ducksay_create_think_animal:n { #1 } } - \tl_set_eq:Nc \l_ducksay_animal_tl - { g_ducksay_animal_ \l_ducksay_say_or_think_tl _#1_tl } + \exp_not:n { \tl_set_eq:NN \l_ducksay_animal_tl } + \exp_after:wN \exp_not:N \cs:w l_ducksay_animal_#2_tl \cs_end: + \exp_not:n { \exp_args:NV \DucksayOptions } + \exp_after:wN + \exp_not:N \cs:w l_ducksay_animal_#2_options_tl \cs_end: } } + \tl_if_exist:cF { l_ducksay_animal_#2_options_tl } + { \tl_new:c { l_ducksay_animal_#2_options_tl } } + \IfBooleanT { #4 } + { \keys_define:nn { ducksay } { default_animal .meta:n = { #2 } } } } +\cs_generate_variant:Nn \ducksay_add_animal_inner:nnnn { nnVn } % \end{macrocode} % \end{macro}^^A<<< % @@ -1117,35 +1235,44 @@ and the derived files ducksay.pdf % % \begin{macro}{\AddAnimal}^^A>>> % \begin{macrocode} -\NewDocumentCommand \AddAnimal { s m +v } +\NewDocumentCommand \AddAnimal { s O{} m +v } { - \ducksay_add_animal_inner:nn { #2 } { #3 } - \bool_if:NT \l_ducksay_also_add_think_bool - { \ducksay_create_think_animal:n { #2 } } - \IfBooleanT{#1} - { \keys_define:nn { ducksay } { default_animal .meta:n = { #2 } } } + \ducksay_add_animal_inner:nnnn { #2 } { #3 } { #4 } { #1 } } % \end{macrocode} % \end{macro}^^A<<< % % \begin{macro}{\AddColoredAnimal}^^A>>> % \begin{macrocode} -\NewDocumentCommand \AddColoredAnimal { s m +v } +\NewDocumentCommand \AddColoredAnimal { s O{} m +v } { - \ducksay_add_animal_inner:nn { #2 } { #3 } - \regex_replace_all:Nnc \c_ducksay_color_delim_regex + \tl_set:Nn \l_ducksay_tmpa_tl { #4 } + \regex_replace_all:NnN \c_ducksay_color_delim_regex { \c{bgroup}\c{color}\cB\{\1\cE\}\2\c{egroup} } - { g_ducksay_animal_say_#2_tl } - \regex_replace_all:Nnc \c_ducksay_color_regex + \l_ducksay_tmpa_tl + \regex_replace_all:NnN \c_ducksay_color_regex { \c{color}\cB\{\1\cE\} } - { g_ducksay_animal_say_#2_tl } - \regex_replace_all:Nnc \c_ducksay_textcolor_regex + \l_ducksay_tmpa_tl + \regex_replace_all:NnN \c_ducksay_textcolor_regex { \c{textcolor}\cB\{\1\cE\}\cB\{\2\cE\} } - { g_ducksay_animal_say_#2_tl } - \bool_if:NT \l_ducksay_also_add_think_bool - { \ducksay_create_think_animal:n { #2 } } - \IfBooleanT{#1} - { \keys_define:nn { ducksay } { default_animal .meta:n = { #2 } } } + \l_ducksay_tmpa_tl + \ducksay_add_animal_inner:nnVn { #2 } { #3 } \l_ducksay_tmpa_tl { #1 } + } +% \end{macrocode} +% \end{macro}^^A<<< +% +% \begin{macro}{\AnimalOptions}^^A>>> +% \begin{macrocode} +\NewDocumentCommand \AnimalOptions { s m m } + { + \tl_if_exist:cTF { l_ducksay_animal_#2_options_tl } + { + \IfBooleanTF { #1 } + { \tl_set:cn } + { \tl_put_right:cn } + } + { \tl_set:cn } + { l_ducksay_animal_#2_options_tl } { #3, } } % \end{macrocode} % \end{macro}^^A<<< @@ -1308,16 +1435,19 @@ and the derived files ducksay.pdf % \end{macrocode} % \end{macro}^^A<<< % -% \begin{macro}{\ducksay_prepare_say_and_think:n}^^A>>> +% \begin{macro}{\ducksay_say_and_think:nn}^^A>>> % Reset some variables % \begin{macrocode} -\cs_new:Npn \ducksay_prepare_say_and_think:n #1 +\cs_new:Npn \ducksay_say_and_think:nn #1 #2 { - \int_set:Nn \l_ducksay_msg_width_int { -\c_max_int } - \int_set:Nn \l_ducksay_msg_height_int { -\c_max_int } - \keys_set:nn { ducksay } { #1 } - \tl_if_empty:NT \l_ducksay_animal_tl - { \keys_set:nn { ducksay } { default_animal } } + \group_begin: + \int_set:Nn \l_ducksay_msg_width_int { -\c_max_int } + \int_set:Nn \l_ducksay_msg_height_int { -\c_max_int } + \keys_set:nn { ducksay } { #1 } + \tl_if_empty:NT \l_ducksay_animal_tl + { \keys_set:nn { ducksay } { default_animal } } + \ducksay_print:nV { #2 } \l_ducksay_rel_align_tl + \group_end: } % \end{macrocode} % \end{macro}^^A<<< @@ -1329,11 +1459,7 @@ and the derived files ducksay.pdf % \begin{macrocode} \NewDocumentCommand \ducksay { O{} m } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { say } - \ducksay_prepare_say_and_think:n { #1 } - \ducksay_print:nV { #2 } \l_ducksay_rel_align_tl - \group_end: + \ducksay_say_and_think:nn { #1 } { #2 } } % \end{macrocode} % \end{macro}^^A<<< @@ -1342,11 +1468,7 @@ and the derived files ducksay.pdf % \begin{macrocode} \NewDocumentCommand \duckthink { O{} m } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { think } - \ducksay_prepare_say_and_think:n { #1 } - \ducksay_print:nV { #2 } \l_ducksay_rel_align_tl - \group_end: + \ducksay_say_and_think:nn { think, #1 } { #2 } } % \end{macrocode} % \end{macro}^^A<<< @@ -1381,6 +1503,8 @@ and the derived files ducksay.pdf The~specified~message~alignment~`\exp_not:n { #1 }`~is~unknown.~ `l`~is~used~as~fallback. } +\msg_new:nnn { ducksay } { v1-key-only } + { The~`\l_keys_key_tl`~key~is~only~available~for~`version=1`. } % \end{macrocode} %^^A<<< % @@ -1444,6 +1568,7 @@ and the derived files ducksay.pdf ,wd* .initial:n = -\c_max_dim ,wd* .value_required:n = true ,none .bool_set:N = \l_ducksay_no_body_bool + ,no-bubble .bool_set:N = \l_ducksay_no_bubble_bool ,body-mirrored .bool_set:N = \l_ducksay_mirrored_body_bool ,ignore-body .bool_set:N = \l_ducksay_ignored_body_bool ,body-x .dim_set:N = \l_ducksay_body_x_offset_dim @@ -1505,7 +1630,7 @@ and the derived files ducksay.pdf ,bubble-bot-kern .initial:n = { .2ex } ,bubble-bot-kern .value_required:n = true ,bubble-side-kern .tl_set:N = \l_ducksay_bubble_side_kern_tl - ,bubble-side-kern .initial:n = { 0.2em } + ,bubble-side-kern .initial:n = { .2em } ,bubble-side-kern .value_required:n = true ,bubble-delim-top .tl_set:N = \l_ducksay_bubble_delim_top_tl ,bubble-delim-left-1 .tl_set:N = \l_ducksay_bubble_delim_left_a_tl @@ -1529,6 +1654,18 @@ and the derived files ducksay.pdf } % \end{macrocode} % +% Redefine keys only intended for version~1 to throw an error: +% +% \begin{macrocode} +\clist_map_inline:nn + { align, rel-align } + { + \keys_define:nn { ducksay } + { #1 .code:n = \msg_error:nn { ducksay } { v1-key-only } } + } +% \end{macrocode} +% +% %^^A<<< % % \subsubsection{Functions}^^A>>> @@ -1618,6 +1755,7 @@ and the derived files ducksay.pdf % \begin{macrocode} \cs_new:Npn \ducksay_digest_options:n #1 { + \group_begin: \keys_set:nn { ducksay } { #1 } \tl_if_empty:NT \l_ducksay_animal_tl { \keys_set:nn { ducksay } { default_animal } } @@ -1672,6 +1810,7 @@ and the derived files ducksay.pdf } \cs_set_eq:NN \ducksay_eat_argument:w \ducksay_eat_argument_tabular:w } + \ducksay_eat_argument:w } % \end{macrocode} % \end{macro}^^A<<< @@ -1708,88 +1847,119 @@ and the derived files ducksay.pdf % \begin{macrocode} \cs_new_protected:Npn \ducksay_shipout: { - \hbox_set:Nn \l_ducksay_tmpa_box - { \l_ducksay_bubble_fount_tl \l_ducksay_bubble_delim_top_tl } - \int_set:Nn \l_ducksay_msg_width_int - { - \fp_eval:n - { - ceil - ( \box_wd:N \l_ducksay_msg_box / \box_wd:N \l_ducksay_tmpa_box ) - } - } - \group_begin: - \l_ducksay_bubble_fount_tl - \exp_args:NNNx - \group_end: - \int_set:Nn \l_ducksay_msg_height_int + \hcoffin_set:Nn \l_ducksay_msg_coffin { \box_use:N \l_ducksay_msg_box } + \bool_if:NF \l_ducksay_no_bubble_bool { - \int_max:nn + \hbox_set:Nn \l_ducksay_tmpa_box + { \l_ducksay_bubble_fount_tl \l_ducksay_bubble_delim_top_tl } + \int_set:Nn \l_ducksay_msg_width_int { \fp_eval:n { - ceil + ceil ( - ( - \box_ht:N \l_ducksay_msg_box - + \box_dp:N \l_ducksay_msg_box - ) - / ( \arraystretch * \baselineskip ) + \box_wd:N \l_ducksay_msg_box / \box_wd:N \l_ducksay_tmpa_box ) } - + \l_ducksay_vpad_int } - { \l_ducksay_msg_height_int } - } - \hcoffin_set:Nn \l_ducksay_bubble_open_coffin - { + \group_begin: \l_ducksay_bubble_fount_tl - \begin{tabular}{@{}l@{}} - \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } - { - \l_ducksay_bubble_delim_left_a_tl - } - { - \l_ducksay_bubble_delim_left_b_tl\\ - \int_step_inline:nnn - { 3 } { \l_ducksay_msg_height_int } + \exp_args:NNNx + \group_end: + \int_set:Nn \l_ducksay_msg_height_int + { + \int_max:nn + { + \fp_eval:n + { + ceil + ( + ( + \box_ht:N \l_ducksay_msg_box + + \box_dp:N \l_ducksay_msg_box + ) + / ( \arraystretch * \baselineskip ) + ) + } + + \l_ducksay_vpad_int + } + { \l_ducksay_msg_height_int } + } + \hcoffin_set:Nn \l_ducksay_bubble_open_coffin + { + \l_ducksay_bubble_fount_tl + \begin{tabular}{@{}l@{}} + \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } { - \kern-\l_ducksay_bubble_side_kern_tl - \l_ducksay_bubble_delim_left_c_tl - \\ + \l_ducksay_bubble_delim_left_a_tl } - \l_ducksay_bubble_delim_left_d_tl - } - \end{tabular} - } - \hcoffin_set:Nn \l_ducksay_bubble_close_coffin - { - \l_ducksay_bubble_fount_tl - \begin{tabular}{@{}r@{}} - \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } - { - \l_ducksay_bubble_delim_right_a_tl - } - { - \l_ducksay_bubble_delim_right_b_tl \\ - \int_step_inline:nnn - { 3 } { \l_ducksay_msg_height_int } { - \l_ducksay_bubble_delim_right_c_tl - \kern-\l_ducksay_bubble_side_kern_tl - \\ + \l_ducksay_bubble_delim_left_b_tl\\ + \int_step_inline:nnn + { 3 } { \l_ducksay_msg_height_int } + { + \kern-\l_ducksay_bubble_side_kern_tl + \l_ducksay_bubble_delim_left_c_tl + \\ + } + \l_ducksay_bubble_delim_left_d_tl } - \l_ducksay_bubble_delim_right_d_tl - } - \end{tabular} - } - \hcoffin_set:Nn \l_ducksay_bubble_top_coffin - { - \l_ducksay_bubble_fount_tl - \int_step_inline:nn { \l_ducksay_msg_width_int + \l_ducksay_hpad_int } - { \l_ducksay_bubble_delim_top_tl } + \end{tabular} + } + \hcoffin_set:Nn \l_ducksay_bubble_close_coffin + { + \l_ducksay_bubble_fount_tl + \begin{tabular}{@{}r@{}} + \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } + { + \l_ducksay_bubble_delim_right_a_tl + } + { + \l_ducksay_bubble_delim_right_b_tl \\ + \int_step_inline:nnn + { 3 } { \l_ducksay_msg_height_int } + { + \l_ducksay_bubble_delim_right_c_tl + \kern-\l_ducksay_bubble_side_kern_tl + \\ + } + \l_ducksay_bubble_delim_right_d_tl + } + \end{tabular} + } + \hcoffin_set:Nn \l_ducksay_bubble_top_coffin + { + \l_ducksay_bubble_fount_tl + \int_step_inline:nn + { \l_ducksay_msg_width_int + \l_ducksay_hpad_int } + { \l_ducksay_bubble_delim_top_tl } + } + \dim_set:Nn \l_ducksay_hpad_dim + { + ( + \coffin_wd:N \l_ducksay_bubble_top_coffin + - \coffin_wd:N \l_ducksay_msg_coffin + ) / 2 + } + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { l } { vc } + \l_ducksay_bubble_open_coffin { r } { vc } + { - \l_ducksay_hpad_dim } { \c_zero_dim } + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { r } { vc } + \l_ducksay_bubble_close_coffin { l } { vc } + { \l_ducksay_hpad_dim } { \c_zero_dim } + \ducksay_set_bubble_top_kern: + \ducksay_set_bubble_bottom_kern: + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { hc } { t } + \l_ducksay_bubble_top_coffin { hc } { b } + { \c_zero_dim } { \l_ducksay_bubble_top_kern_dim } + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { hc } { b } + \l_ducksay_bubble_top_coffin { hc } { t } + { \c_zero_dim } { \l_ducksay_bubble_bottom_kern_dim } } - \hcoffin_set:Nn \l_ducksay_msg_coffin { \box_use:N \l_ducksay_msg_box } \bool_if:NF \l_ducksay_no_body_bool { \hcoffin_set:Nn \l_ducksay_body_coffin @@ -1810,34 +1980,6 @@ and the derived files ducksay.pdf { r } { \tl_set:Nn \l_ducksay_body_to_msg_align_body_tl { l } } } } - } - \dim_set:Nn \l_ducksay_hpad_dim - { - ( - \coffin_wd:N \l_ducksay_bubble_top_coffin - - \coffin_wd:N \l_ducksay_msg_coffin - ) / 2 - } - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { l } { vc } - \l_ducksay_bubble_open_coffin { r } { vc } - { - \l_ducksay_hpad_dim } { \c_zero_dim } - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { r } { vc } - \l_ducksay_bubble_close_coffin { l } { vc } - { \l_ducksay_hpad_dim } { \c_zero_dim } - \ducksay_set_bubble_top_kern: - \ducksay_set_bubble_bottom_kern: - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { hc } { t } - \l_ducksay_bubble_top_coffin { hc } { b } - { \c_zero_dim } { \l_ducksay_bubble_top_kern_dim } - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { hc } { b } - \l_ducksay_bubble_top_coffin { hc } { t } - { \c_zero_dim } { \l_ducksay_bubble_bottom_kern_dim } - \bool_if:NF \l_ducksay_no_body_bool - { \bool_if:NTF \l_ducksay_ignored_body_bool { \coffin_attach:NVnNVnnn } { \coffin_join:NVnNVnnn } @@ -1956,9 +2098,7 @@ and the derived files ducksay.pdf \cs_generate_variant:Nn \coffin_join:NnnNnnnn { NVnNVnnn } \cs_generate_variant:Nn \coffin_attach:NnnNnnnn { NVnNVnnn } \cs_generate_variant:Nn \coffin_typeset:Nnnnn { NVVnn } -\cs_generate_variant:Nn \tl_if_eq:nnT { VnT } \cs_generate_variant:Nn \str_case:nn { Vn } -\cs_generate_variant:Nn \regex_replace_all:NnN { Nnc } % \end{macrocode} % %^^A<<< @@ -1971,10 +2111,7 @@ and the derived files ducksay.pdf % \begin{macrocode} \NewDocumentCommand \ducksay { O{} } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { say } - \ducksay_digest_options:n { #1 } - \ducksay_eat_argument:w + \ducksay_digest_options:n { #1 } } % \end{macrocode} % \end{macro}^^A<<< @@ -1983,10 +2120,7 @@ and the derived files ducksay.pdf % \begin{macrocode} \NewDocumentCommand \duckthink { O{} } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { think } - \ducksay_digest_options:n { #1 } - \ducksay_eat_argument:w + \ducksay_digest_options:n { think, #1 } } % \end{macrocode} % \end{macro}^^A<<< @@ -2077,9 +2211,9 @@ and the derived files ducksay.pdf (") >-( : )-< (__:__)}%<<< -\AddAnimal{hedgehog}%>>> -{ \ .\|//||\||. - \ |/\/||/|//|/| +\AddAnimal[tail-symbol=s]{hedgehog}%>>> +{ s .\|//||\||. + s |/\/||/|//|/| /. `|/\\|/||/|| o__,_|//|/||\||'}%<<< \AddAnimal{kangaroo}%>>> @@ -2091,10 +2225,10 @@ and the derived files ducksay.pdf // \\ ,/' `\_,}%<<< %^^A http://chris.com/ascii/index.php?art=animals/rabbits -\AddAnimal{rabbit}%>>> -{ \ / \`\ __ - \ | \ `\ /`/ \ - \ \_/`\ \-"-/` /\ \ +\AddAnimal[tail-symbol=s,tail-count=3]{rabbit}%>>> +{ s / \`\ __ + s | \ `\ /`/ \ + s \_/`\ \-"-/` /\ \ | | \ | (d b) \_/ / \ @@ -2117,10 +2251,10 @@ and the derived files ducksay.pdf \ _// (')---. _/-_( )o}%<<< -\AddAnimal{dragon}%>>> -{ \ / \ //\ - \ |\___/| / \// \\ - \ /0 0 \__ / // | \ \ +\AddAnimal[tail-symbol=s,tail-count=3]{dragon}%>>> +{ s / \ //\ + s |\___/| / \// \\ + s /0 0 \__ / // | \ \ / / \/_/ // | \ \ @_^_@'/ \/_ // | \ \ //_^_/ \/_ // | \ \ @@ -2179,15 +2313,15 @@ and the derived files ducksay.pdf _// _// /_| /_|}%<<< %^^A https://asciiart.website//index.php?art=animals/other%20(water) -\AddAnimal{whale}%>>> -{ \ |-. - \ .-""-._ \ \.--| - \ / `-..__) ,-' +\AddAnimal[tail-count=3,tail-symbol=s]{whale}%>>> +{ s |-. + s .-""-._ \ \.--| + s / `-..__) ,-' | . / \--.__, .__.,' `-.___'._\_.'}%<<< %^^A from http://www.ascii-art.de/ascii/s/starwars.txt : -\AddAnimal{yoda}%>>> +\AddAnimal[tail-count=3]{yoda}%>>> { \ \ ____ \ _.' : `._ @@ -2224,7 +2358,7 @@ and the derived files ducksay.pdf :-""-.`./-.' / `.___.' \ `t ._ / "-.t-._:'}%<<< -\AddAnimal{yoda-head}%>>> +\AddAnimal[tail-count=3]{yoda-head}%>>> { \ \ ____ \ _.' : `._ @@ -2279,6 +2413,36 @@ and the derived files ducksay.pdf /_ \O========O/ _\ `--...__|`-._ _.-'|__...--' | `' |}%<<< +\AddAnimal[tail-symbol=|,tail-count=1]{crusader}%>>> +{ | +\[T]/} +\csname bool_if:cT\endcsname {l_ducksay_version_one_bool} + {\AnimalOptions{crusader}{tail-1=|,rel-align=c}} +\csname bool_if:cT\endcsname {l_ducksay_version_two_bool} + {\AnimalOptions{crusader}{tail-1=|,body-align=c}}%<<< +%^^A http://ascii.co.uk/art/knights +\AddAnimal[tail-count=3]{knight}%>>> +{ \ + \ ,-"""-. + \ | === | + ) | ( + .=='\" "/`==. + .'\ (`:') /`. + _/_ |_.-' : `-._|__\_ + <___>'\ : / `<___> + / / >=======< / / + _/ .' / ,-:-. \/=,' +/ _/ |__/v^v^v\__) \ +\(\) |V^V^V^V^V|\_/ + (\\ \`---|---'/ + \\ \-._|_,-/ + \\ |__|__| + \\ <___X___> + \\ \..|../ + \\ \ | / + \\ /V|V\ + \|/ | \ + '--' `--`}%<<< %</animals> % \end{macrocode}^^A<<< % diff --git a/Master/texmf-dist/tex/latex/ducksay/ducksay.animals.tex b/Master/texmf-dist/tex/latex/ducksay/ducksay.animals.tex index 32f8df1aa2d..e0077f6f47b 100644 --- a/Master/texmf-dist/tex/latex/ducksay/ducksay.animals.tex +++ b/Master/texmf-dist/tex/latex/ducksay/ducksay.animals.tex @@ -104,9 +104,9 @@ (") >-( : )-< (__:__)}%<<< -\AddAnimal{hedgehog}%>>> -{ \ .\|//||\||. - \ |/\/||/|//|/| +\AddAnimal[tail-symbol=s]{hedgehog}%>>> +{ s .\|//||\||. + s |/\/||/|//|/| /. `|/\\|/||/|| o__,_|//|/||\||'}%<<< \AddAnimal{kangaroo}%>>> @@ -117,10 +117,10 @@ \,\ / \\ // \\ ,/' `\_,}%<<< -\AddAnimal{rabbit}%>>> -{ \ / \`\ __ - \ | \ `\ /`/ \ - \ \_/`\ \-"-/` /\ \ +\AddAnimal[tail-symbol=s,tail-count=3]{rabbit}%>>> +{ s / \`\ __ + s | \ `\ /`/ \ + s \_/`\ \-"-/` /\ \ | | \ | (d b) \_/ / \ @@ -143,10 +143,10 @@ \ _// (')---. _/-_( )o}%<<< -\AddAnimal{dragon}%>>> -{ \ / \ //\ - \ |\___/| / \// \\ - \ /0 0 \__ / // | \ \ +\AddAnimal[tail-symbol=s,tail-count=3]{dragon}%>>> +{ s / \ //\ + s |\___/| / \// \\ + s /0 0 \__ / // | \ \ / / \/_/ // | \ \ @_^_@'/ \/_ // | \ \ //_^_/ \/_ // | \ \ @@ -201,14 +201,14 @@ \_| / / / / _// _// /_| /_|}%<<< -\AddAnimal{whale}%>>> -{ \ |-. - \ .-""-._ \ \.--| - \ / `-..__) ,-' +\AddAnimal[tail-count=3,tail-symbol=s]{whale}%>>> +{ s |-. + s .-""-._ \ \.--| + s / `-..__) ,-' | . / \--.__, .__.,' `-.___'._\_.'}%<<< -\AddAnimal{yoda}%>>> +\AddAnimal[tail-count=3]{yoda}%>>> { \ \ ____ \ _.' : `._ @@ -245,7 +245,7 @@ :-""-.`./-.' / `.___.' \ `t ._ / "-.t-._:'}%<<< -\AddAnimal{yoda-head}%>>> +\AddAnimal[tail-count=3]{yoda-head}%>>> { \ \ ____ \ _.' : `._ @@ -299,6 +299,35 @@ /_ \O========O/ _\ `--...__|`-._ _.-'|__...--' | `' |}%<<< +\AddAnimal[tail-symbol=|,tail-count=1]{crusader}%>>> +{ | +\[T]/} +\csname bool_if:cT\endcsname {l_ducksay_version_one_bool} + {\AnimalOptions{crusader}{tail-1=|,rel-align=c}} +\csname bool_if:cT\endcsname {l_ducksay_version_two_bool} + {\AnimalOptions{crusader}{tail-1=|,body-align=c}}%<<< +\AddAnimal[tail-count=3]{knight}%>>> +{ \ + \ ,-"""-. + \ | === | + ) | ( + .=='\" "/`==. + .'\ (`:') /`. + _/_ |_.-' : `-._|__\_ + <___>'\ : / `<___> + / / >=======< / / + _/ .' / ,-:-. \/=,' +/ _/ |__/v^v^v\__) \ +\(\) |V^V^V^V^V|\_/ + (\\ \`---|---'/ + \\ \-._|_,-/ + \\ |__|__| + \\ <___X___> + \\ \..|../ + \\ \ | / + \\ /V|V\ + \|/ | \ + '--' `--`}%<<< %% %% %% End of file `ducksay.animals.tex'. diff --git a/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v1.tex b/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v1.tex index a5a1bab3414..1d6487c7674 100644 --- a/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v1.tex +++ b/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v1.tex @@ -125,29 +125,24 @@ \group_end: } \cs_generate_variant:Nn \ducksay_print:nn { nV } -\cs_new:Npn \ducksay_prepare_say_and_think:n #1 - { - \int_set:Nn \l_ducksay_msg_width_int { -\c_max_int } - \int_set:Nn \l_ducksay_msg_height_int { -\c_max_int } - \keys_set:nn { ducksay } { #1 } - \tl_if_empty:NT \l_ducksay_animal_tl - { \keys_set:nn { ducksay } { default_animal } } - } -\NewDocumentCommand \ducksay { O{} m } +\cs_new:Npn \ducksay_say_and_think:nn #1 #2 { \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { say } - \ducksay_prepare_say_and_think:n { #1 } + \int_set:Nn \l_ducksay_msg_width_int { -\c_max_int } + \int_set:Nn \l_ducksay_msg_height_int { -\c_max_int } + \keys_set:nn { ducksay } { #1 } + \tl_if_empty:NT \l_ducksay_animal_tl + { \keys_set:nn { ducksay } { default_animal } } \ducksay_print:nV { #2 } \l_ducksay_rel_align_tl \group_end: } +\NewDocumentCommand \ducksay { O{} m } + { + \ducksay_say_and_think:nn { #1 } { #2 } + } \NewDocumentCommand \duckthink { O{} m } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { think } - \ducksay_prepare_say_and_think:n { #1 } - \ducksay_print:nV { #2 } \l_ducksay_rel_align_tl - \group_end: + \ducksay_say_and_think:nn { think, #1 } { #2 } } %% %% diff --git a/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v2.tex b/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v2.tex index fbd1143b637..413e221bbaa 100644 --- a/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v2.tex +++ b/Master/texmf-dist/tex/latex/ducksay/ducksay.code.v2.tex @@ -43,6 +43,8 @@ The~specified~message~alignment~`\exp_not:n { #1 }`~is~unknown.~ `l`~is~used~as~fallback. } +\msg_new:nnn { ducksay } { v1-key-only } + { The~`\l_keys_key_tl`~key~is~only~available~for~`version=1`. } \tl_new:N \l_ducksay_msg_align_vbox_tl \box_new:N \l_ducksay_msg_box \bool_new:N \l_ducksay_eat_arg_box_bool @@ -76,6 +78,7 @@ ,wd* .initial:n = -\c_max_dim ,wd* .value_required:n = true ,none .bool_set:N = \l_ducksay_no_body_bool + ,no-bubble .bool_set:N = \l_ducksay_no_bubble_bool ,body-mirrored .bool_set:N = \l_ducksay_mirrored_body_bool ,ignore-body .bool_set:N = \l_ducksay_ignored_body_bool ,body-x .dim_set:N = \l_ducksay_body_x_offset_dim @@ -137,7 +140,7 @@ ,bubble-bot-kern .initial:n = { .2ex } ,bubble-bot-kern .value_required:n = true ,bubble-side-kern .tl_set:N = \l_ducksay_bubble_side_kern_tl - ,bubble-side-kern .initial:n = { 0.2em } + ,bubble-side-kern .initial:n = { .2em } ,bubble-side-kern .value_required:n = true ,bubble-delim-top .tl_set:N = \l_ducksay_bubble_delim_top_tl ,bubble-delim-left-1 .tl_set:N = \l_ducksay_bubble_delim_left_a_tl @@ -159,6 +162,12 @@ ,bubble-delim-right-4 .initial:n = / ,strip-spaces .bool_set:N = \l_ducksay_msg_strip_spaces_bool } +\clist_map_inline:nn + { align, rel-align } + { + \keys_define:nn { ducksay } + { #1 .code:n = \msg_error:nn { ducksay } { v1-key-only } } + } \cs_new:Npn \ducksay_evaluate_message_alignment_fixed_width_common: { \str_case:Vn \l_ducksay_msg_align_tl @@ -210,6 +219,7 @@ } \cs_new:Npn \ducksay_digest_options:n #1 { + \group_begin: \keys_set:nn { ducksay } { #1 } \tl_if_empty:NT \l_ducksay_animal_tl { \keys_set:nn { ducksay } { default_animal } } @@ -264,6 +274,7 @@ } \cs_set_eq:NN \ducksay_eat_argument:w \ducksay_eat_argument_tabular:w } + \ducksay_eat_argument:w } \cs_new:Npn \ducksay_set_bubble_top_kern: { @@ -285,88 +296,119 @@ } \cs_new_protected:Npn \ducksay_shipout: { - \hbox_set:Nn \l_ducksay_tmpa_box - { \l_ducksay_bubble_fount_tl \l_ducksay_bubble_delim_top_tl } - \int_set:Nn \l_ducksay_msg_width_int - { - \fp_eval:n - { - ceil - ( \box_wd:N \l_ducksay_msg_box / \box_wd:N \l_ducksay_tmpa_box ) - } - } - \group_begin: - \l_ducksay_bubble_fount_tl - \exp_args:NNNx - \group_end: - \int_set:Nn \l_ducksay_msg_height_int + \hcoffin_set:Nn \l_ducksay_msg_coffin { \box_use:N \l_ducksay_msg_box } + \bool_if:NF \l_ducksay_no_bubble_bool { - \int_max:nn + \hbox_set:Nn \l_ducksay_tmpa_box + { \l_ducksay_bubble_fount_tl \l_ducksay_bubble_delim_top_tl } + \int_set:Nn \l_ducksay_msg_width_int { \fp_eval:n { ceil ( - ( - \box_ht:N \l_ducksay_msg_box - + \box_dp:N \l_ducksay_msg_box - ) - / ( \arraystretch * \baselineskip ) + \box_wd:N \l_ducksay_msg_box / \box_wd:N \l_ducksay_tmpa_box ) } - + \l_ducksay_vpad_int } - { \l_ducksay_msg_height_int } - } - \hcoffin_set:Nn \l_ducksay_bubble_open_coffin - { + \group_begin: \l_ducksay_bubble_fount_tl - \begin{tabular}{@{}l@{}} - \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } - { - \l_ducksay_bubble_delim_left_a_tl - } - { - \l_ducksay_bubble_delim_left_b_tl\\ - \int_step_inline:nnn - { 3 } { \l_ducksay_msg_height_int } + \exp_args:NNNx + \group_end: + \int_set:Nn \l_ducksay_msg_height_int + { + \int_max:nn + { + \fp_eval:n + { + ceil + ( + ( + \box_ht:N \l_ducksay_msg_box + + \box_dp:N \l_ducksay_msg_box + ) + / ( \arraystretch * \baselineskip ) + ) + } + + \l_ducksay_vpad_int + } + { \l_ducksay_msg_height_int } + } + \hcoffin_set:Nn \l_ducksay_bubble_open_coffin + { + \l_ducksay_bubble_fount_tl + \begin{tabular}{@{}l@{}} + \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } { - \kern-\l_ducksay_bubble_side_kern_tl - \l_ducksay_bubble_delim_left_c_tl - \\ + \l_ducksay_bubble_delim_left_a_tl } - \l_ducksay_bubble_delim_left_d_tl - } - \end{tabular} - } - \hcoffin_set:Nn \l_ducksay_bubble_close_coffin - { - \l_ducksay_bubble_fount_tl - \begin{tabular}{@{}r@{}} - \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } - { - \l_ducksay_bubble_delim_right_a_tl - } - { - \l_ducksay_bubble_delim_right_b_tl \\ - \int_step_inline:nnn - { 3 } { \l_ducksay_msg_height_int } { - \l_ducksay_bubble_delim_right_c_tl - \kern-\l_ducksay_bubble_side_kern_tl - \\ + \l_ducksay_bubble_delim_left_b_tl\\ + \int_step_inline:nnn + { 3 } { \l_ducksay_msg_height_int } + { + \kern-\l_ducksay_bubble_side_kern_tl + \l_ducksay_bubble_delim_left_c_tl + \\ + } + \l_ducksay_bubble_delim_left_d_tl } - \l_ducksay_bubble_delim_right_d_tl - } - \end{tabular} - } - \hcoffin_set:Nn \l_ducksay_bubble_top_coffin - { - \l_ducksay_bubble_fount_tl - \int_step_inline:nn { \l_ducksay_msg_width_int + \l_ducksay_hpad_int } - { \l_ducksay_bubble_delim_top_tl } + \end{tabular} + } + \hcoffin_set:Nn \l_ducksay_bubble_close_coffin + { + \l_ducksay_bubble_fount_tl + \begin{tabular}{@{}r@{}} + \int_compare:nNnTF { \l_ducksay_msg_height_int } = { \c_one_int } + { + \l_ducksay_bubble_delim_right_a_tl + } + { + \l_ducksay_bubble_delim_right_b_tl \\ + \int_step_inline:nnn + { 3 } { \l_ducksay_msg_height_int } + { + \l_ducksay_bubble_delim_right_c_tl + \kern-\l_ducksay_bubble_side_kern_tl + \\ + } + \l_ducksay_bubble_delim_right_d_tl + } + \end{tabular} + } + \hcoffin_set:Nn \l_ducksay_bubble_top_coffin + { + \l_ducksay_bubble_fount_tl + \int_step_inline:nn + { \l_ducksay_msg_width_int + \l_ducksay_hpad_int } + { \l_ducksay_bubble_delim_top_tl } + } + \dim_set:Nn \l_ducksay_hpad_dim + { + ( + \coffin_wd:N \l_ducksay_bubble_top_coffin + - \coffin_wd:N \l_ducksay_msg_coffin + ) / 2 + } + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { l } { vc } + \l_ducksay_bubble_open_coffin { r } { vc } + { - \l_ducksay_hpad_dim } { \c_zero_dim } + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { r } { vc } + \l_ducksay_bubble_close_coffin { l } { vc } + { \l_ducksay_hpad_dim } { \c_zero_dim } + \ducksay_set_bubble_top_kern: + \ducksay_set_bubble_bottom_kern: + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { hc } { t } + \l_ducksay_bubble_top_coffin { hc } { b } + { \c_zero_dim } { \l_ducksay_bubble_top_kern_dim } + \coffin_join:NnnNnnnn + \l_ducksay_msg_coffin { hc } { b } + \l_ducksay_bubble_top_coffin { hc } { t } + { \c_zero_dim } { \l_ducksay_bubble_bottom_kern_dim } } - \hcoffin_set:Nn \l_ducksay_msg_coffin { \box_use:N \l_ducksay_msg_box } \bool_if:NF \l_ducksay_no_body_bool { \hcoffin_set:Nn \l_ducksay_body_coffin @@ -387,34 +429,6 @@ { r } { \tl_set:Nn \l_ducksay_body_to_msg_align_body_tl { l } } } } - } - \dim_set:Nn \l_ducksay_hpad_dim - { - ( - \coffin_wd:N \l_ducksay_bubble_top_coffin - - \coffin_wd:N \l_ducksay_msg_coffin - ) / 2 - } - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { l } { vc } - \l_ducksay_bubble_open_coffin { r } { vc } - { - \l_ducksay_hpad_dim } { \c_zero_dim } - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { r } { vc } - \l_ducksay_bubble_close_coffin { l } { vc } - { \l_ducksay_hpad_dim } { \c_zero_dim } - \ducksay_set_bubble_top_kern: - \ducksay_set_bubble_bottom_kern: - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { hc } { t } - \l_ducksay_bubble_top_coffin { hc } { b } - { \c_zero_dim } { \l_ducksay_bubble_top_kern_dim } - \coffin_join:NnnNnnnn - \l_ducksay_msg_coffin { hc } { b } - \l_ducksay_bubble_top_coffin { hc } { t } - { \c_zero_dim } { \l_ducksay_bubble_bottom_kern_dim } - \bool_if:NF \l_ducksay_no_body_bool - { \bool_if:NTF \l_ducksay_ignored_body_bool { \coffin_attach:NVnNVnnn } { \coffin_join:NVnNVnnn } @@ -485,22 +499,14 @@ \cs_generate_variant:Nn \coffin_join:NnnNnnnn { NVnNVnnn } \cs_generate_variant:Nn \coffin_attach:NnnNnnnn { NVnNVnnn } \cs_generate_variant:Nn \coffin_typeset:Nnnnn { NVVnn } -\cs_generate_variant:Nn \tl_if_eq:nnT { VnT } \cs_generate_variant:Nn \str_case:nn { Vn } -\cs_generate_variant:Nn \regex_replace_all:NnN { Nnc } \NewDocumentCommand \ducksay { O{} } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { say } - \ducksay_digest_options:n { #1 } - \ducksay_eat_argument:w + \ducksay_digest_options:n { #1 } } \NewDocumentCommand \duckthink { O{} } { - \group_begin: - \tl_set:Nn \l_ducksay_say_or_think_tl { think } - \ducksay_digest_options:n { #1 } - \ducksay_eat_argument:w + \ducksay_digest_options:n { think, #1 } } %% %% diff --git a/Master/texmf-dist/tex/latex/ducksay/ducksay.sty b/Master/texmf-dist/tex/latex/ducksay/ducksay.sty index 6d140038d95..98d096c4175 100644 --- a/Master/texmf-dist/tex/latex/ducksay/ducksay.sty +++ b/Master/texmf-dist/tex/latex/ducksay/ducksay.sty @@ -35,8 +35,8 @@ \NeedsTeXFormat{LaTeX2e} \RequirePackage{xparse,l3keys2e} -\def\ducksay@version{2.2.1} -\def\ducksay@date{2019-01-08} +\def\ducksay@version{2.3} +\def\ducksay@date{2019-01-13} \ProvidesExplPackage {ducksay} {\ducksay@date} @@ -44,22 +44,20 @@ \int_new:N \l_ducksay_msg_width_int \int_new:N \l_ducksay_msg_height_int +\int_new:N \l_ducksay_tail_symbol_count_int \seq_new:N \l_ducksay_msg_lines_seq -\tl_new:N \l_ducksay_say_or_think_tl \tl_new:N \l_ducksay_align_tl \tl_new:N \l_ducksay_msg_align_tl \tl_new:N \l_ducksay_animal_tl \tl_new:N \l_ducksay_body_tl \tl_new:N \l_ducksay_bubble_tl \tl_new:N \l_ducksay_tmpa_tl -\bool_new:N \l_ducksay_also_add_think_bool +\tl_new:N \l_ducksay_tail_symbol_out_one_tl +\tl_new:N \l_ducksay_tail_symbol_out_two_tl +\tl_new:N \l_ducksay_tail_symbol_in_tl \bool_new:N \l_ducksay_version_one_bool \bool_new:N \l_ducksay_version_two_bool \box_new:N \l_ducksay_tmpa_box -\regex_const:Nn \c_ducksay_first_regex { \A(.\s*)\\ } -\regex_const:Nn \c_ducksay_second_regex { \A(.[^\c{null}]*\c{null}\s*)\\ } -\regex_const:Nn \c_ducksay_third_regex { - \A(.[^\c{null}]*\c{null}[^\c{null}]*\c{null}\s*)\\ } \regex_const:Nn \c_ducksay_textcolor_regex { \cO(?:\\textcolor\{(.*?)\}\{(.*?)\}) } \regex_const:Nn \c_ducksay_color_delim_regex @@ -68,6 +66,8 @@ { \cO(?:\\color\{(.*?)\}) } \msg_new:nnn { ducksay } { load-time-only } { The~`#1`~key~is~to~be~used~only~during~package~load~time. } +\msg_new:nnn { ducksay } { deprecated-key } + { The~`\l_keys_key_tl`~key~is~deprecated.~Sorry~for~the~inconvenience. } \keys_define:nn { ducksay } { ,bubble .tl_set:N = \l_ducksay_bubble_tl @@ -91,7 +91,17 @@ ,rel-align .value_required:n = true ,ligatures .tl_set:N = \l_ducksay_ligatures_tl ,ligatures .initial:n = { `<>,'- } - ,add-think .bool_set:N = \l_ducksay_also_add_think_bool + ,tail-1 .tl_set:N = \l_ducksay_tail_symbol_out_one_tl + ,tail-1 .initial:x = \c_backslash_str + ,tail-2 .tl_set:N = \l_ducksay_tail_symbol_out_two_tl + ,tail-2 .initial:x = \c_backslash_str + ,no-tail .meta:n = { tail-1 = { ~ }, tail-2 = { ~ } } + ,think .meta:n = { tail-1 = { O }, tail-2 = { o } } + ,say .code:n = + { + \exp_args:Nx \DucksayOptions + { tail-1 = { \c_backslash_str }, tail-2 = { \c_backslash_str } } + } ,version .choice: ,version / 1 .code:n = { @@ -104,23 +114,23 @@ \bool_set_true:N \l_ducksay_version_two_bool } ,version .initial:n = 2 + ,add-think .code:n = \msg_error:nn { ducksay } { deprecated-key } } \ProcessKeysOptions { ducksay } \keys_define:nn { ducksay } { version .code:n = \msg_error:nnn { ducksay } { load-time-only } { version } } -\cs_generate_variant:Nn \tl_if_eq:nnT { VnT } -\cs_new_protected:Npn \ducksay_create_think_animal:n #1 +\keys_define:nn { ducksay / add-animal } { - \group_begin: - \tl_set_eq:Nc \l_ducksay_tmpa_tl { g_ducksay_animal_say_#1_tl } - \regex_replace_once:NnN \c_ducksay_first_regex { \1O } \l_ducksay_tmpa_tl - \regex_replace_once:NnN \c_ducksay_second_regex { \1o } \l_ducksay_tmpa_tl - \regex_replace_once:NnN \c_ducksay_third_regex { \1o } \l_ducksay_tmpa_tl - \tl_gset_eq:cN { g_ducksay_animal_think_#1_tl } \l_ducksay_tmpa_tl - \group_end: + ,tail-symbol .code:n = + \tl_set:Nx \l_ducksay_tail_symbol_in_tl { \tl_to_str:n { #1 } } + ,tail-symbol .initial:o = \c_backslash_str + ,tail-count .int_set:N = \l_ducksay_tail_symbol_count_int + ,tail-count .initial:n = 2 } +\cs_generate_variant:Nn \tl_replace_once:Nnn { NVn } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NVn } \cs_new_protected:Npx \ducksay_replace_verb_newline:Nn #1 #2 { \tl_replace_all:Nnn #1 { \char_generate:nn { 13 } { 12 } } { #2 } @@ -136,25 +146,63 @@ \ducksay_replace_verb_newline_newline:Nn \ProcessedArgument { #2 } \ducksay_replace_verb_newline:Nn \ProcessedArgument { #1 } } -\cs_new_protected:Npn \ducksay_add_animal_inner:nn #1 #2 +\cs_new_protected:Npn \ducksay_add_animal_inner:nnnn #1 #2 #3 #4 { - \tl_set:Nn \l_ducksay_tmpa_tl { \ #2 } - \tl_map_inline:Nn \l_ducksay_ligatures_tl - { \tl_replace_all:Nnn \l_ducksay_tmpa_tl { ##1 } { { ##1 } } } - \ducksay_replace_verb_newline:Nn \l_ducksay_tmpa_tl { \tabularnewline\null } - \tl_gset_eq:cN { g_ducksay_animal_say_#1_tl } \l_ducksay_tmpa_tl - \keys_define:nn { ducksay } + \group_begin: + \keys_set:nn { ducksay / add-animal } { #1 } + \tl_set:Nn \l_ducksay_tmpa_tl { \ #3 } + \int_compare:nNnTF { \l_ducksay_tail_symbol_count_int } < { \c_zero_int } + { + \tl_replace_once:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_one_tl + \tl_replace_all:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_two_tl + } + { + \int_compare:nNnT { \l_ducksay_tail_symbol_count_int } > + { \c_zero_int } + { + \tl_replace_once:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_one_tl + \int_step_inline:nnn { 2 } { \l_ducksay_tail_symbol_count_int } + { + \tl_replace_once:NVn + \l_ducksay_tmpa_tl + \l_ducksay_tail_symbol_in_tl + \l_ducksay_tail_symbol_out_two_tl + } + } + } + \tl_map_inline:Nn \l_ducksay_ligatures_tl + { \tl_replace_all:Nnn \l_ducksay_tmpa_tl { ##1 } { { ##1 } } } + \ducksay_replace_verb_newline:Nn \l_ducksay_tmpa_tl + { \tabularnewline\null } + \exp_args:NNnV + \group_end: + \tl_set:cn { l_ducksay_animal_#2_tl } \l_ducksay_tmpa_tl + \exp_args:Nnx \keys_define:nn { ducksay } { - #1 .code:n = + #2 .code:n = { - \tl_if_exist:cF - { g_ducksay_animal_ \l_ducksay_say_or_think_tl _#1_tl } - { \ducksay_create_think_animal:n { #1 } } - \tl_set_eq:Nc \l_ducksay_animal_tl - { g_ducksay_animal_ \l_ducksay_say_or_think_tl _#1_tl } + \exp_not:n { \tl_set_eq:NN \l_ducksay_animal_tl } + \exp_after:wN \exp_not:N \cs:w l_ducksay_animal_#2_tl \cs_end: + \exp_not:n { \exp_args:NV \DucksayOptions } + \exp_after:wN + \exp_not:N \cs:w l_ducksay_animal_#2_options_tl \cs_end: } } + \tl_if_exist:cF { l_ducksay_animal_#2_options_tl } + { \tl_new:c { l_ducksay_animal_#2_options_tl } } + \IfBooleanT { #4 } + { \keys_define:nn { ducksay } { default_animal .meta:n = { #2 } } } } +\cs_generate_variant:Nn \ducksay_add_animal_inner:nnnn { nnVn } \NewDocumentCommand \DefaultAnimal { m } { \keys_define:nn { ducksay } { default_animal .meta:n = { #1 } } @@ -163,30 +211,34 @@ { \keys_set:nn { ducksay } { #1 } } -\NewDocumentCommand \AddAnimal { s m +v } +\NewDocumentCommand \AddAnimal { s O{} m +v } { - \ducksay_add_animal_inner:nn { #2 } { #3 } - \bool_if:NT \l_ducksay_also_add_think_bool - { \ducksay_create_think_animal:n { #2 } } - \IfBooleanT{#1} - { \keys_define:nn { ducksay } { default_animal .meta:n = { #2 } } } + \ducksay_add_animal_inner:nnnn { #2 } { #3 } { #4 } { #1 } } -\NewDocumentCommand \AddColoredAnimal { s m +v } +\NewDocumentCommand \AddColoredAnimal { s O{} m +v } { - \ducksay_add_animal_inner:nn { #2 } { #3 } - \regex_replace_all:Nnc \c_ducksay_color_delim_regex + \tl_set:Nn \l_ducksay_tmpa_tl { #4 } + \regex_replace_all:NnN \c_ducksay_color_delim_regex { \c{bgroup}\c{color}\cB\{\1\cE\}\2\c{egroup} } - { g_ducksay_animal_say_#2_tl } - \regex_replace_all:Nnc \c_ducksay_color_regex + \l_ducksay_tmpa_tl + \regex_replace_all:NnN \c_ducksay_color_regex { \c{color}\cB\{\1\cE\} } - { g_ducksay_animal_say_#2_tl } - \regex_replace_all:Nnc \c_ducksay_textcolor_regex + \l_ducksay_tmpa_tl + \regex_replace_all:NnN \c_ducksay_textcolor_regex { \c{textcolor}\cB\{\1\cE\}\cB\{\2\cE\} } - { g_ducksay_animal_say_#2_tl } - \bool_if:NT \l_ducksay_also_add_think_bool - { \ducksay_create_think_animal:n { #2 } } - \IfBooleanT{#1} - { \keys_define:nn { ducksay } { default_animal .meta:n = { #2 } } } + \l_ducksay_tmpa_tl + \ducksay_add_animal_inner:nnVn { #2 } { #3 } \l_ducksay_tmpa_tl { #1 } + } +\NewDocumentCommand \AnimalOptions { s m m } + { + \tl_if_exist:cTF { l_ducksay_animal_#2_options_tl } + { + \IfBooleanTF { #1 } + { \tl_set:cn } + { \tl_put_right:cn } + } + { \tl_set:cn } + { l_ducksay_animal_#2_options_tl } { #3, } } \bool_if:NT \l_ducksay_version_one_bool { \file_input:n { ducksay.code.v1.tex } } |