%%%==============================================================================
%% Copyright 2023-present by Alceu Frigeri
%%
%% This work may be distributed and/or modified under the conditions of
%%
%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
%%   version 1.3c (or later), and/or
%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
%%   version 3 (or later)
%%
%% This work has the LPPL maintenance status *maintained*.
%%
%% The Current Maintainer of this work is Alceu Frigeri
%%
%% This is version {{1.16}} {2025/10/23}
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/codedescribe
%%
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2022/06/01]

\ProvidesExplPackage
    {codedescribe}
    {2025/10/23}
    {{1.16}}
    {LaTeX Code Description/Documentation}

%%%%%%%
%%%
%%% Just an attempt of having my packages info in a regular way
%%% \pkginfograb_set:nn {<pkg-name>} { props} for each and all.
%%%
%%%%%%%
\RequirePackage{pkginfograb}
\pkginfograb_set:nn { codedescribe}
  {
     name        = {codedescribe} ,
     prefix      = {codedesc} ,
     date        = {2025/10/23} ,
     version     = {{1.16}} ,
     description = {\LaTeX~Code~Description/Documentation}
  }
%%%%%%%
%%% End of cut-n-paste
%%%%%%%

\use:c {@reversemargintrue}


%% bbding is need for those hollow stars...
\RequirePackage{xcolor}
\RequirePackage{pifont}
\RequirePackage{xpeekahead}



\bool_new:N \l__codedesc_loadlisting_bool
\bool_set_true:N \l__codedesc_loadlisting_bool

%% instead of using expl scratch variables.
\tl_new:N \l__codedesc_tmpa_tl
\tl_new:N \l__codedesc_tmpb_tl
\seq_new:N \l__codedesc_tmpa_seq
\seq_new:N \l__codedesc_tmpb_seq
\coffin_new:N \l__codedesc_tmpa_coffin
\coffin_new:N \l__codedesc_tmpb_coffin
\fp_new:N \l__codedesc_tmpa_fp
\fp_new:N \l__codedesc_tmpb_fp


%
% Those skips are meant to be small adjustments
%
\cs_generate_variant:Nn \skip_set:Nn {Ne}
\cs_generate_variant:Nn \dim_set:Nn  {Ne}  

\tl_new:N \l__codedesc_ref_tl
\skip_new:N \l__codedesc_null_skip
\skip_new:N \l__codedesc_tiny_skip
\skip_new:N \l__codedesc_small_skip
\skip_new:N \l__codedesc_mid_skip
\skip_new:N \l__codedesc_large_skip
\skip_new:N \l__codedesc_larger_skip
\skip_new:N \l__codedesc_largeline_skip
\skip_new:N \l__codedesc_neg_skip
\skip_new:N \l__codedesc_bigneg_skip
\skip_new:N \l__codedesc_min_skip

\dim_new:N \l__codedesc_tinyskip_dim
\dim_new:N \l__codedesc_nullskip_dim
\dim_new:N \l__codedesc_smallskip_dim
\dim_new:N \l__codedesc_midskip_dim
\dim_new:N \l__codedesc_largeskip_dim
\dim_new:N \l__codedesc_largerskip_dim
\dim_new:N \l__codedesc_baselineskip_dim
\dim_new:N \l__codedesc_largelineskip_dim
\dim_new:N \l__codedesc_coffinskip_dim

%\dim_new:N \l__codedesc_baselineskip_dim
\dim_new:N \l__codedesc_midlineskip_dim
%\dim_new:N \l__codedesc_largelineskip_dim

\cs_new_protected:Npn \__codedesc_set_skips:n #1 
  {
    \tl_set:Ne \l__codedesc_ref_tl       { \fp_eval:n {#1} pt }
    
    \tl_set:Ne \l__codedesc_minusA_tl    { minus~ \fp_eval:n { #1 * 3 / 50 } pt }
    \tl_set:Ne \l__codedesc_minusB_tl    { minus~ \fp_eval:n { #1     / 8  } pt }
    \tl_set:Ne \l__codedesc_plusA_tl     { plus~  \fp_eval:n { #1     / 5  } pt }
    \tl_set:Ne \l__codedesc_plusB_tl     { plus~  \fp_eval:n { #1 * 8 / 25 } pt }

    \dim_set:Ne \l__codedesc_tinyskip_dim       { \fp_eval:n { #1     / 10 } pt }
    \dim_set:Ne \l__codedesc_smallskip_dim      { \fp_eval:n { #1     / 5  } pt }
    \dim_set:Ne \l__codedesc_midskip_dim        { \fp_eval:n { #1 * 2 / 5  } pt }
    \dim_set:Ne \l__codedesc_coffinskip_dim     { \fp_eval:n { #1 * 2 / 5  } pt } % minimum skip to avoid random spacing
    \dim_set:Ne \l__codedesc_largeskip_dim      { \fp_eval:n { #1     / 2  } pt }
    \dim_set:Ne \l__codedesc_largerskip_dim     { \fp_eval:n { #1 * 3 / 5  } pt }
    \dim_set:Ne \l__codedesc_baselineskip_dim   { \fp_eval:n { #1          } pt }
    \dim_set:Ne  \l__codedesc_midlineskip_dim   { \fp_eval:n { #1     / 2  } pt }
    \dim_set:Ne  \l__codedesc_largelineskip_dim { \fp_eval:n { #1 * 3 / 2  } pt }
      
    \skip_set:Nn \l__codedesc_min_skip   { 0 pt plus 1pt minus 1pt }
     
    \skip_set:Ne \l__codedesc_null_skip       { 0 pt                            \l__codedesc_plusA_tl \l__codedesc_minusA_tl }
    \skip_set:Ne \l__codedesc_tiny_skip       { \l__codedesc_tinyskip_dim       \l__codedesc_plusA_tl \l__codedesc_minusA_tl }
    \skip_set:Ne \l__codedesc_small_skip      { \l__codedesc_smallskip_dim      \l__codedesc_plusA_tl \l__codedesc_minusA_tl }
    \skip_set:Ne \l__codedesc_mid_skip        { \l__codedesc_midskip_dim        \l__codedesc_plusB_tl \l__codedesc_minusB_tl }
    \skip_set:Ne \l__codedesc_large_skip      { \l__codedesc_largeskip_dim      \l__codedesc_plusB_tl \l__codedesc_minusB_tl }
    \skip_set:Ne \l__codedesc_larger_skip     { \l__codedesc_largerskip_dim     \l__codedesc_plusB_tl \l__codedesc_minusB_tl }
    \skip_set:Ne \l__codedesc_largeline_skip  { \l__codedesc_largelineskip_dim      \l__codedesc_plusB_tl \l__codedesc_minusB_tl }
    \skip_set:Ne \l__codedesc_neg_skip        { - \l__codedesc_largeskip_dim    \l__codedesc_plusA_tl \l__codedesc_minusB_tl }
    \skip_set:Ne \l__codedesc_bigneg_skip     { - \l__codedesc_baselineskip_dim \l__codedesc_plusA_tl \l__codedesc_minusB_tl }
  }

\__codedesc_set_skips:n {\f@size}


\cs_new_protected:Npn \__codedesc_set_color_scheme:n #1
  {
    \str_case:nnF {#1}
      {
        {default}
          {
            \colorlet{c__codedesc_none_color}{red!70!black}
          	\colorlet{c__codedesc_verb_color}{ black }
          	\colorlet{c__codedesc_marg_color}{ gray!60!black }
          	\colorlet{c__codedesc_oarg_color}{ gray!90!black }
          	\colorlet{c__codedesc_code_color}{ blue!40!black }
          	\colorlet{c__codedesc_syntax_color}{ blue!60!black }
          	\colorlet{c__codedesc_keyval_color}{ teal!40!black }
          	\colorlet{c__codedesc_options_color}{ green!30!black }
          	\colorlet{c__codedesc_defaultval_color}{ blue!60!black }
          	\colorlet{c__codedesc_env_color}{ green!30!black }
          	\colorlet{c__codedesc_pkg_color}{ green!30!black }
          }
        {black}
          {
            \colorlet{c__codedesc_none_color}{red!70!black}
          	\colorlet{c__codedesc_verb_color}{ black }
          	\colorlet{c__codedesc_marg_color}{ gray!60!black }
          	\colorlet{c__codedesc_oarg_color}{ gray!90!black }
          	\colorlet{c__codedesc_code_color}{ black!40!black }
          	\colorlet{c__codedesc_syntax_color}{ black!60!black }
          	\colorlet{c__codedesc_keyval_color}{ black!40!black }
          	\colorlet{c__codedesc_options_color}{ black!30!black }
          	\colorlet{c__codedesc_defaultval_color}{ black!60!black }
          	\colorlet{c__codedesc_env_color}{ black!30!black }
          	\colorlet{c__codedesc_pkg_color}{ black!30!black }
          }        
        {brighter}
          {
            \colorlet{c__codedesc_none_color}{red!70!black}
          	\colorlet{c__codedesc_verb_color}{ black }
          	\colorlet{c__codedesc_marg_color}{ gray!60!black }
          	\colorlet{c__codedesc_oarg_color}{ gray!90!black }
          	\colorlet{c__codedesc_code_color}{ blue!80!black }
          	\colorlet{c__codedesc_syntax_color}{ blue!90!black }
          	\colorlet{c__codedesc_keyval_color}{ teal!80!black }
          	\colorlet{c__codedesc_options_color}{ green!70!black }
          	\colorlet{c__codedesc_defaultval_color}{ blue!90!black }
          	\colorlet{c__codedesc_env_color}{ green!70!black }
          	\colorlet{c__codedesc_pkg_color}{ green!70!black }
          }
        {darker}
          {
            \colorlet{c__codedesc_none_color}{red!70!black}
          	\colorlet{c__codedesc_verb_color}{ black }
          	\colorlet{c__codedesc_marg_color}{ gray!60!black }
          	\colorlet{c__codedesc_oarg_color}{ gray!90!black }
          	\colorlet{c__codedesc_code_color}{ blue!20!black }
          	\colorlet{c__codedesc_syntax_color}{ blue!20!black }
          	\colorlet{c__codedesc_keyval_color}{ teal!20!black }
          	\colorlet{c__codedesc_options_color}{ green!20!black }
          	\colorlet{c__codedesc_defaultval_color}{ blue!20!black }
          	\colorlet{c__codedesc_env_color}{ green!20!black }
          	\colorlet{c__codedesc_pkg_color}{ green!20!black }
          }
      }
      {  % same as default (at least, should be)
            \colorlet{c__codedesc_none_color}{red!70!black}
          	\colorlet{c__codedesc_verb_color}{ black }
          	\colorlet{c__codedesc_marg_color}{ gray!60!black }
          	\colorlet{c__codedesc_oarg_color}{ gray!90!black }
          	\colorlet{c__codedesc_code_color}{ blue!40!black }
          	\colorlet{c__codedesc_syntax_color}{ blue!60!black }
          	\colorlet{c__codedesc_keyval_color}{ teal!40!black }
          	\colorlet{c__codedesc_options_color}{ green!30!black }
          	\colorlet{c__codedesc_defaultval_color}{ blue!60!black }
          	\colorlet{c__codedesc_env_color}{ green!30!black }
          	\colorlet{c__codedesc_pkg_color}{ green!30!black }
      }
  }

\__codedesc_set_color_scheme:n {default}

\keys_define:nn { codedescribe }
  {
    nolisting .usage:n    = load ,
  	nolisting .bool_set_inverse:N = \l__codedesc_loadlisting_bool ,
    nolisting .default:n  = {true} ,
    
    base~ skip .usage:n   = load ,
    base~ skip .code:n  =
      {
        \__codedesc_set_skips:n {#1}
      } ,
    base~ skip .value_required:n = true ,
    
    color ~ scheme .usage:n = load ,
    color ~ scheme .choices:nn =
      { default , black , brighter , darker }
      {
        \exp_args:NV \__codedesc_set_color_scheme:n \l_keys_choice_tl
      } ,
    color ~ scheme .value_required:n = true ,
  
    strict .usage:n    = load ,
    strict .code:n = 
      {
        \msg_redirect_module:nnn {codedesc}      { warning } { error }
      } ,

    info grab .usage:n    = load ,
  	info grab .bool_set:N = \l__codedesc_infograb_aliases_bool ,
    info grab .default:n  = {true} ,
  }
\ProcessKeyOptions [codedescribe ]

\bool_if:NT \l__codedesc_loadlisting_bool
  { \RequirePackage{codelisting} }

\bool_if:NT \l__codedesc_infograb_aliases_bool
  { \pkginfograb_set_aliases: }

\cs_generate_variant:Nn \tl_set:Nn {Ne}
\cs_generate_variant:Nn \keys_set:nn {ne}
\cs_generate_variant:Nn \keys_define:nn {ne}
\cs_generate_variant:Nn \tl_to_str:n {o , e}
 

\msg_new:nnnn {codedesc} {format-err}
  {
    (ID:#1)~Format~Key~(#2)~not~defined!
  }
  {
    You~tried~to~use~a~non~defined~format~key:#2.
    ~Error~Code~ ID:<#1>.
  }

\msg_new:nnnn {codedesc} {group-err}
  {
    (ID:#1)~Format~group~(#2)~not~defined!
  }
  {
    You~tried~to~use~a~non~defined~format~group:#2.
    ~Error~Code~ ID:<#1>.
  }

\msg_new:nnnn {codedesc} {object-err}
  {
    (ID:#1)~Objetc~Type~(#2)~not~defined!
  }
  {
    You~tried~to~use~a~non~defined~object~type:#2.
    ~Error~Code~ ID:<#1>.
  }

\msg_new:nnnn {codedesc} {nested-env}
  {
    (ID:#1)~You~tried~to~nest~\{#2\}~inside~of~\{#3\}. ~Better~ not.
  }
  {
    You~tried~to~begin~\{#2\}~inside~of~\{#3\}.~ Better~ not.
    ~Error~Code~ ID:<#1>.
  }

\msg_new:nnnn {codedesc} {out of scope}
  {
    (ID:#1)~You~tried~to~use~\{#2\}~outside~of~\{#3\} 
  }
  {
    You~tried~to~use~\{#2\}~outside~of~\{#3\}.
    ~Error~Code~ ID:<#1>.
  }


\msg_new:nnnn {codedesc} {syntax dup}
  {
    (ID:#1)~You~declared~the~codesyntax~env~ multiple~times
  }
  {
    (ID:#1)~You~declared~the~codesyntax~env~multiple~times.
    Only~ the~ last~ one~ will~ prevail.
    ~Error~Code~ ID:<#1>.
  }

\msg_new:nnnn {codedesc} {deprecated env}
  {
    (ID:#1)~The~ environment~#2~is~ deprecated~ use~ #3 ~ instead
  }
  {
    You~tried~to~use~a~deprecated~ environment:#2.
    Use~ #3~ instead.
    ~Error~Code~ ID:<#1>.
  }



%%%%%%%
%%%
%%% 'simplified' bold versions of \hline and \rule
%%% those don't peek ahead (to see if they are followed by another line)
%%%
%%%%%%%
\cs_new:Npn \__codedesc_hline:nnnn #1#2#3#4 {\noalign{#1\vskip #2\vskip 0pt\hrule height #3\arrayrulewidth\vskip #4\vskip 0pt}}
\cs_new:Npn \__codedesc_hline:nn #1#2       {\__codedesc_hline:nnnn {#1}{-0.5ex}{#2}{0.25ex}}
\cs_new:Npn \__codedesc_hline:n #1          {\__codedesc_hline:nnnn {#1}{-0.5ex}{2}{0.25ex}}
\cs_new:Npn \__codedesc_rule:n #1 {\hrule height #1\arrayrulewidth}
\cs_new:Npn \__codedesc_rule:     {\hrule height 2\arrayrulewidth}



%%%%%%%
%%%
%%% To get the 'real' columnwidth (multicolumn case)
%%% given the current \linewidth and \textwidth
%%%
%%%%%%%

%\dim_new:N \l__codedesc_linewidth_dim
\dim_new:N \l__codedesc_textcolwidth_dim

\cs_new_protected:Npn \__codedesc_set_textcolwidth: 
  {
    \dim_set:Nn \l__codedesc_textcolwidth_dim {\linewidth}
%    \dim_compare:nNnTF {\linewidth} = {\l__codedesc_linewidth_dim}
%      {}
%      {
%%        \dim_set:Nn \l__codedesc_linewidth_dim {\linewidth}
%%        \fp_set:Nn \l__codedesc_tmpa_fp {(\textwidth - \linewidth) / \textwidth}
%%        \dim_set:Nn \l__codedesc_textcolwidth_dim {\linewidth - \fp_use:N \l__codedesc_tmpa_fp \columnsep}
%
%        \dim_set:Nn \l__codedesc_textcolwidth_dim {\linewidth}
%      }
  }




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



\keys_define:nn { codedesc / scratch_def }
{
  meta.usage:n = general ,
  meta .value_forbidden:n = true ,
  meta .code:n ={ \tl_set:Nn \l__codedesc_tmpfmt_tl {meta} } ,
  
  xmeta.usage:n = general ,
  xmeta .value_forbidden:n = true ,
  xmeta .code:n ={ \tl_set:Nn \l__codedesc_tmpfmt_tl {xmeta} } ,
  
  code.usage:n = general ,
  code .value_forbidden:n = true ,
  code .code:n ={ \tl_set:Nn \l__codedesc_tmpfmt_tl {code} } ,
  
  verb.usage:n = general ,
  verb .value_forbidden:n = true ,
  verb .code:n ={ \tl_set:Nn \l__codedesc_tmpfmt_tl {verb} } ,
  
  xverb.usage:n = general ,
  xverb .value_forbidden:n = true ,
  xverb .code:n ={ \tl_set:Nn \l__codedesc_tmpfmt_tl {xverb} } ,
  
  nofmt.usage:n = general ,
  nofmt .value_forbidden:n = true ,
  nofmt .code:n = {\tl_clear:N \l__codedesc_tmpfmt_tl } ,

  slshape.usage:n = general ,
  slshape .value_forbidden:n = true ,
  slshape .code:n ={ \tl_set:Nn \l__codedesc_tmpshape_tl { slshape} } ,
  
  itshape.usage:n = general ,
  itshape .value_forbidden:n = true ,
  itshape .code:n ={ \tl_set:Nn \l__codedesc_tmpshape_tl { itshape} } ,
  
  noshape.usage:n = general ,
  noshape .value_forbidden:n = true ,
  noshape .code:n ={ \tl_clear:N \l__codedesc_tmpshape_tl } ,
    
  color.usage:n = general ,
  color .value_required:n = true ,
  color.code:n = { \tl_set:Nn \l__codedesc_tmpcolor_tl { #1 } } ,
  
  lbracket .usage:n = general ,
  lbracket .value_required:n = true ,
  lbracket .code:n = { \tl_set:Nn \l__codedesc_tmplbracket_tl { #1 } } ,

  rbracket .usage:n = general ,
  rbracket .value_required:n = true ,
  rbracket .code:n = { \tl_set:Nn \l__codedesc_tmprbracket_tl { #1 } } ,
  
	unknown.code:n = 
    {
     \msg_error:nnxx { codedesc } {format-err} {format}{\l_keys_key_str}
    },    

}


\keys_define:nn { codedesc / grp_scratch }
  {
    unknown .code:n = {}
  }

\cs_new_protected:Npn \__codedesc_group_define:nn #1#2
  {
    \tl_clear:N \l__codedesc_tmpfmt_tl
    \tl_clear:N \l__codedesc_tmpshape_tl
    \tl_clear:N \l__codedesc_tmpcolor_tl        
    \tl_clear:N \l__codedesc_tmplbracket_tl        
    \tl_clear:N \l__codedesc_tmprbracket_tl        

    \keys_set:nn { codedesc / grp_scratch } {#1}
    \keys_set:nn { codedesc / scratch_def } {#2}
    
    \tl_clear:N \l__codedesc_tmpa_tl
    \tl_clear:N \l__codedesc_tmpb_tl
    \tl_if_empty:NF \l__codedesc_tmpfmt_tl
      { 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpfmt_tl
        \tl_set:Nn \l__codedesc_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmpshape_tl
      { 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpb_tl 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpshape_tl
        \tl_set:Nn \l__codedesc_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmpcolor_tl
      { 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpb_tl
        \tl_put_right:Nn \l__codedesc_tmpa_tl{ color =  } 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpcolor_tl
        \tl_set:Nn \l__codedesc_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmplbracket_tl
      { 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpb_tl
        \tl_put_right:Nn \l__codedesc_tmpa_tl { lbracket = } 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmplbracket_tl
        \tl_set:Nn \l__codedesc_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmprbracket_tl
      { 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmpb_tl
        \tl_put_right:Nn \l__codedesc_tmpa_tl { rbracket = } 
        \tl_put_right:NV \l__codedesc_tmpa_tl \l__codedesc_tmprbracket_tl
%        \tl_set:Nn \l__codedesc_tmpb_tl { , }
      }
      
    \keys_define:ne { codedesc / grp_scratch } { #1 .meta:nn = { codedesc / scratch_def } { \l__codedesc_tmpa_tl} }
    \keys_define:ne { codedesc / grp_fmt } { #1 .meta:nn = { codedesc / base_fmt } { \l__codedesc_tmpa_tl} }
  }




\keys_define:nn { codedesc / grp_fmt }
  {
    unknown .code:n = \msg_error:nnxx { codedesc } {group-err} {grpfmt}{\l_keys_key_str}
  }


\cs_new_protected:Npn \__codedesc_object_define:nnn #1#2#3
  {
    \tl_if_blank:nTF {#3}
      {
        \keys_define:nn { codedesc / format } 
          { #1 .meta:nn = { codedesc / grp_fmt } { #2 } }
      }
      {
        \__codedesc_group_define:nn { #1_objfmt } {#3}
        \keys_define:nn { codedesc / format } 
          { #1 .meta:nn = { codedesc / grp_fmt } { #2 , #1_objfmt} }
      }
  }


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\tl_set:Nn    \__codedesc_metasize_tl: {\small}
\tl_set:Nn    \__codedesc_metafont_tl: {\ttfamily}


  %\colorlet{c__codedesc_none_color}{red!70!black}
  %\color_set:nn {c__codedesc_none_color}{red!70!black}

	%\colorlet{c__codedesc_verb_color}{ black }
	%\color_set:nn{c__codedesc_verb_color}{ black }
\__codedesc_group_define:nn {verb} {color=c__codedesc_verb_color}
\__codedesc_object_define:nnn {verb}{verb}{verb}
\__codedesc_object_define:nnn {xverb}{verb}{xverb}

	%\colorlet{c__codedesc_marg_color}{ gray!60!black }
	%\color_set:nn{c__codedesc_marg_color}{ gray!60!black }
\__codedesc_group_define:nn {meta} {meta,color=c__codedesc_marg_color}
\__codedesc_object_define:nnn {meta}{meta}{}
\__codedesc_object_define:nnn {arg}{meta}{}
\__codedesc_object_define:nnn {marg}{meta}{lbracket={\{},rbracket={\}}}

	%\colorlet{c__codedesc_oarg_color}{ gray!90!black }
	%\color_set:nn{c__codedesc_oarg_color}{ gray!90!black }
\__codedesc_group_define:nn {oarg} {meta,color=c__codedesc_oarg_color}
\__codedesc_object_define:nnn {oarg}{oarg}{lbracket={[},rbracket={]}}
\__codedesc_object_define:nnn {parg}{oarg}{lbracket={(},rbracket={)}}
\__codedesc_object_define:nnn {xarg}{oarg}{lbracket={<},rbracket={>}}

	%\colorlet{c__codedesc_code_color}{ blue!40!black }
	%\color_set:nn{c__codedesc_code_color}{ blue!40!black }
\__codedesc_group_define:nn {code} {code,color=c__codedesc_code_color}
\__codedesc_object_define:nnn {code}{code}{}
\__codedesc_object_define:nnn {macro}{code}{}
\__codedesc_object_define:nnn {function}{code}{}
%\__codedesc_group_define:nn {code} {xverb,color=red}
%\__codedesc_object_define:nnn {xcode}{code}{xverb}

	%\colorlet{c__codedesc_syntax_color}{ blue!60!black }
	%\color_set:nn{c__codedesc_syntax_color}{ blue!60!black }
\__codedesc_group_define:nn {syntax} {color=c__codedesc_syntax_color}
\__codedesc_object_define:nnn {syntax}{syntax}{}

	%\colorlet{c__codedesc_keyval_color}{ teal!40!black }
	%\color_set:nn{c__codedesc_keyval_color}{ teal!40!black }
\__codedesc_group_define:nn {keyval} {slshape,color=c__codedesc_keyval_color}
\__codedesc_object_define:nnn {keyval}{keyval}{}
\__codedesc_object_define:nnn {key}{keyval}{}
\__codedesc_object_define:nnn {keys}{keyval}{}
\__codedesc_object_define:nnn {value}{keyval}{}

	%\colorlet{c__codedesc_options_color}{ green!30!black }
	%\color_set:nn{c__codedesc_options_color}{ green!30!black }
\__codedesc_group_define:nn {option} {color=c__codedesc_options_color}
\__codedesc_object_define:nnn {option}{option}{}

	%\colorlet{c__codedesc_defaultval_color}{ blue!60!black }
	%\color_set:nn{c__codedesc_defaultval_color}{ blue!60!black }
\__codedesc_group_define:nn {defaultval} {color=c__codedesc_defaultval_color}
\__codedesc_object_define:nnn {defaultval}{defaultval}{}

	%\colorlet{c__codedesc_env_color}{ green!30!black }
	%\color_set:nn{c__codedesc_env_color}{ green!30!black }
\__codedesc_group_define:nn {env} {slshape,color=c__codedesc_env_color}
\__codedesc_object_define:nnn {env}{env}{}

	%\colorlet{c__codedesc_pkg_color}{ green!30!black }
	%\color_set:nn{c__codedesc_pkg_color}{ green!30!black }
\__codedesc_group_define:nn {pkg} {slshape,color=c__codedesc_pkg_color}
\__codedesc_object_define:nnn {pkg}{pkg}{}
\__codedesc_object_define:nnn {pack}{pkg}{}




\keys_define:nn { codedesc / base_fmt }
{
  meta .usage:n = general , 
  meta .value_forbidden:n = true ,
  meta .code:n  = { 
    \tl_set:Nn \__codedesc_typeset_tl:n { \__codedesc_meta:n }
    \tl_set:Nn \__codedesc_typeset_tl:V { \__codedesc_meta:V }
   } ,

  xmeta .usage:n = general , 
  xmeta .value_forbidden:n = true ,
  xmeta .code:n  = { 
    \tl_set:Nn \__codedesc_typeset_tl:n { \__codedesc_meta*:n }
    \tl_set:Nn \__codedesc_typeset_tl:V { \__codedesc_meta*:V }
   } ,

  verb .usage:n = general , 
  verb .value_forbidden:n = true ,
  verb .code:n  = { 
    \tl_set:Nn \__codedesc_typeset_tl:n { \tl_to_str:n }
    \tl_set:Nn \__codedesc_typeset_tl:V { \tl_to_str:V }   
   } ,
   
  xverb .usage:n = general , 
  xverb .value_forbidden:n = true ,
  xverb .code:n  = { 
    \tl_set:Nn \__codedesc_typeset_tl:n { \__codedesc_verb_nospc_typeset:n }
    \tl_set:Nn \__codedesc_typeset_tl:V { \__codedesc_verb_nospc_typeset:V }   
   } ,
   
  code .usage:n = general , 
  code .value_forbidden:n = true ,
  code .code:n  = { 
    \tl_set:Nn \__codedesc_typeset_tl:n { \__codedesc_macro_typeset:n }
    \tl_set:Nn \__codedesc_typeset_tl:V { \__codedesc_macro_typeset:V }   
   } ,
   
  slshape .usage:n = general , 
  slshape .value_forbidden:n = true ,
  slshape .code:n  = { 
    \tl_set:Nn \__codedesc_metashape_tl: { \slshape}
   } ,
   
  itshape .usage:n = general , 
  itshape .value_forbidden:n = true ,
  itshape .code:n  = { 
    \tl_set:Nn \__codedesc_metashape_tl: { \itshape }
   } , 
  
  lbracket .usage:n = general ,
  lbracket .value_required:n = true ,
  lbracket .code:n = { \tl_set:Nn \__codedesc_Lbracket_tl { #1 } } ,

  rbracket .usage:n = general ,
  rbracket .value_required:n = true ,
  rbracket .code:n = { \tl_set:Nn \__codedesc_Rbracket_tl { #1 } } ,

  color .usage:n = general ,
  color .value_required:n = true ,
  color .code:n = {
    \tl_set:Nn \__codedesc_metacolor_tl: { \color{#1} }
%    \tl_set:Nn \__codedesc_metacolor_tl: { \color_select:n{#1} }
  } ,
}

\keys_define:nn { codedesc / format }
{
  strut .usage:n = general,
  strut .code:n = 
    {
      \tl_set:Nn \__codedesc_strut_tl { \strut }
    },  
   
  unknown.usage:n = general,
	unknown.code:n = 
    {
     \tl_set:Nn \__codedesc_metacolor_tl: { \color{c__codedesc_none_color} }
     \msg_error:nnxx { codedesc } {object-err} {format}{\l_keys_key_str}
    },    
}

\keys_define:nn {}
  { codedesc / desc format .inherit:n = codedesc / format }
\keys_define:nn { codedesc / desc format }  
  {
    new.usage:n = general,
    new.code:n =
      {
        \bool_set_true:N \l__codedesc_descnotes_bool
        \bool_set_true:N \l__codedesc_descdate_new_bool 
  %      \tl_set:Nn       \l__codedesc_descdate_new_tl {#1}
        \seq_put_right:Nn \l__codedesc_descdate_new_seq {#1}
      },
      
    update.usage:n = general,
    update.code:n =
      {
        \bool_set_true:N \l__codedesc_descnotes_bool
        \bool_set_true:N \l__codedesc_descdate_update_bool 
        %\tl_set:Nn       \l__codedesc_descdate_update_tl {#1}
        \seq_put_right:Nn \l__codedesc_descdate_update_seq {#1}
      },
      
    note.usage:n = general,
    note.code:n =
      {
        \bool_set_true:N \l__codedesc_descnotes_bool
        \bool_set_true:N \l__codedesc_sidenote_bool 
  %      \tl_set:Nn       \l__codedesc_sidenote_tl {#1}
        \seq_put_right:Nn \l__codedesc_sidenote_seq {#1}
      },
  
    rulecolor.usage:n = general,
    rulecolor.code:n = 
      {
        \tl_set:Nn \__codedesc_rulecolor_tl: { \color{#1} }
      },
    %
    EXP.usage:n = general,
    EXP.code:n = 
      {
        \tl_set:Nn \__codedesc_exp_tl { ~\hfill{\scriptsize\ding{72}} }
      },
  	%
    rEXP.usage:n = general,
    rEXP.code:n = 
      {
        \tl_set:Nn \__codedesc_exp_tl { ~\hfill{\scriptsize\ding{73}} }
      },
	%
    unknown.usage:n = general,
  	unknown.code:n = 
      {
       \tl_set:Nn \__codedesc_metacolor_tl: { \color{c__codedesc_none_color} }
       \msg_error:nnxx { codedesc } {object-err} {desc ~ format}{\l_keys_key_str}
      },    
  }

\keys_define:nn {}
  { codedesc / list format .inherit:n = codedesc / format }
\keys_define:nn { codedesc / list format }  
  {
    
    mid~ sep.usage:n = general,
    mid~ sep.code:n = 
      {
        \tl_set:Nn \__codedesc_sep_tl { ~#1~ }
      },
  	%
  	%
    sep.usage:n = general,
    sep.code:n = 
      {
        \tl_set:Nn \__codedesc_lastsep_tl { ~#1~ }
      },
  	%
    comma.usage:n = general,
    comma.code:n = 
      {
        \tl_set:Nn \__codedesc_lastsep_tl { ,~ }
      },
    %
    meta~ or .usage:n = general,
    meta~ or .code:n =
      {
        \tl_set:Nn \__codedesc_sep_tl { $|$ }
        \tl_set:Nn \__codedesc_lastsep_tl { $|$ }
        \tl_set:Nn \__codedesc_Lbrace_tl {\ensuremath\langle}
        \tl_set:Nn \__codedesc_Rbrace_tl {\ensuremath\rangle}
      },
      
    bnf~ or .usage:n = general,
    bnf~ or .code:n =
      {
        \tl_set:Nn \__codedesc_sep_tl { $|$ }
        \tl_set:Nn \__codedesc_lastsep_tl { $|$ }
        \tl_set:Nn \__codedesc_Lbrace_tl {[}
        \tl_set:Nn \__codedesc_Rbrace_tl {]}
      },
  
    par~ or .usage:n = general,
    par~ or .code:n =
      {
        \tl_set:Nn \__codedesc_sep_tl { $|$ }
        \tl_set:Nn \__codedesc_lastsep_tl { $|$ }
        \tl_set:Nn \__codedesc_Lbrace_tl {(}
        \tl_set:Nn \__codedesc_Rbrace_tl {)}
      },
  
    unknown.usage:n = general,
  	unknown.code:n = 
      {
       \tl_set:Nn \__codedesc_metacolor_tl: { \color{c__codedesc_none_color} }
       \msg_error:nnxx { codedesc } {object-err} {list ~ format}{\l_keys_key_str}
      },    
  }

\cs_new_protected:Npn \__codedesc_metafmt_clear:
  {
    \tl_set:Nn \__codedesc_rulecolor_tl: { \__codedesc_metacolor_tl: }
    \tl_set:Nn \__codedesc_metashape_tl: { }
    \tl_set:Nn \__codedesc_typeset_tl:n { }
    \tl_set:Nn \__codedesc_typeset_tl:V { }
    \tl_set:Nn \__codedesc_Lbracket_tl { }
    \tl_set:Nn \__codedesc_Rbracket_tl { }
    \tl_set:Nn \__codedesc_sep_tl {,\ }
    \tl_set:Nn \__codedesc_lastsep_tl {\ and\ }
    \tl_set:Nn \__codedesc_exp_tl { }
    \tl_set:Nn \__codedesc_Lbrace_tl { }
    \tl_set:Nn \__codedesc_Rbrace_tl { }
    \tl_set:Nn \__codedesc_strut_tl { }
    
    

    \bool_set_false:N \l__codedesc_descnotes_bool
    \bool_set_false:N \l__codedesc_descdate_new_bool 
    \bool_set_false:N \l__codedesc_descdate_update_bool 
    \bool_set_false:N \l__codedesc_sidenote_bool 
  }

\cs_new_protected:Npn \__codedesc_metafmt_set:nn #1#2
  {
    \__codedesc_metafmt_clear:
    \keys_set:nn {codedesc / #1}{#2}
  }

\cs_new_protected:Npn \__codedesc_metafmt_set:n #1
  {
    \__codedesc_metafmt_clear:
    \keys_set:nn {codedesc / format}{#1}
  }
  
  %%% prob ok {o} => {V}
\cs_generate_variant:Nn \__codedesc_metafmt_set:n {V}

\cs_new_protected:Npn \__codedesc_metafmt:n #1
  {
    \__codedesc_metafmt_set:n {#1}
    \__codedesc_metafmt:
  }

  %%% prob ok {o} => {V}
\cs_generate_variant:Nn \__codedesc_metafmt:n {V}

  
\cs_new_protected:Npn \__codedesc_metafmt: 
  {
    \__codedesc_metasize_tl:
    \__codedesc_metafont_tl:
    \__codedesc_metashape_tl:
    \__codedesc_metacolor_tl:
  }


%%%%%%%
%%%
%%% < meta >
%%%
%%%%%%%
\cs_new_protected:Npn \__codedesc_meta:n #1
  {
    \ensuremath\langle #1 \ensuremath\rangle
  }  
  
\cs_generate_variant:Nn \__codedesc_meta:n {V}  

%%%%%%%
%%%
%%% < meta > 'detokenized'
%%%
%%%%%%%
\cs_new_protected:Npn \__codedesc_meta*:n #1
  {
    \ensuremath\langle \tl_to_str:n {#1} \ensuremath\rangle
  }  


\cs_generate_variant:cn {__codedesc_meta*:n} {V}  

\regex_const:Nn \c__codedesc_spc_regex {\ }
\regex_const:Nn \c__codedesc_tf_regex {TF$}

\cs_new_protected:Npn \__codedesc_macro_typeset:n #1
  {
    \tl_set:Ne \l__codedesc_tmpb_tl {\tl_to_str:n{#1}}
    \regex_replace_all:NnN \c__codedesc_spc_regex {}  \l__codedesc_tmpb_tl
    \regex_replace_once:NnNTF \c__codedesc_tf_regex {}\l__codedesc_tmpb_tl
      {
        \l__codedesc_tmpb_tl\textsl{\underline{TF}}
      }
      { \l__codedesc_tmpb_tl }  
  }

\cs_generate_variant:Nn \__codedesc_macro_typeset:n {V}

\cs_new_protected:Npn \__codedesc_verb_nospc_typeset:n #1
  {
    \tl_set:Ne \l__codedesc_tmpb_tl {\tl_to_str:n{#1}}
    \regex_replace_all:NnN \c__codedesc_spc_regex {}  \l__codedesc_tmpb_tl
    \l__codedesc_tmpb_tl
  }

\cs_generate_variant:Nn \__codedesc_verb_nospc_typeset:n {V}



\cs_new_protected:Npn \__codedesc_list_typeset:nnn #1#2#3
  {
    \seq_set_from_clist:Nn \l__codedesc_tmpa_seq {#1}
    
    \seq_if_empty:NTF \l__codedesc_tmpa_seq
      { \bool_set_true:N \l__codedesc_bool }
      { \bool_set_false:N \l__codedesc_bool }

    \tl_clear:N \l__codedesc_middle_tl
    \tl_clear:N \l__codedesc_lastone_tl
    
    \__codedesc_strut_tl
    \__codedesc_Lbrace_tl

    \bool_until_do:Nn \l__codedesc_bool 
      {
        \seq_pop_left:NNTF \l__codedesc_tmpa_seq \l__codedesc_tmpa_tl
          {
            \seq_if_empty:NTF \l__codedesc_tmpa_seq
              {
                \l__codedesc_lastone_tl
                {
                  \__codedesc_metafmt:
                  \__codedesc_typeset_tl:V \l__codedesc_tmpa_tl
                }
                \bool_set_true:N \l__codedesc_bool
              }
              {
                \l__codedesc_middle_tl                
                {
                  \__codedesc_metafmt:
                  \__codedesc_typeset_tl:V \l__codedesc_tmpa_tl
                }
                \tl_set:Nn \l__codedesc_middle_tl {#2}
                \tl_set:Nn \l__codedesc_lastone_tl {#3}
              }
          }
          {}
      }
    \__codedesc_Rbrace_tl
  }

\cs_generate_variant:Nn \__codedesc_list_typeset:nnn {nVV}




\cs_new_protected:Npn \__codedesc_args_typeset:nnnn #1#2#3#4
  {
    \seq_set_from_clist:Nn \l__codedesc_tmpa_seq {#3}
    \group_begin:
      \__codedesc_metafmt_set:n {#1} 
      \__codedesc_strut_tl
      \__codedesc_metafmt:
      \seq_map_inline:Nn \l__codedesc_tmpa_seq {~\!\!#2 \__codedesc_meta:n {##1} #4 }                                  
    \group_end:    
  }


%%%%%%%%%%%%%%%%%%%
%%%%
%%%%  Variables used in the codedescibe environment
%%%%
%%%%%%%%%%%%%%%%%%%
  
  
\bool_new:N \l__codedesc_longblock_bool

\coffin_new:N \l__codedesc_margin_coffin
\coffin_new:N \l__codedesc_text_coffin
\coffin_new:N \l__codedesc_syntax_coffin
\bool_new:N   \g__codedesc_syntax_bool
\dim_new:N \l__codedesc_syntax_wd_dim
\dim_new:N \l__codedesc_margin_wd_dim
  
\bool_new:N  \l__codedesc_descnotes_bool 
\bool_new:N  \l__codedesc_descdate_new_bool 

\seq_new:N    \l__codedesc_descdate_new_seq 
\bool_new:N  \l__codedesc_descdate_update_bool 

\seq_new:N    \l__codedesc_descdate_update_seq
\bool_new:N  \l__codedesc_sidenote_bool 

\seq_new:N    \l__codedesc_sidenote_seq

\coffin_new:N \__codedesc_describe_coffin
\dim_new:N \__codedesc_describelabel_wd_dim
\dim_new:N \__codedesc_describelist_wd_dim
\tl_new:N \__codedesc_join_tl:
\tl_new:N \__codedesc_ragged_tl:

\dim_new:N \__codedesc_paradvance_dim  
  
  
%%%%%%%%%%%%%%%%%%%
%%%%
%%%%  User/Document level commands
%%%%
%%%%%%%%%%%%%%%%%%%


\NewDocumentCommand \defgroupfmt {mm}
  {
    \__codedesc_group_define:nn {#1} {#2}
  }

\NewDocumentCommand \defobjectfmt {mmm}
  {
    \__codedesc_object_define:nnn {#1} {#2} {#3}
  }


\dim_new:N \l__codedesc_tmpa_dim
\dim_new:N \l__codedesc_tmpb_dim

\NewDocumentEnvironment {codedescribe}{O{code}m}
  {
    \mode_if_horizontal:TF 
      {\unskip\skip_vertical:n{\l__codedesc_mid_skip}}
      {\skip_vertical:n{\l__codedesc_mid_skip}}
    
    \bool_if:NTF \l__codedesc_codedescribe_activ_bool
      {
        \msg_warning:nnnxx {codedesc} {nested-env}
          {syntax:01}{codedescribe~ env}{codedescribe~ env}      
      }
      {
        \bool_set_true:N \l__codedesc_codedescribe_activ_bool
      }
      
    
    \seq_set_from_clist:Nn \l__codedesc_tmpa_seq {#2}
    \__codedesc_set_textcolwidth: 
    \hcoffin_set:Nn \l__codedesc_margin_coffin 
      {
        \__codedesc_metafmt_set:nn {desc format}{#1}
        \__codedesc_metafmt:
        
        \begin{tabular}{@{} l @{} }
          \__codedesc_hline:nnnn {\__codedesc_rulecolor_tl:}{0.5ex}{2}{0.25ex}
          \seq_map_inline:Nn \l__codedesc_tmpa_seq { \__codedesc_typeset_tl:n {##1} \__codedesc_exp_tl \\ } 
          \bool_if:NTF \l__codedesc_descnotes_bool
            {
              \\[-2.5ex]
              \__codedesc_hline:nnnn {\color{black}}{0.5ex}{0.25}{0.25ex} 
              
              \bool_if:NT \l__codedesc_descdate_new_bool
                {
                  \seq_map_inline:Nn \l__codedesc_descdate_new_seq
                    {\scriptsize\color{black}new:~ ##1\\[-1ex]}
                }
              \bool_if:NT \l__codedesc_descdate_update_bool
                {
                  \seq_map_inline:Nn \l__codedesc_descdate_update_seq
                    {\scriptsize\color{black}updated:~ ##1\\[-1ex]}
                }
              \bool_if:NT \l__codedesc_sidenote_bool
                {
                  \seq_map_inline:Nn \l__codedesc_sidenote_seq
                    {\scriptsize\color{black}NB:~ ##1\\[-1ex]}
                }
              \\[-1.5ex]
            }
            {
              \\[-2.5ex]
            }
          \__codedesc_hline:nnnn {\__codedesc_rulecolor_tl:}{-0.25ex}{2}{1ex}
        \end{tabular}
      }
    \dim_set:Nn \l__codedesc_margin_wd_dim {\coffin_wd:N \l__codedesc_margin_coffin}
%    \coffin_mark_handle:Nnnn  \l__codedesc_margin_coffin {r}{T}{blue}
%    \coffin_mark_handle:Nnnn  \l__codedesc_margin_coffin {r}{B}{green}
%    \coffin_mark_handle:Nnnn  \l__codedesc_margin_coffin {r}{t}{red}


    \dim_compare:nNnTF \l__codedesc_margin_wd_dim > \marginparwidth
      {
        \bool_set_true:N \l__codedesc_longblock_bool
        \dim_set:Nn \l__codedesc_syntax_wd_dim {\l__codedesc_textcolwidth_dim - (\l__codedesc_margin_wd_dim - \marginparwidth) }
      }
      {
        \bool_set_false:N \l__codedesc_longblock_bool
        \dim_set:Nn \l__codedesc_syntax_wd_dim {\l__codedesc_textcolwidth_dim}        
      }
    \coffin_clear:N \l__codedesc_syntax_coffin
    \bool_gset_false:N \g__codedesc_syntax_bool
    \vcoffin_set:Nnw \l__codedesc_text_coffin {\l__codedesc_textcolwidth_dim}
    \setlength\parindent{0pt}
  }
  {
    \vcoffin_set_end:
    \bool_if:NF \g__codedesc_syntax_bool
      {
        \vcoffin_gset:Nnn \l__codedesc_syntax_coffin {\l__codedesc_syntax_wd_dim}
          {
            \begin{tabular} { @{} l @{} }
              \__codedesc_hline:nnnn {\color{white}}{0.5ex}{2}{-1.5ex}
              \__codedesc_metacolor_tl:
              \begin{minipage}[t]{\l__codedesc_syntax_wd_dim}
                \obeylines\obeyspaces\setlength\parindent{-2em}
              \end{minipage}\\[-2.5ex]
                  \\                                
                  \__codedesc_hline:nnnn {\color{white}}{0ex}{2}{1ex}      
            \end{tabular}
          }
      }

%    \coffin_mark_handle:Nnnn  \l__codedesc_syntax_coffin {l}{T}{blue}
%    \coffin_mark_handle:Nnnn  \l__codedesc_syntax_coffin {l}{B}{green}
%    \coffin_mark_handle:Nnnn  \l__codedesc_syntax_coffin {l}{t}{red}

    \bool_if:NTF \l__codedesc_longblock_bool
      { % __describeblock starting at marginpar
        \dim_compare:nNnTF {\l__codedesc_margin_wd_dim - \marginparwidth} > {0.33 \marginparsep}
          {
            \coffin_join:NnnNnnnn 
              \l__codedesc_syntax_coffin {l}{t} 
              \l__codedesc_margin_coffin {r}{t} 
              {-\marginparsep}{0pt}
            \coffin_join:NnnNnnnn 
              \l__codedesc_syntax_coffin {l}{b} 
              \l__codedesc_text_coffin   {l}{t} 
              {\marginparwidth+\marginparsep}{\l__codedesc_baselineskip_dim}
          }
          {
            \dim_set:Nn \l__codedesc_tmpa_dim {\coffin_ht_plus_dp:N \l__codedesc_syntax_coffin}
            \coffin_join:NnnNnnnn 
              \l__codedesc_syntax_coffin {l}{t} 
              \l__codedesc_margin_coffin {r}{t} 
              {-\marginparsep + \l__codedesc_margin_wd_dim - \marginparwidth}{0pt}
            \dim_set:Nn \l__codedesc_tmpb_dim {\coffin_ht_plus_dp:N \l__codedesc_syntax_coffin}
            \coffin_join:NnnNnnnn 
              \l__codedesc_syntax_coffin {l}{b} 
              \l__codedesc_text_coffin   {l}{t} 
              {\marginparwidth+\marginparsep}{\l__codedesc_baselineskip_dim  + \l__codedesc_tmpb_dim - \l__codedesc_tmpa_dim}
          }
        \par\noindent        
%\coffin_mark_handle:Nnnn  \l__codedesc_syntax_coffin {r}{T}{blue}
        \coffin_typeset:Nnnnn \l__codedesc_syntax_coffin {l}{t} {-\marginparwidth-\marginparsep}{0pt}              
      }
      { % __describeblock at marginpar
        \bool_if:NTF \g__codedesc_syntax_bool
          {
            \coffin_join:NnnNnnnn 
              \l__codedesc_syntax_coffin {l}{b} 
              \l__codedesc_text_coffin   {l}{t} 
              {0pt}{\l__codedesc_baselineskip_dim}
          }
          {
            \coffin_join:NnnNnnnn 
              \l__codedesc_syntax_coffin {l}{B} 
              \l__codedesc_text_coffin   {l}{T} 
              {0pt}{0pt}
          }
        \coffin_attach:NnnNnnnn 
          \l__codedesc_syntax_coffin {l}{t} 
          \l__codedesc_margin_coffin {r}{t} 
          {-\marginparsep}{0pt}
%\coffin_mark_handle:Nnnn  \l__codedesc_syntax_coffin {r}{T}{red}
        \par\noindent
        \coffin_typeset:Nnnnn \l__codedesc_syntax_coffin {l}{t} {0pt}{0pt}      
      }
      
    \skip_vertical:n{\l__codedesc_large_skip}\par
  }
  
 
  
\NewDocumentEnvironment{codesyntax}{}
  {
    \bool_if:NTF \l__codedesc_codedescribe_activ_bool
      {
        \bool_if:NT \g__codedesc_syntax_bool
          {
            \msg_warning:nnn {codedesc} {syntax dup}
                  {syntax:02}
          }
      }
      {
        \msg_warning:nnnxx {codedesc} {out of scope}
              {syntax:03}{codesyntax~ env}{codedescribe~ env}
      }
      
    \bool_set_true:N \l__codedesc_codesyntax_activ_bool
    
    \vcoffin_gset:Nnw \l__codedesc_syntax_coffin {\l__codedesc_syntax_wd_dim}
    \__codedesc_metafmt:n {syntax}
    \hspace*{2em}     %% !!! together with \parindent{-2em}
    \begin{tabular} { @{} l @{} }
      \__codedesc_hline:nnnn {\color{white}}{0.5ex}{2}{-1.5ex}
      \__codedesc_metacolor_tl:
      \begin{minipage}[t]{\l__codedesc_syntax_wd_dim}
        \obeylines\obeyspaces\setlength\parindent{-2em}
  }
  {
      \end{minipage}\\[-2.5ex]
          \\                                
          \__codedesc_hline:nnnn {\color{white}}{0ex}{2}{1ex}      
    \end{tabular}
    \vcoffin_gset_end:
    \bool_gset_true:N \g__codedesc_syntax_bool

    \bool_set_false:N \l__codedesc_codesyntax_activ_bool    
  }

  
\NewDocumentEnvironment{describelist}{O{20mm}m}
  {
     \skip_vertical:n{\l__codedesc_neg_skip}
  
    \__codedesc_set_textcolwidth: 
    \coffin_clear:N \__codedesc_describe_coffin
    \dim_set:Nn \__codedesc_describelabel_wd_dim {#1}
    \dim_set:Nn \__codedesc_describelist_wd_dim {\l__codedesc_textcolwidth_dim}
    \tl_set:Nn \__codedesc_join_tl: {\coffin_attach:NnnNnnnn}
    \tl_set:Nn \__codedesc_ragged_tl: {\raggedleft}
    \tl_set:Nn \__codedesc_listkind_tl {#2}
    
    \cs_set_eq:NN \describe \__codedesc_describe:nn
  }
  {
  }
  
\NewDocumentEnvironment{describelist*}{O{20mm}m}
  {
    \mode_if_horizontal:TF 
      {\skip_vertical:n{\l__codedesc_neg_skip}}
      {\skip_vertical:n{\l__codedesc_null_skip}}        

    \__codedesc_set_textcolwidth: 
    \coffin_clear:N \__codedesc_describe_coffin
    \dim_set:Nn \__codedesc_describelabel_wd_dim {#1}
    \dim_set:Nn \__codedesc_describelist_wd_dim {\l__codedesc_textcolwidth_dim - \__codedesc_describelabel_wd_dim -\marginparsep}
    \tl_set:Nn \__codedesc_join_tl: {\coffin_join:NnnNnnnn}
    \tl_set:Nn \__codedesc_ragged_tl: {}
    \tl_set:Nn \__codedesc_listkind_tl {#2}
    
    \cs_set_eq:NN \describe \__codedesc_describe:nn
  }
  {
  }

\regex_const:Nn \c__codedesc_describe_regex { \c{describe} }

\cs_new_protected:Npn \__codedesc_describe:nn #1#2
  {    
    \hcoffin_set:Nn \l__codedesc_tmpb_coffin 
      { 
        \__codedesc_metafmt:V \__codedesc_listkind_tl 
        \__codedesc_ragged_tl: \__codedesc_typeset_tl:n {#1}
      }      
    \dim_compare:nNnTF {\coffin_wd:N \l__codedesc_tmpb_coffin} > {\__codedesc_describelabel_wd_dim}
      {
        \vcoffin_set:Nnn \l__codedesc_tmpa_coffin 
          { \__codedesc_describelabel_wd_dim } 
          {  ~\ ~ }
        \coffin_attach:NnnNnnnn
          \l__codedesc_tmpa_coffin {r}{t}
          \l__codedesc_tmpb_coffin {r}{t}
          {0pt}{0pt}   
      }
      {
        \vcoffin_set:Nnn \l__codedesc_tmpa_coffin 
          { \__codedesc_describelabel_wd_dim } 
          { 
            \__codedesc_metafmt:V \__codedesc_listkind_tl
            \noindent\__codedesc_ragged_tl: \__codedesc_typeset_tl:n {#1}
          }          
      }
    \vcoffin_set:Nnn \l__codedesc_tmpb_coffin 
      { \__codedesc_describelist_wd_dim } 
      { \noindent  #2 \skip_vertical:N \l__codedesc_coffinskip_dim }   
      
    \__codedesc_join_tl: 
      \l__codedesc_tmpb_coffin {l}{T} 
      \l__codedesc_tmpa_coffin {r}{B} 
      {-\marginparsep}{0pt}

    \bool_if:NTF \l__codedesc_describe_peek_bool
      { \par }
      {
        \mode_if_horizontal:T { \unskip\par}
        \skip_vertical:N \l__codedesc_small_skip
      }
     
    \noindent
    \coffin_typeset:Nnnnn 
      \l__codedesc_tmpb_coffin {l}{t} {0pt}{-1.5pt}
    
    \xpeekahead_cmd_peek:NTF
      \c__codedesc_describe_regex
      { 
        \bool_set_true:N  \l__codedesc_describe_peek_bool 
      }
      { 
        \bool_set_false:N \l__codedesc_describe_peek_bool 
        \par
        \skip_vertical:N \l__codedesc_mid_skip
      }
  }

  
\NewDocumentCommand \typesetmeta {m} {\__codedesc_meta:n {#1}}

\cs_new_eq:NN \tsmeta \typesetmeta  


\NewDocumentCommand \typesetargs {O{meta}m}
  { 
    \__codedesc_args_typeset:nnnn {#1} {\__codedesc_Lbracket_tl} {#2} {\__codedesc_Rbracket_tl}
  }
  
\cs_new_eq:NN \tsargs \typesetargs  



\NewDocumentCommand \typesetmacro {mO{}m} 
  {
    \__codedesc_metafmt_set:n {code} %.... argh!
    \__codedesc_list_typeset:nnn{#1}{,~}{,~}
%    \__codedesc_macro_typeset:n{#1}
    \,\__codedesc_args_typeset:nnnn {oarg} [ {#2} ]
    \__codedesc_args_typeset:nnnn {marg} \{ {#3} \}
  }
\cs_new_eq:NN \tsmacro \typesetmacro


\NewDocumentCommand \typesetverb {O{code}m} 
  {
    \group_begin:
%      \__codedesc_metafmt:n {#1}
      \__codedesc_metafmt_set:n {#1} 
      \__codedesc_strut_tl
      \__codedesc_metafmt:      
      \tl_to_str:n {#2}
    \group_end:
  }
\cs_new_eq:NN \tsverb \typesetverb

\NewDocumentCommand \typesetobj {O{code}m} 
  {
    \__codedesc_metafmt_set:nn {list format}{#1}
    \__codedesc_list_typeset:nVV{#2} \__codedesc_sep_tl \__codedesc_lastsep_tl
  }

\cs_new_eq:NN \tsobj \typesetobj


\NewDocumentCommand \typesetmarginnote {m}{\marginpar{{\scriptsize\raggedleft #1 \par}}}
\cs_new_eq:NN \tsmarginnote \typesetmarginnote



\bool_new:N \l__codedesc_codedescribe_activ_bool
\bool_set_false:N \l__codedesc_codedescribe_activ_bool
\bool_new:N \l__codedesc_codesyntax_activ_bool
\bool_set_false:N \l__codedesc_codesyntax_activ_bool

\coffin_new:N \l__codedesc_tsremark_coffin

\bool_new:N \l__codedesc_tsremark_peek_bool
\bool_set_false:N \l__codedesc_tsremark_peek_bool

\bool_new:N \l__codedesc_describe_peek_bool
\bool_set_false:N \l__codedesc_describe_peek_bool

\regex_const:Nn \c__codedesc_remark_regex { \c{begin} \cB{tsremark} }

\NewDocumentEnvironment {tsremark} {O{Note:}}
  {
    \xpeekahead_env_set:nNTF {tsremark}
      \c__codedesc_remark_regex
      { 
        \bool_set_true:N  \l__codedesc_tsremark_peek_bool
      }
      { 
        \bool_set_false:N \l__codedesc_tsremark_peek_bool 
        \par
        \skip_vertical:N \l__codedesc_mid_skip
      }

    \__codedesc_set_textcolwidth:
    \group_begin:
      \vcoffin_gset:Nnw \l__codedesc_tsremark_coffin {0.8\l__codedesc_textcolwidth_dim}
        \setlength\parindent{0pt}\small
        \textsl{\textbf{#1}} 
  }
  {
      \skip_vertical:N \l__codedesc_coffinskip_dim
      \vcoffin_gset_end:
      \bool_if:NTF \l__codedesc_tsremark_peek_bool
        {
          \par
        }
        {
          \mode_if_horizontal:T
            { \par }
          \skip_vertical:n{\l__codedesc_tiny_skip}
        }

      \noindent\hspace{0.2\l__codedesc_textcolwidth_dim}
      \coffin_typeset:Nnnnn 
        \l__codedesc_tsremark_coffin 
        {l}{T}  {0pt}{0pt}
    \group_end:
  }
  

\NewDocumentEnvironment {tsremark*} {O{Note:}}
  {
    \msg_warning:nnnnn {codedesc} {deprecated env} {remark*:01}{tsremark*}{tsremark}
    \begin{tsremark}[#1]
  }
  {
    \end{tsremark}
  }


%%%% ARGH !!!!

\keys_define:nn { codedesc / title }
  {
    title    .usage:n = general ,
    title    .value_required:n = true ,
  	title    .tl_set:N = \l__codedesc_title_tl ,

    author   .usage:n = general ,
    author   .value_required:n = true ,
  	author   .tl_set:N = \l__codedesc_author_tl ,

    date     .usage:n = general ,
    date     .value_required:n = true ,
  	date     .tl_set:N = \l__codedesc_descdate_tl ,
  }


\cs_new_protected:Npn \__codedesc_make_title: {%
	\newpage
	\null
	\vskip 2em%
	\begin{center}%
		{\LARGE \l__codedesc_title_tl \par}%
		\vskip 1.5em%
		{\large
			\lineskip .5em%
			\begin{tabular}[t]{c}%
				\l__codedesc_author_tl
			\end{tabular}\par}%
		\vskip 1em%
		{\large \l__codedesc_descdate_tl}%
	\end{center}%
	\par
	\vskip 1.5em
}



\NewDocumentCommand \typesetdate {}
  {
    \int_case:nn {\month}
      {
        {1}{January}
        {2}{February}
        {3}{March}
        {4}{April}
        {5}{May}
        {6}{June}
        {7}{July}
        {8}{August}
        {9}{September}
        {10}{October}
        {11}{November}
        {12}{December}
      }
      \use:n {~} \int_to_arabic:n {\year}
  }
  
\cs_new_eq:NN \tsdate \typesetdate

%%%ARGH !!!!!
%%% 'adapted' from 'abstract.cls'
%%%
%%%

\makeatletter

\tl_new:N \g__codedesc_footnote_tl
\int_new:N \g__codedesc_footnote_int

\cs_new_protected:Npn \__codedesc_footnote:nn #1#2
  {
    \footnotemark[#1]
    \tl_gput_right:Nn \g__codedesc_footnote_tl {\footnotetext[#1]{#2}}
  }

\cs_new_protected:Npn \__codedesc_footnote:n #1
  {
    \int_gincr:N \g__codedesc_footnote_int
    \exp_args:NV \__codedesc_footnote:nn \g__codedesc_footnote_int {#1}
  }
  
\NewDocumentCommand{\__codedesc_footnote:w}{O{}m}
  {
    \tl_if_empty:nTF {#1}
      { \__codedesc_footnote:n  {#2} }
      { \__codedesc_footnote:nn {#1}{#2} }
  }
  
\NewDocumentCommand \typesettitle {m}
  {
    \keys_set:nn {codedesc / title}{#1}
  	\group_begin:
          \cs_set_eq:NN \footnote \__codedesc_footnote:w
          \tl_gclear:N \g__codedesc_footnote_tl
          \int_gzero:N \g__codedesc_footnote_int
        	\def\thefootnote{\@fnsymbol\c@footnote}%
        	\def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
        	\long\def\@makefntext##1{\parindent 1em\noindent
        		\hb@xt@1.8em{%
        			\hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
    	\if@twocolumn
      	\ifnum \col@number=\@ne
        	\__codedesc_make_title:
    	  \else
        	\twocolumn[\__codedesc_make_title:]%
    	  \fi
    	\else
      	\newpage
      	\global\@topnum\z@   % Prevents figures from going at top of page.
      	\__codedesc_make_title:
    	\fi
    	\thispagestyle{plain}
      \g__codedesc_footnote_tl
  	\group_end:
  }

\cs_new_eq:NN \tstitle \typesettitle


\NewDocumentEnvironment{tsabstract}{}
  {
   	\if@twocolumn
     	\section*{\abstractname}%
   	\else
     	\small
     	\begin{center}%
     		{\bfseries \abstractname\vspace{-.5em}\vspace{\z@}}%
     	\end{center}%
     	\quotation
   	\fi
  }
  {
    \if@twocolumn\else\endquotation\fi
  }
\cs_new_eq:NN \typesetabstract \tsabstract
\cs_new_eq:NN \endtypesetabstractend \endtsabstract

\makeatother



