引数として非ASCII文字

引数として非ASCII文字

テキスト内の一部の文字に特別な処理を施したいです。この例では、文字を太字にするだけです。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\newcommand\<[1]{\textbf{#1}}

\begin{document}
f\<oo b\<ar b\<öll
\end{document}

これは最初の2つのケースではうまく機能しますが、非ASCII文字「ö」では機能しません。エラーメッセージが表示されます。

! Package inputenc Error: Unicode char \u8:\check@icr not set up for use with LaTeX.

これは、utf8 で "ö" を構成する 2 つのバイトの間に報告されます。

  1. これは XeLaTeX または LuaLaTeX では機能することがわかっています (inputenc 行を削除するだけです)。pdfLaTeX および (DVI)LaTeX では機能しません。

  2. 回避策の 1 つは、 と記述することです\<{ö}

  3. しかし、その回避策なしでこれを pdflatex で動作させる方法はあるのでしょうか?

(実際のアプリケーションでは、ソース テキストの表示をできるだけ妨げないものにすることが目的であるため、アクティブ キャラクタが使用されます。)

答え1

これを実行することもできますが、実行すべきかどうかはわかりません:-)

ここに画像の説明を入力してください

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

%\newcommand\<[1]{\textbf{#1}}
\makeatletter
\def\<{\expandafter\zz}
\def\zz#1{%
   \ifx\UTFviii@two@octets#1% could be 3 or 4 octets, but not today
     \expandafter\zztwo
    \else
     \expandafter\zzone{#1}%
 \fi}
\def\zztwo#1#2{\zzone{\UTFviii@two@octets#1#2}}
\makeatother
\def\zzone#1{\textbf{#1}}

\begin{document}

f\<oo b\<ar b\<öll


f\<{o}o b\<ar b\<{ö}ll

\end{document}

答え2

LaTeXを使わない回答で申し訳ないのですが、できるUTF-8 コードを通常の 8 ビット pdftex の 1 つのトークンとして扱うと、David と egreg の回答に示されている複雑さを回避できます。UTF-8 でエンコードされたファイルを作成してみてください。

\input lmfonts

\def\<#1{{\bf#1}}
f\<oo b\<öll €\<€ f\<{oö} f\< öo
\bye

で処理しますpdftex -fmt csplain test.tex

egregからの画像

説明: このフォーマットはcsplain、pdfTeX の encTeX 拡張機能を使用して生成されます。これは、入力プロセッサ レベルで UTF-8 コードを解釈し、単一のトークン (バイトまたは制御シーケンス) としてトークン プロセッサに返すことができます。\write元の UTF-8 コードをログとファイルに戻すことができます。

答え3

一般的な回答で、3 バイトと 4 バイトの UTF-8 文字の場合も対象となります。\<öまたは、\<{ö}許可されます。最後の例のようにスペースが入り込むと、スペースは削除されます。

間違った入力をキャッチするために、制御シーケンスのテストを追加する必要があるかもしれません。 または{の後に文字だけがある限り\<、安全なはずです。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp}
\usepackage{lmodern}

\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\<}{}
 {
  \pst_boldify:
 }

\tl_new:N \l__pst_first_byte_tl
\cs_new_protected:Npn \pst_boldify:
 {
  \peek_catcode_ignore_spaces:NTF \c_group_begin_token
   {
    \textbf
   }
   {
    \pst_boldify_aux:N
   }
 }

\cs_new_protected:Npn \pst_boldify_aux:N #1
 {
  \tl_set:Nx \l__pst_first_byte_tl
   {
    \int_compare:nT { `#1 < 128 } { 0 }
    \int_to_bin:n { `#1 }
   }
  \regex_replace_once:nnN { 0[01]*\Z } { } \l__pst_first_byte_tl
  \str_case:on { \l__pst_first_byte_tl }
   {
    { }      { \textbf { #1 } }
    { 11 }   { \pst_do_bold:nn { #1 } }
    { 111 }  { \pst_do_bold:nnn { #1 } }
    { 1111 } { \pst_do_bold:nnnn { #1 } }
   }
 }
\cs_new_protected:Npn \pst_do_bold:nn #1 #2
 {
  \textbf{#1#2}
 }
\cs_new_protected:Npn \pst_do_bold:nnn #1 #2 #3
 {
  \textbf{#1#2#3}
 }
\cs_new_protected:Npn \pst_do_bold:nnnn #1 #2 #3 #4
 {
  \textbf{#1#2#3#4}
 }

\ExplSyntaxOff

\begin{document}
f\<oo b\<öll €\<€ f\<{oö} f\< öo
\end{document}

考え方としては、次のトークン (スペースを削除した後) が中括弧である場合は、ただ が\textbf実行されます。それ以外の場合は、次のトークンが調べられ、バイナリ形式の文字コードに変換されます。管理する必要がある UTF-8 文字が 1 バイト、2 バイト、3 バイト、または 4 バイトであるかどうかを判断するために、最初のゼロからすべてが削除されます。最後に、適切な決定が行われます。

ここに画像の説明を入力してください

正規表現の置換なしで算術テストを実行すると、の定義は\pst_boldify_aux:N次のようになります。

\cs_new_protected:Npn \pst_boldify_aux:N #1
 {
  \int_compare:nTF { `#1<128 }
   {
    \textbf
   }
   {
    \int_compare:nTF { 192 <= `#1 < 224 }
     {
      \pst_do_bold:nn { #1 }
     }
     {
      \int_compare:nTF { 224 <= `#1 < 240 }
       {
        \pst_do_bold:nnn { #1 }
       }
       {
        \pst_do_bold:nnnn { #1 }
       }
     }
   }
 }

残りはそのままです(ただし、ロードはl3regex不要になります)。

関連情報