[latex3-commits] [git/LaTeX3-latex3-latex3] expandable-file-parse: Implement expandable \file_parse_full_name:n (8c3846b5b)

PhelypeOleinik tex.phelype at gmail.com
Wed Jun 24 19:37:12 CEST 2020


Repository : https://github.com/latex3/latex3
On branch  : expandable-file-parse
Link       : https://github.com/latex3/latex3/commit/8c3846b5b18500c9b4743167ec45db13f124888a

>---------------------------------------------------------------

commit 8c3846b5b18500c9b4743167ec45db13f124888a
Author: PhelypeOleinik <tex.phelype at gmail.com>
Date:   Wed Jun 24 14:37:12 2020 -0300

    Implement expandable \file_parse_full_name:n
    
    and have \file_parse_full_name:nNNN use the expandable implementation underneath


>---------------------------------------------------------------

8c3846b5b18500c9b4743167ec45db13f124888a
 l3kernel/l3file.dtx | 152 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 108 insertions(+), 44 deletions(-)

diff --git a/l3kernel/l3file.dtx b/l3kernel/l3file.dtx
index c189e4bdd..8b941181b 100644
--- a/l3kernel/l3file.dtx
+++ b/l3kernel/l3file.dtx
@@ -3358,63 +3358,127 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\file_parse_full_name:nNNN, \file_parse_full_name:VNNN}
-% \begin{macro}
-%   {\@@_parse_full_name_auxi:w, \@@_parse_full_name_split:nNNNTF}
-%   Parsing starts by stripping off any surrounding quotes.  Then find
-%   the directory |#4| by splitting at the last~|/|.  (The auxiliary
-%   returns \texttt{true}/\texttt{false} depending on whether it found
-%   the delimiter.)  We correct for the case of a file in the root |/|,
-%   as in that case we wish to keep the trailing (and only) slash.  Then
-%   split the base name |#5| at the last dot.  If there was indeed a
-%   dot, |#5| contains the name and |#6| the extension without the dot,
-%   which we add back for convenience.  In the special case of no
-%   extension given, the auxiliary stored the name into |#6|, we just
-%   have to move it to |#5|.
-%    \begin{macrocode}
-\cs_new_protected:Npn \file_parse_full_name:nNNN #1#2#3#4
-  {
-    \exp_after:wN \@@_parse_full_name_auxi:w
-      \tl_to_str:n { #1 " #1 " } \s_@@_stop #2#3#4
+% \begin{macro}{\file_parse_full_name:n, \file_parse_full_name_apply:nN}
+% \begin{macro}{\@@_parse_full_name_end:nnn}
+%   The main parsing macro \cs{file_parse_full_name_apply:nN} passes the
+%   file name |#1| thorugh \cs{__kernel_file_name_sanitize:n} so that we
+%   have a single normalised way to treat files internally.
+%   \cs{file_parse_full_name:n} uses the former, with a dummy macro to
+%   leave each part of the name within a pair of braces.
+%    \begin{macrocode}
+\cs_new:Npn \file_parse_full_name:n #1
+  {
+    \file_parse_full_name_apply:nN {#1}
+      \@@_parse_full_name_end:nnn
   }
-\cs_generate_variant:Nn \file_parse_full_name:nNNN { V }
-\cs_new_protected:Npn \@@_parse_full_name_auxi:w
-  #1 " #2 " #3 \s_@@_stop #4#5#6
-  {
-    \@@_parse_full_name_split:nNNNTF {#2} / #4 #5
-      { \str_if_empty:NT #4 { \str_set:Nn #4 { / } } }
-      { }
-    \exp_args:No \@@_parse_full_name_split:nNNNTF {#5} . #5 #6
-      { \str_put_left:Nn #6 { . } }
+\cs_new:Npn \@@_parse_full_name_end:nnn #1 #2 #3
+  { {#1} {#2} {#3} }
+\cs_new:Npn \file_parse_full_name_apply:nN #1
+  {
+    \exp_args:Ne \@@_parse_full_name_auxi:nN
+      { \__kernel_file_name_sanitize:n {#1} }
+  }
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_parse_full_name_auxi:nN}
+% \begin{macro}{\@@_parse_full_name_area:nw}
+%   \cs{@@_parse_full_name_area:nw} splits the file name into chunks
+%   separated by |/|, until the last one is reached.  The last chunk is
+%   the file name plus the extension, and everything before that is the
+%   path.  When \cs{@@_parse_full_name_area:nw} is done, it leaves
+%   the path within braces after the scan mark \cs{s_@@_stop} and
+%   proceeds parsing the actual file name.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_full_name_auxi:nN #1
+  {
+    \@@_parse_full_name_area:nw { } #1
+      / \q_@@_nil \s_@@_stop
+  }
+\cs_new:Npn \@@_parse_full_name_area:nw #1 #2 / #3 \s_@@_stop
+  {
+    \@@_quark_if_nil:nTF {#3}
       {
-        \str_set_eq:NN #5 #6
-        \str_clear:N #6
+        \@@_parse_full_name_base:nw { } #2 . \q_@@_nil
+          \s_@@_stop {#1}
       }
+      { \@@_parse_full_name_area:nw { #1 / #2 } #3 \s_@@_stop }
   }
-\cs_new_protected:Npn \@@_parse_full_name_split:nNNNTF #1#2#3#4
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_parse_full_name_base:nw}
+%   \cs{@@_parse_full_name_base:nw} does roughly the same as above, but
+%   it separates the chunks at each period.  However here there's some
+%   extra complications:  In case |#1| is empty, it is assumed that the
+%   extension is actually empty, and the file name is |#2|.  Besides, an
+%   extra |.| has to be added to |#2| because it is later removed in
+%   \cs{@@_parse_full_name_tidy:nnnN}.  In any case, if there's an
+%   extension, it is returned with a leading |.|.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_full_name_base:nw #1 #2 . #3 \s_@@_stop
   {
-    \cs_set_protected:Npn \@@_tmp:w ##1 ##2 #2 ##3 \s_@@_stop
+    \@@_quark_if_nil:nTF {#3}
       {
-        \tl_if_empty:nTF {##3}
+        \tl_if_empty:nTF {#1}
           {
-            \str_set:Nn #4 {##2}
-            \tl_if_empty:nTF {##1}
-              {
-                \str_clear:N #3
-                \use_ii:nn
-              }
-              {
-                \str_set:Nx #3 { \str_tail:n {##1} }
-                \use_i:nn
-              }
+            \tl_if_empty:nTF {#2}
+              { \@@_parse_full_name_tidy:nnnN { } { } }
+              { \@@_parse_full_name_tidy:nnnN { .#2 } { } }
           }
-          { \@@_tmp:w { ##1 #2 ##2 } ##3 \s_@@_stop }
+          { \@@_parse_full_name_tidy:nnnN {#1} { .#2 } }
       }
-    \@@_tmp:w { } #1 #2 \s_@@_stop
+      { \@@_parse_full_name_base:nw { #1 . #2 } #3 \s_@@_stop }
   }
 %    \end{macrocode}
+%
+% \begin{macro}{\@@_parse_full_name_tidy:nnnN}
+%   Now we just need to tidy some bits left loose before.  The loop
+%   used in the two macros above start with a leading |/| and |.| in the
+%   file path an name, so here we need to remove them, except in the
+%   path, if it is a single |/|, in which case it's left as is.  After
+%   all's done, pass to |#4|.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_full_name_tidy:nnnN #1 #2 #3 #4
+  {
+    \exp_args:Nee #4
+      {
+        \tl_if_empty:nF {#3}
+          {
+            \str_if_eq:nnF {#3} { / }
+              { \use_none:n }
+          }
+            #3
+      }
+      {
+        \tl_if_empty:nF {#1}
+          { \use_none:n }
+            #1
+      }
+      {#2}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
 % \end{macro}
 % \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\file_parse_full_name:nNNN, \file_parse_full_name:VNNN}
+%    \begin{macrocode}
+\cs_new_protected:Npn \file_parse_full_name:nNNN #1 #2 #3 #4
+  {
+    \file_parse_full_name_apply:nN {#1}
+      \@@_full_name_assign:nnnNNN #2 #3 #4
+  }
+\cs_new_protected:Npn \@@_full_name_assign:nnnNNN #1 #2 #3 #4 #5 #6
+  {
+    \str_set:Nn #4 {#1}
+    \str_set:Nn #5 {#2}
+    \str_set:Nn #6 {#3}
+  }
+\cs_generate_variant:Nn \file_parse_full_name:nNNN { V }
+%    \end{macrocode}
+% \end{macro}
 %
 % \begin{macro}{\file_show_list:, \file_log_list:, \@@_list:N}
 % \begin{macro}[EXP]{\@@_list_aux:n}





More information about the latex3-commits mailing list.