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すると下の画像のような文字化けを起こす
解決方法
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まわりの環境による影響が大きいと思います
詳しい仕様や理屈については今回深くまで追いませんが、何かこれ関係で問題を発見した人の検索キーワードの助けになれば幸いです