If I have a LaTeX3 string containing:
def f():
return 42
def g():
return 43
I would like to turn it into:
def f():
return 42
def g():
return 43
i.e., remove the maximum number of leading spaces/tab (forgetting about empty lines containing only spaced/tabs, I count TAB and space as the same unit) to make sure that I removed the same number of spaces on every line without removing actual text.
What is the most efficient solution to do that? (ideally in LaTeX3) I was thinking to use regexp like ^[ \t]$ to check if the line contains only spaces, and then to count on each line the number of leading space with another regex like ^[ \t], but regexp are so inefficient in LaTeX that it is not really a viable solution.
MWE
\documentclass[]{article}
\usepackage{verbatim}
\usepackage{xsimverb}
\begin{document}
\ExplSyntaxOn
\ior_new:N \g__robExt_read_ior%
\NewDocumentEnvironment{getString}{}{%
\XSIMfilewritestart*{\jobname-tmp-file-you-can-remove.tmp}%
}{%
\XSIMfilewritestop%
\ior_open:Nn \g__robExt_read_ior {\jobname-tmp-file-you-can-remove.tmp}%
%% Put the file in l__robExt_tmp_contain_file_str
\str_clear_new:N \l__robExt_tmp_str%
\ior_str_map_inline:Nn \g__robExt_read_ior {%
\str_gput_right:Nx \l__robExt_tmp_str {##1^^J}%
}%
\str_gset_eq:cN {l__my_string_str} \l__robExt_tmp_str%
}%
\NewDocumentCommand{\printVerbatimString}{}{%
% 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_tl \l__my_string_str
\tl_replace_all:Nnn \l__robExt_tmp_tl {^^J} { \mbox{}\par }%mbox needed to print empty lines
\tl_replace_all:Nnn \l__robExt_tmp_cl { ~ } { \ }
\begin{flushleft}\ttfamily%
\l__robExt_tmp_tl
\end{flushleft}%
}
\ExplSyntaxOff
\begin{getString}
def f():
return 42
def g():
return 43
\end{getString}
\noindent Before:
\printVerbatimString
Goal:
\begin{getString}
def f():
return 42
def g():
return 43
\end{getString}
\printVerbatimString
\end{document}


_strfor what must be a_tl? – egreg Feb 19 '24 at 16:09_tl? I want to consider it as a string (i.e. only a sequence of basic letters), and I thought that\ior_str_map_inlinewas always providing str so thattl_to_stris not useful? – tobiasBora Feb 19 '24 at 16:17_strdoesn't make it into a string. And if you try\str_show:N \l__robExt_tmp_stryou'll see an error message. And that token list contains much more than a simple list of characters. – egreg Feb 19 '24 at 17:00\tl_set_eqonly in the printing part, my goal being to convert the string to a token list, as this time I want to add tokens like\parfor new lines etc… – tobiasBora Feb 19 '24 at 17:17getStringenvironment? In the printing part this is indeed a typo I made (fixed). On thegetStringhowever, I would expect this to be a string, what makes it a non-string? – tobiasBora Feb 19 '24 at 17:18\tl_set_eq:NN \l__robExt_tmp_tl \l__my_string_stris wrong .... – cfr Feb 19 '24 at 17:30\tl_set_eq. I can't find any\str_to_tl(white\tl_to_strdoes exist), so I have no idea how to make this correct otherwise. – tobiasBora Feb 19 '24 at 18:33\tl_set_eq:NN \l_tmpa_tl \l_tmpa_stris correct, however, I can guarantee that\tl_set:NV \l_tmpa_tl \l_tmpa_stris correct (though slower). – Skillmon Feb 19 '24 at 19:29lshould only be assigned to locally, a global variable should be named with a leadinggand only be assigned to globally. (\str_gset_eq:cNand\str_gput_right:Nxare global assignments!) – Skillmon Feb 19 '24 at 19:33\l__my_string_strisn't declared, the fact that the first assignment to it is done viac-expansion doesn't change that. Same is true for other variables. Please declare variables before using them. – Skillmon Feb 19 '24 at 19:34