%%%==============================================================================
%% 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.4a} {2025/10/29}
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/pgfkeysearch
%%
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2022/06/01]


\ProvidesExplPackage
    {pgfkeysearch}
    {2025/10/29}
    {1.4a}
    {pgfkeys Search Extension}

\ExplSyntaxOn
%%%%%%%
%%%
%%% 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 { pgfkeysearch }
  {
     name        = {pgfkeysearch} ,
     prefix      = {pgfkeysearch} ,
     date        = {2025/10/29},
     version     = {1.4a} ,
     description = {pgfkeys~ search~ extension}
  }
%%%%%%%
%%% End of cut-n-paste
%%%%%%%


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

\keys_define:nn { pgfkeysearch }
{
  root~ search .usage:n = general,
	root~ search .bool_set:N = \l__pgfkeysearch_root_bool,
  root~ search .initial:n = {false},
}
\ProcessKeyOptions [pgfkeysearch] 

\cs_new_protected:Npn \pgfkeysearch_settings:n #1
  {
    \keys_set:nn {pgfkeysearch}{#1}
  } 

%%%%%%%%%%%%%%%
%%%
%%% _keysearch allows to find a key, 
%%% if it's defined from 'anywhere' in the tree. I mean, upwards until, likely, /tikz/<key>
%%% if it isn't defined, returns nothing (no error triggered)
%%%
%%%%%%%%%%%%%%%
\seq_new:N \l__pgfkeysearch_pathterms_seq
\seq_new:N \l__pgfkeysearch_pathtree_seq
\tl_new:N  \l__pgfkeysearch_path_tl

\cs_generate_variant:Nn \tl_set:Nn {Ne}

%%%%%%%%%%%%%%%
%%%
%%% Given a single path /A/B/C/D it will look after
%%%  /A/B/C/D/<key> 
%%%  /A/B/C/<key>
%%%  /A/B/<key>
%%%  /A/<key>
%%%  /<key> (if "root search" set)
%%%    stoping at the first hit
%%%
%%%%%%%%%%%%%%%
\prg_new_protected_conditional:Npnn \pgfkeysearch_keysearch:nnN #1#2#3 {TF,T,F}
  {
    \seq_set_split:Nne \l__pgfkeysearch_pathterms_seq {/} {#1}
    \seq_remove_all:Nn \l__pgfkeysearch_pathterms_seq {}
    \tl_clear:N \l__pgfkeysearch_path_tl
    \seq_clear:N \l__pgfkeysearch_pathtree_seq
    \bool_if:NTF \l__pgfkeysearch_root_bool
      { \seq_put_right:Nn \l__pgfkeysearch_pathtree_seq {} }
      {}
    \seq_map_inline:Nn \l__pgfkeysearch_pathterms_seq
      {
        \tl_put_right:Nn \l__pgfkeysearch_path_tl {/##1}
        \seq_put_right:NV \l__pgfkeysearch_pathtree_seq \l__pgfkeysearch_path_tl
      }
    \seq_reverse:N \l__pgfkeysearch_pathtree_seq

    \cs_set_eq:NN \__pgfkeysearch_return: \prg_return_false:
    
    \seq_map_inline:Nn \l__pgfkeysearch_pathtree_seq
      {
        \cs_if_exist:cTF {pgfk@##1/#2}
          {
            \tl_set:Ne #3 {\exp_not:c{pgfk@##1/#2}}
            \cs_set_eq:NN \__pgfkeysearch_return: \prg_return_true:
            \seq_map_break:
          }
          {}
      }
    \__pgfkeysearch_return:
  }

 
\cs_new_protected:Npn \pgfkeysearch_keysearch:nnnTF
  {
    \msg_warning:nnnxx {pgfkeysearch} {deprecated} {singlepath}{\cs_to_str:N \pgfkeysearch_keysearch:nnnTF}{\cs_to_str:N \pgfkeysearch_keysearch:nnNTF}
    \pgfkeysearch_keysearch:nnNTF
  }
\cs_new_protected:Npn \pgfkeysearch_keysearch:nnnT
  {
    \msg_warning:nnnxx {pgfkeysearch} {deprecated} {singlepath}{\cs_to_str:N \pgfkeysearch_keysearch:nnnT}{\cs_to_str:N \pgfkeysearch_keysearch:nnNT}
    \pgfkeysearch_keysearch:nnNT
  }
\cs_new_protected:Npn \pgfkeysearch_keysearch:nnnF
  {
    \msg_warning:nnnxx {pgfkeysearch} {deprecated} {singlepath}{\cs_to_str:N \pgfkeysearch_keysearch:nnnF}{\cs_to_str:N \pgfkeysearch_keysearch:nnNF}
    \pgfkeysearch_keysearch:nnNF
  }

%%%%%%%%%%%%%%%
%%%
%%% #1 shall be a comma separated list of paths (can be a single one)
%%% it searchs for a key in every path, stoping at the first hit.
%%%
%%%%%%%%%%%%%%%
\prg_new_protected_conditional:Npnn \pgfkeysearch_multipath_keysearch:nnN #1#2#3 {T,F,TF}
  {
    \bool_set_false:N \l__pgfkeysearch_multipath_keyfound_bool
    \clist_map_inline:nn {#1}
      {
        \pgfkeysearch_keysearch:nnNTF {##1}{#2} #3
          { \clist_map_break: }
          {}
      }
    \__pgfkeysearch_return:
  }
 
\cs_new_protected:Npn \pgfkeysearch_multipath_keysearch:nnnTF
  {
    \msg_warning:nnnxx {pgfkeysearch} {deprecated} {multipath}{\cs_to_str:N \pgfkeysearch_multipath_keysearch:nnnTF}{\cs_to_str:N \pgfkeysearch_multipath_keysearch:nnNTF}
    \pgfkeysearch_multipath_keysearch:nnNTF
  }
\cs_new_protected:Npn \pgfkeysearch_multipath_keysearch:nnnT
  {
    \msg_warning:nnnxx {pgfkeysearch} {deprecated} {multipath}{\cs_to_str:N \pgfkeysearch_multipath_keysearch:nnnT}{\cs_to_str:N \pgfkeysearch_multipath_keysearch:nnNT}
    \pgfkeysearch_multipath_keysearch:nnNT
  }
\cs_new_protected:Npn \pgfkeysearch_multipath_keysearch:nnnF
  {
    \msg_warning:nnnxx {pgfkeysearch} {deprecated} {multipath}{\cs_to_str:N \pgfkeysearch_multipath_keysearch:nnnF}{\cs_to_str:N \pgfkeysearch_multipath_keysearch:nnNF}
    \pgfkeysearch_multipath_keysearch:nnNF
  }


%%%%%%%%%%%%%%%
%%%
%%% The caveats: this isn't expandable.
%%%
%%%%%%%%%%%%%%%
%%%
%%% This is the more generic one. 
%%% #1 is the path (or list of paths)
%%% #2 is the <key>
%%% #3 is the macro that will receive the key value (if any)
%%%
%%%%%%%%%%%%%%%

\NewDocumentCommand{\pgfkeysearchsettings}{m}
  { \pgfkeysearch_settings:n {#1} }

\NewDocumentCommand{\pgfkeysearchvalueof}{mmm}
  {
    \pgfkeysearch_multipath_keysearch:nnNTF {#1}{#2}#3
      { }
      { \tl_set:Nn #3 {} }
  }
\let\pgfkeysearch\pgfkeysearchvalueof

\NewDocumentCommand{\pgfkeysearchvalueofTF}{mmmmm}
  {
    \pgfkeysearch_multipath_keysearch:nnNTF {#1}{#2}#3
      { #4 }
      { 
        \tl_set:Nn #3 {} 
        #5
      }
  }
\let\pgfkeysearchTF\pgfkeysearchvalueofTF
