U+10000 以降の文字の単語カーソル移動について

  1. Kuroさん

    台風も過ぎて、少しは残暑な気温になってきたような…?早く涼しくなってほしいものですね🥵

    さて、U+10000 以降の文字の単語カーソル移動について、あえてそういう仕様にしているということだったら余計なお世話なのですが、ご報告です。

    (1) 末尾側から先頭側に向けて単語カーソル移動 (Ctrl + Left) をしたときにサロゲートペアの間にカーソルが入ってしまう

    再現のため「今日は𠮷野家」という例文を使います。
    下記では、[キャレット 1] を起点とし、Ctrl + Left を順繰り押していって先頭方向に単語カーソル移動をしていきます。[キャレット 1] で Ctrl + Left をしたら、 [キャレット 2] に移動する…というように順序を示しています。

    期待する動作:
    [キャレット 5]今日[キャレット 4]は[キャレット 3]𠮷[キャレット 2]野家[キャレット 1]
    
    実際の動作:
    [キャレット 6]今日[キャレット 5]は[キャレット 4]𠮷[★キャレット 2, 3]野家[キャレット 1]
    

    「実際の動作」で ★ を付けたところにあるように、キャレット位置が同じ箇所に留まるような見た目の動きになります。しかし内部的にはカーソルがサロゲートペアの間に挟まるようなところに移動しているようで、その状態で文字入力すると上位サロゲートと下位サロゲートの間に入力されます。
    キャプチャ: https://imgur.com/a/PtCZNcW

    なお先頭方向から末尾方向にむけて Ctrl + Right をする分には問題ありません。また、U+10000 以上の文字全般の問題と思われ、絵文字などでも同様の事象が起こります。

    (2) U+10000 以降の文字のうちCJK漢字として割り当てられている文字を、単語カーソル移動などの単語の取り扱いで現状の漢字範囲として扱われるようにしてほしい

    これはどちらかといえば要望になりますが…。
    現状、上記の例で挙げたように「𠮷野家」という単語を単語選択しようとすると「𠮷」と「野家」に分かれてしまうと思います。「Meryではこのコードポイント範囲は漢字として扱う」という定義に U+10000 以降は含まれていないのではないかと想像しています。

    もしそうであれば、以下の範囲は漢字扱いの定義に加えてみてはいかがでしょうか?

    U+20000~U+2A6DF CJK Unified Ideographs Extension B CJK統合漢字拡張B (42720文字範囲)
    U+2A700~U+2B73F CJK Unified Ideographs Extension C CJK統合漢字拡張C (4160文字範囲)
    U+2B740~U+2B81F CJK Unified Ideographs Extension D CJK統合漢字拡張D (224文字範囲)
    U+2B820~U+2CEAF CJK Unified Ideographs Extension E CJK統合漢字拡張E (5776文字範囲)
    U+2CEB0~U+2EBEF CJK Unified Ideographs Extension F CJK統合漢字拡張F (7488文字範囲)
    U+2F800~U+2FA1F CJK Compatibility Ideographs Supplement CJK互換漢字補助 (544文字範囲)
    U+30000~U+3134F CJK Unified Ideographs Extension G CJK統合漢字拡張G (4944文字範囲)

     |  yuko  |  返信
  2. 動作環境を書き漏らしていたので追記です。

    Mery Ver 3.5.9
    Win 11 Pro 22H2

     |  yuko  |  返信
  3. ご報告いただきありがとうございます。

    今日の気温は少しましになったようですねー。こちらは雨のため湿度が相当高いですが😓

    > (1) 末尾側から先頭側に向けて単語カーソル移動 (Ctrl + Left) をしたときにサロゲートペアの間にカーソルが入ってしまう

    現象、確認しました。これは改善が必要ですね。次のバージョンで修正できるよう、調査してみます。

    > (2) U+10000 以降の文字のうちCJK漢字として割り当てられている文字を、単語カーソル移動などの単語の取り扱いで現状の漢字範囲として扱われるようにしてほしい

    これはなかなか難しい問題です。

    ご推察のとおり、Mery は Unicode のコード ポイント別に文字のカテゴリを定義しているテーブルを持っていますが、これは U+FFFF までしかカバーしておらず、U+10000 以上の文字には対応していません。

    というのも、Mery は Unicode に対応していますが、内部的な文字データは 16 ビット (1 文字 2バイト) なもので、U+0001 から U+FFFF の範囲内の文字しか扱えないんです。

    > もしそうであれば、以下の範囲は漢字扱いの定義に加えてみてはいかがでしょうか?

    テーブルの定義に加えることができれば簡単なのですが、上記の理由から、U+10000 以上の範囲はテーブルとして定義できません。

    ちなみに、Windows 11 のメモ帳や秀〇エディタさん、E〇Editor さんでも、Ctrl + Right で移動すると「𠮷」と「野家」が分割される現象が見られますので、これらも同じ理由によるものと考えられます。

    > U+20000~U+2A6DF CJK Unified Ideographs Extension B CJK統合漢字拡張B (42720文字範囲)

    この範囲を実装する場合、テーブル定義ではなく、パーサー (構文解析) として U+10000 以上の漢字の処理を行うプログラムを組むことで対応できるような気はします。

    テーブルから定義を取得する方法と比較して、パーサープログラムは速度が遅くなる可能性がありますが、体感的には大丈夫かも…?

    うーん、できるかどうか微妙なところではありますが、ちょっと検討させてくださいませ。

     |  Kuro  |  返信
  4. ご確認ありがとうございます。

    > この範囲を実装する場合、テーブル定義ではなく、パーサー (構文解析) として U+10000 以上の漢字の処理を行うプログラムを組むことで対応できるような気はします。
    >
    > テーブルから定義を取得する方法と比較して、パーサープログラムは速度が遅くなる可能性がありますが、体感的には大丈夫かも…?
    >
    > うーん、できるかどうか微妙なところではありますが、ちょっと検討させてくださいませ。

    なるほど、テーブル方式では対応できなかったのですね。従来方式で簡単にいく話ではなかったようで、失礼しました😅

    U+FFFFと違い、もう2byte先まで読まないと文字として読み取れないからパーサーが必要と… それはたしかにテーブルから一発でピックアップする方法と比べれば幾分か低速にはなりそうですね。
    まぁ常用漢字として定義されている文字は1文字を除きU+FFFF以内に収まっているという状況から、通常の文章でパーサーが何度も呼び出されることがなく速度低下が顕著にならないという具合ならいいのですが…🤔

     |  yuko  |  返信
  5. ご返信ありがとうございます。

    > U+FFFFと違い、もう2byte先まで読まないと文字として読み取れないからパーサーが必要と… それはたしかにテーブルから一発でピックアップする方法と比べれば幾分か低速にはなりそうですね。

    そうですね。適切に対応するには、2 バイト先まで読んで 4 バイトを 1 つの文字として処理する方法が考えられますが、これは少し複雑そうです。

    検討した結果、「なんちゃって」方式を採用すれば対応できるかもしれません😓

    以下がその仕様です。

    まず、現在の Mery が対応している Unicode のバージョンは Ver 15.0 で、データは次のリンクのものを使用しています。

    https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt

    このデータを調査したところ、いただいた情報と一部異なる箇所があるようです。

    【UnicodeData.txt より抜粋】
    U+20000 ~ U+2A6DF CJK Ideograph Extension B
    U+2A700 ~ U+2B739 CJK Ideograph Extension C
    U+2B740 ~ U+2B81D CJK Ideograph Extension D
    U+2B820 ~ U+2CEA1 CJK Ideograph Extension E
    U+2CEB0 ~ U+2EBE0 CJK Ideograph Extension F
    U+2F800 ~ U+2FA1D CJK COMPATIBILITY IDEOGRAPH
    U+30000 ~ U+3134A CJK Ideograph Extension G
    U+31350 ~ U+323AF CJK Ideograph Extension H

    いただいた情報の情報元が分からなかったもので、もし意図的に漢字の範囲を追加している場合は、その詳細を教えていただけると助かります。

    ちなみに、9 月に公開予定の Unicode 15.1 では以下の範囲も追加されるようです。

    U+2EBF0 ~ U+2EE5D CJK Ideograph Extension I

    さて、「なんちゃって」方式です。

    2 バイト先まで読んで 4 バイトを 1 つの文字として扱い、上記の範囲に該当するかどうかを確認するという方法は正確ですが、すべての文字に対してこれを行うのは効率的ではありません。

    > 通常の文章でパーサーが何度も呼び出されることがなく速度低下が顕著にならないという具合ならいいのですが…🤔

    そうなんですよね。そこで、正確さは落ちますが、従来の処理速度を保ちつつ、必要最低限のパースで対応する方法を検討しました。

    たとえば、U+20000 は 2 バイトに分割すると、U+D840 (上位サロゲート) + U+DC00 (下位サロゲート) となります。なお、下位サロゲートは U+DC00 ~ U+DFFF の範囲に該当します。

    これを漢字の範囲に適用すると、

    U+20000 ~ U+2A6DF = U+D840 + U+DC00 ~ U+D869 + U+DEDF

    となります。

    ここからが「なんちゃって」なところですが、いっそのこと、下位サロゲートを無視し、U+D840 ~ U+D869 を漢字として扱い、テーブルの定義に追加します。

    これにより、従来どおりのテーブル方式で U+D840 ~ U+D869 の文字が漢字として処理され、パーサーで行う処理は U+DC00 ~ U+DFFF を無視するだけとなります。

    ただし、「なんちゃって」方式の弱点として、上位サロゲートと下位サロゲートの組み合わせを正確に識別することはできないため、たとえば、U+2A6DF の次の U+2A6E0 などは漢字の範囲に含まれるべきではありませんが、

    U+2A6E0 = U+D869 + U+DEE0

    となるため、漢字として処理されてしまうことになります。

    しかしながら、Unicode のデータを見る限り、U+20000 (U+D840 + U+DC00) ~ U+323AF (U+D888 + U+DFAF) の範囲はほぼ CJK 文字に割り当てられているようです。

    そのため、下位サロゲートを無視してざっくりと漢字と判断するのもアリかなと思うのですが、いかがでしょうか。

     |  Kuro  |  返信
  6. > いただいた情報の情報元が分からなかったもので、もし意図的に漢字の範囲を追加している場合は、その詳細を教えていただけると助かります。

    おや、、誤報をしてしまったようで、失礼しました。
    個人的によく参照する https://0g0.org を参考にピックアップしたのですが、微妙にズレがあったようですね。。
    もちろんこれはイチ個人サイトですから、Unicodeの公開文書の方が正ですね。

    > そのため、下位サロゲートを無視してざっくりと漢字と判断するのもアリかなと思うのですが、いかがでしょうか。

    軽さと正確さのバランスとして、十分に良さそうです。
    たしかにCJK Ideograph Extension B 末尾 ~ C 開始の間で微妙な開きがあったりはするものの、そこに新たに漢字以外のなにかが定義されることも無い気がしますし…。

    > U+20000 ~ U+2A6DF = U+D840 + U+DC00 ~ U+D869 + U+DEDF

    ちなみにCJK Ideograph Extension C以降は今回対象外とする感じでしょうか?

     |  yuko  |  返信
  7. 情報ありがとうございます。

    > もちろんこれはイチ個人サイトですから、Unicodeの公開文書の方が正ですね。

    そうでしたか。おそらく、Unicode のバージョンが異なるのでしょうね。バージョンが具体的に記載されていないようなので詳細はわかりませんが…

    > ちなみにCJK Ideograph Extension C以降は今回対象外とする感じでしょうか?

    いいえ、そうではありません。

    上位サロゲートと下位サロゲートを計算するのは手間がかかるため、今回は例として最初の範囲のみを計算して記載した、というだけです。

    この仕様に同意いただければ、開発時に以下のすべての範囲の上位サロゲートと下位サロゲートを計算し、上位サロゲートをテーブルの定義として使用する予定です👍

    U+20000 ~ U+2A6DF CJK Ideograph Extension B
    U+2A700 ~ U+2B739 CJK Ideograph Extension C
    U+2B740 ~ U+2B81D CJK Ideograph Extension D
    U+2B820 ~ U+2CEA1 CJK Ideograph Extension E
    U+2CEB0 ~ U+2EBE0 CJK Ideograph Extension F
    U+2F800 ~ U+2FA1D CJK COMPATIBILITY IDEOGRAPH
    U+30000 ~ U+3134A CJK Ideograph Extension G
    U+31350 ~ U+323AF CJK Ideograph Extension H

    U+2EBF0 ~ U+2EE5D CJK Ideograph Extension I ← 9 月以降にする?

    そのため、上位サロゲートの間にも隙間がある場合、それらの部分は範囲に含まれないように除外されるはずです。

     |  Kuro  |  返信
  8. > そうでしたか。おそらく、Unicode のバージョンが異なるのでしょうね。

    バージョン違いでブロックの幅も変わるんですねぇ、、、と思ってWikipediaを覗いてみたところ、Unicode 9.0時点での解説が載っており、それは先刻ご報告したサイトと同様の範囲になっていそうなので、どうやらバージョン違いで範囲が違う、でビンゴなようです。さすが👏
    https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF_(Unicode)

    > 上位サロゲートと下位サロゲートを計算するのは手間がかかるため、今回は例として最初の範囲のみを計算して記載した、というだけです。
    >
    > この仕様に同意いただければ、開発時に以下のすべての範囲の上位サロゲートと下位サロゲートを計算し、上位サロゲートをテーブルの定義として使用する予定です👍

    さすがにそうですよね😅 お手間をとらせてすみませんが、引き続きよろしくお願いできればと思います。
    上位サロゲートだけで見なす簡易判定、拡張漢字のブロックがうまいこと固まってくれていて多少はテーブル定義もまとまりがよさそうでよかったです。

     |  yuko  |  返信
  9. Kuroさん

    本件の対応、ありがとうございました。
    今扱っている仕事で割とサロゲートペアな4 byte漢字に触れることが多く、今回の機能は目立たずとも足元をしっかり支えてくれる機能って感じで、大変助かっています。
    そしてgrepも速くなって益々快適になりましたね!

     |  yuko  |  返信
  10. 早速お試しいただき、ありがとうございます。

    サロゲート ペアが多用されているプロジェクト、それはちょっとワクワクしつつ、少し怖いですね…😱 それでも、お役に立てたなら嬉しいです。

    漢字の範囲で、Unicode 15.1 はまだドラフト段階なので、15.1 の正式版がリリースされたらまた修正が必要かもしれません。

    > そしてgrepも速くなって益々快適になりましたね!

    これは少し地味でしたね。ブログ記事で盛り上げようと試みましたが、誰からも 1 ミリも反応がなく、やっぱり地味だったと感じて、お酒を飲んでおりました😭

    それはさておき、開発支援 (投げギフ) を送っていただき、本当にありがとうございます。モチベーションが高まりました!

    次のバージョンでは、ちょっとマニアックかもしれませんが、yuko さんが興味を持ってくれるかもしれない、2 ストロークのショートカット キーに対応する開発に取り組んでみようと思っています👍

    今後とも応援、よろしくお願いいたします!

     |  Kuro  |  返信
  11. > それはさておき、開発支援 (投げギフ) を送っていただき、本当にありがとうございます。モチベーションが高まりました!

    いえいえー。こちらこそ、いつも要望対応にバグ修正と、ありがとうございます😊
    Kuroさんほしいものリストを見ていて気づいたんですが、SSDの低価格化っぷりがすごいですね。最初に同じリストで見たときは8, 9000円くらいだった気がするんですが…。120GBなんて2000円でお釣りが来るほどで、SDカードも真っ青な価格になったものです。

    > 次のバージョンでは、ちょっとマニアックかもしれませんが、yuko さんが興味を持ってくれるかもしれない、2 ストロークのショートカット キーに対応する開発に取り組んでみようと思っています👍

    おおーっ!これは期待がめちゃくちゃ高まります。
    設定画面のUIも一工夫いりそうでなかなか頭をひねりそうですが、応援しています。

     |  yuko  |  返信
  12. > いえいえー。こちらこそ、いつも要望対応にバグ修正と、ありがとうございます😊

    いえいえ、本当にお気遣いなく。こちらこそ、いただいた開発支援を心から感謝しています!

    > Kuroさんほしいものリストを見ていて気づいたんですが、SSDの低価格化っぷりがすごいですね。

    確かにそうですね。セール時には、120GB の SSD が1000 円程度で販売されているのを見かけます。ただ、私はそのメーカーを知らなかったので購入はしませんでしたが…。でも、SSD は本当に何個あっても困らないアイテムですよね😅

    > 設定画面のUIも一工夫いりそうでなかなか頭をひねりそうですが、応援しています。

    ありがとうございます!

    そうなんですよね。まだ調査段階ではありますが、国産の有名なエディターの多くは、ユーザー メニューという機能を使って 2 ストローク キーを実現しているようです。

    でも、その設定が少し複雑なので、Mery ではネイティブにサポートしたいところです。

    UI については、Java 系の IDE では 2 ストロークを有効にするためのチェック ボックスのようなものがあり、それにチェックを入れて 2 つ目のキーを設定するという方法もあるようですね。

    ただ、Visual Studio や VSCode、Word (Word が 2 ストローク キーに対応していたことは最近知りましたが) のように、元々の設定画面から簡単に設定できるのが理想的ですね。

    また、私自身は 2 ストローク キーをあまり使ったことがないので、その操作性のメリットなどを実際に試してみるところから始めています。

    何か便利な 2 ストローク キーの使い方やキー割り当て、おすすめのアプリなどのアイデアがあれば、ぜひ教えていただけると嬉しいです!😋

     |  Kuro  |  返信
  13. > Word が 2 ストローク キーに対応していたことは最近知りましたが

    なんと…それは初耳でした😳
    複数文字選択といい、ちょいちょい高機能なWordさん。

    > 何か便利な 2 ストローク キーの使い方やキー割り当て、おすすめのアプリなどのアイデアがあれば、ぜひ教えていただけると嬉しいです!😋

    私はVSCodeにSublime Textのキーバインドアドインを入れているので標準とはちょっと違うかもしれませんが、Ctrl-k, Ctrl-u (大文字変換)、Ctrl-k, Ctrl-l (小文字変換)、Ctrl-k, m (プログラミング言語指定)をよく使ってますね。特に Ctrl-u は範囲選択を取り消す操作と衝突するので、2ストロークショートカットが重宝する場面です。

     |  yuko  |  返信
  14. ご返信ありがとうございます。

    > 複数文字選択といい、ちょいちょい高機能なWordさん。

    そうなんですよね。実際、手元のパソコンで確認してみると、Office 2007 の時点で既に 2 ストローク キーが設定可能だったことには驚きました😱

    > Ctrl-k, Ctrl-u (大文字変換)、Ctrl-k, Ctrl-l (小文字変換)、Ctrl-k, m (プログラミング言語指定)をよく使ってますね。

    Sublime Text はまだ試していないのですが、興味深いですね。

    なるほど、確かに、最近のバージョンの Mery でも Ctrl+U は複数選択を元に戻す操作になっているため、大文字変換は Shift+Ctrl+U に変更されていて、使いにくいかもしれませんね。

    Ctrl+K, Ctrl+U で大文字変換、Ctrl+K, Ctrl+L で小文字変換は分かりやすくて良さそうです。

    ちなみに、Visual Studio 2022 では Ctrl+K, Ctrl+K でブックマークの設定、Ctrl+K, Ctrl+L でブックマークのクリアに割り当てられていました。

    Ctrl+K, Ctrl+L をどちらに設定するか検討が必要ですが、2 ストローク キーのデモ用途として初期設定にするのであれば、Sublime Text のキー割り当ての方が役立つかもしれません。

    それから、Ctrl+K, M についても知りませんでしたが、これは VSCode のデフォルトのキー割り当てなのですね。

    Mery にはそもそも、ショートカットからプログラミング言語を指定する (編集モードの選択) 機能が備わっていないため、これを実装することができれば、Ctrl+K, M を割り当てて使えそうですね。

    いただいたご意見は参考にさせていただきます!

     |  Kuro  |  返信
スポンサーリンク