带有 UTF-8 字符的 Expl3 标记列表(或将其视为字节列表)

带有 UTF-8 字符的 Expl3 标记列表(或将其视为字节列表)

我目前正在一个项目中使用expl3代码。这是一个缓慢的学习过程。

现在我需要处理 UTF-8 输入流,但是,我已经怀疑处理 2 字节编码存在问题。

实际上,输入是否为 UTF-8 与我的情况无关。例如,我想要处理并até得到以下结果:at和。换句话说,一次处理一个字节。在 LaTex 中,我想要得到类似的东西 ,并有4 个标记 tl。0xC30xA9\processtl{até}at{0xC3}{0xA9}

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[brazilian]{babel}

\ExplSyntaxOn

\newcommand{\processtl}[1]{
    \tl_set:Nn \l_tokens_tl { #1 }
    \tl_map_inline:Nn \l_tokens_tl { (##1) } %% Here: check one byte!
}

\ExplSyntaxOff

\begin{document}
token list: \processtl{abc{$\beta$}}\par
% token list with á and ç: \processtl{ábç{$\beta$}}\par  % FAILS
\end{document}

有没有办法识别它0xC3并将其与后面的字节分开处理?

就像是:

\IfTestByte{#1=0xC3){                  % check if current byte is the first UTF-8
    \showinhexadecimal(0xC3}           % output it in hex
    \getnexttoken                      % get the second byte
    \showinhexadecimal{\thenexttoken}  % output it in hex
}

我无法转换tlstr因为某些标记可​​以是宏,并且可以对str 它们进行反标记。

我查看了这些char功能,但找不到任何有用的功能。我是不是错过了什么有用的东西?

答案1

使用pdflatex函数\tl_map_inline:nn只会将其á视为两个字节。我们可以检查字符代码是否为高字节并采取相应措施。如果传递给它的对象不止一个标记,例如 for {$\beta$},我们可以按原样打印它。

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[brazilian]{babel}

\ExplSyntaxOn

\NewDocumentCommand{\processtl}{m}
 {
  \jander_process_tl:n { #1 }
 }

\cs_new_protected:Nn \jander_process_tl:n
 {
  \tl_map_inline:nn { #1 }
   {
    ( % open parenthesis
    \tl_if_single:nTF { ##1 }
     {
      \__jander_process_highbyte:en { `\token_to_str:N ##1 } { ##1 }
     }
     { ##1 }
     ) % close parenthesis
   }
 }
\cs_new:Nn \__jander_process_highbyte:nn
 {
  \int_compare:nTF { #1>127 } { 0x\int_to_Hex:n { #1 } } { #2 }
 }
\cs_generate_variant:Nn \__jander_process_highbyte:nn { e }

\ExplSyntaxOff

\begin{document}

token list: \processtl{abc{$\beta$}}

token list with á and ç: \processtl{ábç{$\beta$}}

\end{document}

会发生什么?当á找到时,它后面实际上0xC3跟着0xA1。就 而言,无论是哪种情况,它都是单个标记的序列pdftex。所以我们可以计算它的字符代码(但我们需要使其成为“其他字符”,因为它可能是活动的),并将其传递给另一个函数,检查它是否是高字节。

在此处输入图片描述

考虑到单个标记可能是一个控制序列,进行了修改。

\documentclass[a4paper]{article}

\ExplSyntaxOn

\NewDocumentCommand{\processtl}{m}
 {
  \sys_if_engine_pdftex:TF
   {
    \jander_process_tl_onebyte:n { #1 }
   }
   {
    \jander_process_tl_unicode:n { #1 }
   }
 }

\cs_new_protected:Nn \jander_process_tl_onebyte:n
 {
  \tl_map_inline:nn { #1 }
   {
    ( % open parenthesis
    \bool_lazy_or:nnTF { ! \tl_if_single_p:n { ##1 } } { \token_if_cs_p:N ##1 }
     {
      ##1
     }
     {
      \__jander_process_highbyte:en { `\token_to_str:N ##1 } { ##1 }
     }
     ) % close parenthesis
   }
 }
\cs_new:Nn \__jander_process_highbyte:nn
 {
  \int_compare:nTF { #1>127 } { 0x\int_to_Hex:n { #1 } } { #2 }
 }
\cs_generate_variant:Nn \__jander_process_highbyte:nn { e }

\ExplSyntaxOff

\begin{document}

token list: \processtl{abc{$\beta$}}

token list with á and ç: \processtl{ábç{$\beta$}\LaTeX}

\end{document}

在此处输入图片描述

节省编码的技巧是使用\bool_lazy_or:nnTF;第一个条件为“没有单个标记”,第二个条件为“控制序列”。由于我们使用惰性求值,当第一个条件为真时(因此我们没有单个标记),第二个条件不会被求值。

在此处输入图片描述

答案2

我认为你想要这样的东西(只要多花点功夫就可以用十六进制打印)

在此处输入图片描述

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[brazilian]{babel}

\ExplSyntaxOn
\makeatletter

\newcommand{\processtl}[1]{{
\def\UTFviii@two@octets##1{\number\expandafter`\string##1}
\def\UTFviii@invalid@err##1{\number\expandafter`\string##1}
    \tl_map_inline:nn {#1} { (##1) } %% Here: check one byte!
}}
\makeatother
\ExplSyntaxOff

\begin{document}
token list: \processtl{abc{$\beta$}}

 token list with á and ç: \processtl{ábç{$\beta$}}\par  % FAILS
\end{document}

相关内容