LoginSignup
1
0

More than 1 year has passed since last update.

Pryのlsを使うと謎の^A^B^A^Bとかが表示されて格闘した話

Last updated at Posted at 2021-11-18

pryを0.14.1に更新したらなんかls機能が正しく動いてない

shellのlsではなく、pryのlsの話です

最後に付け加えていますが、0.14.1だからバグるという話ではないみたいです

2023/01/30 追記 0.14.2で修正されました

元はANSIエスケープシーケンス文字を見た目上でちゃんと非表示にするための変更だったようです。
readlineにあるオプションに従って \001\002 を差し込んだところ、実際には多くの環境で仕様が言っているように消えるどころか、それそのものが文字化け、あるいは正しくない状態で表示されていました。

※ちなみに私の別の環境では ^A^B ではなくいわゆる豆腐が表示されていました

導入された当時のPRがこちらで、今回 0.14.2 に含まれる形でこのPRをrevertする運びとなったようです。

問題の現象

pry> ls ActiveRecord::Base

pryでページングが必要になるような長いリストを出力されるようなものをlsすると下の画像のような文字化けを起こす

image.png

解決方法

export PAGER=" less --raw-control-chars -F -X"
  • 環境変数PAGERにlessをオプション付きで設定する
  • lessの直前にあるスペースが とても とても 重要

pry/pry Non-Visible Characters Printed with Pager #2185このコメント に解決方法を記載してくれている人がいました

そもそもページング機能いらないよっていう場合

# .pryrc

Pry.config.pager = false

これで解決できます

lessが必要になりそうな長いリストでも全て表示するため、lessの機能を使わない、かつスクロールが自由にできる端末環境であればぶっちゃけこれでいいと思います

ちなみにless以外のものを使うという選択肢もありますが、色々試してみてそちらでも解決しなかったので今回は記載していません

再現手順

ruby -e 'puts "\u0001\u0002hoge"' | less

^A^Bhoge

ruby -e 'puts "\u0001\u0002hoge"' | less --raw-control-chars

hoge

原因

https://github.com/pry/pry/blob/master/lib/pry/pager.rb#L135
抜粋

class Pry
  # 略
  class Pager
    # 略
    class SystemPager < NullPager
      def self.default_pager
        pager = Pry::Env['PAGER'] || ''

        # Default to less, and make sure less is being passed the correct
        # options
        pager = "less -R -F -X" if pager.strip.empty? || pager =~ /^less\b/

        pager
      end
    end
  end
end

ここでlessにオプションを設定しようとしてPAGERを頑張って書いても、スペースを入れるトリックをやらない限り、
pager =~ /^less\b/ という無慈悲な正規表現があるためデフォルトに上書きされてしまいます

またlessにおいて -r および -R と、 --raw-control-chars は意味が違うらしく、Pryではデフォルトとして -R を採用しているために問題が発生しました
これを環境変数PAGERを工夫して設定することで回避しようというお話でした

PRの方でもっと詳しく解説されているので知りたい方はこちらを参照してください
https://github.com/pry/pry/pull/2207#issue-936203009

動作が確認できたlessのバージョンなど

※多分そこまで関係ないけど記録のために残しておきます

MacOSに標準で入っていたless

$ less -V
less 487 (POSIX regular expressions)
Copyright (C) 1984-2016  Mark Nudelman

Homebrew経由で入れたgnu由来のless

$ /usr/local/Cellar/less/590/bin/less -V
less 590 (PCRE2 regular expressions)
Copyright (C) 1984-2021  Mark Nudelman

この2つにおいてはとりあえずサポートされていました

ちなみに問題はpryじゃないかもというお話

^A^B といった文字の正体はunicodeにおけるSOHとSTXという制御用文字らしいです
それぞれ \u0001\u0002 でこの文字を扱うことができます
これがreadlineのバージョンによってサポートされていたりされなかったり、そもそも実行環境に含まれていなかったり、という違いで現象が発生するようです

pry 0.14.1 を名指ししてはいますが、実は問題のPAGERを扱う部分のコードは少なくとも0.12.2の段階でも存在しているため直接的な原因ではないと考えられます
同時期に発売されたMacbook AirとMac Miniで試して、Airの方の環境では再現できなかったためreadlineまわりの環境による影響が大きいと思います

詳しい仕様や理屈については今回深くまで追いませんが、何かこれ関係で問題を発見した人の検索キーワードの助けになれば幸いです

1
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
1
0