summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/cprotectinside/cprotectinside.sty
blob: 53afd0beb1cc2659a50269978420e3cd7a7d1fed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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}