%% %% This is file `ducksay.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% ducksay.dtx (with options: `pkg') %% %% -------------------------------------------------------------- %% ducksay -- cowsay for LaTeX %% 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) 2017-2022 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 ducksay.dtx %% and the derived files ducksay.pdf %% ducksay.sty %% ducksay.code.v1.tex %% ducksay.code.v2.tex and %% ducksay.animals.tex. %% \NeedsTeXFormat{LaTeX2e} \@ifundefined{NewDocumentCommand}{\RequirePackage{xparse}}{} \def\ducksay@version{2.7} \def\ducksay@date{2024-03-29} \ProvidesExplPackage {ducksay} {\ducksay@date} {\ducksay@version} {cowsay for LaTeX} \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 \seq_new:N \l_ducksay_defined_animals_seq \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 \bool_new:N \l_ducksay_version_one_bool \bool_new:N \l_ducksay_version_two_bool \bool_new:N \l_ducksay_random_animal_bool \box_new:N \l_ducksay_tmpa_box \regex_const:Nn \c_ducksay_textcolor_regex { \cO(?:\\textcolor\{(.*?)\}\{(.*?)\}) } \regex_const:Nn \c_ducksay_color_delim_regex { \cO(?:\\bgroup\\color\{(.*?)\}(.*)\\egroup) } \regex_const:Nn \c_ducksay_color_regex { \cO(?:\\color\{(.*?)\}) } \msg_new:nnn { ducksay } { load-time-only } { The~`#1`~key~is~to~be~used~only~during~package~load~time. } \keys_define:nn { ducksay } { ,bubble .tl_set:N = \l_ducksay_bubble_tl ,body .tl_set:N = \l_ducksay_body_tl ,align .tl_set:N = \l_ducksay_align_tl ,align .value_required:n = true ,wd .int_set:N = \l_ducksay_msg_width_int ,wd .initial:n = -\c_max_int ,wd .value_required:n = true ,ht .int_set:N = \l_ducksay_msg_height_int ,ht .initial:n = -\c_max_int ,ht .value_required:n = true ,animal .code:n = { \keys_define:nn { ducksay } { default_animal .meta:n = { #1 } } } ,animal .initial:n = duck ,msg-align .tl_set:N = \l_ducksay_msg_align_tl ,msg-align .initial:n = l ,msg-align .value_required:n = true ,rel-align .tl_set:N = \l_ducksay_rel_align_tl ,rel-align .initial:n = l ,rel-align .value_required:n = true ,ligatures .tl_set:N = \l_ducksay_ligatures_tl ,ligatures .initial:n = { `<>,'- } ,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 } } ,random .bool_set:N = \l_ducksay_random_animal_bool ,say .code:n = { \exp_args:Nx \DucksayOptions { tail-1 = { \c_backslash_str }, tail-2 = { \c_backslash_str } } } ,schroedinger .code:n = { \int_compare:nNnTF { \int_rand:n { 2 } } = \c_one_int { \keys_set:nn { ducksay } { animal = schroedinger-dead } } { \keys_set:nn { ducksay } { animal = schroedinger-alive } } } ,schroedinger .value_forbidden:n = true ,version .choice: ,version / 1 .code:n = { \bool_set_false:N \l_ducksay_version_two_bool \bool_set_true:N \l_ducksay_version_one_bool } ,version / 2 .code:n = { \bool_set_false:N \l_ducksay_version_one_bool \bool_set_true:N \l_ducksay_version_two_bool } ,version .initial:n = 2 } \cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions [ ducksay ] } { \RequirePackage { l3keys2e } \ProcessKeysOptions { ducksay } } \keys_define:nn { ducksay } { version .code:n = \msg_error:nnn { ducksay } { load-time-only } { version } } \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 } \cs_generate_variant:Nn \tl_replace_once:Nnn { NVn } \cs_generate_variant:Nn \tl_replace_all:Nnn { NVn } \cs_generate_variant:Nn \keys_set:nn { nx } \cs_set_eq:NN \__ducksay_everyeof:w \tex_everyeof:D \cs_set_eq:NN \__ducksay_scantokens:w \tex_scantokens:D \IfFormatAtLeastTF{2024-06-01} { \cs_new_protected:Npn \ducksay_replace_verb_newline:Nn #1 #2 { \tl_replace_all:Nnn #1 \obeyedline {#2} } } { \cs_new_protected:Npx \ducksay_replace_verb_newline:Nn #1 #2 { \tl_replace_all:Nnn #1 { \char_generate:nn { 13 } { 12 } } {#2} } } \IfFormatAtLeastTF{2024-06-01} { \cs_new_protected:Npn \ducksay_replace_verb_newline_newline:Nn #1 #2 { \tl_replace_all:Nnn #1 { \obeyedline \obeyedline } {#2} } } { \cs_new_protected:Npx \ducksay_replace_verb_newline_newline:Nn #1 #2 { \tl_replace_all:Nnn #1 { \char_generate:nn { 13 } { 12 } \char_generate:nn { 13 } { 12 } } {#2} } } \cs_new_protected:Npn \ducksay_process_verb_newline:nnn #1 #2 #3 { \tl_set:Nn \ProcessedArgument { #3 } \ducksay_replace_verb_newline_newline:Nn \ProcessedArgument { #2 } \ducksay_replace_verb_newline:Nn \ProcessedArgument { #1 } } \cs_new_protected:Npn \ducksay_add_animal_inner:nnnn #1 #2 #3 #4 { \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 } { #2 .code:n = { \exp_not:n { \tl_set_eq:NN \l_ducksay_animal_tl } \exp_not:c { l_ducksay_animal_#2_tl } \exp_not:n { \exp_args:NV \DucksayOptions } \exp_not:c { l_ducksay_animal_#2_options_tl } } } \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 } } } \seq_if_in:NnF \l_ducksay_defined_animals_seq { #2 } { \seq_push:Nn \l_ducksay_defined_animals_seq { #2 } } } \cs_generate_variant:Nn \ducksay_add_animal_inner:nnnn { nnVn } \cs_new_protected:Npn \ducksay_default_or_random_animal: { \tl_if_empty:NT \l_ducksay_animal_tl { \bool_if:NTF \l_ducksay_random_animal_bool { \keys_set:nx { ducksay } { \seq_rand_item:N \l_ducksay_defined_animals_seq } } { \keys_set:nn { ducksay } { default_animal } } } } \NewDocumentCommand \DefaultAnimal { m } { \keys_define:nn { ducksay } { default_animal .meta:n = { #1 } } } \NewDocumentCommand \DucksayOptions { m } { \keys_set:nn { ducksay } { #1 } } \NewDocumentCommand \AddAnimal { s O{} m +v } { \ducksay_add_animal_inner:nnnn { #2 } { #3 } { #4 } { #1 } } \NewDocumentCommand \AddColoredAnimal { s O{} m +v } { \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} } \l_ducksay_tmpa_tl \regex_replace_all:NnN \c_ducksay_color_regex { \c{color}\cB\{\1\cE\} } \l_ducksay_tmpa_tl \regex_replace_all:NnN \c_ducksay_textcolor_regex { \c{textcolor}\cB\{\1\cE\}\cB\{\2\cE\} } \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 } } \bool_if:NT \l_ducksay_version_two_bool { \file_input:n { ducksay.code.v2.tex } } \ExplSyntaxOff \input{ducksay.animals.tex} %% %% %% End of file `ducksay.sty'.