0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

カタカナを半角カタカナにしたい

Posted at

LaTeX でも半角カタカナを利用したいことはあるでしょう。しかし、半角カタカナを愚直に入力すると、コードが見づらかったり、濁点・半濁点の入力が面倒だったりします。
そのため、カタカナを半角カタカナに変換するコマンドがあると便利です。

そこで本記事では、すべてのカタカナを半角カタカナに変換する hankana パッケージを作って対応しようという試みです。

\aj半角 による半角カタカナ

実は、japanese-otf パッケージや luatexja-otf パッケージでは \aj半角 があり、これを使うことでカタカナを半角カタカナに変換できます。
しかし、この方法では全てのカタカナを半角カタカナに変換出来ません。

例えば、次のような文字を変換しようとすると、濁点・半濁点のあるカタカナや半角カタカナの無い小書きのカタカナは豆腐として出力されてしまいます。(原ノ味フォントを使用)

\aj半角{マンゴー}\aj半角{パイナップル}\aj半角{シークヮーサー}は沖縄の特産です。

image-image-1.png

これは、対応するグリフがフォントから与えられていないことに起因します。そのため、うまく対応するフォントを探さない限り、この問題を解消する方法はありません。

そこで今回、すべてのカタカナが半角カタカナになる方法を提供するパッケージを作成してみました。

hankana パッケージを作ってみた

hankana パッケージは事前にマッピングされた全角カタカナと半角カタカナの表を利用して変換を行います。

そのため、変換されないカタカナは存在しません。

使い方

使い方は簡単です。hankana パッケージを読み込むだけです。

\documentclass{jlreq}
\usepackage{hankana}
\begin{document}

すべての\hankana{カタカナ}\hankana[hankaku-others]{半角}になる。

\end{document}

image-image-2.png

\aj半角 では、次のようなカタカナは半角になりませんでした。

  • 濁点・半濁点の付いたカタカナ
  • 「ヮ」や「ㇻ」等の小書きのカタカナ

hankana パッケージでは、濁点・半濁点の付いたカタカナを半角カタカナ+半角濁点・半濁点、小書きのカタカナを平体にした半角カタカナあるいは疑似的に半角幅にした小書きのカタカナに変換します。(小書きのカタカナには半角カタカナが与えられていないため、疑似的に対応しています)

\hankana{マンゴー}\hankana{パイナップル}\hankana{シークヮーサー}は沖縄の特産です。

image-image-3.png

オプション

パッケージオプションとコマンドオプションに共通したオプションがあります。

  • hankaku-kogaki (true): 半角カタカナに対応が無い小書きのカタカナをどのように半角幅にするか

    • true: 半角カタカナを平体に変形
      • 平体にする割合は kogaki-heitai から調整可能
    • false: 小書きのカタカナを半角幅に変形
      • 小書きのカタカナ周囲はスペースがあるため、トリミング量を kogaki-trim から調整可能
  • hankaku-others (false): カタカナ以外の文字を半角にするか

加えて、濁点・半濁点のあるカタカナのための 2 つの調整用オプションがあります。

  • dakuten-sep: 濁点・半濁点と半角カタカナの間のスペース量
  • dakuten-after-sep: 濁点・半濁点の左側のスペース量

hankaku-kogaki に関しては次のような結果を得ます。(「ッ」には半角カタカナがありますが、「ㇱ」や「ㇷ」には半角カタカナがありません)

image-image-5.png

また、濁点・半濁点のスペースを調整するオプションを利用すると、次のような違いを得ます。

image-image-6.png

実装

実装は、一文字ずつ文字列を取り出して、カタカナを対応する半角カタカナに置き替えているだけです。この対応するマップは 別ファイル にしています。

対応する文字に変換するには、以下のように \str_case_e を使った関数を使用しています。これによって、入力されたトークンリストに対応した文字が同じトークンリスト変数に返ってきます。

\cs_new_protected:Npn \__hankana_katakana_mapping:Nn #1#2 {
    \tl_set:Nx #1
    { \str_case_e:nn { \tl_use:N #1 } {#2} }
}
\cs_generate_variant:Nn \__hankana_katakana_mapping:Nn { NV }

%% マッピングリストは別ファイルからトークンリストとして導入される
\__hankana_katakana_mapping:NV \l_tmpb_tl \l__hankana_katakana_zenkaku_mapping_tl

%% \l_tmpb_tl の内容をシーケンスリストに右側から挿入される
\seq_put_right:NV \l__hankana_output_seq \l_tmpb_tl

また、小書きのカタカナや漢字は平体や長体に変形しています。これは、以下のように \box_resize_to_wd_and_ht を使って変形しています。

%% 長体に変形する関数
\cs_new:Npn \__hankana_cjk_trans_chotai:N #1 {
    \hbox_set:Nn \l_tmpb_box { \tl_use:N #1 }
    \box_resize_to_wd_and_ht:Nnn \l_tmpb_box { 0.5 \c__zw_unit_dim } { 1 \c__zw_unit_dim }
    \box_use_drop:N \l_tmpb_box
}

これをトークンリストとして呼び出して、シーケンスリストとしてダンプします。シーケンスリストは半角カタカナや平体に変形した小書きのカタカナ等が順にダンプされています。

%% \l_tmpb_tl が \l__hankana_cjk_trans_chotai によって書き変えられて \l_tmpb_tl にセットされる
\tl_set:Nx \l_tmpb_tl { \__hankana_cjk_trans_chotai:N \l_tmpb_tl }

%% \l_tmpb_tl の内容をシーケンスリストに右側から挿入される
\seq_put_right:NV \l__hankana_output_seq \l_tmpb_tl

これを \seq_map_inline:Nn \l__hankana_output_seq { ##1 } とすることで左から順に並べて出力しています。

余談

すべてのカタカナを半角カタカナに変換するパッケージを作ってみました。

フォントに依存せず、愚直に 1 文字ずつ半角カタカナに変換しているので、表示できない半角カタカナはありません。また、Unicode に存在しない小書きのカタカナの半角に関しては半角幅に調整することで、疑似的に半角カタカナとなるように調整しています。

hankana パッケージを使えば、オンドゥル語も簡単に出力できるようになりますね。

\hankana{オンドゥルルラギッタンディスカー!}

image-image-4.png

expl3 メモ

hankana パッケージでは文字の置換を 1 文字ずつ \str_case_e で行っています。

例えば、促音の「っ」や拗音の「ゃ」「ゅ」「ょ」を普通の「つ」「や」「ゆ」「よ」に置き替える \replaceKogaki を構成するには、次のようにします。

\cs_new_protected:Npn \__sokuon_youon_mapping:Nn #1#2 {
    \tl_set:Nx #1
    { \str_case_e:nnF { \tl_use:N #1 } { #2 } { \tl_use:N #1 } }
}
\cs_generate_variant:Nn \__sokuon_youon_mapping:Nn { NV }

\tl_new:N \l__mappiing_tl
\tl_set:Nn \l__mapping_tl {
    {} {}
    {} {}
    {} {}
    {} {}
}

\tl_new:N \l__input_tl
\tl_new:N \l__output_tl
\NewDocumentCommand{ \replaceKogaki } { m } {
    \tl_set:Nn \l__input_tl { #1 }
    \int_step_inline:nnnn { 1 } { 1 } { \tl_count:N \l__input_tl }
    {
        \tl_set:Ne \l_tmpb_tl { \tl_range:Nnn \l__input_tl { ##1 } { ##1 } }
        \__sokuon_youon_mapping:NV \l_tmpb_tl \l__mapping_tl
        \tl_put_right:NV \l__output_tl \l_tmpb_tl
    }
    \tl_use:N \l__output_tl
}

この方法は、与えられた文字列を 1 文字ずつ置換して全体の文字列を出力します。

この他にも、\regex_replace_case_all を利用して置換もできます。こちらの方が簡単に書けます。ただし、置換後の文字に \c_ampersand_str 等が利用できません。(どうして……)

\tl_new:N \l__mapping_tl
\tl_set:Nn \l__mapping_tl
{
    {} {}
    {} {}
    {} {}
    {} {}
}

\tl_new:N \l__input_tl
\cs_generate_variant:Nn \regex_replace_case_all:nN { VN }
\NewDocumentCommand{ \replaceKogaki }{ m }{
    \tl_set:Nn \l__input_tl { #1 }
    \regex_replace_case_all:VN \l__mapping_tl \l__input_tl
    \tl_use:N \l__input_tl
}

実は、hankana パッケージを実装するときに \regex_replace_case_all を知らなかったので \str_case_e を利用しているという事情もあります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?