On 17/09/2015 12:00, Alexander Grahn wrote: > I am puzzled. What exactly do I have to do in order to adjust existing > code which uses the lowercase trick > > \group_begin: > \char_set_lccode:nn{...}{...} > \tl_to_lowercase:n{ > \group_end: > ... > } > > ? It will depend on what outcome you want, hence giving some different possibilities: for some cases there are several alternative formulations. Taking some examples from media9 :-) \group_begin: \char_set_lccode:nn{`\+}{`\@} \tl_to_lowercase:n{ \group_end: \cs_new:Npn\mix_parse_windowedarg:w#1+#2+#3\q_stop{ \tl_if_blank:nF{#1}{\tl_gset:Nn\g_mix_winsize_tl{#1}} \tl_if_blank:nF{#2}{\tl_gset:Nn\g_mix_winpos_tl{#2}} } \cs_new:Nn\mix_parse_windowedarg:N{ \exp_after:wN\mix_parse_windowedarg:w#1++\q_stop } } doesn't really need anything 'tricky' at all, as \group_begin: \char_set_catcode_other:n { `\@ } \cs_new_protected:Npn \mix_parse_windowedarg:w #1 @ #2 @ #3 \q_stop { \tl_if_blank:nF {#1} { \tl_gset:Nn \g_mix_winsize_tl {#1} } \tl_if_blank:nF {#2} { \tl_gset:Nn \g_mix_winpos_tl {#2} } } \cs_new_protected:Nn \mix_parse_windowedarg:N { \exp_after:wN \mix_parse_windowedarg:w #1 @ @ \q_stop } \group_end: does the same. (I've made protected as 'best practice.) On the other hand \group_begin: \char_set_catcode_active:N\~ \cs_new:Npn\mix_uribegin:{ \group_begin: %code contributed by E. Gregorio \tl_map_inline:nn{.:;?!/"'*+,->=<$@][)(^_`|~}{ \group_begin: \char_set_lccode:nn{`\~}{`##1} \tl_to_lowercase:n{\group_end:\cs_set:Npn~}{\token_to_str:N##1} } \cs_set:Npn\#{\token_to_str:N\#} \cs_set:Npn\&{\token_to_str:N\&} \cs_set:Npn\%{\token_to_str:N\%} \cs_set:Npn\\{\token_to_str:N\\} \cs_set:Npn\{{\token_to_str:N\{} \cs_set:Npn\}{\token_to_str:N\}} } \group_end: does need some way to make active tokens, which is now available as \char_set_active_eq:NN \group_begin: \char_set_catcode_other:n { `\~ } \cs_new_protected_nopar:Npn \mix_uribegin: { \tl_map_inline:nn { .:;?!/"'*+,->=<$@[]()^_`|~ } { \cs_set_nopar:Npx \__mix_tmp:w { \token_to_str:N ##1 } \char_set_active_eq:NN ##1 \__mix_tmp:w } \tl_map_inline:nn { \# \& \% \\ \{ \} } { \cs_set_nopar:Npx ##1 { \token_to_str:N ##1 } } } \group_end: where I need the change of catcode for ~ so that it is N-type for the loop/active setting. (Internally \char_set_active_eq:NN does use the 'lowercase trick': we are however providing a wrapper which better describes the outcome.) Some other examples from siunitx. I've altered \cs_new_protected:Npn \@@_unit_format_literal_extras_aux:nN #1#2 { \char_set_lccode:nn { `\@ } {#1} \tl_to_lowercase:n { \tl_replace_all:NnV \l_@@_unit_tl { @ } #2 } } to \cs_new_protected:Npn \@@_unit_format_literal_extras_aux:nN #1#2 { \tl_replace_all:Nxn \l_@@_unit_tl { \char_generate:nn { #1 } { 12 } } {#2} } as here I need to generate a char token from its char code. I've got several uses of \char_set_active_eq:NN now for situations like the above media9 example. In places where I want say a 'standard' category code _ I've changed for example \char_set_lccode:nn { `\@ } { `\_ } \char_set_catcode_math_subscript:N \@ \tl_to_lowercase:n { \group_end: \DeclareSIUnit \clight { \text { \ensuremath { c @ { 0 } } } } \DeclareSIUnit \electronmass { \text { \ensuremath { m @ { \text { e } } } } } } into the slightly tricky \cs_set_eq:NN \endgroup \group_end: \char_set_catcode_math_subscript:N \_ \use:n { \endgroup \DeclareSIUnit \clight { \text { \ensuremath { c _ { 0 } } } } \DeclareSIUnit \electronmass { \text { \ensuremath { m _ { \textup { e } } } } } } which could also have been done using an x-type expansion and \char_generate:nn (more complex in this case, hence avoiding it). Finally, one example from ctex, where I've suggested \group_begin: \char_set_catcode_other:N \P \char_set_catcode_other:N \T \tex_lowercase:D { \cs_new:Npn \@@_default_pt:w #1 PT #2 \q_stop { #1 PT } } becomes \use:x { \cs_new:Npn \exp_not:N \@@_default_pt:w ##1 \tl_to_str:n { pt } ##2 \exp_not:N \q_stop { ##1 \tl_to_str:n { pt } } } using an x-type expansion to make string-like tokens. (Aside: we will soon extend the l3str module to have more handy 'string constants' such as \c_backslash_str ready 'out of the box'.) I hope this helps: depending on the use case, the best/clearest approach can vary a bit. Joseph