diff options
Diffstat (limited to 'macros/latex/contrib/robust-externalize/robust-externalize.sty')
-rw-r--r-- | macros/latex/contrib/robust-externalize/robust-externalize.sty | 175 |
1 files changed, 172 insertions, 3 deletions
diff --git a/macros/latex/contrib/robust-externalize/robust-externalize.sty b/macros/latex/contrib/robust-externalize/robust-externalize.sty index 0a36647946..488cbb7c8f 100644 --- a/macros/latex/contrib/robust-externalize/robust-externalize.sty +++ b/macros/latex/contrib/robust-externalize/robust-externalize.sty @@ -1,4 +1,4 @@ -\ProvidesPackage{robust-externalize}[2.5 Cache anything (tikz, latex, python) in a robust, efficient and pure way.] +\ProvidesPackage{robust-externalize}[2.6 Cache anything (tikz, latex, python) in a robust, efficient and pure way.] % todo: % change order argument replace from list, it is hard to read this way @@ -184,12 +184,17 @@ \cs_generate_variant:Nn \cs_replacement_spec:N { c } \cs_generate_variant:Nn \cs_argument_spec:N { c } +\cs_generate_variant:Nn \str_count_ignore_spaces:n { V } +\cs_generate_variant:Nn \str_count_spaces:n { e } + \cs_generate_variant:Nn \regex_extract_all:nnN { VVN, nVN, VVN } \cs_generate_variant:Nn \regex_extract_all:NnN { NVN } \cs_generate_variant:Nn \regex_match:nnTF { nVTF } +\cs_generate_variant:Nn \seq_set_split_keep_spaces:Nnn {Nnv} + %%% %%% String manipulation %%% @@ -234,6 +239,7 @@ \msg_new:nnn {robExt}{dependency does not exist}{The~dependency~#1~does~not~exist.} \msg_new:nnn {robExt}{missing compiled pdf parallel with log}{The~compilation~of~the~code~block~at~line~#2~failed:~the~following ~ file~is~indeed~missing: ~ #1.pdf. ~ The ~ compilation ~ command ~ "#3"~used~to~compile~the~environment~on~line~#2~ certainly ~ failed~with~errors:^^Jvvvvvv^^J\l__robExt_tmp_str^^J\string^\string^\string^\string^\string^\string^ ^^JSee~full~logs~#4~ or ~ in ~ #1-compilation.log.} +\msg_new:nnn {robExt}{remove spaces until non spaces characters}{The~placeholder~#1~contains~characters~other~than~spaces~(#2)~before~the~separator~#3.} \msg_new:nnn {robExt}{auto forward not in cachemecode}{Auto~forward~is~less~efficient~in~cacheMeCode.} @@ -674,7 +680,7 @@ if __name__ == '__main__': % For some reasons, newlines are displayed as \Omega. We need to replace them with \\ % https://tex.stackexchange.com/questions/694716/print-latex3-string-verbatim/694717 \tl_set_eq:Nc \l__robExt_tmp_str { l__robExt_placeholder_#2_str } - \tl_replace_all:Nnn \l__robExt_tmp_str {^^J} { \par } + \tl_replace_all:Nnn \l__robExt_tmp_str {^^J} { \mbox{}\par } % mbox is helpful to print empty lines \tl_replace_all:Nnn \l__robExt_tmp_str { ~ } { \ } \IfBooleanTF{#1}{\texttt{\use:c{l__robExt_placeholder_#2_str}}}{\begin{flushleft}\ttfamily% \l__robExt_tmp_str @@ -688,7 +694,7 @@ if __name__ == '__main__': % For some reasons, newlines are displayed as \Omega. We need to replace them with \\ % https://tex.stackexchange.com/questions/694716/print-latex3-string-verbatim/694717 \tl_set_eq:NN \l__robExt_tmp_str \l_robExt_result_str - \tl_replace_all:Nnn \l__robExt_tmp_str {^^J} { \par } + \tl_replace_all:Nnn \l__robExt_tmp_str {^^J} { \mbox{}\par } \tl_replace_all:Nnn \l__robExt_tmp_str { ~ } { \ } \IfBooleanTF{#1}{\texttt{\l__robExt_tmp_str}}{\begin{flushleft}\ttfamily% \l__robExt_tmp_str @@ -1300,6 +1306,128 @@ if __name__ == '__main__': } \let\placeholderReplaceInplaceEval\robExtPlaceholderReplaceInplaceEval + +% \group_begin: +% \char_set_catcode_other:N \^^I +% Usage: +% \robExtPlaceholderRemoveSpacesUntil{__MY_PLACEHOLDER__}{>>>} +\group_begin: +\char_set_catcode_other:N \^^I +\cs_new_protected:Npn \__robExt_replace_tabs:N #1 { + \str_replace_all:Nnn #1 { ^^I } { ~ } +} +\group_end: + +\NewDocumentCommand{\robExtPlaceholderRemoveSpacesUntil}{mO{1}m}{ + %% Cut the string in lines + \seq_set_split_keep_spaces:Nnv \l_tmpa_seq {^^J} { l__robExt_placeholder_#1_str } + \str_clear:c { l__robExt_placeholder_#1_str } + %% We iterate over the lines + \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl { + % \l_tmpa_tl contains the current line + \seq_set_split_keep_spaces:NnV \l_tmpb_seq {#3} \l_tmpa_tl + %% In any case, the first item must only contain spaces. + % The separator was present. Check that the line only contains spaces before the separator + \seq_get_left:NN \l_tmpb_seq \l_tmpb_tl + \__robExt_replace_tabs:N \l_tmpb_tl + %\str_replace_all:Nnn \l__robExt_tmp_str { ^^I } { ~ } + %\tl_replace_all:Nnn \l_tmpb_tl {^^I} {~} % we replace tabs with spaces, check if it works + % Save the size of the string + \int_set:Nn \l_tmpa_int {\str_count:N \l_tmpb_tl} + % we remove spaces + \tl_trim_spaces:N \l_tmpb_tl + \tl_if_empty:VTF \l_tmpb_tl { + \int_compare:nNnTF {\seq_count:N \l_tmpb_seq} > {1} { + % Empty line: we add it to the current placeholder + \str_put_right:cx { l__robExt_placeholder_#1_str } { + % the placeholder is a string, so I expect l_tmpa_tl to also be a string. No problem? + \str_range:Nnn \l_tmpa_tl {\l_tmpa_int + \str_count:n {#3} + 1 + #2} {-1} ^^J + } + } { + % No separator: it means the line is empty + \str_put_right:cn { l__robExt_placeholder_#1_str } {^^J} + } + }{ + % The string was not completely empty: raise an error + \msg_error:nnxxx{robExt}{remove spaces until non spaces characters}{#1}{\l_tmpa_tl}{#3} + } + } +} +\let\placeholderRemoveSpacesUntil\robExtPlaceholderRemoveSpacesUntil + +% Usage: +% \robExtPlaceholderPrependAllLines{__MY_PLACEHOLDER__}{ } +\NewDocumentCommand{\robExtPlaceholderPrependAllLines}{mm}{ + %% Cut the string in lines + \seq_set_split_keep_spaces:Nnv \l_tmpa_seq {^^J} { l__robExt_placeholder_#1_str } + \str_clear:c { l__robExt_placeholder_#1_str } + %% We iterate over the lines + \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl { + \str_put_right:cx { l__robExt_placeholder_#1_str } { + #2 + \l_tmpa_tl ^^J} + } +} +\let\placeholderPrependAllLines\robExtPlaceholderPrependAllLines + + +%% https://tex.stackexchange.com/questions/709973/latex3-efficient-way-to-remove-spaces-in-front-of-a-command/710006?noredirect=1#comment1765909_710006 +%% Modifies \l_tmpa_tl so that it contains the current number of spaces to remove +%% It also uses \l_tmpa_str +\group_begin: +\char_set_catcode_other:N \^^I +\cs_new_protected:Npn \__robExt_count_leading_whitespace:n #1 +{ + \str_set:Nn \l_tmpa_str {#1} + \str_replace_all:Nnn \l_tmpa_str { ^^I } { ~ } + \tl_if_blank:VF \l_tmpa_str + { + \int_set:Nn \l_tmpa_int + { + \int_min:nn + { \l_tmpa_int } + { + \str_count_spaces:N \l_tmpa_str - + \str_count_spaces:e + { \exp_last_unbraced:NV \use:n \l_tmpa_str {} } + } + } + } +} +\cs_generate_variant:Nn \__robExt_count_leading_whitespace:n { V } +\group_end: + +\NewDocumentCommand{\robExtPlaceholderRemoveLeadingSpaces}{m}{ + %% Cut the string in lines + \seq_set_split_keep_spaces:Nnv \l_tmpa_seq {^^J} { l__robExt_placeholder_#1_str } + %% Stores the number of spaces we can trim. Since we will take the minimum, we add infinity first + \int_set_eq:NN \l_tmpa_int \c_max_int + %% We iterate over the lines to find the minimum number of spaces to trim + \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl { + % If the line is empty, let's just remove it: + \int_compare:nNnTF {\str_count_ignore_spaces:V \l_tmpa_tl} > {0} { + % The line contains also letters, let us count the number of spaces. + \__robExt_count_leading_whitespace:V \l_tmpa_tl + } { + % line contains only spaces, we don't care + } + } + %% We check if the string was not all empty (e.g. if the content is empty) + \int_compare:nNnTF {\l_tmpa_int} = {\c_max_int} {} { + \str_clear:c { l__robExt_placeholder_#1_str } + %% We iterate over the lines to recreate the appropriate placeholder + \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl { + \str_put_right:cx { l__robExt_placeholder_#1_str } { + \str_range:Nnn \l_tmpa_tl {\l_tmpa_int + 1} {-1} + ^^J + } + } + } +} +\let\placeholderRemoveLeadingSpaces\robExtPlaceholderRemoveLeadingSpaces + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%% Placeholders groups %%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2371,6 +2499,25 @@ if __name__ == '__main__': \robExtRemovePlaceholder{__ROBEXT_TMP__}% let us clean our variables \let\robExtCurrentlyDefiningPreset\undefined% }, + add before preset/.code 2 args={% + \robExtStrSetDoubleHash{\robExtTmpStr}{#2}% + % Sadly, \expanded{\noexpand } does not work, as I get extra {} around the def, creating a group + % so the simpler seems to use this library ^^ + \robExtPlaceholderFromString{__ROBEXT_TMP__}{\robExtTmpStr}% + \robExtEvalPlaceholderReplaceFromList{__ROBEXT_TMP__}{% + \pgfkeys{% + /robExt/.cd, + #1/.prefix style={% + % Some styles run differently if inside a preset or not, + % like if matches word. This macro helps with detecting it. + /utils/exec={\def\robExtCurrentlyDefiningPreset{}},% + __ROBEXT_TMP__% + },% + }% + }% + \robExtRemovePlaceholder{__ROBEXT_TMP__}% let us clean our variables + \let\robExtCurrentlyDefiningPreset\undefined% + }, new preset/.code 2 args={% \robExtStrSetDoubleHash{\robExtTmpStr}{#2}% % Sadly, \expanded{\noexpand } does not work, as I get extra {} around the def, creating a group @@ -2512,6 +2659,22 @@ if __name__ == '__main__': placeholder double number hashes in place/.code={\robExtPlaceholderDoubleNumberHashesInplace{#1}}, placeholder replace in place/.code n args={3}{\robExtPlaceholderReplaceInplace{#1}{#2}{#3}}, placeholder replace in place eval/.code n args={3}{\robExtPlaceholderReplaceInplaceEval{#1}{#2}{#3}}, + placeholder prepend all lines/.code 2 args={\robExtPlaceholderPrependAllLines{#1}{#2}}, + prepend all lines/.style={ + placeholder prepend all lines={__ROBEXT_MAIN_CONTENT_ORIG__}{#1}, + }, + placeholder remove spaces until/.code 2 args={\robExtPlaceholderRemoveSpacesUntil{#1}{#2}}, + remove spaces until/.style={ + placeholder remove spaces until={__ROBEXT_MAIN_CONTENT_ORIG__}{#1}, + }, + placeholder strictly remove spaces until/.code 2 args={\robExtPlaceholderRemoveSpacesUntil{#1}[0]{#2}}, + strictly remove spaces until/.style={ + placeholder remove spaces until nospace={__ROBEXT_MAIN_CONTENT_ORIG__}{#1}, + }, + placeholder remove leading spaces/.code={\robExtPlaceholderRemoveLeadingSpaces{#1}}, + remove leading spaces/.code={\robExtPlaceholderRemoveLeadingSpaces{__ROBEXT_MAIN_CONTENT_ORIG__}}, + remove leading spaces if not disabled/.code={\ifdefined\robExtDoNotRemoveLeadingSpaces\else\robExtPlaceholderRemoveLeadingSpaces{__ROBEXT_MAIN_CONTENT_ORIG__}\fi}, + do not remove leading spaces/.code={\def\robExtDoNotRemoveLeadingSpaces{}}, % Interface to set template set template/.style={ set placeholder first={__ROBEXT_TEMPLATE__}{#1}, @@ -3484,6 +3647,7 @@ finished_with_no_error() add import/.style={ add to placeholder no space={__ROBEXT_PYTHON_IMPORT__}{##1^^J}, }, + remove leading spaces if not disabled, } } @@ -3577,8 +3741,13 @@ print_file.close() { \dim_to_decimal_in_unit:nn { #2 } { 1 #1 } #1 } +\DeclareExpandableDocumentCommand{\robExtLenToCmNoUnit}{ O{cm} m } +{ + \dim_to_decimal_in_unit:nn { #2 } { 1 #1 } +} \ExplSyntaxOff \let\lenToCm\robExtLenToCm +\let\lenToCmNoUnit\robExtLenToCmNoUnit \robExtConfigure{ verbatim text/.style={ |