%%%==============================================================================
%% 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.24a} {2026/02/14}
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/codedescribe
%%
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2025/06/01]
   
%%%%%%%
%%%
%%% Just an attempt at having my package's info in a regular way
%%%   \pkginfograb_set:nn {<pkg-name>} { props} sets package info
%%%
%%%   \pkginfograbProvidesExplPackage {<pkg-name>} { props} sets package info
%%%     and calls \ProvidesExplPackage
%%%
%%%%%%%
\RequirePackage{pkginfograb}
\pkginfograbProvidesExplPackage {codelisting}
  {
     name        = {codelisting} ,
     prefix      = {codelist} ,
     date        = {2026/02/14} ,
     version     = {1.24a} ,
     description = {LaTeX Code Listing}
  }
%%%%%%%
%%% End of cut-n-paste
%%%%%%%



\RequirePackage{xpeekahead,codecmm}
\RequirePackage{xcolor,listings,scontents}

%%%%
%%%% TODO: keep it???
%%%%
%\IfPackageLoadedTF {fancyvrb}
%  {
%    \lstset{fancyvrb = true}
%    \fvset{commentchar=\%}
%  }
%  {}


\bool_new:N \l__codelist_pckopt_xtradialects_bool
\tl_set:Nn \l__codelist_pckopt_dialect_tl {alsolanguage = [doctools]TeX ,}

\tl_set:Nn \l__codelist_pckopt_colorsbright_tl {default}

\keys_define:nn { codelisting }
  {    
    load~ xtra~ dialects .usage:n    = load ,
  	load~ xtra~ dialects .bool_set:N = \l__codelist_pckopt_xtradialects_bool ,
    load~ xtra~ dialects .value_forbidden:n  = true ,
    
    TeX~ dialects  .usage:n   =  general,
    TeX~ dialects  .code:n    =  
      { 
        \tl_clear:N \l__codelist_pckopt_dialect_tl
        \clist_map_inline:nn {#1}
          {
            \tl_put_right:Nn 
              \l__codelist_pckopt_dialect_tl 
              { 
                alsolanguage = [##1]TeX ,
              } 
          } 
      },
    TeX~ dialects  .value_required:n = true,
 
    colors .usage:n = load ,
    colors .choices:nn =
      { default , black , brighter , darker }
      { \tl_set_eq:NN \l__codelist_pckopt_colorsbright_tl \l_keys_choice_tl } ,
    colors .value_required:n = true ,   
    
    strict .usage:n = load ,
    strict .code:n  =
      {
        \msg_redirect_module:nnn { codelist / warnings } { warning } { error }  
      } ,

    suppress~ deprecated .usage:n                 = load ,
    suppress~ deprecated .code:n                  = 
      { 
        \msg_redirect_module:nnn { codelist / deprecated } { warning } { none }  
      } ,
      
  }
\ProcessKeyOptions [codelisting ]



%%%
%%% This might be promoted to a package option... maybe
%%%
\int_const:Nn \l__codelist_nkeys_int {8}

\lstdefinelanguage[doctools]{TeX}[LaTeX]{TeX}
  {
   moretexcs       =     {setlength,
      usepackage,newcommand,renewcommand,providecommand,RequirePackage,
      SelectInputMappings,ifpdftex,ifpdfoutput,AtBeginEnvironment,ProvidesPackage,
      maketitle,text,includegraphics,chapter,section,subsection,subsubsection,paragraph,
      textmu,enquote,blockquote,ding,mathds,ifcsdef,Bra,Ket,Braket,subcaption,lettrine,
      mdfsetup,captionof,listoffigures,listoftables,tableofcontents,appendix,
      newcolumntype,rowfont,taburowcolors,rowcolor,rowcolors,bottomrule,
      toprule,midrule,hypersetup,gls,printglossary,glsadd,newglossaryentry,newacronym,
      mainmatter,frontmatter,geometry,KOMAoptions,setkomafont,addtokomafont,
      si,SI,sisetup,unit,unitfrac,micro,newblock,ExecuteBibliographyOptions,addbibresource,
      operatorname,frac,sfrac,dfrac,DeclareMathOperator,mathcal,underset,
      democodefile,package,cs,command,env,DemoError,PrintDemo,theadstart,tbody,tsubheadstart,
      tsubhead,tend,DefineCodeSection,SetCodeSection,BeginCodeSection,EndCodeSection,
      IfDefined,IfUndefined,IfElseDefined,IfElseUndefined,IfMultDefined,IfNotDraft,
      IfNotDraftElse,IfDraft,IfPackageLoaded,IfElsePackageLoaded,IfPackageNotLoaded,
      IfPackagesLoaded,IfPackagesNotLoaded,ExecuteAfterPackage,ExecuteBeforePackage,
      IfTikzLibraryLoaded,IfColumntypeDefined,IfColumntypesDefined,IfColorDefined,
      IfColorsDefined,IfMathVersionDefined,SetTemplateDefinition,UseDefinition,IfFileExists,
      iflanguage,setuptablefontsize,tablefontsize,setuptablestyle,tablestyle,
      setuptablecolor,tablecolor,disablealternatecolors,tablealtcolored,tbegin,
      tbody,tend,thead,theadstart,tsubheadstart,tsubhead,theadrow,tsubheadrow,
      resettablestyle,theadend,tsubheadend,tableitemize,PreserveBackslash,
      todo,missingfigure,lstloadlanguages,lstdefinestyle,lstset,
      indexsetup,newglossarystyle,glossarystyle,deftranslation,newglossary,
      usetikzlibrary,definecolor,colorlet,captionsetup,DeclareCaptionStyle,
      floatsetup,EnableCrossrefs,DisableCrossrefs,PageIndex,CodelineIndex,CodelineNumbered,
      cref,Cref,vref,eqnref,figref,tabref,secref,chapref}
  }


\bool_if:NTF \l__codelist_pckopt_xtradialects_bool
  { 
    \RequirePackage{codelstlang} %% pre-loading those definined in this
    \lstloadlanguages{
      [LaTeX]TeX,
      [doctools]TeX,
      [l3kernelsign]TeX,
      [l3expsign]TeX,
      [l3amssign]TeX,
      [l3pgfsign]TeX,
      [l3bibtexsign]TeX,
      [l3kernel]TeX,
      [l3exp]TeX,
      [l3ams]TeX,
      [l3pgf]TeX,
      [l3bibtex]TeX,
      [kernel]TeX,
      [xpacks]TeX,
      [ams]TeX,
      [pgf]TeX,
      [pgfplots]TeX,
      [bibtex]TeX,
      [babel]TeX,
      [hyperref]TeX
    }
  }
  { 
    \lstloadlanguages{[LaTeX]TeX,[doctools]TeX}
  }


%\msg_new:nnnn {codelist} {invalid key}
%  {
%    (#1)~Key (#2) ~not~defined!
%  }
%  {
%    You~tried~to~use~a~non~defined~key:#2.
%    ~Error~Code~ ID:<#1>.
%  }

\msg_new:nnnn { codelist / deprecated } {command}
  {
    (#1)~The~ command~#2~ is ~being~ deprecated~ use~ #3~ instead.
  }
  {
    You~tried~to~use~a~command,~#2,~ being~ deprecated.
    use~ #3~ instead.
    ~Error~Code~ ID:<#1>.
  }

\msg_new:nnnn { codelist / deprecated } {key}
  {
    (#1)~The~ keyword~#2~ is ~being~ deprecated~ use~ #3~ instead.
  }
  {
    You~tried~to~use~a~keyword,~#2,~ which~is ~being~ deprecated.
    use~ #3~ instead.
    ~Error~Code~ ID:<#1>.
  }


\dim_new:N \l__codelist_demo_parindent_dim
\dim_new:N \l__codelist_org_parindent_dim

\dim_set:Nn\l__codelist_org_parindent_dim{\parindent}


%%\msg_redirect_module:nnn { codelist / deprecated } {warning} {none}
\cs_new_protected:Npn \__codelist_opt_put_right:nnwnw #1#2[#3]#4#5 \q_stop
  {
    \quark_if_nil:NTF {#4}
      { \tl_show:n {syntax~err!} }
      { \__codelist_opt_put_right:ncnn {#1}{#2 \int_to_Alph:n #3 _clist}{#3}{#4} }
  }

\cs_new_protected:Npn \__codelist_opt_put_right:nNnn #1#2#3#4
  {
    \clist_put_right:Nn #2 {#4}
    \seq_put_right:Nn \l__codelist_opt_keys_seq { {#1}{#3}{#2} }
  }  
\cs_generate_variant:Nn \__codelist_opt_put_right:nNnn {nc}


\cs_new_protected:Npn \__codelist_opt_set:nnwnw #1#2[#3]#4#5 \q_stop
  {
    \quark_if_nil:nTF {#4}
      { \tl_show:n {syntax~err!} }
      { \__codelist_opt_set:ncnn {#1}{#2 \int_to_Alph:n #3 _clist}{#3}{#4} }
  }


\cs_new_protected:Npn \__codelist_opt_set:nNnn #1#2#3#4
  {
    \clist_set:Nn #2 {#4}
    \seq_put_right:Nn \l__codelist_opt_keys_seq { {#1}{#3}{#2} }
  }  
\cs_generate_variant:Nn  \__codelist_opt_set:nNnn {nc}


\cs_new_protected:Npn \__codelist_opt_set:nwnw #1[#2]#3#4 \q_stop
  {
    \quark_if_nil:nTF {#3}
      { \tl_show:n {syntax~err!} }
      { \tl_set:cn {#1 \int_to_Alph:n #2 _tl}{#3} }
  }

\int_new:N   \l__codelist_loop_i_int
\clist_new:N \l__codelist_lstenv_clist
\seq_new:N   \l__codelist_opt_keys_seq  

\int_zero:N \l__codelist_loop_i_int
\int_do_while:nNnn {\l__codelist_loop_i_int} < \l__codelist_nkeys_int
  {
    \int_incr:N \l__codelist_loop_i_int

    \clist_new:c {l__codelist_opt_texcs_ \int_to_Alph:n \l__codelist_loop_i_int _clist}
    \clist_new:c {l__codelist_opt_keywd_ \int_to_Alph:n \l__codelist_loop_i_int _clist}
    \clist_new:c {l__codelist_opt_emph_ \int_to_Alph:n \l__codelist_loop_i_int _clist}
  }


\cs_new_protected:Npn \__codelist_set_colors:nnn #1#2#3
  {
    \__codecmm_color_set:ee 
      {c__codelist_texcs #3 _color}    
      {\l__codelist_colorscheme_texcs_tl  ! \fp_eval:n{ 12 * #2 * #1 + 18 * #1 }   ! black ! \fp_eval:n {105 - 5 * #2 } }
      
    \__codecmm_color_set:ee 
      {c__codelist_keywd #3 _color}    
      {\l__codelist_colorscheme_keywd_tl  ! \fp_eval:n{ 12 * #2 * #1 + 18 * #1 }   ! black ! \fp_eval:n {105 - 5 * #2 } }    

    \__codecmm_color_set:ee 
      {c__codelist_emph #3 _color}    
      {\l__codelist_colorscheme_emph_tl   ! \fp_eval:n{ 12 * #2 * #1 + 18 * #1 }   ! black ! \fp_eval:n {105 - 5 * #2 } }    
  }
\cs_generate_variant:Nn   \__codelist_set_colors:nnn {nVe}
  
\cs_new_protected:Npn \__codelist_set_colors:n #1
  {
    %% background, was \fp_eval:n{  2.5 - 0.5 * #1 }
    %% now it's a constant... 98% white.
    \__codecmm_color_set:ne {c__codelist_bckgnd_color}          { \l__codelist_colorscheme_bckgnd_tl  ! 2 ! white ! 100  }
    
    \__codecmm_color_set:ne {c__codelist_string_color}          { \l__codelist_colorscheme_string_tl  ! \fp_eval:n{ 10 + 20 * #1 }      ! black ! 100 }
    \__codecmm_color_set:ne {c__codelist_comment_color}         { \l__codelist_colorscheme_comment_tl ! \fp_eval:n{ 10 + 20 * #1 }      ! black ! 100 }
    
%    \__codecmm_color_set:ne {c__codelist_rule_color}            { \l__codelist_colorscheme_rule_tl   ! \fp_eval:n{ 50 * #1 }      ! gray ! 100 }
%    \__codecmm_color_set:ne {c__codelist_number_color}          { \l__codelist_colorscheme_number_tl   ! \fp_eval:n{ 50 * #1 }      ! gray ! 100 }
    \__codecmm_color_set:ne {c__codelist_rule_color}            { \l__codelist_colorscheme_rule_tl    !    \fp_eval:n{ 40 + 20 * #1 } !  white}
    \__codecmm_color_set:ne {c__codelist_number_color}          { \l__codelist_colorscheme_number_tl  !    \fp_eval:n{ 40 + 20 * #1 } ! white }

    \int_zero:N \l__codelist_loop_i_int
    \int_do_while:nNnn \l__codelist_loop_i_int < \l__codelist_nkeys_int
      {
        \int_incr:N \l__codelist_loop_i_int
        \__codelist_set_colors:nVe {#1} \l__codelist_loop_i_int {\int_to_Alph:n \l__codelist_loop_i_int}
      }
  }


\cs_new_protected:Npn \__codelist_set_color_brightness:n #1
  {
    \str_case:enF {#1}
      {
        {default}
          { \__codelist_set_colors:n {1} }
        {black}
          { \__codelist_set_colors:n {0} }        
        {brighter}
          { \__codelist_set_colors:n {1.5} }
        {darker}
          { \__codelist_set_colors:n {0.7} }
      } %% fail-safe: default
      { \__codelist_set_colors:n {1} }
  }
\cs_generate_variant:Nn   \__codelist_set_color_brightness:n {V}


\keys_define:nn { codelist / color scheme } 
  {
    bckgnd   .usage:n              = general ,
    bckgnd   .tl_set:N             = \l__codelist_colorscheme_bckgnd_tl ,
    bckgnd   .default:n            = black ,

    string    .usage:n             = general ,
    string    .tl_set:N            = \l__codelist_colorscheme_string_tl ,
    string    .default:n           = teal ,
  
    comment   .usage:n             = general ,
    comment   .tl_set:N            = \l__codelist_colorscheme_comment_tl ,
    comment   .default:n           = green ,
    
    texcs     .usage:n             = general ,
    texcs     .tl_set:N            = \l__codelist_colorscheme_texcs_tl ,
    texcs     .default:n           = blue ,
    
    keywd     .usage:n             = general ,
    keywd     .tl_set:N            = \l__codelist_colorscheme_keywd_tl ,
    keywd     .default:n           = cyan ,
    
    emph      .usage:n             = general ,
    emph      .tl_set:N            = \l__codelist_colorscheme_emph_tl ,
    emph      .default:n           = red ,
      
    rule      .usage:n             = general ,
    rule      .tl_set:N            = \l__codelist_colorscheme_rule_tl ,
    rule      .default:n           = black ,

    number    .usage:n             = general ,
    number    .tl_set:N            = \l__codelist_colorscheme_number_tl ,
    number    .default:n           = black ,
    
    brightness  .usage:n           = general ,
    brightness  .tl_set:N          = \l__codelist_colorscheme_bright_tl ,
    brightness  .default:n         = 1 ,
    
    scheme    .usage:n             = general ,
    scheme    .choice: ,
    scheme    .default:n           = default ,
  }


\cs_new_protected:Npn \__codelist_set_colorscheme:n #1
  {
    \keys_set:nn { codelist / color scheme } {#1}
    \__codelist_set_colors:n \l__codelist_colorscheme_bright_tl    
  }


\cs_new_protected:Npn \__codelist_new_colorscheme:nn #1#2
  { 
    \keys_precompile:nnN { codelist / color scheme } {#2}
      \l__codelist_colorscheme_tmp_tl
    \keys_define:ne { codelist / color scheme }
      {
        scheme / #1
          .code:n = { \exp_not:V \l__codelist_colorscheme_tmp_tl }
      }
  }

\__codelist_new_colorscheme:nn
  {default}
  { bckgnd , string , comment , texcs , keywd , emph , rule , number , brightness }

\keys_set:nn { codelist / color scheme } 
  {scheme=default}

\__codelist_set_color_brightness:n \l__codelist_pckopt_colorsbright_tl


\NewDocumentCommand \setlistcolorscheme {m}
  { \__codelist_set_colorscheme:n {#1} }


\NewDocumentCommand \newlistcolorscheme {mm}
  { \__codelist_new_colorscheme:nn {#1}{#2} }


\keys_define:nn {codelist / options} 
  {  
    lststyle      .usage:n   =  general,
    lststyle      .value_required:n = true , 
    lststyle      .code:n    =  { \tl_set:Nn \l__codelist_opt_basestyle_tl {#1} }, 
  
    stringstyle   .usage:n   =   general,
    stringstyle   .value_required:n = true , 
    stringstyle   .code:n    =  { \tl_set:Nn \l__codelist_opt_stringstyle_tl {#1} },
  
    commentstyle  .usage:n   =   general,
    commentstyle  .value_required:n = true , 
    commentstyle  .code:n    =  { \tl_set:Nn \l__codelist_opt_commentstyle_tl {#1} },
  
    bckgndcolor   .usage:n   =   general,
    bckgndcolor   .value_required:n = true , 
    bckgndcolor   .code:n    =  { \tl_set:Nn \l__codelist_opt_bckgndcolor_tl { \__codecmm_color_select:n {#1} } },
  
    rulecolor     .usage:n   =   general,
    rulecolor     .value_required:n = true , 
    rulecolor     .code:n    =  { \tl_set:Nn \l__codelist_opt_rulecolor_tl { \__codecmm_color_select:n {#1} } },
  
    numbers       .usage:n   =   general,
    numbers       .value_required:n = true , 
    numbers       .code:n    =  { \tl_set:Nn \l__codelist_opt_numbers_tl {#1} },
  
    firstnumber   .usage:n   =   general,
    firstnumber   .value_required:n = true , 
    firstnumber   .code:n    =  { \tl_set:Nn \l__codelist_opt_firstnumber_tl {#1} },
  
    numberstyle   .usage:n   =   general,
    numberstyle   .value_required:n = true , 
    numberstyle   .code:n    =  { \tl_set:Nn \l__codelist_opt_numberstyle_tl {#1} },
  
    parindent     .usage:n   =   general,
    parindent     .value_required:n = true , 
    parindent     .code:n    =  { \dim_set:Nn\l__codelist_demo_parindent_dim{#1} },
  
  	codeprefix    .usage:n   =   general,
    codeprefix    .value_required:n = true , 
  	codeprefix    .code:n    =  { \tl_set:Nn \l__codelist_opt_codeprefix_tl {#1} },
  
  	resultprefix  .usage:n   =   general,
    resultprefix  .value_required:n = true , 
  	resultprefix  .code:n    =  { \tl_set:Nn \l__codelist_opt_resultprefix_tl {#1} },
  
    ruleht        .usage:n   =   general,
    ruleht        .value_required:n = true , 
    ruleht        .code:n    =  { \tl_set:Nn \l__codelist_ruleheight_tl {#1} },
    
    letter        .usage:n   =   general,
    letter        .value_required:n = true , 
    letter        .code:n    =  { \tl_set:Nn \l__codelist_opt_alsoletter_tl {#1} },
    
    other        .usage:n    =   general,
    other        .value_required:n = true , 
    other        .code:n     =  { \tl_set:Nn \l__codelist_opt_alsoother_tl {#1} },
    
    basicstyle    .usage:n   =   general,
    basicstyle    .value_required:n = true , 
    basicstyle    .code:n    =  { \tl_set:Nn \l__codelist_opt_basicstyle_tl {#1} },
  }


\cs_new_protected:Npn \__codelist_mainkeys:nnNN #1#2#3#4
  {
    \keys_define:nn {codelist / options} 
      {
        set #1       .usage:n   =  general,
        set #1       .value_required:n = true ,
        set #1       .code:n    =  
          { 
            \str_compare:eNeTF {\tl_head:n{##1}} = {[}
              { \__codelist_opt_set:nnwnw { #2 }{l__codelist_opt_ #1 _} ##1 ] \q_nil \q_stop    }
              { \__codelist_opt_set:nNnn  { #2 }{ #4 } {1} {##1}    }
          },
    
         #1          .usage:n   =   general,
         #1          .value_required:n = true , 
         #1          .code:n    =  
          { 
            \str_compare:eNeTF {\tl_head:n{##1}} = {[}
              { \__codelist_opt_put_right:nnwnw { #2 }{l__codelist_opt_ #1 _}   ##1 ] \q_nil \q_stop  }
              { \__codelist_opt_put_right:nNnn  { #2 }{ #4 } {1} {##1}   }
          },
     
         #1 style    .usage:n   =   general,
         #1 style    .value_required:n = true , 
         #1 style    .code:n    =  
          { 
            \str_compare:eNeTF {\tl_head:n{##1}} = {[}
              { \__codelist_opt_set:nwnw {l__codelist_opt_ #1 style_} ##1 ] \q_nil \q_stop   }
              { \tl_set:Nn #3 {##1}  }
          },
      }
  }

\__codelist_mainkeys:nnNN {texcs}{moretexcs}
  \l__codelist_opt_texcsstyle_A_tl
  \l__codelist_opt_texcs_A_clist
\__codelist_mainkeys:nnNN {keywd}{morekeywords}
  \l__codelist_opt_keywdstyle_A_tl
  \l__codelist_opt_keywd_A_clist  
\__codelist_mainkeys:nnNN {emph}{moreemph}
  \l__codelist_opt_emphstyle_A_tl
  \l__codelist_opt_emph_A_clist


\tl_new:N \l__codelist_deprecated_ones_tl
%%{texcs}{moretexcs}{1...4}{A...D}
\cs_new_protected:Npn \__codelist_deprecated_ones:nnnn #1#2#3#4
  {

    \tl_put_right:Ne \l__codelist_deprecated_ones_tl
      {
        set #1  #3      .usage:n   =   general ,
        set #1  #3      .value_required:n = true ,
        set #1  #3      .code:n    =  
          { 
            \exp_not:N \msg_warning:nnnnn { codelist / deprecated } {key}
              {key0 #3-A}{set #1  #3 }{set #1  = [ #3 ]{##1}}
    
            \exp_not:N \__codelist_opt_set:nNnn {#2} \exp_not:c {l__codelist_opt_ #1 _  #4 _clist}{ #3 }{##1}
          } ,
      
         #1  #3         .usage:n   =   general,
         #1  #3         .value_required:n = true ,
         #1  #3         .code:n    =  
          { 
            \exp_not:N \msg_warning:nnnnn { codelist / deprecated } {key}
              {key0 #3-B}{ #1  #3 }{ #1  = [ #3 ]{##1}}
    
            \exp_not:N \__codelist_opt_put_right:nNnn {#2} \exp_not:c {l__codelist_opt_ #1 _  #4 _clist}{ #3 }{##1}
          } ,
      
         #1  #3 style   .usage:n   =   general ,
         #1  #3 style   .value_required:n = true ,
         #1  #3 style   .code:n    =  
          { 
            \exp_not:N \msg_warning:nnnnn { codelist / deprecated } {key}
              {key0 #3-C}{ #1  #3 style}{ #1 style = [ #3 ]{##1}}
    
            \exp_not:N \tl_set:Nn \exp_not:c {l__codelist_opt_ #1 style_ #4 _tl} {##1}
          } ,
      }  
  
  }
\cs_generate_variant:Nn   \__codelist_deprecated_ones:nnnn {nnVe}

    \int_set:Nn \l__codelist_loop_i_int {1}
    \int_do_while:nNnn \l__codelist_loop_i_int < 4
      {
        \int_incr:N \l__codelist_loop_i_int
        \__codelist_deprecated_ones:nnVe {texcs}{moretexcs}{\l__codelist_loop_i_int} {\int_to_Alph:n \l__codelist_loop_i_int}
        \__codelist_deprecated_ones:nnVe {keywd}{morekeywords}{\l__codelist_loop_i_int} {\int_to_Alph:n \l__codelist_loop_i_int}
        \__codelist_deprecated_ones:nnVe {emph}{moreemph}{\l__codelist_loop_i_int} {\int_to_Alph:n \l__codelist_loop_i_int}
      }
%\tl_show:N \l__codelist_deprecated_ones_tl

\cs_generate_variant:Nn \keys_define:nn {nV}

\keys_define:nV {codelist / options} \l__codelist_deprecated_ones_tl



%%%%%%
%%% This one can't be protected
%%%%%%
\cs_new:Npn \__codelist_set_options:n #1 
  { \keys_set:nn {codelist / options}{#1} }


\tl_new:N \l__codelist_lstenv_initkeys_tl
\cs_new_protected:Npn \__codelist_init_styles:nn #1#2
  {
    \tl_set:cn 
      {l__codelist_opt_texcsstyle_ #1 _tl}
      {\bfseries \__codecmm_color_select:n { c__codelist_texcs #1 _color } }
    \tl_put_right:Ne 
      \l__codelist_lstenv_initkeys_tl
      { texcsstyle = *[#2]{\exp_not:c {l__codelist_opt_texcsstyle_ #1 _tl}} , }
      
    \tl_set:cn 
      {l__codelist_opt_keywdstyle_ #1 _tl}
      {\bfseries \__codecmm_color_select:n { c__codelist_keywd #1 _color } }
    \tl_put_right:Ne 
      \l__codelist_lstenv_initkeys_tl
      { keywordstyle = [#2]{\exp_not:c {l__codelist_opt_keywdstyle_ #1 _tl}} , }

    \tl_set:cn 
      {l__codelist_opt_emphstyle_ #1 _tl}
      {\bfseries \__codecmm_color_select:n { c__codelist_emph #1 _color } }
    \tl_put_right:Ne 
      \l__codelist_lstenv_initkeys_tl
      { emphstyle = [#2]{\exp_not:c {l__codelist_opt_emphstyle_ #1 _tl}} ,  }
  }
\cs_generate_variant:Nn \__codelist_init_styles:nn {eV}

\int_zero:N \l__codelist_loop_i_int
\int_do_while:nNnn \l__codelist_loop_i_int < \l__codelist_nkeys_int
  {
    \int_incr:N \l__codelist_loop_i_int
    \__codelist_init_styles:eV  
      {\int_to_Alph:n \l__codelist_loop_i_int}
      {\l__codelist_loop_i_int}
  }
%\tl_show:N \l__codelist_lstenv_initkeys_tl

\__codelist_set_options:n 
  {
	  stringstyle  = \__codecmm_color_select:n{ c__codelist_string_color }    , 
    commentstyle = \__codecmm_color_select:n{ c__codelist_comment_color }   ,
    basicstyle   = \footnotesize\ttfamily  , 
    lststyle     = {codestyle} , 
	  numbers      = none        , 
    numberstyle  = \tiny\__codecmm_color_select:n{ c__codelist_number_color }  , 
    codeprefix   = \LaTeX{} Code:       , 
    resultprefix = \LaTeX{} Result:     ,
    bckgndcolor  = c__codelist_bckgnd_color ,
    rulecolor    = c__codelist_rule_color   ,
    ruleht       = 1 ,
    parindent    = \l__codelist_org_parindent_dim ,
    letter       = { _ , : , @ } ,
    other        = { } ,
    firstnumber  = last ,
  }


%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%
%%%
%%%  From doctools.dtx file
%%% lstlistings 'definitions'
%%%
%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%

%%% listings
%

\cs_new_protected:Npn \__codelist_set_style:nn #1#2
  {
    \lstdefinestyle{codestyle}{
      extendedchars     =      true  , % allows or prohibits extended characters
      keepspaces        =      true  ,   %
      linewidth         =      \linewidth  ,   % defines the base line width for listings.
      showlines         =      false  , % prints empty lines at the end of listings
                                  %%%  Space and placement
      floatplacement    =      tbp  ,      % is used as float place specifier
      boxpos            =      c  , % c  ,b  ,t
                                  %%% characters
                                  % in listings  , that means (national)
                                  % characters of codes 128-255.
      upquote           =      true  ,   % determines printing of quotes
      tabsize           =      2  ,   % chars of tab
      showtabs          =      false  ,   % do not show tabs
      showspaces        =      false  ,   % do not show spaces
      showstringspaces  =      false  ,   % do not show blank spaces in string
    
      numberbychapter   =      true  ,   %
      captionpos        =      b  ,   % t  ,b
      abovecaptionskip  =      \smallskipamount  , % the vertical space respectively above
      belowcaptionskip  =      \smallskipamount  , % or below each caption
                                  %%% Margins and line shape
      xleftmargin       =      0pt  ,   % extra margins
      xrightmargin      =      0pt  ,   %
      resetmargins      =      false  ,   % indention from list environments like enumerate
                                  % or itemize is reset  , i.e. not used.
      columns           =      flexible  ,   % 

    	basicstyle        =      {\l__codelist_opt_basicstyle_tl}  , %%\footnotesize\ttfamily  ,  
    
      numberstyle       =      {\l__codelist_opt_numberstyle_tl}  ,   % style of numbers
      numbersep         =      5pt  ,            % distance to text
      numberblanklines  =      true  ,    %
      stepnumber        =      1  ,             % seperation between numbers
      numberfirstline   =      false  ,    % number first line always
        
      rulecolor         =      {\l__codelist_opt_rulecolor_tl}  ,
    	backgroundcolor   =      {\l__codelist_opt_bckgndcolor_tl}  ,
      stringstyle       =      {\l__codelist_opt_stringstyle_tl}  ,
      commentstyle      =      {\l__codelist_opt_commentstyle_tl}  ,
      
      %morecomment       =      [if][][2]{//} ,
      %morecomment       =      [if][\color{red}][2]{//} , %{#2} ,
      
      framerule         =      0pt  ,                        %0.4pt  ,
    	nolol             =      true  ,
    	frame             =      none  ,
    	aboveskip         =      0pt  ,%-2ex  ,
      belowskip         =      0pt  ,%-2ex  ,
      lineskip          =      0pt  , % specifies additional space between lines in listings.
      
    	rulesep           =      0pt  ,
      breakatwhitespace =      false  ,   % allows line breaks only at white space.
      breakautoindent   =      true  ,   % apply intendation	
      breaklines        =      true  ,
    	breakindent       =      3em  ,

      language          =     [LaTeX]TeX  ,

%%% LaTeX Dialects    
      #1                %% This must end in a comma

%%% Styles [1-8]
      #2
    }
  }
\cs_generate_variant:Nn \__codelist_set_style:nn {VV}

\__codelist_set_style:VV \l__codelist_pckopt_dialect_tl \l__codelist_lstenv_initkeys_tl
%{\char_generate:nn{13}{12}}
%\__codelist_set_style:Vn \l__codelist_pckopt_dialect_tl {^^M}

\lstset{style=codestyle}

%%%
%%% extending scontents package options !!!!
%%% changing it's default key handling from \msg_error to 'store-env'.
%%%
\keys_define:nn { scontents / scontents}
  {
  	st          .meta:nn          = 
      { scontents } 
      { store-env = {#1} } ,
    st          .value_required:n = true ,
  	store-at    .meta:nn          = 
      { scontents } 
      { store-env = {#1} } ,
    store-at    .value_required:n = true,
    unknown     .undefine: ,
    unknown     .code:n           = 
      { 
        \keys_set:ne {scontents}
          { store-env = {\l_keys_key_str} } 
      }
 }

\newenvsc{codestore}


%%%%%%%%%
%%%
%%% yep, redefining <verbatimsc> environment from scontents
%%% to change the 'listings' defaults/highlights !
%%%
%%%%%%%%%


\cs_undefine:c{verbatimsc}
\cs_undefine:c{verbatimsc@@}
\cs_undefine:c{verbatimsc@}
\cs_undefine:c{endverbatimsc}

\tl_new:N \l__codelist_lstenv_tmpa_tl
\cs_new_protected:Npn \__codelist_opt_grab:nnn #1#2#3
  {
    \tl_put_right:Nn \l__codelist_lstenv_tmpa_tl { #1 = [#2]{#3} , }
  }
\cs_new_protected:Npn \__codelist_lstset:
  {
    \seq_if_empty:NF \l__codelist_opt_keys_seq
      {
        \seq_remove_duplicates:N \l__codelist_opt_keys_seq
        \seq_map_inline:Nn \l__codelist_opt_keys_seq 
          {
            \__codelist_opt_grab:nnn ##1    %% each item has three parameters...
          }
      }
      
    \exp_args:Ne \lstset
      {
        style         =     {\l__codelist_opt_basestyle_tl},
        alsoletter    =     {\l__codelist_opt_alsoletter_tl},
        alsoother     =     {\l__codelist_opt_alsoother_tl},
  	    numbers       =     {\l__codelist_opt_numbers_tl},
        firstnumber   =     {\l__codelist_opt_firstnumber_tl},
        \l__codelist_lstenv_tmpa_tl
      }
  }
    
%%%%%%%%%%%%%%
%%%
%%% keeping this consistent with 
%%% \lstnewenvironment{codesyntax*}[1][]
%%%
%%%%%%%%%%%%%%
\lstnewenvironment{verbatimsc}
  { \__codelist_lstset: }
  {}


\NewDocumentCommand \setcodekeys {m}
  { \keys_set:nn {codelist / options}{#1} }


\NewDocumentCommand \newcodekey {mm}
  {
    \keys_precompile:nnN {codelist / options} {#2}
      \l__codelist_tmpa_tl
 
    \keys_define:ne {codelist / options}
      {
        #1 .value_forbidden:n = true ,
        #1 .code:n = {\exp_not:V \l__codelist_tmpa_tl} ,
      }
  }  

\NewDocumentCommand \setnewcodekey {mm}
  {
    \msg_warning:nnnnn { codelist / deprecated } {command} {codekey01}
      {\setnewcodekey} {\newcodekey}
    \newcodekey{#1}{#2}
  }

\cs_new_protected:Npn \__codelist_ts_settings:nn #1#2
  {
    \bool_if:NTF #1
      { % paragraph wide OR one below the other
        \dim_set:Nn \l__codelist_width_dim {\l__codecmm_textcolwidth_dim}
        \dim_set:Nn \l__codelist_offset_dim {0pt}
        \cs_set:Npn \__codelist_rule_in: {\__codecmm_rule:n {\l__codelist_ruleheight_tl}}
        \cs_set:Npn \__codelist_rule_out: {}
      }
      { % half as wide OR side-by-side
        \dim_set:Nn \l__codelist_width_dim {0.5\l__codecmm_textcolwidth_dim}
        \dim_set:Nn \l__codelist_offset_dim {0.5\l__codelist_width_dim}
        \cs_set:Npn \__codelist_rule_in: {}
        \cs_set:Npn \__codelist_rule_out: {\__codecmm_rule:n {\l__codelist_ruleheight_tl}}
      }
  
      \__codelist_set_options:n {#2}
      \tl_if_blank:VTF \l__codelist_opt_codeprefix_tl
        {
          \vcoffin_set:Nnn \__codelist_code_label_coffin {\l__codelist_width_dim}
            {}
        }
        {
          \vcoffin_set:Nnn \__codelist_code_label_coffin {\l__codelist_width_dim}
            {
              \raggedright
              \l__codelist_opt_codeprefix_tl
            }
        }
        
%       \coffin_show_structure:N \__codelist_code_label_coffin

      \tl_if_blank:VTF \l__codelist_opt_resultprefix_tl
        {
          \vcoffin_set:Nnn \__codelist_demo_label_coffin {\l__codelist_width_dim}
            {}
        }
        {
          \vcoffin_set:Nnn \__codelist_demo_label_coffin {\l__codelist_width_dim}
            {
              \raggedright
              \l__codelist_opt_resultprefix_tl
            }
        }
  }

\cs_new_protected:Npn \__codelist_codecoffin:nnnn #1#2#3#4
  {
    \vcoffin_set:Nnn \__codelist_code_coffin {\l__codelist_width_dim}
      {
        \raggedright #4
        \tl_if_blank:nTF {#2}
          { #3 {#1} }
          { #3 [#2]{#1} }
      }
  }

\cs_new_protected:Npn \__codelist_democoffin:nn #1#2
  {
    \vcoffin_set:Nnn \__codelist_demo_coffin {\l__codelist_width_dim}
      { 
        \__codelist_rule_in:
        \group_begin:
%          \skip_vertical:n {\l__codecmm_largerskip_dim}
          \skip_vertical:n {\l__codecmm_tinyskip_dim}
          \setlength\parindent{\l__codelist_demo_parindent_dim}
          \tl_if_blank:nTF {#2}
            { \getstored {#1} }
            { \getstored [#2]{#1} }
          \skip_vertical:n {\l__codecmm_tinyskip_dim}
        \group_end:
        \__codelist_rule_in:
      }
  }

\cs_new_protected:Npn \__codelist_ts_code:nnnnn #1#2#3#4#5
  {
    \__codecmm_set_textcolwidth:
    \group_begin:
      \__codelist_ts_settings:nn {#1}{#2}
      \__codelist_codecoffin:nnnn {#3}{#4}{#5}{}
      
        \coffin_join:NnnNnnnn
          \__codelist_code_label_coffin {l}{b}
          \__codelist_code_coffin {l}{t}
          {0pt}{-1ex}
        \skip_vertical:n{-1ex}\noindent
        \coffin_typeset:Nnnnn \__codelist_code_label_coffin {l}{t}{\l__codelist_offset_dim}{0pt}
        \bool_if:NTF \l__codelist_tscode_peek_bool
          { \skip_vertical:n {\l__codecmm_large_skip} }
          { \skip_vertical:n {\l__codecmm_largeline_skip} }
    \group_end: 
  }


\bool_new:N \l__codelist_tscode_peek_bool
\tl_new:N \l__codelist_tscode_tl

\regex_const:Nn \c__codelist_peek_regex 
  {
    \c{typesetcode} | \c{tscode} | \c{typesetmergedcode} | \c{tsmergedcode} | 
    \c{typesetdemo} | \c{tsdemo} | \c{typesetresult} | \c{tsresult}
  }

\xpeekahead_set:NNTF
  \__codelist_cmd_peek_tscode:
  \c__codelist_peek_regex
  { 
   \bool_set_true:N  \l__codelist_tscode_peek_bool
    \l__codelist_tscode_tl
  }
  { 
    \bool_set_false:N \l__codelist_tscode_peek_bool
    \l__codelist_tscode_tl
  }    
  



\NewDocumentCommand{\tscode}{sO{}mO{}}
  {
    \tl_set:Nn \l__codelist_tscode_tl { \__codelist_ts_code:nnnnn {#1}{#2}{#3}{#4}{\typestored} }
    \xpeekahead_cmd_peek:N \__codelist_cmd_peek_tscode:
  }
\cs_new_eq:NN \typesetcode \tscode 


\NewDocumentCommand{\tsmergedcode}{sO{}m}
  {
    \tl_set:Nn \l__codelist_tscode_tl { \__codelist_ts_code:nnnnn {#1}{#2}{#3}{}{\mergesc[typestored,print-cmd]} }
    \xpeekahead_cmd_peek:N \__codelist_cmd_peek_tscode:
  }
\cs_new_eq:NN \typesetmergedcode \tsmergedcode

\coffin_new:N \__codelist_code_coffin
\coffin_new:N \__codelist_code_label_coffin
\coffin_new:N \__codelist_demo_coffin
\coffin_new:N \__codelist_demo_label_coffin
\coffin_new:N \__codelist_code_demo_coffin

\dim_new:N \l__codelist_width_dim
\dim_new:N \l__codelist_offset_dim

\dim_new:N \l__codelist_code_height_dim
\dim_new:N \l__codelist_demo_height_dim


\cs_new_protected:Npn \__codelist_ts_democode:nnnn #1#2#3#4
  {
    \__codecmm_set_textcolwidth:
    \group_begin:
      \par\setlength\parindent{0pt}
      \__codelist_ts_settings:nn {#1}{#2}
      
      \__codelist_codecoffin:nnnn {#3}{#4}{\typestored}{ \skip_vertical:n {0.1ex} }
      \__codelist_democoffin:nn {#3}{#4}

      \bool_if:NTF #1
        { % one below the other
          \coffin_join:NnnNnnnn
            \__codelist_code_label_coffin {l}{b}
            \__codelist_code_coffin {l}{t}
            {0pt}{-1ex}
          \skip_vertical:n {-1ex}
          \coffin_typeset:Nnnnn \__codelist_code_label_coffin {l}{t}{0pt}{0pt}
          \skip_vertical:n {1ex}
          \coffin_join:NnnNnnnn
            \__codelist_demo_label_coffin {l}{b}
            \__codelist_demo_coffin {l}{t}
            {0pt}{-1ex}
          \coffin_typeset:Nnnnn \__codelist_demo_label_coffin {l}{t}{0pt}{0pt}
          \bool_if:NTF \l__codelist_tscode_peek_bool
            { \skip_vertical:n {\l__codecmm_large_skip} }
            { \skip_vertical:n {\l__codecmm_largeline_skip} }
        }
        { % side-by-side          
          \dim_set:Ne \l__codelist_code_height_dim { \coffin_ht_plus_dp:N \__codelist_code_coffin}
          \dim_set:Ne \l__codelist_demo_height_dim { \coffin_ht_plus_dp:N \__codelist_demo_coffin}

          \coffin_join:NnnNnnnn
            \__codelist_code_label_coffin {r}{b}
            \__codelist_demo_label_coffin {l}{b}
            {0pt}{0pt}    
          \coffin_join:NnnNnnnn
            \__codelist_code_coffin {r}{vc}
            \__codelist_demo_coffin {l}{vc}
            {0pt}{0pt}  
              
        %%%
        %%% a new coffin, just to have the rules inside
        %%%     
          \dim_compare:nNnTF \l__codelist_code_height_dim < \l__codelist_demo_height_dim
            {
              \vcoffin_set:Nnn \__codelist_code_demo_coffin {2\l__codelist_width_dim}
                {
                  \coffin_typeset:Nnnnn \__codelist_code_label_coffin {l}{t}{0pt}{0pt}
                  \skip_vertical:n {0.5ex}
                  \__codelist_rule_out:
%                  \skip_vertical:n {0.8611pt}  % was 0.20ex
                  \skip_vertical:n {0.20ex}  % was 0.20ex
                  \coffin_typeset:Nnnnn \__codelist_code_coffin {l}{t}{0pt}{0pt}
%                  \skip_vertical:n {0.8611pt}  % was 0.20ex
                  \skip_vertical:n {0.20ex}  % was 0.20ex
                  \__codelist_rule_out:
                }
            }
            {
              \vcoffin_set:Nnn \__codelist_code_demo_coffin {2\l__codelist_width_dim}
                {
                  \coffin_typeset:Nnnnn \__codelist_code_label_coffin {l}{t}{0pt}{0pt}                  
                  \skip_vertical:n {0.5ex}
                  \__codelist_rule_out:
                  \skip_vertical:n {0.8611pt} % was 0.20ex
                  \coffin_typeset:Nnnnn \__codelist_code_coffin {l}{t}{0pt}{0pt}
                  \skip_vertical:n {1.0764pt} % was 0.25ex
                  \__codelist_rule_out:
                }
            }

          \coffin_typeset:Nnnnn \__codelist_code_demo_coffin {l}{t}{0pt}{0pt}
          
          \bool_if:NTF \l__codelist_tscode_peek_bool
            { \skip_vertical:n {\l__codecmm_large_skip} }
            { \skip_vertical:n {\l__codecmm_largeline_skip} }
        }
    \group_end:
  }
  
\NewDocumentCommand{\tsdemo}{sO{}mO{}}
  {
    \tl_set:Nn \l__codelist_tscode_tl { \__codelist_ts_democode:nnnn {#1}{#2}{#3}{#4} }
    \xpeekahead_cmd_peek:N \__codelist_cmd_peek_tscode: 
  }
\cs_new_eq:NN \typesetdemo \tsdemo 

\NewDocumentCommand{\tsexec}{mO{}}
  {
    \tl_if_blank:nTF {#2}
      { \getstored{#1} }
      { \getstored[#2]{#1} }
  }

\cs_new_protected:Npn \__codelist_ts_demo:nnnn #1#2#3#4
  {
    \__codecmm_set_textcolwidth:
    \group_begin:
      \par\setlength\parindent{0pt}
      \__codelist_ts_settings:nn {#1}{#2}
      
      \cs_set:Npn \__codelist_rule_in: {\__codecmm_rule:n {\l__codelist_ruleheight_tl}}
    
      \__codelist_democoffin:nn {#3}{#4}

      \coffin_join:NnnNnnnn
        \__codelist_demo_label_coffin {l}{b}
        \__codelist_demo_coffin {l}{t}
        {0pt}{-1ex}
      \coffin_typeset:Nnnnn \__codelist_demo_label_coffin {l}{t}{\l__codelist_offset_dim}{0pt}
        \bool_if:NTF \l__codelist_tscode_peek_bool
          { \skip_vertical:n {\l__codecmm_large_skip} }
          { \skip_vertical:n {\l__codecmm_largeline_skip} }
    \group_end:
  }

\NewDocumentCommand{\tsresult}{sO{}mO{}}
  {
    \tl_set:Nn \l__codelist_tscode_tl { \__codelist_ts_demo:nnnn {#1}{#2}{#3}{#4} }
    \xpeekahead_cmd_peek:N \__codelist_cmd_peek_tscode:
  }
\cs_new_eq:NN \typesetresult \tsresult 


%%%
%%% from https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue
\lstset{literate=
  {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1
  {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1
  {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1
  {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1
  {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1
  {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1
  {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1
  {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1
	{ã}{{\~{a}}}1 {Ã}{{\~{A}}}1 
  {õ}{{\~{o}}}1	{Õ}{{\~{O}}}1
	{ñ}{{\~{n}}}1 {Ñ}{{\~{N}}}1
  {ý}{{\'{y}}}1 {Ý}{{\'{Y}}}1  {ÿ}{{\"{y}}}1 {Ÿ}{{\"{Y}}}1
  {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1
  {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1
  {€}{{\EUR}}1 {£}{{\pounds}}1
}

%\seq_show:N \l__codelist_opt_keys_seq  
%\seq_clear:N \l__codelist_opt_keys_seq  
\endinput
