%% %% This is file `ducksay.code.v2.tex', %% generated with the docstrip utility. %% %% The original source files were: %% %% ducksay.dtx (with options: `code.v2') %% %% -------------------------------------------------------------- %% 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-2020 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. %% \ProvidesFile{ducksay.code.v2.tex} [\ducksay@date\space v\ducksay@version\space ducksay code version 2] \RequirePackage{array,grabbox} \msg_new:nnn { ducksay } { justify~unavailable } { Justified~content~is~not~available~for~tabular~argument~mode~without~fixed~ width.~`l`~column~is~used~instead. } \msg_new:nnn { ducksay } { unknown~message~alignment } { 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 \bool_new:N \l_ducksay_eat_arg_tab_verb_bool \bool_new:N \l_ducksay_mirrored_body_bool \bool_new:N \l_ducksay_msg_eq_body_width_bool \coffin_new:N \l_ducksay_body_coffin \coffin_new:N \l_ducksay_bubble_close_coffin \coffin_new:N \l_ducksay_bubble_open_coffin \coffin_new:N \l_ducksay_bubble_top_coffin \coffin_new:N \l_ducksay_msg_coffin \dim_new:N \l_ducksay_hpad_dim \dim_new:N \l_ducksay_bubble_bottom_kern_dim \dim_new:N \l_ducksay_bubble_top_kern_dim \dim_new:N \l_ducksay_msg_width_dim \keys_define:nn { ducksay } { ,arg .choice: ,arg / box .code:n = \bool_set_true:N \l_ducksay_eat_arg_box_bool ,arg / tab .code:n = { \bool_set_false:N \l_ducksay_eat_arg_box_bool \bool_set_false:N \l_ducksay_eat_arg_tab_verb_bool } ,arg / tab* .code:n = { \bool_set_false:N \l_ducksay_eat_arg_box_bool \bool_set_true:N \l_ducksay_eat_arg_tab_verb_bool } ,arg .initial:n = tab ,wd* .dim_set:N = \l_ducksay_msg_width_dim ,wd* .initial:n = -\c_max_dim ,wd* .value_required:n = true ,wd-eq-body .bool_set:N = \l_ducksay_msg_eq_body_width_bool ,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 ,body-x .value_required:n = true ,body-y .dim_set:N = \l_ducksay_body_y_offset_dim ,body-y .value_required:n = true ,body-to-msg .tl_set:N = \l_ducksay_body_to_msg_align_body_tl ,msg-to-body .tl_set:N = \l_ducksay_body_to_msg_align_msg_tl ,body-align .choice: ,body-align / l .meta:n = { body-to-msg = l , msg-to-body = l } ,body-align / c .meta:n = { body-to-msg = hc , msg-to-body = hc } ,body-align / r .meta:n = { body-to-msg = r , msg-to-body = r } ,body-align .initial:n = l ,body-bigger .int_set:N = \l_ducksay_body_bigger_int ,body-bigger .initial:n = \c_zero_int ,msg-align .choice: ,msg-align / l .code:n = { \tl_set:Nn \l_ducksay_msg_align_tl { l } } ,msg-align / c .code:n = { \tl_set:Nn \l_ducksay_msg_align_tl { c } } ,msg-align / r .code:n = { \tl_set:Nn \l_ducksay_msg_align_tl { r } } ,msg-align / j .code:n = { \tl_set:Nn \l_ducksay_msg_align_tl { j } } ,msg-align-l .tl_set:N = \l_ducksay_msg_align_l_tl ,msg-align-l .initial:n = \raggedright ,msg-align-c .tl_set:N = \l_ducksay_msg_align_c_tl ,msg-align-c .initial:n = \centering ,msg-align-r .tl_set:N = \l_ducksay_msg_align_r_tl ,msg-align-r .initial:n = \raggedleft ,msg-align-j .tl_set:N = \l_ducksay_msg_align_j_tl ,msg-align-j .initial:n = {} ,out-h .tl_set:N = \l_ducksay_output_h_pole_tl ,out-h .initial:n = l ,out-v .tl_set:N = \l_ducksay_output_v_pole_tl ,out-v .initial:n = vc ,out-x .dim_set:N = \l_ducksay_output_x_offset_dim ,out-x .value_required:n = true ,out-y .dim_set:N = \l_ducksay_output_y_offset_dim ,out-y .value_required:n = true ,t .meta:n = { out-v = t } ,c .meta:n = { out-v = vc } ,b .meta:n = { out-v = b } ,body* .tl_set:N = \l_ducksay_body_fount_tl ,msg* .tl_set:N = \l_ducksay_msg_fount_tl ,bubble* .tl_set:N = \l_ducksay_bubble_fount_tl ,body* .initial:n = \verbatim@font ,msg* .initial:n = \verbatim@font ,bubble* .initial:n = \verbatim@font ,body .code:n = \tl_put_right:Nn \l_ducksay_body_fount_tl { #1 } ,msg .code:n = \tl_put_right:Nn \l_ducksay_msg_fount_tl { #1 } ,bubble .code:n = \tl_put_right:Nn \l_ducksay_bubble_fount_tl { #1 } ,MSG .meta:n = { msg = #1 , bubble = #1 } ,MSG* .meta:n = { msg* = #1 , bubble* = #1 } ,hpad .int_set:N = \l_ducksay_hpad_int ,hpad .initial:n = 2 ,hpad .value_required:n = true ,vpad .int_set:N = \l_ducksay_vpad_int ,vpad .value_required:n = true ,col .tl_set:N = \l_ducksay_msg_tabular_column_tl ,bubble-top-kern .tl_set:N = \l_ducksay_bubble_top_kern_tl ,bubble-top-kern .initial:n = { -.5ex } ,bubble-top-kern .value_required:n = true ,bubble-bot-kern .tl_set:N = \l_ducksay_bubble_bottom_kern_tl ,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 = { .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 ,bubble-delim-left-2 .tl_set:N = \l_ducksay_bubble_delim_left_b_tl ,bubble-delim-left-3 .tl_set:N = \l_ducksay_bubble_delim_left_c_tl ,bubble-delim-left-4 .tl_set:N = \l_ducksay_bubble_delim_left_d_tl ,bubble-delim-right-1 .tl_set:N = \l_ducksay_bubble_delim_right_a_tl ,bubble-delim-right-2 .tl_set:N = \l_ducksay_bubble_delim_right_b_tl ,bubble-delim-right-3 .tl_set:N = \l_ducksay_bubble_delim_right_c_tl ,bubble-delim-right-4 .tl_set:N = \l_ducksay_bubble_delim_right_d_tl ,bubble-delim-top .initial:n = { { - } } ,bubble-delim-left-1 .initial:n = ( ,bubble-delim-left-2 .initial:n = / ,bubble-delim-left-3 .initial:n = | ,bubble-delim-left-4 .initial:n = \c_backslash_str ,bubble-delim-right-1 .initial:n = ) ,bubble-delim-right-2 .initial:n = \c_backslash_str ,bubble-delim-right-3 .initial:n = | ,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 { { l } { \exp_not:N \l_ducksay_msg_align_l_tl } { c } { \exp_not:N \l_ducksay_msg_align_c_tl } { r } { \exp_not:N \l_ducksay_msg_align_r_tl } { j } { \exp_not:N \l_ducksay_msg_align_j_tl } } } \cs_new:Npn \ducksay_evaluate_message_alignment_fixed_width_tabular: { \tl_if_empty:NT \l_ducksay_msg_tabular_column_tl { \tl_set:Nx \l_ducksay_msg_tabular_column_tl { > { \ducksay_evaluate_message_alignment_fixed_width_common: \exp_not:N \arraybackslash } p { \exp_not:N \l_ducksay_msg_width_dim } } } } \cs_new:Npn \ducksay_evaluate_message_alignment_fixed_width_vbox: { \tl_set:Nx \l_ducksay_msg_align_vbox_tl { \ducksay_evaluate_message_alignment_fixed_width_common: } } \cs_new:Npn \ducksay_calculate_msg_width_from_int: { \hbox_set:Nn \l_ducksay_tmpa_box { { \l_ducksay_msg_fount_tl M } } \dim_set:Nn \l_ducksay_msg_width_dim { \l_ducksay_msg_width_int \box_wd:N \l_ducksay_tmpa_box } } \cs_new:Npn \ducksay_msg_tabular_begin: { \ducksay_msg_tabular_begin_inner:V \l_ducksay_msg_tabular_column_tl } \cs_new:Npn \ducksay_msg_tabular_begin_inner:n #1 { \begin { tabular } { @{} #1 @{} } } \cs_generate_variant:Nn \ducksay_msg_tabular_begin_inner:n { V } \cs_new:Npn \ducksay_msg_tabular_end: { \end { tabular } } \cs_new:Npn \ducksay_width_case_none_int_dim:nnn #1 #2 #3 { \dim_compare:nNnTF { \l_ducksay_msg_width_dim } < { \c_zero_dim } { \int_compare:nNnTF { \l_ducksay_msg_width_int } < { \c_zero_int } { #1 } { #2 } } { #3 } } \cs_new:Npn \ducksay_digest_options:n #1 { \group_begin: \keys_set:nn { ducksay } { #1 } \ducksay_default_or_random_animal: \bool_if:NF \l_ducksay_no_body_bool { \hcoffin_set:Nn \l_ducksay_body_coffin { \frenchspacing \l_ducksay_body_fount_tl \begin{tabular} { @{} l @{} } \l_ducksay_animal_tl \ducksay_make_body_bigger: \relax \end{tabular} } \bool_if:NT \l_ducksay_msg_eq_body_width_bool { \bool_lazy_and:nnT { \int_compare_p:nNn \l_ducksay_msg_width_int < \c_zero_int } { \dim_compare_p:nNn \l_ducksay_msg_width_dim < \c_zero_dim } { \dim_set:Nn \l_ducksay_msg_width_dim { \coffin_wd:N \l_ducksay_body_coffin } } } } \bool_if:NTF \l_ducksay_eat_arg_box_bool { \ducksay_width_case_none_int_dim:nnn { \ducksay_eat_argument_hbox:w } { \ducksay_calculate_msg_width_from_int: \ducksay_eat_argument_vbox:w } { \ducksay_eat_argument_vbox:w } } { \ducksay_width_case_none_int_dim:nnn { \tl_if_empty:NT \l_ducksay_msg_tabular_column_tl { \str_case:Vn \l_ducksay_msg_align_tl { { l } { \tl_set:Nn \l_ducksay_msg_tabular_column_tl { l } } { c } { \tl_set:Nn \l_ducksay_msg_tabular_column_tl { c } } { r } { \tl_set:Nn \l_ducksay_msg_tabular_column_tl { r } } { j } { \msg_error:nn { ducksay } { justify~unavailable } \tl_set:Nn \l_ducksay_msg_tabular_column_tl { l } } } } } { \ducksay_calculate_msg_width_from_int: \ducksay_evaluate_message_alignment_fixed_width_tabular: } { \ducksay_evaluate_message_alignment_fixed_width_tabular: } \ducksay_eat_argument_tabular:w } } \cs_new:Npn \ducksay_set_bubble_top_kern: { \group_begin: \l_ducksay_bubble_fount_tl \exp_args:NNNx \group_end: \dim_set:Nn \l_ducksay_bubble_top_kern_dim { \dim_eval:n { \l_ducksay_bubble_top_kern_tl } } } \cs_new:Npn \ducksay_set_bubble_bottom_kern: { \group_begin: \l_ducksay_bubble_fount_tl \exp_args:NNNx \group_end: \dim_set:Nn \l_ducksay_bubble_bottom_kern_dim { \dim_eval:n { \l_ducksay_bubble_bottom_kern_tl } } } \cs_new:Npn \ducksay_make_body_bigger: { \int_step_function:nN \l_ducksay_body_bigger_int \ducksay_make_body_bigger_aux:n } \cs_new:Npn \ducksay_make_body_bigger_aux:n #1 { \\ } \cs_new_protected:Npn \ducksay_shipout: { \hcoffin_set:Nn \l_ducksay_msg_coffin { \box_use:N \l_ducksay_msg_box } \bool_if:NF \l_ducksay_no_bubble_bool { \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 { \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 } { \l_ducksay_bubble_delim_left_a_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 } \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 } } \bool_if:NF \l_ducksay_no_body_bool { \bool_if:NT \l_ducksay_mirrored_body_bool { \coffin_scale:Nnn \l_ducksay_body_coffin { -\c_one_int } { \c_one_int } \str_case:Vn \l_ducksay_body_to_msg_align_body_tl { { l } { \tl_set:Nn \l_ducksay_body_to_msg_align_body_tl { r } } { r } { \tl_set:Nn \l_ducksay_body_to_msg_align_body_tl { l } } } } \bool_if:NTF \l_ducksay_ignored_body_bool { \coffin_attach:NVnNVnnn } { \coffin_join:NVnNVnnn } \l_ducksay_msg_coffin \l_ducksay_body_to_msg_align_msg_tl { b } \l_ducksay_body_coffin \l_ducksay_body_to_msg_align_body_tl { t } { \l_ducksay_body_x_offset_dim } { \l_ducksay_body_y_offset_dim } } \coffin_typeset:NVVnn \l_ducksay_msg_coffin \l_ducksay_output_h_pole_tl \l_ducksay_output_v_pole_tl { \l_ducksay_output_x_offset_dim } { \l_ducksay_output_y_offset_dim } \group_end: } \cs_new:Npn \ducksay_eat_argument_tabular:w { \bool_if:NTF \l_ducksay_eat_arg_tab_verb_bool { \ducksay_eat_argument_tabular_verb:w } { \ducksay_eat_argument_tabular_normal:w } } \cs_new:Npn \ducksay_eat_argument_tabular_inner:w #1 { \hbox_set:Nn \l_ducksay_msg_box { \l_ducksay_msg_fount_tl \ducksay_msg_tabular_begin: #1 \ducksay_msg_tabular_end: } \ducksay_shipout: } \NewDocumentCommand \ducksay_eat_argument_tabular_verb:w { >{ \ducksay_process_verb_newline:nnn { ~ } { ~ \par } } +v } { \ducksay_eat_argument_tabular_inner:w { \group_begin: \__ducksay_everyeof:w { \exp_not:N } \exp_after:wN \group_end: \__ducksay_scantokens:w { #1 } } } \NewDocumentCommand \ducksay_eat_argument_tabular_normal:w { +m } { \ducksay_eat_argument_tabular_inner:w { #1 } } \cs_new_protected_nopar:Npn \ducksay_eat_argument_hbox:w { \bool_if:NTF \l_ducksay_msg_strip_spaces_bool { \@grabbox } { \@grabbox* } {} \l_ducksay_msg_box \l_ducksay_msg_fount_tl \hbox {} \ducksay_shipout: } \cs_new_protected_nopar:Npn \ducksay_eat_argument_vbox:w { \ducksay_evaluate_message_alignment_fixed_width_vbox: \bool_if:NTF \l_ducksay_msg_strip_spaces_bool { \@grabbox } { \@grabbox* } { \hsize \l_ducksay_msg_width_dim \linewidth \hsize \l_ducksay_msg_align_vbox_tl \@afterindentfalse \@afterheading } \l_ducksay_msg_box \l_ducksay_msg_fount_tl \vbox {} \ducksay_shipout: } \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 \str_case:nn { Vn } \NewDocumentCommand \ducksay { O{} } { \ducksay_digest_options:n { #1 } } \NewDocumentCommand \duckthink { O{} } { \ducksay_digest_options:n { think, #1 } } %% %% %% End of file `ducksay.code.v2.tex'.