%%%==============================================================================
%% 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.5} {2025/02/10}
%%
%% 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/02/10}
    {1.5}
    {LaTeX Code Description/Documentation}

%%%%%%%
%%%
%%% Just an attempt of having my packages info in a regular way
%%% Idea being: { <pck-name> / pkg info } for each and all.
%%%
%%%%%%%
\keys_define:nn { codedescribe / pkg info}
  {
     name        .code:n = {codedescribe} ,
     prefix      .code:n = {codedesc} ,
     date        .code:n = {2025/02/10} ,
     version     .code:n = {1.5} ,
     description .code:n = {\LaTeX~Code~Description/Documentation}
  }
\cs_if_exist:NF \PkgInfo 
  {
    \NewDocumentCommand \PkgInfo {mm} { \keys_set:nn {#1 / pkg info}{#2} } 
    \NewDocumentCommand \PkgDescription {m} 
      { \noindent Package~ \textbf{\PkgInfo{#1}{name}}~Version:~\PkgInfo{#1}{version}~ -~ \PkgInfo{#1}{date}\par \emph{\PkgInfo{#1}{description}}~\par } 
  }  
%%%%%%%
%%% End of cut-n-paste
%%%%%%%

\use:c {@reversemargintrue}

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

\keys_define:nn { codedescribe }
{
  nolisting.usage:n = load,
	nolisting.bool_set_inverse:N = \l__codedesc_loadlisting_bool,
  nolisting.default:n = {true},
}
\ProcessKeyOptions [codedescribe ]

%% bbding is need for those hollow stars...
\RequirePackage{xcolor}
\RequirePackage{pifont}
\bool_if:nT {\l__codedesc_loadlisting_bool}
  {
    \RequirePackage{codelisting}
  }



\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>.
  }


%%%%%%%
%%%
%%% '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_compare:nNnTF {\linewidth} = {\l__codedesc_linewidth_dim}
      {}
      {
%        \dim_set:Nn \l__codedesc_linewidth_dim {\linewidth}
%        \fp_set:Nn \l_tmpa_fp {(\textwidth - \linewidth) / \textwidth}
%        \dim_set:Nn \l__codedesc_textcolwidth_dim {\linewidth - \fp_use:N \l_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_tmpa_tl
    \tl_clear:N \l_tmpb_tl
    \tl_if_empty:NF \l__codedesc_tmpfmt_tl
      { 
        \tl_put_right:No \l_tmpa_tl{\l__codedesc_tmpfmt_tl} 
        \tl_set:Nn \l_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmpshape_tl
      { 
        \tl_put_right:No \l_tmpa_tl{ \l_tmpb_tl } 
        \tl_put_right:No \l_tmpa_tl{\l__codedesc_tmpshape_tl} 
        \tl_set:Nn \l_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmpcolor_tl
      { 
        \tl_put_right:No \l_tmpa_tl{ \l_tmpb_tl } 
        \tl_put_right:Nn \l_tmpa_tl{ color =  } 
        \tl_put_right:No \l_tmpa_tl{ \l__codedesc_tmpcolor_tl} 
        \tl_set:Nn \l_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmplbracket_tl
      { 
        \tl_put_right:No \l_tmpa_tl{ \l_tmpb_tl } 
        \tl_put_right:Nn \l_tmpa_tl{ lbracket = } 
        \tl_put_right:No \l_tmpa_tl{ \l__codedesc_tmplbracket_tl} 
        \tl_set:Nn \l_tmpb_tl { , }
      }
    \tl_if_empty:NF \l__codedesc_tmprbracket_tl
      { 
        \tl_put_right:No \l_tmpa_tl{ \l_tmpb_tl } 
        \tl_put_right:Nn \l_tmpa_tl{ rbracket = } 
        \tl_put_right:No \l_tmpa_tl{ \l__codedesc_tmprbracket_tl} 
%        \tl_set:Nn \l_tmpb_tl { , }
      }
      
    \keys_define:ne { codedesc / grp_scratch } { #1 .meta:nn = { codedesc / scratch_def } { \l_tmpa_tl} }
    \keys_define:ne { codedesc / grp_fmt } { #1 .meta:nn = { codedesc / base_fmt } { \l_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}

	\colorlet{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 }
\__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 }
\__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 }
\__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}

	\colorlet{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 }
\__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 }
\__codedesc_group_define:nn {option} {color=c__codedesc_options_color}
\__codedesc_object_define:nnn {option}{option}{}

	\colorlet{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 }
\__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 }
\__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:o { \__codedesc_meta:o }
   } ,

  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:o { \__codedesc_meta*:o }
   } ,

  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:o { \tl_to_str:o }   
   } ,
   
  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:o { \__codedesc_verb_nospc_typeset:o }   
   } ,
   
  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:o { \__codedesc_macro_typeset:o }   
   } ,
   
  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} }
  } ,
}

\keys_define:nn { codedesc / format }
{
  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}} }
    },
	%
  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 { ,~ }
    },
  %
  rulecolor.usage:n = general,
  rulecolor.code:n = 
    {
      \tl_set:Nn \__codedesc_rulecolor_tl: { \color{#1} }
    },
  %
  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}
    },
    
  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}
    },    
}

\cs_new_protected:Npn \__codedesc_metafmt_set:n #1
  {
    \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:o { }
    \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 { }
    

    \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 

    \keys_set:nn {codedesc / format}{#1}
  }
  
\cs_generate_variant:Nn \__codedesc_metafmt_set:n {o}

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

\cs_generate_variant:Nn \__codedesc_metafmt:n {o}

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


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

%%%%%%%
%%%
%%% < 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} {o}  



\cs_new_protected:Npn \__codedesc_macro_typeset:n #1
  {
    \tl_set:Ne \l_tmpb_tl {\tl_to_str:n{#1}}
    \regex_replace_all:nnN {\ }{}  \l_tmpb_tl
    \regex_replace_once:nnNTF {TF}{}\l_tmpb_tl
      {
        \l_tmpb_tl\textsl{\underline{TF}}
      }
      { \l_tmpb_tl }  
  }

\cs_generate_variant:Nn \__codedesc_macro_typeset:n {o}

\cs_new_protected:Npn \__codedesc_verb_nospc_typeset:n #1
  {
    \tl_set:Ne \l_tmpb_tl {\tl_to_str:n{#1}}
    \regex_replace_all:nnN {\ }{}  \l_tmpb_tl
    \l_tmpb_tl
  }

\cs_generate_variant:Nn \__codedesc_verb_nospc_typeset:n {o}



\cs_new_protected:Npn \__codedesc_list_typeset:nnn #1#2#3
  {
    \seq_set_from_clist:Nn \l_tmpa_seq {#1}
    \bool_set:Nn \l__codedesc_bool {\seq_if_empty_p:N \l_tmpa_seq}
    \tl_set:Nn \l__codedesc_middle_tl {}
    \tl_set:Nn \l__codedesc_lastone_tl {}
    \bool_until_do:Nn \l__codedesc_bool 
      {
        \seq_pop_left:NNTF \l_tmpa_seq \l_tmpa_tl
          {
            \seq_if_empty:NTF \l_tmpa_seq
              {
                \l__codedesc_lastone_tl
                {
                  \__codedesc_metafmt:
                  \__codedesc_typeset_tl:o \l_tmpa_tl
                }
                \bool_set_true:N \l__codedesc_bool
              }
              {
                \l__codedesc_middle_tl                
                {
                  \__codedesc_metafmt:
                  \__codedesc_typeset_tl:o \l_tmpa_tl
                }
                \tl_set:Nn \l__codedesc_middle_tl {#2}
                \tl_set:Nn \l__codedesc_lastone_tl {#3}
              }
          }
          {}
      }
  }

\cs_generate_variant:Nn \__codedesc_list_typeset:nnn {noo}




\cs_new_protected:Npn \__codedesc_args_typeset:nnnn #1#2#3#4
  {
    \seq_set_from_clist:Nn \l_tmpa_seq {#3}
    \group_begin:
      \__codedesc_metafmt:n {#1}
      \seq_map_inline:Nn \l_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   \l__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 
%\tl_new:N    \l__codedesc_descdate_new_tl 
\seq_new:N    \l__codedesc_descdate_new_seq 
\bool_new:N  \l__codedesc_descdate_update_bool 
%\tl_new:N    \l__codedesc_descdate_update_tl
\seq_new:N    \l__codedesc_descdate_update_seq
\bool_new:N  \l__codedesc_sidenote_bool 
%\tl_new:N    \l__codedesc_sidenote_tl
\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:nn {#1} {#2} {#3}
  }
  
\NewDocumentEnvironment {codedescribe}{O{code}m}
  {
    \mode_if_horizontal:TF
      {
        \dim_set:Nn \__codedesc_paradvance_dim {\baselineskip}
      }
      {
        \dim_set:Nn \__codedesc_paradvance_dim {0pt}
      }
    \seq_set_from_clist:Nn \l_tmpa_seq {#2}
    \__codedesc_set_textcolwidth: 
    \hcoffin_set:Nn \l__codedesc_margin_coffin 
      {
        \__codedesc_metafmt:n {#1}
        
        \begin{tabular}{@{} l @{} }
          \__codedesc_hline:nnnn {\__codedesc_rulecolor_tl:}{0.5ex}{2}{0.25ex}
          \seq_map_inline:Nn \l_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} 
%%%                {\scriptsize\color{black}new:~ \l__codedesc_descdate_new_tl\\[-1ex]}
              \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} 
%%%                {\scriptsize\color{black}update:~ \l__codedesc_descdate_update_tl\\[-1ex]}
              \bool_if:nT {\l__codedesc_descdate_update_bool} 
                {
                  \seq_map_inline:Nn \l__codedesc_descdate_update_seq
                    {\scriptsize\color{black}update:~ ##1\\[-1ex]}
                }
%%%              \bool_if:nT {\l__codedesc_sidenote_bool} 
%%%                {\scriptsize\color{black}NB:~ \l__codedesc_sidenote_tl\\[-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}
    \bool_if:nTF { \dim_compare_p:nNn \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_set_false:N \l__codedesc_syntax_bool
    \vcoffin_set:Nnw \l__codedesc_text_coffin {\l__codedesc_textcolwidth_dim}
    \setlength\parindent{0pt}
    \begin{minipage}[t]{\l__codedesc_textcolwidth_dim} 
  }
  {
    \end{minipage}
    \vcoffin_set_end:
    \bool_if:NF \l__codedesc_syntax_bool
      {
        \vcoffin_gset:Nnn \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}
          }
      }
    \bool_if:NTF \l__codedesc_longblock_bool
      { % __describeblock starting at marginpar
        \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}{\baselineskip}
        \par\noindent
        \coffin_typeset:Nnnnn \l__codedesc_syntax_coffin {l}{t} {-\marginparwidth-\marginparsep}{\__codedesc_paradvance_dim}              
      }
      { % __describeblock at marginpar
        \coffin_attach: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} {0pt}{\baselineskip}
        \par\noindent
        \coffin_typeset:Nnnnn \l__codedesc_syntax_coffin {l}{t} {0pt}{\__codedesc_paradvance_dim}      
      }
    \\[0.5\baselineskip]
    %\\[\__codedesc_paradvance_dim]%[-0.5\baselineskip]
  }
  
 
  
\NewDocumentEnvironment{codesyntax}{}
  {
    \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}
    %\color{black}
    \vcoffin_gset_end:
    \bool_set_true:N \l__codedesc_syntax_bool
  }

  
  
  \NewDocumentEnvironment{describelist}{O{20mm}m}
  {
    %\vspace*{-1.5ex}
    \mode_if_horizontal:TF 
      {\\[-0.5\baselineskip]} 
      {}
    \__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}
  }
  {
%    \par\noindent\coffin_typeset:Nnnnn \__codedesc_describe_coffin {l}{t}{0pt}{10pt}
  }
  
\NewDocumentEnvironment{describelist*}{O{20mm}m}
  {
    %\vspace*{-1.5ex}
    \mode_if_horizontal:TF 
      {\\[-0.5\baselineskip]}%{\vspace*{-1ex}} 
      {}
    \__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}
  }
  {
%    \par\noindent\coffin_typeset:Nnnnn \__codedesc_describe_coffin {l}{t}{0pt}{10pt}
  }

\NewDocumentCommand \describe {mm}
  {    
    \hcoffin_set:Nn \l_tmpb_coffin 
      { 
        \__codedesc_metafmt:o { \__codedesc_listkind_tl }
        \__codedesc_ragged_tl: \__codedesc_typeset_tl:n {#1}
      }      
    \dim_compare:nNnTF {\coffin_wd:N \l_tmpb_coffin} > {\__codedesc_describelabel_wd_dim}
      {
        \vcoffin_set:Nnn \l_tmpa_coffin 
          { \__codedesc_describelabel_wd_dim } 
          {  ~\ ~ }
        \coffin_attach:NnnNnnnn
          \l_tmpa_coffin {r}{t}
          \l_tmpb_coffin    {r}{t}
          {0pt}{0pt}
      
      }
      {
        \vcoffin_set:Nnn \l_tmpa_coffin 
          { \__codedesc_describelabel_wd_dim } 
          { 
            \__codedesc_metafmt:o { \__codedesc_listkind_tl }
            \noindent\__codedesc_ragged_tl: \__codedesc_typeset_tl:n {#1}
          }          
      }
    \vcoffin_set:Nnn \l_tmpb_coffin 
      { \__codedesc_describelist_wd_dim } 
      { 
        \noindent
        \begin{minipage}[t]{ \__codedesc_describelist_wd_dim }
          #2
        \end{minipage}
      }      
    \__codedesc_join_tl: 
      \l_tmpb_coffin {l}{t} 
      \l_tmpa_coffin {r}{t} 
      {-\marginparsep}{0pt}
    \mode_if_horizontal:TF 
      {
        \\[-\baselineskip] 
      }
      {   }

    \noindent
    \coffin_typeset:Nnnnn 
      \l_tmpb_coffin {l}{t} {0pt}{0pt}
    \\ 
    
  }


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

\cs_new_eq:NN \tsmeta \typesetmeta  


\NewDocumentCommand \typesetargs {O{meta}m}
  { 
%    \keys_set:nn {codedesc / delimiters}{#1}
  \group_begin:
    \__codedesc_metafmt:n {#1}
    \__codedesc_args_typeset:nnnn {#1} {\__codedesc_Lbracket_tl} {#2} {\__codedesc_Rbracket_tl}
  \group_end:
  }
  
\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}
      \tl_to_str:n {#2}
    \group_end:
  }
\cs_new_eq:NN \tsverb \typesetverb

\NewDocumentCommand \typesetobj {O{code}m} 
  {
    \__codedesc_metafmt_set:n {#1}
    \__codedesc_list_typeset:noo{#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


\NewDocumentEnvironment {tsremark} {O{Note:}}
  {
    \mode_if_horizontal:TF 
      {\par\vspace*{0.25\baselineskip}}%\vspace*{-1.5ex}} 
      {\vspace*{0.75\baselineskip}}   
    \__codedesc_set_textcolwidth:
    \group_begin:
      \noindent\hspace{0.2\l__codedesc_textcolwidth_dim}
      \begin{minipage}{0.8\l__codedesc_textcolwidth_dim}
        \setlength\parindent{0pt}\small
        \textsl{\textbf{#1}} %\dim_to_decimal:n {\linewidth}
  }
  {
      \end{minipage}
    \group_end:
    \\[0.5\baselineskip]
  }


%%%% 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}%
		\let \footnote \thanks
		{\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


\NewDocumentCommand \typesettitle {m}
  {
    \keys_set:nn {codedesc / title}{#1}
  
  	\group_begin:
    	\renewcommand\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}\@thanks
  	\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



