summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/cprotectinside/cprotectinside.sty
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/cprotectinside/cprotectinside.sty')
-rw-r--r--macros/latex/contrib/cprotectinside/cprotectinside.sty78
1 files changed, 78 insertions, 0 deletions
diff --git a/macros/latex/contrib/cprotectinside/cprotectinside.sty b/macros/latex/contrib/cprotectinside/cprotectinside.sty
new file mode 100644
index 0000000000..53afd0beb1
--- /dev/null
+++ b/macros/latex/contrib/cprotectinside/cprotectinside.sty
@@ -0,0 +1,78 @@
+% File: cprotectinside.sty
+% Copyright 2022 user202729
+%
+% This work may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this license or
+% (at your option) any later version. The latest version of this license is in
+% the file:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is user202729.
+
+\ProvidesExplPackage{cprotectinside}{2022/06/25}{0.0.0}{Use cprotect arbitrarily deeply nested}
+
+% '__' ↔ '_cpi_'
+
+\msg_new:nnn {cprotectinside} {delimiter-not-match} {Delimiters~does~not~match!}
+
+\int_new:N \_cpi_used
+
+\edef \cprotectinsideAppend { \c_backslash_str empty }
+% 12 is other catcode
+
+\cs_generate_variant:Nn \tl_replace_all:Nnn {Nnx}
+
+% #1: single character for the delimiter e.g. '+'
+% #2: the body
+
+
+\NewDocumentCommand\cprotectinside{v +v}{
+
+ %\seq_set_split_keep_spaces:Nnn \_cpi_entries {#1} {#2}
+ % cannot do this in old version
+
+ \tl_set:Nn \_cpi_entries {#2}
+ \tl_replace_all:Nnx \_cpi_entries {~} { \char_generate:nn {`\ } {12} } % replace space <space> with other <space>
+ \seq_set_split:NnV \_cpi_entries {#1} \_cpi_entries % so that they're not lost here. Support older versions without \seq_set_split_keep_spaces
+
+ \int_if_even:nT {\seq_count:N \_cpi_entries} {
+ \msg_error:nn {cprotectinside} {delimiter-not-match}
+ }
+ \tl_build_gbegin:N \_cpi_result
+ \seq_map_indexed_inline:Nn \_cpi_entries {
+ % ##1 is index, ##2 is item
+ \int_if_even:nTF {##1} {
+ % index 2, 4, 6...: content to be cprotect-ed
+ \int_incr:N \_cpi_used
+ \exp_args:NV \_cpi_aux:nn \cprotectinsideAppend {##2}
+ \tl_build_gput_right:Nx \_cpi_result { \c_backslash_str cpiContentA \romannumeral \_cpi_used / }
+
+ } {
+ % index 1, 3, 5...: normal text
+ \tl_build_gput_right:Nn \_cpi_result {##2}
+ }
+ }
+ %\tl_build_gput_right:Nn \_cpi_result {##2}
+ \tl_build_gend:N \_cpi_result
+ \begingroup
+ \newlinechar=13~ % have to setup like this because +v collect newline as char 13
+ \exp_args:NNNV \expandafter \endgroup \scantokens \_cpi_result
+}
+
+\def \_cpi_aux:nn #1 #2 {
+ \protected \cs_set_protected:cpn {cpiContentA \romannumeral \_cpi_used} / {\cprotectinsideReexec{#2 #1}}
+}
+
+\def \cprotectinsideReexec #1 {
+ \begingroup
+ \newlinechar=13~
+ \expandafter % expand the \scantokens once when newlinechar=13
+ \endgroup
+ \scantokens {#1} % then execute the code with original newlinechar value
+}
+
+\cs_generate_variant:Nn \_cpi_aux:n {V}
+\cs_generate_variant:Nn \tl_gset_rescan:Nnn {NnV}